@actual-app/api 6.10.0 → 24.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/@types/loot-core/client/state-types/modals.d.ts +17 -11
  2. package/@types/loot-core/client/state-types/prefs.d.ts +4 -9
  3. package/@types/loot-core/client/state-types/queries.d.ts +4 -4
  4. package/@types/loot-core/mocks/index.d.ts +2 -7
  5. package/@types/loot-core/server/accounts/rules.d.ts +3 -4
  6. package/@types/loot-core/server/aql/schema/index.d.ts +8 -0
  7. package/@types/loot-core/server/db/index.d.ts +2 -2
  8. package/@types/loot-core/server/main-app.d.ts +1 -1
  9. package/@types/loot-core/server/preferences/app.d.ts +12 -0
  10. package/@types/loot-core/server/preferences/types/handlers.d.ts +8 -0
  11. package/@types/loot-core/server/prefs.d.ts +4 -6
  12. package/@types/loot-core/server/util/rschedule.d.ts +0 -1
  13. package/@types/loot-core/shared/errors.d.ts +1 -1
  14. package/@types/loot-core/shared/months.d.ts +2 -0
  15. package/@types/loot-core/shared/rules.d.ts +5 -32
  16. package/@types/loot-core/shared/transactions.d.ts +2 -0
  17. package/@types/loot-core/shared/util.d.ts +4 -2
  18. package/@types/loot-core/types/handlers.d.ts +2 -0
  19. package/@types/loot-core/types/models/dashboard.d.ts +37 -4
  20. package/@types/loot-core/types/models/reports.d.ts +3 -13
  21. package/@types/loot-core/types/models/rule.d.ts +4 -1
  22. package/@types/loot-core/types/models/schedule.d.ts +18 -14
  23. package/@types/loot-core/types/models/transaction-filter.d.ts +4 -2
  24. package/@types/loot-core/types/models/transaction.d.ts +2 -0
  25. package/@types/loot-core/types/prefs.d.ts +38 -50
  26. package/@types/loot-core/types/server-events.d.ts +1 -0
  27. package/@types/loot-core/types/server-handlers.d.ts +4 -6
  28. package/@types/loot-core/types/util.d.ts +2 -0
  29. package/@types/migrations/1723665565000_prefs.d.ts +4 -0
  30. package/dist/app/bundle.api.js +1164 -781
  31. package/dist/migrations/1723665565000_prefs.js +51 -0
  32. package/dist/package.json +1 -1
  33. package/package.json +1 -1
  34. /package/@types/loot-core/server/budget/{rollover.d.ts → envelope.d.ts} +0 -0
@@ -4619,145 +4619,6 @@
4619
4619
  ];
4620
4620
  /***/
4621
4621
  }),
4622
- /***/ "./node_modules/@rschedule/json-tools/es2015/Schedule.js":
4623
- /*!***************************************************************!*\
4624
- !*** ./node_modules/@rschedule/json-tools/es2015/Schedule.js ***!
4625
- \***************************************************************/
4626
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4627
- "use strict";
4628
- __webpack_require__.r(__webpack_exports__);
4629
- /* harmony import */ var _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @rschedule/core/generators */ "./node_modules/@rschedule/core/es2015/generators.js");
4630
- /* harmony import */ var _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @rschedule/json-tools */ "./node_modules/@rschedule/json-tools/es2015/main.js");
4631
- /* harmony import */ var _rschedule_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @rschedule/core */ "./node_modules/@rschedule/core/es2015/main.js");
4632
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates.prototype.toJSON = function serialize(opts = {}) {
4633
- const json = {
4634
- type: 'Dates',
4635
- dates: this.adapters.map(adapter => adapter.toJSON()),
4636
- };
4637
- if (!opts.nested)
4638
- json.timezone = this.timezone;
4639
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.serializeDataToJSON)(this, json, opts);
4640
- return json;
4641
- };
4642
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates.fromJSON = function parse(json, options = {}) {
4643
- if (json.type !== 'Dates') {
4644
- throw new _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.ParseJSONError('Invalid Dates JSON');
4645
- }
4646
- return new _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates({
4647
- dates: json.dates.map(date => _rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateAdapterBase.adapter.fromJSON(date)),
4648
- data: typeof options.data === 'function' ? options.data(json) : json.data,
4649
- timezone: options.timezone || json.timezone,
4650
- });
4651
- };
4652
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.registerJSONSerializerFn)('Dates', _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates.fromJSON);
4653
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule.prototype.toJSON = function serialize(opts = {}) {
4654
- const json = {
4655
- type: 'Rule',
4656
- config: Object.assign(Object.assign({}, (0, _rschedule_core__WEBPACK_IMPORTED_MODULE_2__.cloneJSON)(this.options)), {
4657
- start: this.normalizeDateInput(this.options.start).toJSON(),
4658
- }),
4659
- };
4660
- if (this.options.end) {
4661
- json.config.end = this.normalizeDateInput(this.options.end).toJSON();
4662
- }
4663
- if (!opts.nested)
4664
- json.timezone = this.timezone;
4665
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.serializeDataToJSON)(this, json, opts);
4666
- return json;
4667
- };
4668
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule.fromJSON = function fromJSON(json, options = {}) {
4669
- const config = Object.assign(Object.assign({}, json.config), {
4670
- start: _rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateAdapterBase.adapter.fromJSON(json.config.start),
4671
- end: json.config.end && _rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateAdapterBase.adapter.fromJSON(json.config.end),
4672
- });
4673
- return new _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule(config, {
4674
- data: typeof options.data === 'function' ? options.data(json) : json.data,
4675
- timezone: options.timezone || json.timezone,
4676
- });
4677
- };
4678
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.registerJSONSerializerFn)('Rule', _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule.fromJSON);
4679
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Schedule.prototype.toJSON = function serialize(opts = {}) {
4680
- const json = {
4681
- type: 'Schedule',
4682
- rrules: this.rrules.map(rule => rule.toJSON(Object.assign(Object.assign({}, opts), { nested: true }))),
4683
- exrules: this.exrules.map(rule => rule.toJSON(Object.assign(Object.assign({}, opts), { nested: true }))),
4684
- rdates: this.rdates.toJSON(Object.assign(Object.assign({}, opts), { nested: true })),
4685
- exdates: this.exdates.toJSON(Object.assign(Object.assign({}, opts), { nested: true })),
4686
- };
4687
- if (!opts.nested)
4688
- json.timezone = this.timezone;
4689
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.serializeDataToJSON)(this, json, opts);
4690
- return json;
4691
- };
4692
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Schedule.fromJSON = function parse(json, options = {}) {
4693
- if (json.type !== 'Schedule') {
4694
- throw new _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.ParseJSONError('Invalid Schedule JSON');
4695
- }
4696
- return new _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Schedule({
4697
- rrules: json.rrules.map(rule => _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule.fromJSON(rule, Object.assign({ timezone: json.timezone }, options))),
4698
- exrules: json.exrules.map(rule => _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Rule.fromJSON(rule, Object.assign({ timezone: json.timezone }, options))),
4699
- rdates: _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates.fromJSON(json.rdates, Object.assign({ timezone: json.timezone }, options)),
4700
- exdates: _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Dates.fromJSON(json.exdates, Object.assign({ timezone: json.timezone }, options)),
4701
- data: typeof options.data === 'function' ? options.data(json) : json.data,
4702
- timezone: options.timezone || json.timezone,
4703
- });
4704
- };
4705
- (0, _rschedule_json_tools__WEBPACK_IMPORTED_MODULE_0__.registerJSONSerializerFn)('Schedule', _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_1__.Schedule.fromJSON);
4706
- /***/
4707
- }),
4708
- /***/ "./node_modules/@rschedule/json-tools/es2015/main.js":
4709
- /*!***********************************************************!*\
4710
- !*** ./node_modules/@rschedule/json-tools/es2015/main.js ***!
4711
- \***********************************************************/
4712
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4713
- "use strict";
4714
- __webpack_require__.r(__webpack_exports__);
4715
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4716
- /* harmony export */ ParseJSONError: () => ( /* binding */ParseJSONError),
4717
- /* harmony export */ SerializeJSONError: () => ( /* binding */SerializeJSONError),
4718
- /* harmony export */ registerJSONSerializerFn: () => ( /* binding */registerJSONSerializerFn),
4719
- /* harmony export */ serializeDataToJSON: () => ( /* binding */serializeDataToJSON)
4720
- /* harmony export */
4721
- });
4722
- /* harmony import */ var _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @rschedule/core/generators */ "./node_modules/@rschedule/core/es2015/generators.js");
4723
- class ParseJSONError extends Error {
4724
- }
4725
- class SerializeJSONError extends Error {
4726
- }
4727
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__.OccurrenceGenerator.JSON_FN_MAP = new Map();
4728
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__.OccurrenceGenerator.prototype.toJSON = function serialize(opts) {
4729
- throw new SerializeJSONError(`To support smaller bundles, ${this.constructor.name}#toJSON() ` +
4730
- `must be manually added. See "@rschedule/json-tools" in the rSchedule docs.`);
4731
- };
4732
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__.OccurrenceGenerator.fromJSON = function parse(json, options) {
4733
- if (typeof json !== 'object' || json === null) {
4734
- throw new ParseJSONError(`Invalid json "${json}"`);
4735
- }
4736
- const fn = _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__.OccurrenceGenerator.JSON_FN_MAP.get(json.type);
4737
- if (!fn) {
4738
- throw new ParseJSONError(`Unknown rSchedule object type "${json.type}". Have you added a json serializer ` +
4739
- `for "${json.type}"? ` +
4740
- `See "@rschedule/json-tools" in the rSchedule docs.`);
4741
- }
4742
- return fn(json, options);
4743
- };
4744
- function serializeDataToJSON(gen, json, opt) {
4745
- if (!opt.data)
4746
- return;
4747
- if (opt.data === true) {
4748
- json.data = gen.data;
4749
- }
4750
- else {
4751
- json.data = opt.data(gen);
4752
- }
4753
- if (json.data === undefined)
4754
- delete json.data;
4755
- }
4756
- function registerJSONSerializerFn(name, fn) {
4757
- _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_0__.OccurrenceGenerator.JSON_FN_MAP.set(name, fn);
4758
- }
4759
- /***/
4760
- }),
4761
4622
  /***/ "./node_modules/@rschedule/standard-date-adapter/es2015/main.js":
4762
4623
  /*!**********************************************************************!*\
4763
4624
  !*** ./node_modules/@rschedule/standard-date-adapter/es2015/main.js ***!
@@ -18249,6 +18110,50 @@
18249
18110
  module.exports = defineProperties;
18250
18111
  /***/
18251
18112
  }),
18113
+ /***/ "./node_modules/err-code/index.js":
18114
+ /*!****************************************!*\
18115
+ !*** ./node_modules/err-code/index.js ***!
18116
+ \****************************************/
18117
+ /***/ ((module) => {
18118
+ "use strict";
18119
+ function assign(obj, props) {
18120
+ for (const key in props) {
18121
+ Object.defineProperty(obj, key, {
18122
+ value: props[key],
18123
+ enumerable: true,
18124
+ configurable: true,
18125
+ });
18126
+ }
18127
+ return obj;
18128
+ }
18129
+ function createError(err, code, props) {
18130
+ if (!err || typeof err === 'string') {
18131
+ throw new TypeError('Please pass an Error to err-code');
18132
+ }
18133
+ if (!props) {
18134
+ props = {};
18135
+ }
18136
+ if (typeof code === 'object') {
18137
+ props = code;
18138
+ code = undefined;
18139
+ }
18140
+ if (code != null) {
18141
+ props.code = code;
18142
+ }
18143
+ try {
18144
+ return assign(err, props);
18145
+ }
18146
+ catch (_) {
18147
+ props.message = err.message;
18148
+ props.stack = err.stack;
18149
+ const ErrClass = function () { };
18150
+ ErrClass.prototype = Object.create(Object.getPrototypeOf(err));
18151
+ return assign(new ErrClass(), props);
18152
+ }
18153
+ }
18154
+ module.exports = createError;
18155
+ /***/
18156
+ }),
18252
18157
  /***/ "./node_modules/es-define-property/index.js":
18253
18158
  /*!**************************************************!*\
18254
18159
  !*** ./node_modules/es-define-property/index.js ***!
@@ -24213,6 +24118,54 @@
24213
24118
  ];
24214
24119
  /***/
24215
24120
  }),
24121
+ /***/ "./node_modules/promise-retry/index.js":
24122
+ /*!*********************************************!*\
24123
+ !*** ./node_modules/promise-retry/index.js ***!
24124
+ \*********************************************/
24125
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
24126
+ "use strict";
24127
+ var errcode = __webpack_require__(/*! err-code */ "./node_modules/err-code/index.js");
24128
+ var retry = __webpack_require__(/*! retry */ "./node_modules/retry/index.js");
24129
+ var hasOwn = Object.prototype.hasOwnProperty;
24130
+ function isRetryError(err) {
24131
+ return err && err.code === 'EPROMISERETRY' && hasOwn.call(err, 'retried');
24132
+ }
24133
+ function promiseRetry(fn, options) {
24134
+ var temp;
24135
+ var operation;
24136
+ if (typeof fn === 'object' && typeof options === 'function') {
24137
+ // Swap options and fn when using alternate signature (options, fn)
24138
+ temp = options;
24139
+ options = fn;
24140
+ fn = temp;
24141
+ }
24142
+ operation = retry.operation(options);
24143
+ return new Promise(function (resolve, reject) {
24144
+ operation.attempt(function (number) {
24145
+ Promise.resolve()
24146
+ .then(function () {
24147
+ return fn(function (err) {
24148
+ if (isRetryError(err)) {
24149
+ err = err.retried;
24150
+ }
24151
+ throw errcode(new Error('Retrying'), 'EPROMISERETRY', { retried: err });
24152
+ }, number);
24153
+ })
24154
+ .then(resolve, function (err) {
24155
+ if (isRetryError(err)) {
24156
+ err = err.retried;
24157
+ if (operation.retry(err || new Error())) {
24158
+ return;
24159
+ }
24160
+ }
24161
+ reject(err);
24162
+ });
24163
+ });
24164
+ });
24165
+ }
24166
+ module.exports = promiseRetry;
24167
+ /***/
24168
+ }),
24216
24169
  /***/ "./node_modules/regexp.prototype.flags/implementation.js":
24217
24170
  /*!***************************************************************!*\
24218
24171
  !*** ./node_modules/regexp.prototype.flags/implementation.js ***!
@@ -24344,6 +24297,239 @@
24344
24297
  };
24345
24298
  /***/
24346
24299
  }),
24300
+ /***/ "./node_modules/retry/index.js":
24301
+ /*!*************************************!*\
24302
+ !*** ./node_modules/retry/index.js ***!
24303
+ \*************************************/
24304
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
24305
+ module.exports = __webpack_require__(/*! ./lib/retry */ "./node_modules/retry/lib/retry.js");
24306
+ /***/
24307
+ }),
24308
+ /***/ "./node_modules/retry/lib/retry.js":
24309
+ /*!*****************************************!*\
24310
+ !*** ./node_modules/retry/lib/retry.js ***!
24311
+ \*****************************************/
24312
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
24313
+ var RetryOperation = __webpack_require__(/*! ./retry_operation */ "./node_modules/retry/lib/retry_operation.js");
24314
+ exports.operation = function (options) {
24315
+ var timeouts = exports.timeouts(options);
24316
+ return new RetryOperation(timeouts, {
24317
+ forever: options && options.forever,
24318
+ unref: options && options.unref,
24319
+ maxRetryTime: options && options.maxRetryTime
24320
+ });
24321
+ };
24322
+ exports.timeouts = function (options) {
24323
+ if (options instanceof Array) {
24324
+ return [].concat(options);
24325
+ }
24326
+ var opts = {
24327
+ retries: 10,
24328
+ factor: 2,
24329
+ minTimeout: 1 * 1000,
24330
+ maxTimeout: Infinity,
24331
+ randomize: false
24332
+ };
24333
+ for (var key in options) {
24334
+ opts[key] = options[key];
24335
+ }
24336
+ if (opts.minTimeout > opts.maxTimeout) {
24337
+ throw new Error('minTimeout is greater than maxTimeout');
24338
+ }
24339
+ var timeouts = [];
24340
+ for (var i = 0; i < opts.retries; i++) {
24341
+ timeouts.push(this.createTimeout(i, opts));
24342
+ }
24343
+ if (options && options.forever && !timeouts.length) {
24344
+ timeouts.push(this.createTimeout(i, opts));
24345
+ }
24346
+ // sort the array numerically ascending
24347
+ timeouts.sort(function (a, b) {
24348
+ return a - b;
24349
+ });
24350
+ return timeouts;
24351
+ };
24352
+ exports.createTimeout = function (attempt, opts) {
24353
+ var random = (opts.randomize)
24354
+ ? (Math.random() + 1)
24355
+ : 1;
24356
+ var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt));
24357
+ timeout = Math.min(timeout, opts.maxTimeout);
24358
+ return timeout;
24359
+ };
24360
+ exports.wrap = function (obj, options, methods) {
24361
+ if (options instanceof Array) {
24362
+ methods = options;
24363
+ options = null;
24364
+ }
24365
+ if (!methods) {
24366
+ methods = [];
24367
+ for (var key in obj) {
24368
+ if (typeof obj[key] === 'function') {
24369
+ methods.push(key);
24370
+ }
24371
+ }
24372
+ }
24373
+ for (var i = 0; i < methods.length; i++) {
24374
+ var method = methods[i];
24375
+ var original = obj[method];
24376
+ obj[method] = function retryWrapper(original) {
24377
+ var op = exports.operation(options);
24378
+ var args = Array.prototype.slice.call(arguments, 1);
24379
+ var callback = args.pop();
24380
+ args.push(function (err) {
24381
+ if (op.retry(err)) {
24382
+ return;
24383
+ }
24384
+ if (err) {
24385
+ arguments[0] = op.mainError();
24386
+ }
24387
+ callback.apply(this, arguments);
24388
+ });
24389
+ op.attempt(function () {
24390
+ original.apply(obj, args);
24391
+ });
24392
+ }.bind(obj, original);
24393
+ obj[method].options = options;
24394
+ }
24395
+ };
24396
+ /***/
24397
+ }),
24398
+ /***/ "./node_modules/retry/lib/retry_operation.js":
24399
+ /*!***************************************************!*\
24400
+ !*** ./node_modules/retry/lib/retry_operation.js ***!
24401
+ \***************************************************/
24402
+ /***/ ((module) => {
24403
+ function RetryOperation(timeouts, options) {
24404
+ // Compatibility for the old (timeouts, retryForever) signature
24405
+ if (typeof options === 'boolean') {
24406
+ options = { forever: options };
24407
+ }
24408
+ this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
24409
+ this._timeouts = timeouts;
24410
+ this._options = options || {};
24411
+ this._maxRetryTime = options && options.maxRetryTime || Infinity;
24412
+ this._fn = null;
24413
+ this._errors = [];
24414
+ this._attempts = 1;
24415
+ this._operationTimeout = null;
24416
+ this._operationTimeoutCb = null;
24417
+ this._timeout = null;
24418
+ this._operationStart = null;
24419
+ if (this._options.forever) {
24420
+ this._cachedTimeouts = this._timeouts.slice(0);
24421
+ }
24422
+ }
24423
+ module.exports = RetryOperation;
24424
+ RetryOperation.prototype.reset = function () {
24425
+ this._attempts = 1;
24426
+ this._timeouts = this._originalTimeouts;
24427
+ };
24428
+ RetryOperation.prototype.stop = function () {
24429
+ if (this._timeout) {
24430
+ clearTimeout(this._timeout);
24431
+ }
24432
+ this._timeouts = [];
24433
+ this._cachedTimeouts = null;
24434
+ };
24435
+ RetryOperation.prototype.retry = function (err) {
24436
+ if (this._timeout) {
24437
+ clearTimeout(this._timeout);
24438
+ }
24439
+ if (!err) {
24440
+ return false;
24441
+ }
24442
+ var currentTime = new Date().getTime();
24443
+ if (err && currentTime - this._operationStart >= this._maxRetryTime) {
24444
+ this._errors.unshift(new Error('RetryOperation timeout occurred'));
24445
+ return false;
24446
+ }
24447
+ this._errors.push(err);
24448
+ var timeout = this._timeouts.shift();
24449
+ if (timeout === undefined) {
24450
+ if (this._cachedTimeouts) {
24451
+ // retry forever, only keep last error
24452
+ this._errors.splice(this._errors.length - 1, this._errors.length);
24453
+ this._timeouts = this._cachedTimeouts.slice(0);
24454
+ timeout = this._timeouts.shift();
24455
+ }
24456
+ else {
24457
+ return false;
24458
+ }
24459
+ }
24460
+ var self = this;
24461
+ var timer = setTimeout(function () {
24462
+ self._attempts++;
24463
+ if (self._operationTimeoutCb) {
24464
+ self._timeout = setTimeout(function () {
24465
+ self._operationTimeoutCb(self._attempts);
24466
+ }, self._operationTimeout);
24467
+ if (self._options.unref) {
24468
+ self._timeout.unref();
24469
+ }
24470
+ }
24471
+ self._fn(self._attempts);
24472
+ }, timeout);
24473
+ if (this._options.unref) {
24474
+ timer.unref();
24475
+ }
24476
+ return true;
24477
+ };
24478
+ RetryOperation.prototype.attempt = function (fn, timeoutOps) {
24479
+ this._fn = fn;
24480
+ if (timeoutOps) {
24481
+ if (timeoutOps.timeout) {
24482
+ this._operationTimeout = timeoutOps.timeout;
24483
+ }
24484
+ if (timeoutOps.cb) {
24485
+ this._operationTimeoutCb = timeoutOps.cb;
24486
+ }
24487
+ }
24488
+ var self = this;
24489
+ if (this._operationTimeoutCb) {
24490
+ this._timeout = setTimeout(function () {
24491
+ self._operationTimeoutCb();
24492
+ }, self._operationTimeout);
24493
+ }
24494
+ this._operationStart = new Date().getTime();
24495
+ this._fn(this._attempts);
24496
+ };
24497
+ RetryOperation.prototype.try = function (fn) {
24498
+ console.log('Using RetryOperation.try() is deprecated');
24499
+ this.attempt(fn);
24500
+ };
24501
+ RetryOperation.prototype.start = function (fn) {
24502
+ console.log('Using RetryOperation.start() is deprecated');
24503
+ this.attempt(fn);
24504
+ };
24505
+ RetryOperation.prototype.start = RetryOperation.prototype.try;
24506
+ RetryOperation.prototype.errors = function () {
24507
+ return this._errors;
24508
+ };
24509
+ RetryOperation.prototype.attempts = function () {
24510
+ return this._attempts;
24511
+ };
24512
+ RetryOperation.prototype.mainError = function () {
24513
+ if (this._errors.length === 0) {
24514
+ return null;
24515
+ }
24516
+ var counts = {};
24517
+ var mainError = null;
24518
+ var mainErrorCount = 0;
24519
+ for (var i = 0; i < this._errors.length; i++) {
24520
+ var error = this._errors[i];
24521
+ var message = error.message;
24522
+ var count = (counts[message] || 0) + 1;
24523
+ counts[message] = count;
24524
+ if (count >= mainErrorCount) {
24525
+ mainError = error;
24526
+ mainErrorCount = count;
24527
+ }
24528
+ }
24529
+ return mainError;
24530
+ };
24531
+ /***/
24532
+ }),
24347
24533
  /***/ "./node_modules/sax/lib/sax.js":
24348
24534
  /*!*************************************!*\
24349
24535
  !*** ./node_modules/sax/lib/sax.js ***!
@@ -27211,6 +27397,65 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
27211
27397
  }
27212
27398
  /***/
27213
27399
  }),
27400
+ /***/ "./packages/loot-core/migrations/1723665565000_prefs.js":
27401
+ /*!**************************************************************!*\
27402
+ !*** ./packages/loot-core/migrations/1723665565000_prefs.js ***!
27403
+ \**************************************************************/
27404
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
27405
+ "use strict";
27406
+ __webpack_require__.r(__webpack_exports__);
27407
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
27408
+ /* harmony export */ "default": () => ( /* binding */runMigration)
27409
+ /* harmony export */
27410
+ });
27411
+ const SYNCED_PREF_KEYS = [
27412
+ 'firstDayOfWeekIdx',
27413
+ 'dateFormat',
27414
+ 'numberFormat',
27415
+ 'hideFraction',
27416
+ 'isPrivacyEnabled',
27417
+ /^show-extra-balances-/,
27418
+ /^hide-cleared-/,
27419
+ /^parse-date-/,
27420
+ /^csv-mappings-/,
27421
+ /^csv-delimiter-/,
27422
+ /^csv-has-header-/,
27423
+ /^ofx-fallback-missing-payee-/,
27424
+ /^flip-amount-/,
27425
+ 'budgetType',
27426
+ /^flags\./
27427
+ ];
27428
+ async function runMigration(db, { fs, fileId }) {
27429
+ await db.execQuery(`
27430
+ CREATE TABLE preferences
27431
+ (id TEXT PRIMARY KEY,
27432
+ value TEXT);
27433
+ `);
27434
+ try {
27435
+ const budgetDir = fs.getBudgetDir(fileId);
27436
+ const fullpath = fs.join(budgetDir, 'metadata.json');
27437
+ const prefs = JSON.parse(await fs.readFile(fullpath));
27438
+ if (typeof prefs !== 'object') {
27439
+ return;
27440
+ }
27441
+ await Promise.all(Object.keys(prefs).map(async (key) => {
27442
+ // Check if the current key is of synced-keys type
27443
+ if (!SYNCED_PREF_KEYS.find((keyMatcher) => keyMatcher instanceof RegExp ? keyMatcher.test(key) : keyMatcher === key)) {
27444
+ return;
27445
+ }
27446
+ // insert the synced prefs in the new table
27447
+ await db.runQuery('INSERT INTO preferences (id, value) VALUES (?, ?)', [
27448
+ key,
27449
+ String(prefs[key])
27450
+ ]);
27451
+ }));
27452
+ }
27453
+ catch (e) {
27454
+ // Do nothing
27455
+ }
27456
+ }
27457
+ /***/
27458
+ }),
27214
27459
  /***/ "./packages/loot-core/src/client/platform.electron.ts":
27215
27460
  /*!************************************************************!*\
27216
27461
  !*** ./packages/loot-core/src/client/platform.electron.ts ***!
@@ -28256,15 +28501,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
28256
28501
  "use strict";
28257
28502
  __webpack_require__.r(__webpack_exports__);
28258
28503
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
28259
- /* harmony export */ _setDocumentDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_2__._setDocumentDir),
28504
+ /* harmony export */ _setDocumentDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_3__._setDocumentDir),
28260
28505
  /* harmony export */ basename: () => ( /* binding */basename),
28261
28506
  /* harmony export */ bundledDatabasePath: () => ( /* binding */bundledDatabasePath),
28262
28507
  /* harmony export */ copyFile: () => ( /* binding */copyFile),
28263
28508
  /* harmony export */ demoBudgetPath: () => ( /* binding */demoBudgetPath),
28264
28509
  /* harmony export */ exists: () => ( /* binding */exists),
28265
- /* harmony export */ getBudgetDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_2__.getBudgetDir),
28510
+ /* harmony export */ getBudgetDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_3__.getBudgetDir),
28266
28511
  /* harmony export */ getDataDir: () => ( /* binding */getDataDir),
28267
- /* harmony export */ getDocumentDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_2__.getDocumentDir),
28512
+ /* harmony export */ getDocumentDir: () => ( /* reexport safe */_shared__WEBPACK_IMPORTED_MODULE_3__.getDocumentDir),
28268
28513
  /* harmony export */ getModifiedTime: () => ( /* binding */getModifiedTime),
28269
28514
  /* harmony export */ init: () => ( /* binding */init),
28270
28515
  /* harmony export */ join: () => ( /* binding */join),
@@ -28283,7 +28528,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
28283
28528
  /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/ __webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
28284
28529
  /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! path */ "path");
28285
28530
  /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/ __webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
28286
- /* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shared */ "./packages/loot-core/src/platform/server/fs/shared.ts");
28531
+ /* harmony import */ var promise_retry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! promise-retry */ "./node_modules/promise-retry/index.js");
28532
+ /* harmony import */ var promise_retry__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/ __webpack_require__.n(promise_retry__WEBPACK_IMPORTED_MODULE_2__);
28533
+ /* harmony import */ var _shared__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shared */ "./packages/loot-core/src/platform/server/fs/shared.ts");
28287
28534
  // @ts-strict-ignore
28288
28535
  let rootPath = path__WEBPACK_IMPORTED_MODULE_1__.join(__dirname, '..', '..', '..', '..');
28289
28536
  if (__filename.match('bundle')) {
@@ -28369,13 +28616,36 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
28369
28616
  });
28370
28617
  });
28371
28618
  };
28372
- const writeFile = (filepath, contents) => {
28373
- return new Promise(function (resolve, reject) {
28374
- // @ts-expect-error contents type needs refining
28375
- fs__WEBPACK_IMPORTED_MODULE_0__.writeFile(filepath, contents, 'utf8', function (err) {
28376
- return err ? reject(err) : resolve(undefined);
28619
+ const writeFile = async (filepath, contents) => {
28620
+ try {
28621
+ await promise_retry__WEBPACK_IMPORTED_MODULE_2___default()((retry, attempt) => {
28622
+ return new Promise((resolve, reject) => {
28623
+ // @ts-expect-error contents type needs refining
28624
+ fs__WEBPACK_IMPORTED_MODULE_0__.writeFile(filepath, contents, 'utf8', (err) => {
28625
+ if (err) {
28626
+ console.error(`Failed to write to ${filepath}. Attempted ${attempt} times. Something is locking the file - potentially a virus scanner or backup software.`);
28627
+ reject(err);
28628
+ }
28629
+ else {
28630
+ if (attempt > 1) {
28631
+ console.info(`Successfully recovered from file lock. It took ${attempt} retries`);
28632
+ }
28633
+ resolve(undefined);
28634
+ }
28635
+ });
28636
+ }).catch(retry);
28637
+ }, {
28638
+ retries: 20,
28639
+ minTimeout: 100,
28640
+ maxTimeout: 500,
28641
+ factor: 1.5
28377
28642
  });
28378
- });
28643
+ return undefined;
28644
+ }
28645
+ catch (err) {
28646
+ console.error(`Unable to recover from file lock on file ${filepath}`);
28647
+ throw err;
28648
+ }
28379
28649
  };
28380
28650
  const removeFile = (filepath) => {
28381
28651
  return new Promise(function (resolve, reject) {
@@ -28604,7 +28874,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
28604
28874
  }
28605
28875
  }
28606
28876
  function regexp(regex, text) {
28607
- return new RegExp(regex).test(text) ? 1 : 0;
28877
+ return new RegExp(regex).test(text || '') ? 1 : 0;
28608
28878
  }
28609
28879
  function openDatabase(pathOrBuffer) {
28610
28880
  const db = new (better_sqlite3__WEBPACK_IMPORTED_MODULE_0___default())(pathOrBuffer);
@@ -29337,7 +29607,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
29337
29607
  const rules = (0, _shared_schedules__WEBPACK_IMPORTED_MODULE_2__.recurConfigToRSchedule)(desc);
29338
29608
  return {
29339
29609
  type: 'recur',
29340
- // @ts-expect-error fix me
29341
29610
  schedule: new _util_rschedule__WEBPACK_IMPORTED_MODULE_6__.Schedule({
29342
29611
  rrules: rules,
29343
29612
  data: {
@@ -29458,30 +29727,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
29458
29727
  assert(Array.isArray(value), 'no-empty-array', `oneOf must have an array value (field: ${fieldName}): ${JSON.stringify(value)}`);
29459
29728
  return value.filter(Boolean).map((val) => val.toLowerCase());
29460
29729
  }
29730
+ assert(typeof value === 'string', 'not-string', `Invalid string value (field: ${fieldName})`);
29461
29731
  if (op === 'contains' || op === 'matches' || op === 'doesNotContain' || op === 'hasTags') {
29462
- assert(typeof value === 'string' && value.length > 0, 'no-empty-string', `contains must have non-empty string (field: ${fieldName})`);
29463
- }
29464
- return value.toLowerCase();
29465
- }
29466
- },
29467
- imported_payee: {
29468
- ops: [
29469
- 'is',
29470
- 'contains',
29471
- 'matches',
29472
- 'oneOf',
29473
- 'isNot',
29474
- 'doesNotContain',
29475
- 'notOneOf'
29476
- ],
29477
- nullable: true,
29478
- parse(op, value, fieldName) {
29479
- if (op === 'oneOf' || op === 'notOneOf') {
29480
- assert(Array.isArray(value), 'no-empty-array', `${op} must have an array value (field: ${fieldName}): ${JSON.stringify(value)}`);
29481
- return value.filter(Boolean).map((val) => val.toLowerCase());
29482
- }
29483
- if (op === 'contains' || op === 'matches' || op === 'doesNotContain') {
29484
- assert(typeof value === 'string' && value.length > 0, 'no-empty-string', `${op} must have non-empty string (field: ${fieldName})`);
29732
+ assert(value.length > 0, 'no-empty-string', `${op} must have non-empty string (field: ${fieldName})`);
29485
29733
  }
29486
29734
  return value.toLowerCase();
29487
29735
  }
@@ -29524,14 +29772,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
29524
29772
  }
29525
29773
  };
29526
29774
  class Condition {
29527
- constructor(op, field, value, options, fieldTypes) {
29528
- const typeName = fieldTypes.get(field);
29775
+ constructor(op, field, value, options) {
29776
+ const typeName = _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES.get(field);
29529
29777
  assert(typeName, 'internal', 'Invalid condition field: ' + field);
29530
29778
  const type = CONDITION_TYPES[typeName];
29531
29779
  // It's important to validate rules because a faulty rule might mess
29532
29780
  // up the user's transaction (and be very confusing)
29533
29781
  assert(type, 'internal', `Invalid condition type: ${typeName} (field: ${field})`);
29534
- assert(type.ops.includes(op), 'internal', `Invalid condition operator: ${op} (type: ${typeName}, field: ${field})`);
29782
+ assert((0, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.isValidOp)(field, op), 'internal', `Invalid condition operator: ${op} (type: ${typeName}, field: ${field})`);
29535
29783
  if (type.nullable !== true) {
29536
29784
  assert(value != null, 'no-null', `Field cannot be empty: ${field}`);
29537
29785
  }
@@ -29723,10 +29971,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
29723
29971
  'append-notes'
29724
29972
  ];
29725
29973
  class Action {
29726
- constructor(op, field, value, options, fieldTypes) {
29974
+ constructor(op, field, value, options) {
29727
29975
  assert(ACTION_OPS.includes(op), 'internal', `Invalid action operation: ${op}`);
29728
29976
  if (op === 'set') {
29729
- const typeName = fieldTypes.get(field);
29977
+ const typeName = _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES.get(field);
29730
29978
  assert(typeName, 'internal', `Invalid field for action: ${field}`);
29731
29979
  this.field = field;
29732
29980
  this.type = typeName;
@@ -29883,12 +30131,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
29883
30131
  return update;
29884
30132
  }
29885
30133
  class Rule {
29886
- constructor({ id, stage, conditionsOp, conditions, actions, fieldTypes }) {
30134
+ constructor({ id, stage, conditionsOp, conditions, actions }) {
29887
30135
  this.id = id;
29888
30136
  this.stage = stage;
29889
30137
  this.conditionsOp = conditionsOp;
29890
- this.conditions = conditions.map((c) => new Condition(c.op, c.field, c.value, c.options, fieldTypes));
29891
- this.actions = actions.map((a) => new Action(a.op, a.field, a.value, a.options, fieldTypes));
30138
+ this.conditions = conditions.map((c) => new Condition(c.op, c.field, c.value, c.options));
30139
+ this.actions = actions.map((a) => new Action(a.op, a.field, a.value, a.options));
29892
30140
  }
29893
30141
  evalConditions(object) {
29894
30142
  if (this.conditions.length === 0) {
@@ -30245,6 +30493,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
30245
30493
  return account.balances.current;
30246
30494
  }
30247
30495
  }
30496
+ async function updateAccountBalance(id, balance) {
30497
+ await _db__WEBPACK_IMPORTED_MODULE_4__.runQuery('UPDATE accounts SET balance_current = ? WHERE id = ?', [
30498
+ (0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.amountToInteger)(balance),
30499
+ id
30500
+ ]);
30501
+ }
30248
30502
  async function getGoCardlessAccounts(userId, userKey, id) {
30249
30503
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.getItem('user-token');
30250
30504
  if (!userToken)
@@ -30744,7 +30998,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
30744
30998
  else {
30745
30999
  throw new Error(`Unrecognized bank-sync provider: ${acctRow.account_sync_source}`);
30746
31000
  }
30747
- const { transactions: originalTransactions } = download;
31001
+ const { transactions: originalTransactions, accountBalance } = download;
30748
31002
  if (originalTransactions.length === 0) {
30749
31003
  return {
30750
31004
  added: [],
@@ -30757,6 +31011,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
30757
31011
  }));
30758
31012
  return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
30759
31013
  const result = await reconcileTransactions(id, transactions, true, useStrictIdChecking);
31014
+ if (accountBalance)
31015
+ await updateAccountBalance(id, accountBalance);
30760
31016
  return result;
30761
31017
  });
30762
31018
  }
@@ -31153,10 +31409,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31153
31409
  function makeRule(data) {
31154
31410
  let rule;
31155
31411
  try {
31156
- rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
31157
- ...ruleModel.toJS(data),
31158
- fieldTypes: _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES
31159
- });
31412
+ rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule(ruleModel.toJS(data));
31160
31413
  }
31161
31414
  catch (e) {
31162
31415
  console.warn('Invalid rule', e);
@@ -31282,7 +31535,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31282
31535
  return cond;
31283
31536
  }
31284
31537
  try {
31285
- return new _rules__WEBPACK_IMPORTED_MODULE_10__.Condition(cond.op, cond.field, cond.value, cond.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
31538
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Condition(cond.op, cond.field, cond.value, cond.options);
31286
31539
  }
31287
31540
  catch (e) {
31288
31541
  errors.push(e.type || 'internal');
@@ -31574,15 +31827,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31574
31827
  }
31575
31828
  try {
31576
31829
  if (action.op === 'set-split-amount') {
31577
- return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
31830
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, action.options);
31578
31831
  }
31579
31832
  else if (action.op === 'link-schedule') {
31580
- return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
31833
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null);
31581
31834
  }
31582
31835
  else if (action.op === 'prepend-notes' || action.op === 'append-notes') {
31583
- return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
31836
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null);
31584
31837
  }
31585
- return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
31838
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, action.field, action.value, action.options);
31586
31839
  }
31587
31840
  catch (e) {
31588
31841
  console.log('Action error', e);
@@ -31674,8 +31927,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31674
31927
  field: 'payee',
31675
31928
  value: to
31676
31929
  }
31677
- ],
31678
- fieldTypes: _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES
31930
+ ]
31679
31931
  });
31680
31932
  return insertRule(rule.serialize());
31681
31933
  }
@@ -31790,8 +32042,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31790
32042
  field: 'category',
31791
32043
  value: category
31792
32044
  }
31793
- ],
31794
- fieldTypes: _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES
32045
+ ]
31795
32046
  });
31796
32047
  await insertRule(newRule.serialize());
31797
32048
  }
@@ -34861,6 +35112,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34861
35112
  id: f('id'),
34862
35113
  note: f('string')
34863
35114
  },
35115
+ preferences: {
35116
+ id: f('id'),
35117
+ value: f('string')
35118
+ },
34864
35119
  transaction_filters: {
34865
35120
  id: f('id'),
34866
35121
  name: f('string'),
@@ -35484,12 +35739,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35484
35739
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
35485
35740
  /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
35486
35741
  /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
35487
- /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../prefs */ "./packages/loot-core/src/server/prefs.ts");
35488
- /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../sheet */ "./packages/loot-core/src/server/sheet.ts");
35489
- /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
35742
+ /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../sheet */ "./packages/loot-core/src/server/sheet.ts");
35743
+ /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
35490
35744
  // @ts-strict-ignore
35491
35745
  async function getSheetValue(sheetName, cell) {
35492
- const node = await _sheet__WEBPACK_IMPORTED_MODULE_4__.getCell(sheetName, cell);
35746
+ const node = await _sheet__WEBPACK_IMPORTED_MODULE_3__.getCell(sheetName, cell);
35493
35747
  return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)(typeof node.value === 'number' ? node.value : 0);
35494
35748
  }
35495
35749
  // We want to only allow the positive movement of money back and
@@ -35501,11 +35755,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35501
35755
  return buffered + amount;
35502
35756
  }
35503
35757
  function getBudgetTable() {
35504
- const { budgetType } = _prefs__WEBPACK_IMPORTED_MODULE_3__.getPrefs() || {};
35505
- return budgetType === 'report' ? 'reflect_budgets' : 'zero_budgets';
35758
+ return isReflectBudget() ? 'reflect_budgets' : 'zero_budgets';
35506
35759
  }
35507
35760
  function isReflectBudget() {
35508
- const { budgetType } = _prefs__WEBPACK_IMPORTED_MODULE_3__.getPrefs();
35761
+ const budgetType = _db__WEBPACK_IMPORTED_MODULE_2__.firstSync(`SELECT value FROM preferences WHERE id = ?`, [
35762
+ 'budgetType'
35763
+ ]) ?? 'rollover';
35509
35764
  return budgetType === 'report';
35510
35765
  }
35511
35766
  function dbMonth(month) {
@@ -35521,7 +35776,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35521
35776
  ]);
35522
35777
  }
35523
35778
  function getAllMonths(startMonth) {
35524
- const { createdMonths } = _sheet__WEBPACK_IMPORTED_MODULE_4__.get().meta();
35779
+ const { createdMonths } = _sheet__WEBPACK_IMPORTED_MODULE_3__.get().meta();
35525
35780
  let latest = null;
35526
35781
  for (const month of createdMonths) {
35527
35782
  if (latest == null || month > latest) {
@@ -35618,7 +35873,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35618
35873
  const prevMonth = dbMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(month));
35619
35874
  const table = getBudgetTable();
35620
35875
  const budgetData = await getBudgetData(table, prevMonth.toString());
35621
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
35876
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35622
35877
  budgetData.forEach((prevBudget) => {
35623
35878
  if (prevBudget.is_income === 1 && !isReflectBudget()) {
35624
35879
  return;
@@ -35634,7 +35889,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35634
35889
  async function copySinglePreviousMonth({ month, category }) {
35635
35890
  const prevMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(month);
35636
35891
  const newAmount = await getSheetValue(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(prevMonth), 'budget-' + category);
35637
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
35892
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35638
35893
  setBudget({
35639
35894
  category,
35640
35895
  month,
@@ -35644,7 +35899,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35644
35899
  }
35645
35900
  async function setZero({ month }) {
35646
35901
  const categories = await _db__WEBPACK_IMPORTED_MODULE_2__.all('SELECT * FROM v_categories WHERE tombstone = 0');
35647
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
35902
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35648
35903
  categories.forEach((cat) => {
35649
35904
  if (cat.is_income === 1 && !isReflectBudget()) {
35650
35905
  return;
@@ -35662,7 +35917,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35662
35917
  const prevMonth1 = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(month);
35663
35918
  const prevMonth2 = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(prevMonth1);
35664
35919
  const prevMonth3 = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(prevMonth2);
35665
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
35920
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35666
35921
  for (const cat of categories) {
35667
35922
  if (cat.is_income === 1 && !isReflectBudget()) {
35668
35923
  continue;
@@ -35692,7 +35947,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35692
35947
  sumAmount += await getSheetValue(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(prevMonth), 'sum-amount-' + category);
35693
35948
  prevMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(prevMonth);
35694
35949
  }
35695
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
35950
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35696
35951
  let avg = Math.round(sumAmount / N);
35697
35952
  if (categoryFromDb.is_income === 0) {
35698
35953
  avg *= -1;
@@ -35738,10 +35993,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35738
35993
  amount: fromBudgeted - amountCovered
35739
35994
  });
35740
35995
  }
35741
- await setBudget({
35742
- category: to,
35743
- month,
35744
- amount: toBudgeted + amountCovered
35996
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35997
+ await setBudget({
35998
+ category: to,
35999
+ month,
36000
+ amount: toBudgeted + amountCovered
36001
+ });
36002
+ await addMovementNotes({
36003
+ month,
36004
+ amount: amountCovered,
36005
+ to,
36006
+ from
36007
+ });
35745
36008
  });
35746
36009
  }
35747
36010
  async function transferAvailable({ month, amount, category }) {
@@ -35759,40 +36022,78 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35759
36022
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
35760
36023
  const toBudget = await getSheetValue(sheetName, 'to-budget');
35761
36024
  const categoryBudget = await getSheetValue(sheetName, 'budget-' + category);
35762
- await setBudget({
35763
- category,
35764
- month,
35765
- amount: categoryBudget + toBudget
36025
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
36026
+ await setBudget({
36027
+ category,
36028
+ month,
36029
+ amount: categoryBudget + toBudget
36030
+ });
36031
+ await addMovementNotes({
36032
+ month,
36033
+ amount: -toBudget,
36034
+ from: category,
36035
+ to: 'overbudgeted'
36036
+ });
35766
36037
  });
35767
36038
  }
35768
36039
  async function transferCategory({ month, amount, from, to }) {
35769
36040
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
35770
36041
  const fromBudgeted = await getSheetValue(sheetName, 'budget-' + from);
35771
- await setBudget({
35772
- category: from,
35773
- month,
35774
- amount: fromBudgeted - amount
35775
- });
35776
- // If we are simply moving it back into available cash to budget,
35777
- // don't do anything else
35778
- if (to !== 'to-be-budgeted') {
35779
- const toBudgeted = await getSheetValue(sheetName, 'budget-' + to);
36042
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35780
36043
  await setBudget({
35781
- category: to,
36044
+ category: from,
35782
36045
  month,
35783
- amount: toBudgeted + amount
36046
+ amount: fromBudgeted - amount
36047
+ });
36048
+ // If we are simply moving it back into available cash to budget,
36049
+ // don't do anything else
36050
+ if (to !== 'to-be-budgeted') {
36051
+ const toBudgeted = await getSheetValue(sheetName, 'budget-' + to);
36052
+ await setBudget({
36053
+ category: to,
36054
+ month,
36055
+ amount: toBudgeted + amount
36056
+ });
36057
+ }
36058
+ await addMovementNotes({
36059
+ month,
36060
+ amount,
36061
+ to,
36062
+ from
35784
36063
  });
35785
- }
36064
+ });
35786
36065
  }
35787
36066
  async function setCategoryCarryover({ startMonth, category, flag }) {
35788
36067
  const table = getBudgetTable();
35789
36068
  const months = getAllMonths(startMonth);
35790
- await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
36069
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_4__.batchMessages)(async () => {
35791
36070
  for (const month of months) {
35792
36071
  setCarryover(table, category, dbMonth(month).toString(), flag);
35793
36072
  }
35794
36073
  });
35795
36074
  }
36075
+ function addNewLine(notes) {
36076
+ return !notes ? '' : `${notes}${notes && '\n'}`;
36077
+ }
36078
+ async function addMovementNotes({ month, amount, to, from }) {
36079
+ const displayAmount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.integerToCurrency)(amount);
36080
+ const monthBudgetNotesId = `budget-${month}`;
36081
+ const existingMonthBudgetNotes = addNewLine(_db__WEBPACK_IMPORTED_MODULE_2__.firstSync(`SELECT n.note FROM notes n WHERE n.id = ?`, [
36082
+ monthBudgetNotesId
36083
+ ])?.note);
36084
+ const displayDay = _shared_months__WEBPACK_IMPORTED_MODULE_0__.format(_shared_months__WEBPACK_IMPORTED_MODULE_0__.currentDate(), 'MMMM dd');
36085
+ const categories = await _db__WEBPACK_IMPORTED_MODULE_2__.getCategories([
36086
+ from,
36087
+ to
36088
+ ].filter((c) => c !== 'to-be-budgeted' && c !== 'overbudgeted'));
36089
+ const fromCategoryName = from === 'to-be-budgeted' ? 'To Budget' : categories.find((c) => c.id === from)?.name;
36090
+ const toCategoryName = to === 'to-be-budgeted' ? 'To Budget' : to === 'overbudgeted' ? 'Overbudgeted' : categories.find((c) => c.id === to)?.name;
36091
+ const note = `Reassigned ${displayAmount} from ${fromCategoryName} → ${toCategoryName} on ${displayDay}`;
36092
+ await _db__WEBPACK_IMPORTED_MODULE_2__.update('notes', {
36093
+ id: monthBudgetNotesId,
36094
+ note: `${existingMonthBudgetNotes}- ${note}`
36095
+ });
36096
+ }
35796
36097
  /***/
35797
36098
  }),
35798
36099
  /***/ "./packages/loot-core/src/server/budget/app.ts":
@@ -35856,8 +36157,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35856
36157
  /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../sheet */ "./packages/loot-core/src/server/sheet.ts");
35857
36158
  /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
35858
36159
  /* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./actions */ "./packages/loot-core/src/server/budget/actions.ts");
35859
- /* harmony import */ var _report__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./report */ "./packages/loot-core/src/server/budget/report.ts");
35860
- /* harmony import */ var _rollover__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./rollover */ "./packages/loot-core/src/server/budget/rollover.ts");
36160
+ /* harmony import */ var _envelope__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./envelope */ "./packages/loot-core/src/server/budget/envelope.ts");
36161
+ /* harmony import */ var _report__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./report */ "./packages/loot-core/src/server/budget/report.ts");
35861
36162
  /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./util */ "./packages/loot-core/src/server/budget/util.ts");
35862
36163
  // @ts-strict-ignore
35863
36164
  function getBudgetType() {
@@ -35900,10 +36201,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35900
36201
  }
35901
36202
  });
35902
36203
  if (getBudgetType() === 'rollover') {
35903
- _rollover__WEBPACK_IMPORTED_MODULE_7__.createCategory(cat, sheetName, prevSheetName);
36204
+ _envelope__WEBPACK_IMPORTED_MODULE_6__.createCategory(cat, sheetName, prevSheetName);
35904
36205
  }
35905
36206
  else {
35906
- _report__WEBPACK_IMPORTED_MODULE_6__.createCategory(cat, sheetName, prevSheetName);
36207
+ _report__WEBPACK_IMPORTED_MODULE_7__.createCategory(cat, sheetName, prevSheetName);
35907
36208
  }
35908
36209
  }
35909
36210
  function createCategoryGroup(group, sheetName) {
@@ -35991,7 +36292,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35991
36292
  }
35992
36293
  else if (newValue.tombstone === 0 && (!oldValue || oldValue.tombstone === 1)) {
35993
36294
  if (budgetType === 'rollover') {
35994
- _rollover__WEBPACK_IMPORTED_MODULE_7__.createBlankCategory(newValue, months);
36295
+ _envelope__WEBPACK_IMPORTED_MODULE_6__.createBlankCategory(newValue, months);
35995
36296
  }
35996
36297
  months.forEach((month) => {
35997
36298
  const prevMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(month);
@@ -36155,7 +36456,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36155
36456
  meta.createdMonths = meta.createdMonths || new Set();
36156
36457
  const budgetType = getBudgetType();
36157
36458
  if (budgetType === 'rollover') {
36158
- _rollover__WEBPACK_IMPORTED_MODULE_7__.createBudget(meta, categories, months);
36459
+ _envelope__WEBPACK_IMPORTED_MODULE_6__.createBudget(meta, categories, months);
36159
36460
  }
36160
36461
  months.forEach((month) => {
36161
36462
  if (!meta.createdMonths.has(month)) {
@@ -36170,10 +36471,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36170
36471
  createCategoryGroup(group, sheetName);
36171
36472
  });
36172
36473
  if (budgetType === 'rollover') {
36173
- _rollover__WEBPACK_IMPORTED_MODULE_7__.createSummary(groups, categories, prevSheetName, sheetName);
36474
+ _envelope__WEBPACK_IMPORTED_MODULE_6__.createSummary(groups, categories, prevSheetName, sheetName);
36174
36475
  }
36175
36476
  else {
36176
- _report__WEBPACK_IMPORTED_MODULE_6__.createSummary(groups, categories, sheetName);
36477
+ _report__WEBPACK_IMPORTED_MODULE_7__.createSummary(groups, categories, sheetName);
36177
36478
  }
36178
36479
  meta.createdMonths.add(month);
36179
36480
  }
@@ -36557,6 +36858,171 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36557
36858
  }
36558
36859
  /***/
36559
36860
  }),
36861
+ /***/ "./packages/loot-core/src/server/budget/envelope.ts":
36862
+ /*!**********************************************************!*\
36863
+ !*** ./packages/loot-core/src/server/budget/envelope.ts ***!
36864
+ \**********************************************************/
36865
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
36866
+ "use strict";
36867
+ __webpack_require__.r(__webpack_exports__);
36868
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
36869
+ /* harmony export */ createBlankCategory: () => ( /* binding */createBlankCategory),
36870
+ /* harmony export */ createBudget: () => ( /* binding */createBudget),
36871
+ /* harmony export */ createCategory: () => ( /* binding */createCategory),
36872
+ /* harmony export */ createSummary: () => ( /* binding */createSummary)
36873
+ /* harmony export */
36874
+ });
36875
+ /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
36876
+ /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
36877
+ /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../sheet */ "./packages/loot-core/src/server/sheet.ts");
36878
+ /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
36879
+ /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util */ "./packages/loot-core/src/server/budget/util.ts");
36880
+ // @ts-strict-ignore
36881
+ function getBlankSheet(months) {
36882
+ const blankMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(months[0]);
36883
+ return _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(blankMonth);
36884
+ }
36885
+ function createBlankCategory(cat, months) {
36886
+ if (months.length > 0) {
36887
+ const sheetName = getBlankSheet(months);
36888
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `carryover-${cat.id}`, false);
36889
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `leftover-${cat.id}`, 0);
36890
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `leftover-pos-${cat.id}`, 0);
36891
+ }
36892
+ }
36893
+ function createBlankMonth(categories, sheetName, months) {
36894
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'is-blank', true);
36895
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'to-budget', 0);
36896
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'buffered', 0);
36897
+ categories.forEach((cat) => createBlankCategory(cat, months));
36898
+ }
36899
+ function createCategory(cat, sheetName, prevSheetName) {
36900
+ if (!cat.is_income) {
36901
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `budget-${cat.id}`, 0);
36902
+ // This makes the app more robust by "fixing up" null budget values.
36903
+ // Those should not be allowed, but in case somehow a null value
36904
+ // ends up there, we are resilient to it. Preferrably the
36905
+ // spreadsheet would have types and be more strict about what is
36906
+ // allowed to be set.
36907
+ if (_sheet__WEBPACK_IMPORTED_MODULE_2__.get().getCellValue(sheetName, `budget-${cat.id}`) == null) {
36908
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().set((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_3__.resolveName)(sheetName, `budget-${cat.id}`), 0);
36909
+ }
36910
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `carryover-${cat.id}`, false);
36911
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, `leftover-${cat.id}`, {
36912
+ initialValue: 0,
36913
+ dependencies: [
36914
+ `budget-${cat.id}`,
36915
+ `sum-amount-${cat.id}`,
36916
+ `${prevSheetName}!carryover-${cat.id}`,
36917
+ `${prevSheetName}!leftover-${cat.id}`,
36918
+ `${prevSheetName}!leftover-pos-${cat.id}`
36919
+ ],
36920
+ run: (budgeted, spent, prevCarryover, prevLeftover, prevLeftoverPos) => {
36921
+ return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(budgeted) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(spent) + (prevCarryover ? (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(prevLeftover) : (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(prevLeftoverPos)));
36922
+ }
36923
+ });
36924
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'leftover-pos-' + cat.id, {
36925
+ initialValue: 0,
36926
+ dependencies: [
36927
+ `leftover-${cat.id}`
36928
+ ],
36929
+ run: (leftover) => {
36930
+ return leftover < 0 ? 0 : leftover;
36931
+ }
36932
+ });
36933
+ }
36934
+ }
36935
+ function createSummary(groups, categories, prevSheetName, sheetName) {
36936
+ const incomeGroup = groups.filter((group) => group.is_income)[0];
36937
+ const expenseCategories = categories.filter((cat) => !cat.is_income);
36938
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'buffered', 0);
36939
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'from-last-month', {
36940
+ initialValue: 0,
36941
+ dependencies: [
36942
+ `${prevSheetName}!to-budget`,
36943
+ `${prevSheetName}!buffered`
36944
+ ],
36945
+ run: (toBudget, buffered) => (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(toBudget) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(buffered))
36946
+ });
36947
+ // Alias the group income total to `total-income`
36948
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-income', {
36949
+ initialValue: 0,
36950
+ dependencies: [
36951
+ `group-sum-amount-${incomeGroup.id}`
36952
+ ],
36953
+ run: (amount) => amount
36954
+ });
36955
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'available-funds', {
36956
+ initialValue: 0,
36957
+ dependencies: [
36958
+ 'total-income',
36959
+ 'from-last-month'
36960
+ ],
36961
+ run: (income, fromLastMonth) => (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(income) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(fromLastMonth))
36962
+ });
36963
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'last-month-overspent', {
36964
+ initialValue: 0,
36965
+ dependencies: (0, _util__WEBPACK_IMPORTED_MODULE_4__.flatten2)(expenseCategories.map((cat) => [
36966
+ `${prevSheetName}!leftover-${cat.id}`,
36967
+ `${prevSheetName}!carryover-${cat.id}`
36968
+ ])),
36969
+ run: (...data) => {
36970
+ data = (0, _util__WEBPACK_IMPORTED_MODULE_4__.unflatten2)(data);
36971
+ return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)(data.reduce((total, [leftover, carryover]) => {
36972
+ if (carryover) {
36973
+ return total;
36974
+ }
36975
+ return total + Math.min(0, (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(leftover));
36976
+ }, 0));
36977
+ }
36978
+ });
36979
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-budgeted', {
36980
+ initialValue: 0,
36981
+ dependencies: groups.filter((group) => !group.is_income).map((group) => `group-budget-${group.id}`),
36982
+ run: (...amounts) => {
36983
+ // Negate budgeted amount
36984
+ return -(0, _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts)(...amounts);
36985
+ }
36986
+ });
36987
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'buffered', {
36988
+ initialValue: 0
36989
+ });
36990
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'to-budget', {
36991
+ initialValue: 0,
36992
+ dependencies: [
36993
+ 'available-funds',
36994
+ 'last-month-overspent',
36995
+ 'total-budgeted',
36996
+ 'buffered'
36997
+ ],
36998
+ run: (available, lastOverspent, totalBudgeted, buffered) => {
36999
+ return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(available) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(lastOverspent) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(totalBudgeted) - (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(buffered));
37000
+ }
37001
+ });
37002
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-spent', {
37003
+ initialValue: 0,
37004
+ dependencies: groups.filter((group) => !group.is_income).map((group) => `group-sum-amount-${group.id}`),
37005
+ run: _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts
37006
+ });
37007
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-leftover', {
37008
+ initialValue: 0,
37009
+ dependencies: groups.filter((group) => !group.is_income).map((group) => `group-leftover-${group.id}`),
37010
+ run: _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts
37011
+ });
37012
+ }
37013
+ function createBudget(meta, categories, months) {
37014
+ // The spreadsheet is now strict - so we need to fill in some
37015
+ // default values for the month before the first month. Only do this
37016
+ // if it doesn't already exist
37017
+ const blankSheet = getBlankSheet(months);
37018
+ if (meta.blankSheet !== blankSheet) {
37019
+ _sheet__WEBPACK_IMPORTED_MODULE_2__.get().clearSheet(meta.blankSheet);
37020
+ createBlankMonth(categories, blankSheet, months);
37021
+ meta.blankSheet = blankSheet;
37022
+ }
37023
+ }
37024
+ /***/
37025
+ }),
36560
37026
  /***/ "./packages/loot-core/src/server/budget/goals/goalsAverage.ts":
36561
37027
  /*!********************************************************************!*\
36562
37028
  !*** ./packages/loot-core/src/server/budget/goals/goalsAverage.ts ***!
@@ -37723,171 +38189,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
37723
38189
  }
37724
38190
  /***/
37725
38191
  }),
37726
- /***/ "./packages/loot-core/src/server/budget/rollover.ts":
37727
- /*!**********************************************************!*\
37728
- !*** ./packages/loot-core/src/server/budget/rollover.ts ***!
37729
- \**********************************************************/
37730
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
37731
- "use strict";
37732
- __webpack_require__.r(__webpack_exports__);
37733
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
37734
- /* harmony export */ createBlankCategory: () => ( /* binding */createBlankCategory),
37735
- /* harmony export */ createBudget: () => ( /* binding */createBudget),
37736
- /* harmony export */ createCategory: () => ( /* binding */createCategory),
37737
- /* harmony export */ createSummary: () => ( /* binding */createSummary)
37738
- /* harmony export */
37739
- });
37740
- /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
37741
- /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
37742
- /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../sheet */ "./packages/loot-core/src/server/sheet.ts");
37743
- /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
37744
- /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util */ "./packages/loot-core/src/server/budget/util.ts");
37745
- // @ts-strict-ignore
37746
- function getBlankSheet(months) {
37747
- const blankMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(months[0]);
37748
- return _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(blankMonth);
37749
- }
37750
- function createBlankCategory(cat, months) {
37751
- if (months.length > 0) {
37752
- const sheetName = getBlankSheet(months);
37753
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `carryover-${cat.id}`, false);
37754
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `leftover-${cat.id}`, 0);
37755
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `leftover-pos-${cat.id}`, 0);
37756
- }
37757
- }
37758
- function createBlankMonth(categories, sheetName, months) {
37759
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'is-blank', true);
37760
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'to-budget', 0);
37761
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'buffered', 0);
37762
- categories.forEach((cat) => createBlankCategory(cat, months));
37763
- }
37764
- function createCategory(cat, sheetName, prevSheetName) {
37765
- if (!cat.is_income) {
37766
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `budget-${cat.id}`, 0);
37767
- // This makes the app more robust by "fixing up" null budget values.
37768
- // Those should not be allowed, but in case somehow a null value
37769
- // ends up there, we are resilient to it. Preferrably the
37770
- // spreadsheet would have types and be more strict about what is
37771
- // allowed to be set.
37772
- if (_sheet__WEBPACK_IMPORTED_MODULE_2__.get().getCellValue(sheetName, `budget-${cat.id}`) == null) {
37773
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().set((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_3__.resolveName)(sheetName, `budget-${cat.id}`), 0);
37774
- }
37775
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, `carryover-${cat.id}`, false);
37776
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, `leftover-${cat.id}`, {
37777
- initialValue: 0,
37778
- dependencies: [
37779
- `budget-${cat.id}`,
37780
- `sum-amount-${cat.id}`,
37781
- `${prevSheetName}!carryover-${cat.id}`,
37782
- `${prevSheetName}!leftover-${cat.id}`,
37783
- `${prevSheetName}!leftover-pos-${cat.id}`
37784
- ],
37785
- run: (budgeted, spent, prevCarryover, prevLeftover, prevLeftoverPos) => {
37786
- return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(budgeted) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(spent) + (prevCarryover ? (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(prevLeftover) : (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(prevLeftoverPos)));
37787
- }
37788
- });
37789
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'leftover-pos-' + cat.id, {
37790
- initialValue: 0,
37791
- dependencies: [
37792
- `leftover-${cat.id}`
37793
- ],
37794
- run: (leftover) => {
37795
- return leftover < 0 ? 0 : leftover;
37796
- }
37797
- });
37798
- }
37799
- }
37800
- function createSummary(groups, categories, prevSheetName, sheetName) {
37801
- const incomeGroup = groups.filter((group) => group.is_income)[0];
37802
- const expenseCategories = categories.filter((cat) => !cat.is_income);
37803
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createStatic(sheetName, 'buffered', 0);
37804
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'from-last-month', {
37805
- initialValue: 0,
37806
- dependencies: [
37807
- `${prevSheetName}!to-budget`,
37808
- `${prevSheetName}!buffered`
37809
- ],
37810
- run: (toBudget, buffered) => (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(toBudget) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(buffered))
37811
- });
37812
- // Alias the group income total to `total-income`
37813
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-income', {
37814
- initialValue: 0,
37815
- dependencies: [
37816
- `group-sum-amount-${incomeGroup.id}`
37817
- ],
37818
- run: (amount) => amount
37819
- });
37820
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'available-funds', {
37821
- initialValue: 0,
37822
- dependencies: [
37823
- 'total-income',
37824
- 'from-last-month'
37825
- ],
37826
- run: (income, fromLastMonth) => (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(income) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(fromLastMonth))
37827
- });
37828
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'last-month-overspent', {
37829
- initialValue: 0,
37830
- dependencies: (0, _util__WEBPACK_IMPORTED_MODULE_4__.flatten2)(expenseCategories.map((cat) => [
37831
- `${prevSheetName}!leftover-${cat.id}`,
37832
- `${prevSheetName}!carryover-${cat.id}`
37833
- ])),
37834
- run: (...data) => {
37835
- data = (0, _util__WEBPACK_IMPORTED_MODULE_4__.unflatten2)(data);
37836
- return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)(data.reduce((total, [leftover, carryover]) => {
37837
- if (carryover) {
37838
- return total;
37839
- }
37840
- return total + Math.min(0, (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(leftover));
37841
- }, 0));
37842
- }
37843
- });
37844
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-budgeted', {
37845
- initialValue: 0,
37846
- dependencies: groups.filter((group) => !group.is_income).map((group) => `group-budget-${group.id}`),
37847
- run: (...amounts) => {
37848
- // Negate budgeted amount
37849
- return -(0, _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts)(...amounts);
37850
- }
37851
- });
37852
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'buffered', {
37853
- initialValue: 0
37854
- });
37855
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'to-budget', {
37856
- initialValue: 0,
37857
- dependencies: [
37858
- 'available-funds',
37859
- 'last-month-overspent',
37860
- 'total-budgeted',
37861
- 'buffered'
37862
- ],
37863
- run: (available, lastOverspent, totalBudgeted, buffered) => {
37864
- return (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.safeNumber)((0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(available) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(lastOverspent) + (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(totalBudgeted) - (0, _util__WEBPACK_IMPORTED_MODULE_4__.number)(buffered));
37865
- }
37866
- });
37867
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-spent', {
37868
- initialValue: 0,
37869
- dependencies: groups.filter((group) => !group.is_income).map((group) => `group-sum-amount-${group.id}`),
37870
- run: _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts
37871
- });
37872
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().createDynamic(sheetName, 'total-leftover', {
37873
- initialValue: 0,
37874
- dependencies: groups.filter((group) => !group.is_income).map((group) => `group-leftover-${group.id}`),
37875
- run: _util__WEBPACK_IMPORTED_MODULE_4__.sumAmounts
37876
- });
37877
- }
37878
- function createBudget(meta, categories, months) {
37879
- // The spreadsheet is now strict - so we need to fill in some
37880
- // default values for the month before the first month. Only do this
37881
- // if it doesn't already exist
37882
- const blankSheet = getBlankSheet(months);
37883
- if (meta.blankSheet !== blankSheet) {
37884
- _sheet__WEBPACK_IMPORTED_MODULE_2__.get().clearSheet(meta.blankSheet);
37885
- createBlankMonth(categories, blankSheet, months);
37886
- meta.blankSheet = blankSheet;
37887
- }
37888
- }
37889
- /***/
37890
- }),
37891
38192
  /***/ "./packages/loot-core/src/server/budget/statements.ts":
37892
38193
  /*!************************************************************!*\
37893
38194
  !*** ./packages/loot-core/src/server/budget/statements.ts ***!
@@ -37919,6 +38220,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
37919
38220
  FROM notes n
37920
38221
  JOIN categories c ON n.id = c.id
37921
38222
  WHERE c.id = n.id
38223
+ AND c.tombstone = 0
37922
38224
  AND (lower(note) LIKE '%${_template_notes__WEBPACK_IMPORTED_MODULE_1__.TEMPLATE_PREFIX}%'
37923
38225
  OR lower(note) LIKE '%${_template_notes__WEBPACK_IMPORTED_MODULE_1__.GOAL_PREFIX}%')
37924
38226
  `);
@@ -38519,7 +38821,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38519
38821
  'net-worth-card',
38520
38822
  'cash-flow-card',
38521
38823
  'spending-card',
38522
- 'custom-report'
38824
+ 'custom-report',
38825
+ 'markdown-card'
38523
38826
  ].includes(widget.type)) {
38524
38827
  throw new _errors__WEBPACK_IMPORTED_MODULE_8__.ValidationError(`Invalid widget.${idx}.type value ${widget.type}.`);
38525
38828
  }
@@ -38921,20 +39224,26 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38921
39224
  }
38922
39225
  // Data-specific functions. Ideally this would be split up into
38923
39226
  // different files
38924
- async function getCategories() {
38925
- return await all(`
38926
- SELECT c.* FROM categories c WHERE c.tombstone = 0
38927
- ORDER BY c.sort_order, c.id
38928
- `);
38929
- }
38930
- async function getCategoriesGrouped() {
38931
- const groups = await all(`
38932
- SELECT cg.* FROM category_groups cg WHERE cg.tombstone = 0 ORDER BY cg.is_income, cg.sort_order, cg.id
38933
- `);
38934
- const categories = await all(`
38935
- SELECT c.* FROM categories c WHERE c.tombstone = 0
38936
- ORDER BY c.sort_order, c.id
38937
- `);
39227
+ async function getCategories(ids) {
39228
+ const whereIn = ids ? `c.id IN (${toSqlQueryParameters(ids)}) AND` : '';
39229
+ const query = `SELECT c.* FROM categories c WHERE ${whereIn} c.tombstone = 0 ORDER BY c.sort_order, c.id`;
39230
+ return ids ? await all(query, [
39231
+ ...ids
39232
+ ]) : await all(query);
39233
+ }
39234
+ async function getCategoriesGrouped(ids) {
39235
+ const categoryGroupWhereIn = ids ? `cg.id IN (${toSqlQueryParameters(ids)}) AND` : '';
39236
+ const categoryGroupQuery = `SELECT cg.* FROM category_groups cg WHERE ${categoryGroupWhereIn} cg.tombstone = 0
39237
+ ORDER BY cg.is_income, cg.sort_order, cg.id`;
39238
+ const categoryWhereIn = ids ? `c.cat_group IN (${toSqlQueryParameters(ids)}) AND` : '';
39239
+ const categoryQuery = `SELECT c.* FROM categories c WHERE ${categoryWhereIn} c.tombstone = 0
39240
+ ORDER BY c.sort_order, c.id`;
39241
+ const groups = ids ? await all(categoryGroupQuery, [
39242
+ ...ids
39243
+ ]) : await all(categoryGroupQuery);
39244
+ const categories = ids ? await all(categoryQuery, [
39245
+ ...ids
39246
+ ]) : await all(categoryQuery);
38938
39247
  return groups.map((group) => {
38939
39248
  return {
38940
39249
  ...group,
@@ -39161,7 +39470,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39161
39470
  return all(`
39162
39471
  SELECT p.id as id, p.name as name, p.favorite as favorite,
39163
39472
  p.category as category, TRUE as common, NULL as transfer_acct,
39164
- count(*) as c,
39473
+ count(*) as c,
39165
39474
  max(t.date) as latest
39166
39475
  FROM payees p
39167
39476
  LEFT JOIN v_transactions_internal_alive t on t.payee == p.id
@@ -39169,7 +39478,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39169
39478
  AND p.tombstone = 0
39170
39479
  AND t.date > ${twelveWeeksAgo}
39171
39480
  GROUP BY p.id
39172
- ORDER BY c DESC ,p.transfer_acct IS NULL DESC, p.name
39481
+ ORDER BY c DESC ,p.transfer_acct IS NULL DESC, p.name
39173
39482
  COLLATE NOCASE
39174
39483
  LIMIT ${limit}
39175
39484
  `);
@@ -39270,6 +39579,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39270
39579
  async function deleteTransaction(transaction) {
39271
39580
  return delete_('transactions', transaction.id);
39272
39581
  }
39582
+ function toSqlQueryParameters(params) {
39583
+ return params.map(() => '?').join(',');
39584
+ }
39273
39585
  /***/
39274
39586
  }),
39275
39587
  /***/ "./packages/loot-core/src/server/db/mappings.ts":
@@ -40761,7 +41073,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40761
41073
  /* harmony import */ var _actual_app_api_injected__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @actual-app/api/injected */ "./packages/api/injected.js");
40762
41074
  /* harmony import */ var _actual_app_crdt__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @actual-app/crdt */ "@actual-app/crdt");
40763
41075
  /* harmony import */ var _actual_app_crdt__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/ __webpack_require__.n(_actual_app_crdt__WEBPACK_IMPORTED_MODULE_4__);
40764
- /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
41076
+ /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
40765
41077
  /* harmony import */ var _mocks_budget__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../mocks/budget */ "./packages/loot-core/src/mocks/budget.ts");
40766
41078
  /* harmony import */ var _platform_exceptions__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../platform/exceptions */ "./packages/loot-core/src/platform/exceptions/index.electron.ts");
40767
41079
  /* harmony import */ var _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../platform/server/asyncStorage */ "./packages/loot-core/src/platform/server/asyncStorage/index.electron.ts");
@@ -40798,26 +41110,27 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40798
41110
  /* harmony import */ var _notes_app__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./notes/app */ "./packages/loot-core/src/server/notes/app.ts");
40799
41111
  /* harmony import */ var _platform__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./platform */ "./packages/loot-core/src/server/platform.ts");
40800
41112
  /* harmony import */ var _post__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./post */ "./packages/loot-core/src/server/post.ts");
40801
- /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./prefs */ "./packages/loot-core/src/server/prefs.ts");
40802
- /* harmony import */ var _reports_app__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./reports/app */ "./packages/loot-core/src/server/reports/app.ts");
40803
- /* harmony import */ var _rules_app__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./rules/app */ "./packages/loot-core/src/server/rules/app.ts");
40804
- /* harmony import */ var _schedules_app__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./schedules/app */ "./packages/loot-core/src/server/schedules/app.ts");
40805
- /* harmony import */ var _server_config__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./server-config */ "./packages/loot-core/src/server/server-config.ts");
40806
- /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./sheet */ "./packages/loot-core/src/server/sheet.ts");
40807
- /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
40808
- /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./sync */ "./packages/loot-core/src/server/sync/index.ts");
40809
- /* harmony import */ var _sync_migrate__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./sync/migrate */ "./packages/loot-core/src/server/sync/migrate.ts");
40810
- /* harmony import */ var _tools_app__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./tools/app */ "./packages/loot-core/src/server/tools/app.ts");
40811
- /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./undo */ "./packages/loot-core/src/server/undo.ts");
40812
- /* harmony import */ var _update__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./update */ "./packages/loot-core/src/server/update.ts");
40813
- /* harmony import */ var _util_budget_name__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ./util/budget-name */ "./packages/loot-core/src/server/util/budget-name.ts");
41113
+ /* harmony import */ var _preferences_app__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./preferences/app */ "./packages/loot-core/src/server/preferences/app.ts");
41114
+ /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./prefs */ "./packages/loot-core/src/server/prefs.ts");
41115
+ /* harmony import */ var _reports_app__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./reports/app */ "./packages/loot-core/src/server/reports/app.ts");
41116
+ /* harmony import */ var _rules_app__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./rules/app */ "./packages/loot-core/src/server/rules/app.ts");
41117
+ /* harmony import */ var _schedules_app__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./schedules/app */ "./packages/loot-core/src/server/schedules/app.ts");
41118
+ /* harmony import */ var _server_config__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./server-config */ "./packages/loot-core/src/server/server-config.ts");
41119
+ /* harmony import */ var _sheet__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./sheet */ "./packages/loot-core/src/server/sheet.ts");
41120
+ /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
41121
+ /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./sync */ "./packages/loot-core/src/server/sync/index.ts");
41122
+ /* harmony import */ var _sync_migrate__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./sync/migrate */ "./packages/loot-core/src/server/sync/migrate.ts");
41123
+ /* harmony import */ var _tools_app__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./tools/app */ "./packages/loot-core/src/server/tools/app.ts");
41124
+ /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./undo */ "./packages/loot-core/src/server/undo.ts");
41125
+ /* harmony import */ var _update__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ./update */ "./packages/loot-core/src/server/update.ts");
41126
+ /* harmony import */ var _util_budget_name__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ./util/budget-name */ "./packages/loot-core/src/server/util/budget-name.ts");
40814
41127
  // @ts-strict-ignore
40815
41128
  const DEMO_BUDGET_ID = '_demo-budget';
40816
41129
  const TEST_BUDGET_ID = '_test-budget';
40817
41130
  // util
40818
41131
  function onSheetChange({ names }) {
40819
41132
  const nodes = names.map((name) => {
40820
- const node = _sheet__WEBPACK_IMPORTED_MODULE_46__.get()._getNode(name);
41133
+ const node = _sheet__WEBPACK_IMPORTED_MODULE_47__.get()._getNode(name);
40821
41134
  return {
40822
41135
  name: node.name,
40823
41136
  value: node.value
@@ -40830,13 +41143,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40830
41143
  // is /currently/ empty but we promise to fill it in later
40831
41144
  let handlers = {};
40832
41145
  handlers['undo'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function () {
40833
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.undo)();
41146
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.undo)();
40834
41147
  });
40835
41148
  handlers['redo'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(function () {
40836
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.redo)();
41149
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.redo)();
40837
41150
  });
40838
41151
  handlers['transactions-batch-update'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ added, deleted, updated, learnCategories }) {
40839
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41152
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
40840
41153
  const result = await (0, _accounts_transactions__WEBPACK_IMPORTED_MODULE_22__.batchUpdateTransactions)({
40841
41154
  added,
40842
41155
  updated,
@@ -40896,14 +41209,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40896
41209
  handlers['get-budget-bounds'] = async function () {
40897
41210
  return _budget_base__WEBPACK_IMPORTED_MODULE_27__.createAllBudgets();
40898
41211
  };
40899
- handlers['rollover-budget-month'] = async function ({ month }) {
41212
+ handlers['envelope-budget-month'] = async function ({ month }) {
40900
41213
  const groups = await _db__WEBPACK_IMPORTED_MODULE_30__.getCategoriesGrouped();
40901
41214
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_13__.sheetForMonth(month);
40902
41215
  function value(name) {
40903
- const v = _sheet__WEBPACK_IMPORTED_MODULE_46__.getCellValue(sheetName, name);
41216
+ const v = _sheet__WEBPACK_IMPORTED_MODULE_47__.getCellValue(sheetName, name);
40904
41217
  return {
40905
41218
  value: v === '' ? 0 : v,
40906
- name: (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__.resolveName)(sheetName, name)
41219
+ name: (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__.resolveName)(sheetName, name)
40907
41220
  };
40908
41221
  }
40909
41222
  let values = [
@@ -40935,21 +41248,23 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40935
41248
  value(`budget-${cat.id}`),
40936
41249
  value(`sum-amount-${cat.id}`),
40937
41250
  value(`leftover-${cat.id}`),
40938
- value(`carryover-${cat.id}`)
41251
+ value(`carryover-${cat.id}`),
41252
+ value(`goal-${cat.id}`),
41253
+ value(`long-goal-${cat.id}`)
40939
41254
  ]);
40940
41255
  }
40941
41256
  }
40942
41257
  }
40943
41258
  return values;
40944
41259
  };
40945
- handlers['report-budget-month'] = async function ({ month }) {
41260
+ handlers['tracking-budget-month'] = async function ({ month }) {
40946
41261
  const groups = await _db__WEBPACK_IMPORTED_MODULE_30__.getCategoriesGrouped();
40947
41262
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_13__.sheetForMonth(month);
40948
41263
  function value(name) {
40949
- const v = _sheet__WEBPACK_IMPORTED_MODULE_46__.getCellValue(sheetName, name);
41264
+ const v = _sheet__WEBPACK_IMPORTED_MODULE_47__.getCellValue(sheetName, name);
40950
41265
  return {
40951
41266
  value: v === '' ? 0 : v,
40952
- name: (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__.resolveName)(sheetName, name)
41267
+ name: (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__.resolveName)(sheetName, name)
40953
41268
  };
40954
41269
  }
40955
41270
  let values = [
@@ -40971,7 +41286,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40971
41286
  values = values.concat([
40972
41287
  value(`budget-${cat.id}`),
40973
41288
  value(`sum-amount-${cat.id}`),
40974
- value(`leftover-${cat.id}`)
41289
+ value(`leftover-${cat.id}`),
41290
+ value(`goal-${cat.id}`),
41291
+ value(`long-goal-${cat.id}`)
40975
41292
  ]);
40976
41293
  if (!group.is_income) {
40977
41294
  values.push(value(`carryover-${cat.id}`));
@@ -40980,26 +41297,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40980
41297
  }
40981
41298
  return values;
40982
41299
  };
40983
- handlers['budget-set-type'] = async function ({ type }) {
40984
- if (!_prefs__WEBPACK_IMPORTED_MODULE_41__.BUDGET_TYPES.includes(type)) {
40985
- throw new Error('Invalid budget type: ' + type);
40986
- }
40987
- // It's already the same; don't do anything
40988
- if (type === _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().budgetType) {
40989
- return;
40990
- }
40991
- // Save prefs
40992
- return _prefs__WEBPACK_IMPORTED_MODULE_41__.savePrefs({
40993
- budgetType: type
40994
- });
40995
- };
40996
41300
  handlers['category-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ name, groupId, isIncome, hidden }) {
40997
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41301
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
40998
41302
  if (!groupId) {
40999
41303
  throw (0, _errors__WEBPACK_IMPORTED_MODULE_33__.APIError)('Creating a category: groupId is required');
41000
41304
  }
41001
41305
  return _db__WEBPACK_IMPORTED_MODULE_30__.insertCategory({
41002
- name,
41306
+ name: name.trim(),
41003
41307
  cat_group: groupId,
41004
41308
  is_income: isIncome ? 1 : 0,
41005
41309
  hidden: hidden ? 1 : 0
@@ -41007,9 +41311,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41007
41311
  });
41008
41312
  });
41009
41313
  handlers['category-update'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function (category) {
41010
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41314
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41011
41315
  try {
41012
- await _db__WEBPACK_IMPORTED_MODULE_30__.updateCategory(category);
41316
+ await _db__WEBPACK_IMPORTED_MODULE_30__.updateCategory({
41317
+ ...category,
41318
+ name: category.name.trim()
41319
+ });
41013
41320
  }
41014
41321
  catch (e) {
41015
41322
  if (e.message.toLowerCase().includes('unique constraint')) {
@@ -41025,17 +41332,17 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41025
41332
  });
41026
41333
  });
41027
41334
  handlers['category-move'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, groupId, targetId }) {
41028
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41029
- await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41335
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41336
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41030
41337
  await _db__WEBPACK_IMPORTED_MODULE_30__.moveCategory(id, groupId, targetId);
41031
41338
  });
41032
41339
  return 'ok';
41033
41340
  });
41034
41341
  });
41035
41342
  handlers['category-delete'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, transferId }) {
41036
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41343
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41037
41344
  let result = {};
41038
- await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41345
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41039
41346
  const row = await _db__WEBPACK_IMPORTED_MODULE_30__.first('SELECT is_income FROM categories WHERE id = ?', [
41040
41347
  id
41041
41348
  ]);
@@ -41080,7 +41387,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41080
41387
  return await _db__WEBPACK_IMPORTED_MODULE_30__.getCategoriesGrouped();
41081
41388
  };
41082
41389
  handlers['category-group-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ name, isIncome }) {
41083
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41390
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41084
41391
  return _db__WEBPACK_IMPORTED_MODULE_30__.insertCategoryGroup({
41085
41392
  name,
41086
41393
  is_income: isIncome ? 1 : 0
@@ -41088,24 +41395,24 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41088
41395
  });
41089
41396
  });
41090
41397
  handlers['category-group-update'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function (group) {
41091
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41398
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41092
41399
  return _db__WEBPACK_IMPORTED_MODULE_30__.updateCategoryGroup(group);
41093
41400
  });
41094
41401
  });
41095
41402
  handlers['category-group-move'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, targetId }) {
41096
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41097
- await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41403
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41404
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41098
41405
  await _db__WEBPACK_IMPORTED_MODULE_30__.moveCategoryGroup(id, targetId);
41099
41406
  });
41100
41407
  return 'ok';
41101
41408
  });
41102
41409
  });
41103
41410
  handlers['category-group-delete'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, transferId }) {
41104
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41411
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41105
41412
  const groupCategories = await _db__WEBPACK_IMPORTED_MODULE_30__.all('SELECT id FROM categories WHERE cat_group = ? AND tombstone = 0', [
41106
41413
  id
41107
41414
  ]);
41108
- return (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41415
+ return (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41109
41416
  if (transferId) {
41110
41417
  await _budget_base__WEBPACK_IMPORTED_MODULE_27__.doTransfer(groupCategories.map((c) => c.id), transferId);
41111
41418
  }
@@ -41129,15 +41436,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41129
41436
  // If there are any non-zero budget values, also force the user to
41130
41437
  // transfer the category.
41131
41438
  return [
41132
- ..._sheet__WEBPACK_IMPORTED_MODULE_46__.get().meta().createdMonths
41439
+ ..._sheet__WEBPACK_IMPORTED_MODULE_47__.get().meta().createdMonths
41133
41440
  ].some((month) => {
41134
41441
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_13__.sheetForMonth(month);
41135
- const value = _sheet__WEBPACK_IMPORTED_MODULE_46__.get().getCellValue(sheetName, 'budget-' + id);
41442
+ const value = _sheet__WEBPACK_IMPORTED_MODULE_47__.get().getCellValue(sheetName, 'budget-' + id);
41136
41443
  return value != null && value !== 0;
41137
41444
  });
41138
41445
  };
41139
41446
  handlers['payee-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ name }) {
41140
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41447
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41141
41448
  return _db__WEBPACK_IMPORTED_MODULE_30__.insertPayee({
41142
41449
  name
41143
41450
  });
@@ -41163,7 +41470,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41163
41470
  return payeeCounts;
41164
41471
  };
41165
41472
  handlers['payees-merge'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ targetId, mergeIds }) {
41166
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41473
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41167
41474
  return _db__WEBPACK_IMPORTED_MODULE_30__.mergePayees(targetId, mergeIds);
41168
41475
  }, {
41169
41476
  targetId,
@@ -41171,8 +41478,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41171
41478
  });
41172
41479
  });
41173
41480
  handlers['payees-batch-change'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ added, deleted, updated }) {
41174
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41175
- return (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41481
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41482
+ return (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41176
41483
  if (deleted) {
41177
41484
  await Promise.all(deleted.map((p) => _db__WEBPACK_IMPORTED_MODULE_30__.deletePayee(p)));
41178
41485
  }
@@ -41201,7 +41508,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41201
41508
  'name',
41202
41509
  'value'
41203
41510
  ];
41204
- const node = _sheet__WEBPACK_IMPORTED_MODULE_46__.get()._getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__.resolveName)(sheetName, name));
41511
+ const node = _sheet__WEBPACK_IMPORTED_MODULE_47__.get()._getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__.resolveName)(sheetName, name));
41205
41512
  if (fields) {
41206
41513
  const res = {};
41207
41514
  fields.forEach((field) => {
@@ -41220,13 +41527,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41220
41527
  };
41221
41528
  handlers['getCells'] = async function ({ names }) {
41222
41529
  return names.map((name) => ({
41223
- value: _sheet__WEBPACK_IMPORTED_MODULE_46__.get()._getNode(name).value
41530
+ value: _sheet__WEBPACK_IMPORTED_MODULE_47__.get()._getNode(name).value
41224
41531
  }));
41225
41532
  };
41226
41533
  handlers['getCellNamesInSheet'] = async function ({ sheetName }) {
41227
41534
  const names = [];
41228
- for (const name of _sheet__WEBPACK_IMPORTED_MODULE_46__.get().getNodes().keys()) {
41229
- const { sheet: nodeSheet, name: nodeName } = (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__.unresolveName)(name);
41535
+ for (const name of _sheet__WEBPACK_IMPORTED_MODULE_47__.get().getNodes().keys()) {
41536
+ const { sheet: nodeSheet, name: nodeName } = (0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__.unresolveName)(name);
41230
41537
  if (nodeSheet === sheetName) {
41231
41538
  names.push(nodeName);
41232
41539
  }
@@ -41234,7 +41541,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41234
41541
  return names;
41235
41542
  };
41236
41543
  handlers['debugCell'] = async function ({ sheetName, name }) {
41237
- const node = _sheet__WEBPACK_IMPORTED_MODULE_46__.get().getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_47__.resolveName)(sheetName, name));
41544
+ const node = _sheet__WEBPACK_IMPORTED_MODULE_47__.get().getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_48__.resolveName)(sheetName, name));
41238
41545
  return {
41239
41546
  ...node,
41240
41547
  _run: node._run && node._run.toString()
@@ -41243,7 +41550,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41243
41550
  handlers['create-query'] = async function ({ sheetName, name, query }) {
41244
41551
  // Always run it regardless of cache. We don't know anything has changed
41245
41552
  // between the cache value being saved and now
41246
- _sheet__WEBPACK_IMPORTED_MODULE_46__.get().createQuery(sheetName, name, query);
41553
+ _sheet__WEBPACK_IMPORTED_MODULE_47__.get().createQuery(sheetName, name, query);
41247
41554
  return 'ok';
41248
41555
  };
41249
41556
  handlers['query'] = async function (query) {
@@ -41253,7 +41560,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41253
41560
  return (0, _aql__WEBPACK_IMPORTED_MODULE_24__.runQuery)(query);
41254
41561
  };
41255
41562
  handlers['account-update'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, name }) {
41256
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41563
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41257
41564
  await _db__WEBPACK_IMPORTED_MODULE_30__.update('accounts', {
41258
41565
  id,
41259
41566
  name
@@ -41299,7 +41606,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41299
41606
  });
41300
41607
  }
41301
41608
  else {
41302
- id = (0, uuid__WEBPACK_IMPORTED_MODULE_54__["default"])();
41609
+ id = (0, uuid__WEBPACK_IMPORTED_MODULE_55__["default"])();
41303
41610
  await _db__WEBPACK_IMPORTED_MODULE_30__.insertWithUUID('accounts', {
41304
41611
  id,
41305
41612
  account_id: account.account_id,
@@ -41343,7 +41650,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41343
41650
  });
41344
41651
  }
41345
41652
  else {
41346
- id = (0, uuid__WEBPACK_IMPORTED_MODULE_54__["default"])();
41653
+ id = (0, uuid__WEBPACK_IMPORTED_MODULE_55__["default"])();
41347
41654
  await _db__WEBPACK_IMPORTED_MODULE_30__.insertWithUUID('accounts', {
41348
41655
  id,
41349
41656
  account_id: externalAccount.account_id,
@@ -41368,7 +41675,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41368
41675
  return 'ok';
41369
41676
  };
41370
41677
  handlers['account-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ name, balance, offBudget, closed }) {
41371
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41678
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41372
41679
  const id = await _db__WEBPACK_IMPORTED_MODULE_30__.insertAccount({
41373
41680
  name,
41374
41681
  offbudget: offBudget ? 1 : 0,
@@ -41400,7 +41707,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41400
41707
  await handlers['account-unlink']({
41401
41708
  id
41402
41709
  });
41403
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41710
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41404
41711
  const account = await _db__WEBPACK_IMPORTED_MODULE_30__.first('SELECT * FROM accounts WHERE id = ? AND tombstone = 0', [
41405
41712
  id
41406
41713
  ]);
@@ -41425,7 +41732,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41425
41732
  const { id: payeeId } = await _db__WEBPACK_IMPORTED_MODULE_30__.first('SELECT id FROM payees WHERE transfer_acct = ?', [
41426
41733
  id
41427
41734
  ]);
41428
- await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.batchMessages)(async () => {
41735
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.batchMessages)(async () => {
41429
41736
  // TODO: what this should really do is send a special message that
41430
41737
  // automatically marks the tombstone value for all transactions
41431
41738
  // within an account... or something? This is problematic
@@ -41466,7 +41773,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41466
41773
  transferAccountId
41467
41774
  ]);
41468
41775
  await handlers['transaction-add']({
41469
- id: (0, uuid__WEBPACK_IMPORTED_MODULE_54__["default"])(),
41776
+ id: (0, uuid__WEBPACK_IMPORTED_MODULE_55__["default"])(),
41470
41777
  payee: payeeId,
41471
41778
  amount: -balance,
41472
41779
  account: id,
@@ -41479,7 +41786,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41479
41786
  });
41480
41787
  });
41481
41788
  handlers['account-reopen'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id }) {
41482
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41789
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41483
41790
  await _db__WEBPACK_IMPORTED_MODULE_30__.update('accounts', {
41484
41791
  id,
41485
41792
  closed: 0
@@ -41487,7 +41794,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41487
41794
  });
41488
41795
  });
41489
41796
  handlers['account-move'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function ({ id, targetId }) {
41490
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
41797
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41491
41798
  await _db__WEBPACK_IMPORTED_MODULE_30__.moveAccount(id, targetId);
41492
41799
  });
41493
41800
  });
@@ -41500,7 +41807,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41500
41807
  };
41501
41808
  }
41502
41809
  try {
41503
- return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().BASE_SERVER + '/secret', {
41810
+ return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().BASE_SERVER + '/secret', {
41504
41811
  name,
41505
41812
  value
41506
41813
  }, {
@@ -41522,7 +41829,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41522
41829
  };
41523
41830
  }
41524
41831
  try {
41525
- return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().BASE_SERVER + '/secret/' + name, {
41832
+ return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().BASE_SERVER + '/secret/' + name, {
41526
41833
  'X-ACTUAL-TOKEN': userToken
41527
41834
  });
41528
41835
  }
@@ -41549,7 +41856,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41549
41856
  cb('timeout');
41550
41857
  return;
41551
41858
  }
41552
- const data = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().GOCARDLESS_SERVER + '/get-accounts', {
41859
+ const data = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().GOCARDLESS_SERVER + '/get-accounts', {
41553
41860
  upgradingAccountId,
41554
41861
  requisitionId
41555
41862
  }, {
@@ -41589,7 +41896,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41589
41896
  error: 'unauthorized'
41590
41897
  };
41591
41898
  }
41592
- return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().GOCARDLESS_SERVER + '/status', {}, {
41899
+ return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().GOCARDLESS_SERVER + '/status', {}, {
41593
41900
  'X-ACTUAL-TOKEN': userToken
41594
41901
  });
41595
41902
  };
@@ -41600,7 +41907,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41600
41907
  error: 'unauthorized'
41601
41908
  };
41602
41909
  }
41603
- return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIMPLEFIN_SERVER + '/status', {}, {
41910
+ return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIMPLEFIN_SERVER + '/status', {}, {
41604
41911
  'X-ACTUAL-TOKEN': userToken
41605
41912
  });
41606
41913
  };
@@ -41612,7 +41919,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41612
41919
  };
41613
41920
  }
41614
41921
  try {
41615
- return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIMPLEFIN_SERVER + '/accounts', {}, {
41922
+ return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIMPLEFIN_SERVER + '/accounts', {}, {
41616
41923
  'X-ACTUAL-TOKEN': userToken
41617
41924
  }, 60000);
41618
41925
  }
@@ -41629,7 +41936,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41629
41936
  error: 'unauthorized'
41630
41937
  };
41631
41938
  }
41632
- return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().GOCARDLESS_SERVER + '/get-banks', {
41939
+ return (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().GOCARDLESS_SERVER + '/get-banks', {
41633
41940
  country,
41634
41941
  showDemo: (0, _shared_environment__WEBPACK_IMPORTED_MODULE_12__.isNonProductionEnvironment)()
41635
41942
  }, {
@@ -41648,7 +41955,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41648
41955
  };
41649
41956
  }
41650
41957
  try {
41651
- return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().GOCARDLESS_SERVER + '/create-web-token', {
41958
+ return await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().GOCARDLESS_SERVER + '/create-web-token', {
41652
41959
  upgradingAccountId,
41653
41960
  institutionId,
41654
41961
  accessValidForDays
@@ -41738,7 +42045,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41738
42045
  };
41739
42046
  };
41740
42047
  handlers['transactions-import'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(function ({ accountId, transactions, isPreview }) {
41741
- return (0, _undo__WEBPACK_IMPORTED_MODULE_51__.withUndo)(async () => {
42048
+ return (0, _undo__WEBPACK_IMPORTED_MODULE_52__.withUndo)(async () => {
41742
42049
  if (typeof accountId !== 'string') {
41743
42050
  throw (0, _errors__WEBPACK_IMPORTED_MODULE_33__.APIError)('transactions-import: accountId must be an id');
41744
42051
  }
@@ -41799,7 +42106,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41799
42106
  bankId
41800
42107
  ]);
41801
42108
  try {
41802
- await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().GOCARDLESS_SERVER + '/remove-account', {
42109
+ await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().GOCARDLESS_SERVER + '/remove-account', {
41803
42110
  requisitionId
41804
42111
  }, {
41805
42112
  'X-ACTUAL-TOKEN': userToken
@@ -41828,60 +42135,65 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41828
42135
  if ('theme' in prefs) {
41829
42136
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('theme', prefs.theme);
41830
42137
  }
42138
+ if ('preferredDarkTheme' in prefs) {
42139
+ await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('preferred-dark-theme', prefs.preferredDarkTheme);
42140
+ }
41831
42141
  if ('serverSelfSignedCert' in prefs) {
41832
42142
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('server-self-signed-cert', prefs.serverSelfSignedCert);
41833
42143
  }
41834
42144
  return 'ok';
41835
42145
  };
41836
42146
  handlers['load-global-prefs'] = async function () {
41837
- const [[, floatingSidebar], [, maxMonths], [, documentDir], [, encryptKey], [, theme]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.multiGet([
42147
+ const [[, floatingSidebar], [, maxMonths], [, documentDir], [, encryptKey], [, theme], [, preferredDarkTheme]] = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.multiGet([
41838
42148
  'floating-sidebar',
41839
42149
  'max-months',
41840
42150
  'document-dir',
41841
42151
  'encrypt-key',
41842
- 'theme'
42152
+ 'theme',
42153
+ 'preferred-dark-theme'
41843
42154
  ]);
41844
42155
  return {
41845
42156
  floatingSidebar: floatingSidebar === 'true' ? true : false,
41846
42157
  maxMonths: (0, _shared_util__WEBPACK_IMPORTED_MODULE_15__.stringToInteger)(maxMonths || ''),
41847
42158
  documentDir: documentDir || getDefaultDocumentDir(),
41848
42159
  keyId: encryptKey && JSON.parse(encryptKey).id,
41849
- theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'auto'
42160
+ theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'auto',
42161
+ preferredDarkTheme: preferredDarkTheme === 'dark' || preferredDarkTheme === 'midnight' ? preferredDarkTheme : 'dark'
41850
42162
  };
41851
42163
  };
41852
42164
  handlers['save-prefs'] = async function (prefsToSet) {
41853
- const { cloudFileId } = _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs();
42165
+ const { cloudFileId } = _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs();
41854
42166
  // Need to sync the budget name on the server as well
41855
42167
  if (prefsToSet.budgetName && cloudFileId) {
41856
42168
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.getItem('user-token');
41857
- await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SYNC_SERVER + '/update-user-filename', {
42169
+ await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SYNC_SERVER + '/update-user-filename', {
41858
42170
  token: userToken,
41859
42171
  fileId: cloudFileId,
41860
42172
  name: prefsToSet.budgetName
41861
42173
  });
41862
42174
  }
41863
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.savePrefs(prefsToSet);
42175
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.savePrefs(prefsToSet);
41864
42176
  return 'ok';
41865
42177
  };
41866
42178
  handlers['load-prefs'] = async function () {
41867
- return _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs();
42179
+ return _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs();
41868
42180
  };
41869
42181
  handlers['sync-reset'] = async function () {
41870
- return await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.resetSync)();
42182
+ return await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.resetSync)();
41871
42183
  };
41872
42184
  handlers['sync-repair'] = async function () {
41873
- await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.repairSync)();
42185
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.repairSync)();
41874
42186
  };
41875
42187
  // A user can only enable/change their key with the file loaded. This
41876
42188
  // will change in the future: during onboarding the user should be
41877
42189
  // able to enable encryption. (Imagine if they are importing data from
41878
42190
  // another source, they should be able to encrypt first)
41879
42191
  handlers['key-make'] = async function ({ password }) {
41880
- if (!_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs()) {
42192
+ if (!_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs()) {
41881
42193
  throw new Error('user-set-key must be called with file loaded');
41882
42194
  }
41883
42195
  const salt = _encryption__WEBPACK_IMPORTED_MODULE_32__.randomBytes(32).toString('base64');
41884
- const id = (0, uuid__WEBPACK_IMPORTED_MODULE_54__["default"])();
42196
+ const id = (0, uuid__WEBPACK_IMPORTED_MODULE_55__["default"])();
41885
42197
  const key = await _encryption__WEBPACK_IMPORTED_MODULE_32__.createKey({
41886
42198
  id,
41887
42199
  password,
@@ -41890,11 +42202,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41890
42202
  // Load the key
41891
42203
  await _encryption__WEBPACK_IMPORTED_MODULE_32__.loadKey(key);
41892
42204
  // Make some test data to use if the key is valid or not
41893
- const testContent = await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.makeTestMessage)(key.getId());
42205
+ const testContent = await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.makeTestMessage)(key.getId());
41894
42206
  // Changing your key necessitates a sync reset as well. This will
41895
42207
  // clear all existing encrypted data from the server so you won't
41896
42208
  // have a mix of data encrypted with different keys.
41897
- return await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.resetSync)({
42209
+ return await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.resetSync)({
41898
42210
  key,
41899
42211
  salt,
41900
42212
  testContent: JSON.stringify({
@@ -41908,11 +42220,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41908
42220
  handlers['key-test'] = async function ({ fileId, password }) {
41909
42221
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.getItem('user-token');
41910
42222
  if (fileId == null) {
41911
- fileId = _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().cloudFileId;
42223
+ fileId = _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs().cloudFileId;
41912
42224
  }
41913
42225
  let res;
41914
42226
  try {
41915
- res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SYNC_SERVER + '/user-get-key', {
42227
+ res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SYNC_SERVER + '/user-get-key', {
41916
42228
  token: userToken,
41917
42229
  fileId
41918
42230
  });
@@ -41961,8 +42273,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41961
42273
  // Save the key id in prefs if the are loaded. If they aren't, we
41962
42274
  // are testing a key to download a file and when the file is
41963
42275
  // actually downloaded it will update the prefs with the latest key id
41964
- if (_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs()) {
41965
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.savePrefs({
42276
+ if (_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs()) {
42277
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.savePrefs({
41966
42278
  encryptKeyId: key.getId()
41967
42279
  });
41968
42280
  }
@@ -41973,7 +42285,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41973
42285
  };
41974
42286
  handlers['subscribe-needs-bootstrap'] = async function ({ url } = {}) {
41975
42287
  try {
41976
- if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)(url)) {
42288
+ if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)(url)) {
41977
42289
  return {
41978
42290
  bootstrapped: true,
41979
42291
  hasServer: false
@@ -41987,7 +42299,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41987
42299
  }
41988
42300
  let res;
41989
42301
  try {
41990
- res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)(url).SIGNUP_SERVER + '/needs-bootstrap');
42302
+ res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)(url).SIGNUP_SERVER + '/needs-bootstrap');
41991
42303
  }
41992
42304
  catch (err) {
41993
42305
  return {
@@ -42016,7 +42328,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42016
42328
  handlers['subscribe-bootstrap'] = async function ({ password }) {
42017
42329
  let res;
42018
42330
  try {
42019
- res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIGNUP_SERVER + '/bootstrap', {
42331
+ res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIGNUP_SERVER + '/bootstrap', {
42020
42332
  password
42021
42333
  });
42022
42334
  }
@@ -42034,7 +42346,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42034
42346
  };
42035
42347
  };
42036
42348
  handlers['subscribe-get-user'] = async function () {
42037
- if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)()) {
42349
+ if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)()) {
42038
42350
  if (!await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.getItem('did-bootstrap')) {
42039
42351
  return null;
42040
42352
  }
@@ -42047,7 +42359,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42047
42359
  return null;
42048
42360
  }
42049
42361
  try {
42050
- const res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIGNUP_SERVER + '/validate', {
42362
+ const res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIGNUP_SERVER + '/validate', {
42051
42363
  headers: {
42052
42364
  'X-ACTUAL-TOKEN': userToken
42053
42365
  }
@@ -42080,7 +42392,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42080
42392
  };
42081
42393
  }
42082
42394
  try {
42083
- await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIGNUP_SERVER + '/change-password', {
42395
+ await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIGNUP_SERVER + '/change-password', {
42084
42396
  token: userToken,
42085
42397
  password
42086
42398
  });
@@ -42098,7 +42410,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42098
42410
  }
42099
42411
  let res;
42100
42412
  try {
42101
- res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().SIGNUP_SERVER + '/login', {
42413
+ res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().SIGNUP_SERVER + '/login', {
42102
42414
  loginMethod,
42103
42415
  password
42104
42416
  });
@@ -42125,14 +42437,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42125
42437
  return 'ok';
42126
42438
  };
42127
42439
  handlers['get-server-version'] = async function () {
42128
- if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)()) {
42440
+ if (!(0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)()) {
42129
42441
  return {
42130
42442
  error: 'no-server'
42131
42443
  };
42132
42444
  }
42133
42445
  let version;
42134
42446
  try {
42135
- const res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().BASE_SERVER + '/info');
42447
+ const res = await (0, _post__WEBPACK_IMPORTED_MODULE_40__.get)((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().BASE_SERVER + '/info');
42136
42448
  const info = JSON.parse(res);
42137
42449
  version = info.build.version;
42138
42450
  }
@@ -42146,7 +42458,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42146
42458
  };
42147
42459
  };
42148
42460
  handlers['get-server-url'] = async function () {
42149
- return (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)() && (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)().BASE_SERVER;
42461
+ return (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)() && (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)().BASE_SERVER;
42150
42462
  };
42151
42463
  handlers['set-server-url'] = async function ({ url, validate = true }) {
42152
42464
  if (url == null) {
@@ -42168,11 +42480,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42168
42480
  }
42169
42481
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('server-url', url);
42170
42482
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('did-bootstrap', true);
42171
- (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.setServer)(url);
42483
+ (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.setServer)(url);
42172
42484
  return {};
42173
42485
  };
42174
42486
  handlers['sync'] = async function () {
42175
- return (0, _sync__WEBPACK_IMPORTED_MODULE_48__.fullSync)();
42487
+ return (0, _sync__WEBPACK_IMPORTED_MODULE_49__.fullSync)();
42176
42488
  };
42177
42489
  handlers['get-budgets'] = async function () {
42178
42490
  const paths = await _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.listDir(_platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.getDocumentDir());
@@ -42216,16 +42528,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42216
42528
  };
42217
42529
  handlers['reset-budget-cache'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.mutator)(async function () {
42218
42530
  // Recomputing everything will update the cache
42219
- await _sheet__WEBPACK_IMPORTED_MODULE_46__.loadUserBudgets(_db__WEBPACK_IMPORTED_MODULE_30__);
42220
- _sheet__WEBPACK_IMPORTED_MODULE_46__.get().recomputeAll();
42221
- await _sheet__WEBPACK_IMPORTED_MODULE_46__.waitOnSpreadsheet();
42531
+ await _sheet__WEBPACK_IMPORTED_MODULE_47__.loadUserBudgets(_db__WEBPACK_IMPORTED_MODULE_30__);
42532
+ _sheet__WEBPACK_IMPORTED_MODULE_47__.get().recomputeAll();
42533
+ await _sheet__WEBPACK_IMPORTED_MODULE_47__.waitOnSpreadsheet();
42222
42534
  });
42223
42535
  handlers['upload-budget'] = async function ({ id } = {}) {
42224
42536
  if (id) {
42225
- if (_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs()) {
42537
+ if (_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs()) {
42226
42538
  throw new Error('upload-budget: id given but prefs already loaded');
42227
42539
  }
42228
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.loadPrefs(id);
42540
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.loadPrefs(id);
42229
42541
  }
42230
42542
  try {
42231
42543
  await _cloud_storage__WEBPACK_IMPORTED_MODULE_28__.upload();
@@ -42246,7 +42558,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42246
42558
  }
42247
42559
  finally {
42248
42560
  if (id) {
42249
- _prefs__WEBPACK_IMPORTED_MODULE_41__.unloadPrefs();
42561
+ _prefs__WEBPACK_IMPORTED_MODULE_42__.unloadPrefs();
42250
42562
  }
42251
42563
  }
42252
42564
  return {};
@@ -42259,9 +42571,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42259
42571
  catch (e) {
42260
42572
  if (e.type === 'FileDownloadError') {
42261
42573
  if (e.reason === 'file-exists' && e.meta.id) {
42262
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.loadPrefs(e.meta.id);
42263
- const name = _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().budgetName;
42264
- _prefs__WEBPACK_IMPORTED_MODULE_41__.unloadPrefs();
42574
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.loadPrefs(e.meta.id);
42575
+ const name = _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs().budgetName;
42576
+ _prefs__WEBPACK_IMPORTED_MODULE_42__.unloadPrefs();
42265
42577
  e.meta = {
42266
42578
  ...e.meta,
42267
42579
  name
@@ -42295,12 +42607,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42295
42607
  };
42296
42608
  // open and sync, but don’t close
42297
42609
  handlers['sync-budget'] = async function () {
42298
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode)('enabled');
42299
- const result = await (0, _sync__WEBPACK_IMPORTED_MODULE_48__.initialFullSync)();
42610
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode)('enabled');
42611
+ const result = await (0, _sync__WEBPACK_IMPORTED_MODULE_49__.initialFullSync)();
42300
42612
  return result;
42301
42613
  };
42302
42614
  handlers['load-budget'] = async function ({ id }) {
42303
- const currentPrefs = _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs();
42615
+ const currentPrefs = _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs();
42304
42616
  if (currentPrefs) {
42305
42617
  if (currentPrefs.id === id) {
42306
42618
  // If it's already loaded, do nothing
@@ -42330,9 +42642,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42330
42642
  message: 'Closing budget'
42331
42643
  });
42332
42644
  // The spreadsheet may be running, wait for it to complete
42333
- await _sheet__WEBPACK_IMPORTED_MODULE_46__.waitOnSpreadsheet();
42334
- _sheet__WEBPACK_IMPORTED_MODULE_46__.unloadSpreadsheet();
42335
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.clearFullSyncTimeout)();
42645
+ await _sheet__WEBPACK_IMPORTED_MODULE_47__.waitOnSpreadsheet();
42646
+ _sheet__WEBPACK_IMPORTED_MODULE_47__.unloadSpreadsheet();
42647
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.clearFullSyncTimeout)();
42336
42648
  await _main_app__WEBPACK_IMPORTED_MODULE_36__.app.stopServices();
42337
42649
  await _db__WEBPACK_IMPORTED_MODULE_30__.closeDatabase();
42338
42650
  try {
@@ -42343,7 +42655,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42343
42655
  // budget. We want to unload whatever has already been loaded but
42344
42656
  // be resilient to anything failing
42345
42657
  }
42346
- _prefs__WEBPACK_IMPORTED_MODULE_41__.unloadPrefs();
42658
+ _prefs__WEBPACK_IMPORTED_MODULE_42__.unloadPrefs();
42347
42659
  (0, _backups__WEBPACK_IMPORTED_MODULE_25__.stopBackupService)();
42348
42660
  return 'ok';
42349
42661
  };
@@ -42375,16 +42687,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42375
42687
  // Unfortunately we need to load all of the existing files first
42376
42688
  // so we can detect conflicting names.
42377
42689
  const files = await handlers['get-budgets']();
42378
- budgetName = await (0, _util_budget_name__WEBPACK_IMPORTED_MODULE_53__.uniqueFileName)(files);
42690
+ budgetName = await (0, _util_budget_name__WEBPACK_IMPORTED_MODULE_54__.uniqueFileName)(files);
42379
42691
  }
42380
- id = await (0, _util_budget_name__WEBPACK_IMPORTED_MODULE_53__.idFromFileName)(budgetName);
42692
+ id = await (0, _util_budget_name__WEBPACK_IMPORTED_MODULE_54__.idFromFileName)(budgetName);
42381
42693
  }
42382
42694
  const budgetDir = _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.getBudgetDir(id);
42383
42695
  await _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.mkdir(budgetDir);
42384
42696
  // Create the initial database
42385
42697
  await _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.copyFile(_platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.bundledDatabasePath, _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.join(budgetDir, 'db.sqlite'));
42386
42698
  // Create the initial prefs file
42387
- await _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.writeFile(_platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.join(budgetDir, 'metadata.json'), JSON.stringify(_prefs__WEBPACK_IMPORTED_MODULE_41__.getDefaultPrefs(id, budgetName)));
42699
+ await _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.writeFile(_platform_server_fs__WEBPACK_IMPORTED_MODULE_9__.join(budgetDir, 'metadata.json'), JSON.stringify(_prefs__WEBPACK_IMPORTED_MODULE_42__.getDefaultPrefs(id, budgetName)));
42388
42700
  // Load it in
42389
42701
  const { error } = await loadBudget(id);
42390
42702
  if (error) {
@@ -42459,7 +42771,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42459
42771
  };
42460
42772
  }
42461
42773
  try {
42462
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.loadPrefs(id);
42774
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.loadPrefs(id);
42463
42775
  await _db__WEBPACK_IMPORTED_MODULE_30__.openDatabase(id);
42464
42776
  }
42465
42777
  catch (e) {
@@ -42474,14 +42786,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42474
42786
  }
42475
42787
  // Older versions didn't tag the file with the current user, so do
42476
42788
  // so now
42477
- if (!_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().userId) {
42789
+ if (!_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs().userId) {
42478
42790
  const userId = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.getItem('user-token');
42479
- _prefs__WEBPACK_IMPORTED_MODULE_41__.savePrefs({
42791
+ _prefs__WEBPACK_IMPORTED_MODULE_42__.savePrefs({
42480
42792
  userId
42481
42793
  });
42482
42794
  }
42483
42795
  try {
42484
- await (0, _update__WEBPACK_IMPORTED_MODULE_52__.updateVersion)();
42796
+ await (0, _update__WEBPACK_IMPORTED_MODULE_53__.updateVersion)();
42485
42797
  }
42486
42798
  catch (e) {
42487
42799
  console.warn('Error updating', e);
@@ -42508,7 +42820,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42508
42820
  return result;
42509
42821
  }
42510
42822
  await _db__WEBPACK_IMPORTED_MODULE_30__.loadClock();
42511
- if (_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().resetClock) {
42823
+ if (_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs().resetClock) {
42512
42824
  // If we need to generate a fresh clock, we need to generate a new
42513
42825
  // client id. This happens when the database is transferred to a
42514
42826
  // new device.
@@ -42519,7 +42831,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42519
42831
  await _db__WEBPACK_IMPORTED_MODULE_30__.runQuery('INSERT OR REPLACE INTO messages_clock (id, clock) VALUES (1, ?)', [
42520
42832
  _actual_app_crdt__WEBPACK_IMPORTED_MODULE_4__.serializeClock(_actual_app_crdt__WEBPACK_IMPORTED_MODULE_4__.getClock())
42521
42833
  ]);
42522
- await _prefs__WEBPACK_IMPORTED_MODULE_41__.savePrefs({
42834
+ await _prefs__WEBPACK_IMPORTED_MODULE_42__.savePrefs({
42523
42835
  resetClock: false
42524
42836
  });
42525
42837
  }
@@ -42527,7 +42839,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42527
42839
  (0, _backups__WEBPACK_IMPORTED_MODULE_25__.startBackupService)(id);
42528
42840
  }
42529
42841
  try {
42530
- await _sheet__WEBPACK_IMPORTED_MODULE_46__.loadSpreadsheet(_db__WEBPACK_IMPORTED_MODULE_30__, onSheetChange);
42842
+ await _sheet__WEBPACK_IMPORTED_MODULE_47__.loadSpreadsheet(_db__WEBPACK_IMPORTED_MODULE_30__, onSheetChange);
42531
42843
  }
42532
42844
  catch (e) {
42533
42845
  (0, _platform_exceptions__WEBPACK_IMPORTED_MODULE_6__.captureException)(e);
@@ -42537,25 +42849,28 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42537
42849
  };
42538
42850
  }
42539
42851
  // This is a bit leaky, but we need to set the initial budget type
42540
- _sheet__WEBPACK_IMPORTED_MODULE_46__.get().meta().budgetType = _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().budgetType;
42852
+ const { value: budgetType = 'rollover' } = await _db__WEBPACK_IMPORTED_MODULE_30__.first('SELECT value from preferences WHERE id = ?', [
42853
+ 'budgetType'
42854
+ ]) ?? {};
42855
+ _sheet__WEBPACK_IMPORTED_MODULE_47__.get().meta().budgetType = budgetType;
42541
42856
  await _budget_base__WEBPACK_IMPORTED_MODULE_27__.createAllBudgets();
42542
42857
  // Load all the in-memory state
42543
42858
  await _db_mappings__WEBPACK_IMPORTED_MODULE_31__.loadMappings();
42544
42859
  await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_21__.loadRules();
42545
- await _sync_migrate__WEBPACK_IMPORTED_MODULE_49__.listen();
42860
+ await _sync_migrate__WEBPACK_IMPORTED_MODULE_50__.listen();
42546
42861
  await _main_app__WEBPACK_IMPORTED_MODULE_36__.app.startServices();
42547
- (0, _undo__WEBPACK_IMPORTED_MODULE_51__.clearUndo)();
42862
+ (0, _undo__WEBPACK_IMPORTED_MODULE_52__.clearUndo)();
42548
42863
  // Ensure that syncing is enabled
42549
42864
  if (true) {
42550
42865
  if (id === DEMO_BUDGET_ID) {
42551
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode)('disabled');
42866
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode)('disabled');
42552
42867
  }
42553
42868
  else {
42554
- if ((0, _server_config__WEBPACK_IMPORTED_MODULE_45__.getServer)()) {
42555
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode)('enabled');
42869
+ if ((0, _server_config__WEBPACK_IMPORTED_MODULE_46__.getServer)()) {
42870
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode)('enabled');
42556
42871
  }
42557
42872
  else {
42558
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode)('disabled');
42873
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode)('disabled');
42559
42874
  }
42560
42875
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.setItem('lastBudget', id);
42561
42876
  // Only upload periodically on desktop
@@ -42598,16 +42913,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42598
42913
  return null;
42599
42914
  };
42600
42915
  handlers['app-focused'] = async function () {
42601
- if (_prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs() && _prefs__WEBPACK_IMPORTED_MODULE_41__.getPrefs().id) {
42916
+ if (_prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs() && _prefs__WEBPACK_IMPORTED_MODULE_42__.getPrefs().id) {
42602
42917
  // First we sync
42603
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.fullSync)();
42918
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.fullSync)();
42604
42919
  }
42605
42920
  };
42606
42921
  handlers = (0, _api__WEBPACK_IMPORTED_MODULE_23__.installAPI)(handlers);
42607
42922
  _actual_app_api_injected__WEBPACK_IMPORTED_MODULE_3__.override((name, args) => (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.runHandler)(_main_app__WEBPACK_IMPORTED_MODULE_36__.app.handlers[name], args));
42608
42923
  // A hack for now until we clean up everything
42609
42924
  _main_app__WEBPACK_IMPORTED_MODULE_36__.app.handlers = handlers;
42610
- _main_app__WEBPACK_IMPORTED_MODULE_36__.app.combine(_schedules_app__WEBPACK_IMPORTED_MODULE_44__.app, _budget_app__WEBPACK_IMPORTED_MODULE_26__.app, _dashboard_app__WEBPACK_IMPORTED_MODULE_29__.app, _notes_app__WEBPACK_IMPORTED_MODULE_38__.app, _tools_app__WEBPACK_IMPORTED_MODULE_50__.app, _filters_app__WEBPACK_IMPORTED_MODULE_34__.app, _reports_app__WEBPACK_IMPORTED_MODULE_42__.app, _rules_app__WEBPACK_IMPORTED_MODULE_43__.app);
42925
+ _main_app__WEBPACK_IMPORTED_MODULE_36__.app.combine(_schedules_app__WEBPACK_IMPORTED_MODULE_45__.app, _budget_app__WEBPACK_IMPORTED_MODULE_26__.app, _dashboard_app__WEBPACK_IMPORTED_MODULE_29__.app, _notes_app__WEBPACK_IMPORTED_MODULE_38__.app, _preferences_app__WEBPACK_IMPORTED_MODULE_41__.app, _tools_app__WEBPACK_IMPORTED_MODULE_51__.app, _filters_app__WEBPACK_IMPORTED_MODULE_34__.app, _reports_app__WEBPACK_IMPORTED_MODULE_43__.app, _rules_app__WEBPACK_IMPORTED_MODULE_44__.app);
42611
42926
  function getDefaultDocumentDir() {
42612
42927
  if (_platform__WEBPACK_IMPORTED_MODULE_39__.isMobile) {
42613
42928
  // On mobile, unfortunately we need to be backwards compatible
@@ -42682,7 +42997,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42682
42997
  if (!url) {
42683
42998
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_7__.removeItem('user-token');
42684
42999
  }
42685
- (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.setServer)(url);
43000
+ (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.setServer)(url);
42686
43001
  _platform_server_connection__WEBPACK_IMPORTED_MODULE_8__.init(socketName, _main_app__WEBPACK_IMPORTED_MODULE_36__.app.handlers);
42687
43002
  // Allow running DB queries locally
42688
43003
  global.$query = _aql__WEBPACK_IMPORTED_MODULE_24__.runQuery;
@@ -42690,7 +43005,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42690
43005
  if (isDev) {
42691
43006
  global.$send = (name, args) => (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.runHandler)(_main_app__WEBPACK_IMPORTED_MODULE_36__.app.handlers[name], args);
42692
43007
  global.$db = _db__WEBPACK_IMPORTED_MODULE_30__;
42693
- global.$setSyncingMode = _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode;
43008
+ global.$setSyncingMode = _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode;
42694
43009
  }
42695
43010
  }
42696
43011
  // eslint-disable-next-line import/no-unused-modules
@@ -42714,7 +43029,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42714
43029
  ]);
42715
43030
  _platform_server_fs__WEBPACK_IMPORTED_MODULE_9__._setDocumentDir(dataDir || process.cwd());
42716
43031
  if (serverURL) {
42717
- (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.setServer)(serverURL);
43032
+ (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.setServer)(serverURL);
42718
43033
  if (config.password) {
42719
43034
  await (0, _mutators__WEBPACK_IMPORTED_MODULE_37__.runHandler)(handlers['subscribe-sign-in'], {
42720
43035
  password: config.password
@@ -42724,9 +43039,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42724
43039
  else {
42725
43040
  // This turns off all server URLs. In this mode we don't want any
42726
43041
  // access to the server, we are doing things locally
42727
- (0, _server_config__WEBPACK_IMPORTED_MODULE_45__.setServer)(null);
43042
+ (0, _server_config__WEBPACK_IMPORTED_MODULE_46__.setServer)(null);
42728
43043
  _main_app__WEBPACK_IMPORTED_MODULE_36__.app.events.on('load-budget', () => {
42729
- (0, _sync__WEBPACK_IMPORTED_MODULE_48__.setSyncingMode)('offline');
43044
+ (0, _sync__WEBPACK_IMPORTED_MODULE_49__.setSyncingMode)('offline');
42730
43045
  });
42731
43046
  }
42732
43047
  return lib;
@@ -42764,21 +43079,23 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42764
43079
  /* harmony export */ withMigrationsDir: () => ( /* binding */withMigrationsDir)
42765
43080
  /* harmony export */
42766
43081
  });
42767
- /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
42768
43082
  /* harmony import */ var _migrations_1632571489012_remove_cache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../migrations/1632571489012_remove_cache */ "./packages/loot-core/migrations/1632571489012_remove_cache.js");
42769
43083
  /* harmony import */ var _migrations_1722717601000_reports_move_selected_categories__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../migrations/1722717601000_reports_move_selected_categories */ "./packages/loot-core/migrations/1722717601000_reports_move_selected_categories.js");
42770
43084
  /* harmony import */ var _migrations_1722804019000_create_dashboard_table__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../migrations/1722804019000_create_dashboard_table */ "./packages/loot-core/migrations/1722804019000_create_dashboard_table.js");
42771
- /* harmony import */ var _platform_server_fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../platform/server/fs */ "./packages/loot-core/src/platform/server/fs/index.electron.ts");
42772
- /* harmony import */ var _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../platform/server/sqlite */ "./packages/loot-core/src/platform/server/sqlite/index.electron.ts");
43085
+ /* harmony import */ var _migrations_1723665565000_prefs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../migrations/1723665565000_prefs */ "./packages/loot-core/migrations/1723665565000_prefs.js");
43086
+ /* harmony import */ var _platform_server_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../platform/server/fs */ "./packages/loot-core/src/platform/server/fs/index.electron.ts");
43087
+ /* harmony import */ var _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../platform/server/sqlite */ "./packages/loot-core/src/platform/server/sqlite/index.electron.ts");
43088
+ /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../prefs */ "./packages/loot-core/src/server/prefs.ts");
42773
43089
  // @ts-strict-ignore
42774
43090
  // We have to bundle in JS migrations manually to avoid having to `eval`
42775
43091
  // them which doesn't play well with CSP. There isn't great, and eventually
42776
43092
  // we can remove this migration.
42777
- let MIGRATIONS_DIR = _platform_server_fs__WEBPACK_IMPORTED_MODULE_3__.migrationsPath;
43093
+ let MIGRATIONS_DIR = _platform_server_fs__WEBPACK_IMPORTED_MODULE_4__.migrationsPath;
42778
43094
  const javascriptMigrations = {
42779
43095
  1632571489012: _migrations_1632571489012_remove_cache__WEBPACK_IMPORTED_MODULE_0__["default"],
42780
43096
  1722717601000: _migrations_1722717601000_reports_move_selected_categories__WEBPACK_IMPORTED_MODULE_1__["default"],
42781
- 1722804019000: _migrations_1722804019000_create_dashboard_table__WEBPACK_IMPORTED_MODULE_2__["default"]
43097
+ 1722804019000: _migrations_1722804019000_create_dashboard_table__WEBPACK_IMPORTED_MODULE_2__["default"],
43098
+ 1723665565000: _migrations_1723665565000_prefs__WEBPACK_IMPORTED_MODULE_3__["default"]
42782
43099
  };
42783
43100
  async function withMigrationsDir(dir, func) {
42784
43101
  const oldDir = MIGRATIONS_DIR;
@@ -42804,20 +43121,20 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42804
43121
  const newFiltersMigration = 1688749527273;
42805
43122
  const appliedIds = await getAppliedMigrations(db);
42806
43123
  if (appliedIds.includes(badFiltersMigration)) {
42807
- await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.runQuery(db, 'DELETE FROM __migrations__ WHERE id = ?', [
43124
+ await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.runQuery(db, 'DELETE FROM __migrations__ WHERE id = ?', [
42808
43125
  badFiltersMigration
42809
43126
  ]);
42810
- await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.runQuery(db, 'INSERT INTO __migrations__ (id) VALUES (?)', [
43127
+ await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.runQuery(db, 'INSERT INTO __migrations__ (id) VALUES (?)', [
42811
43128
  newFiltersMigration
42812
43129
  ]);
42813
43130
  }
42814
43131
  }
42815
43132
  async function getAppliedMigrations(db) {
42816
- const rows = await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.runQuery(db, 'SELECT * FROM __migrations__ ORDER BY id ASC', [], true);
43133
+ const rows = await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.runQuery(db, 'SELECT * FROM __migrations__ ORDER BY id ASC', [], true);
42817
43134
  return rows.map((row) => row.id);
42818
43135
  }
42819
43136
  async function getMigrationList(migrationsDir) {
42820
- const files = await _platform_server_fs__WEBPACK_IMPORTED_MODULE_3__.listDir(migrationsDir);
43137
+ const files = await _platform_server_fs__WEBPACK_IMPORTED_MODULE_4__.listDir(migrationsDir);
42821
43138
  return files.filter((name) => name.match(/(\.sql|\.js)$/)).sort((m1, m2) => {
42822
43139
  const id1 = getMigrationId(m1);
42823
43140
  const id2 = getMigrationId(m2);
@@ -42838,19 +43155,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42838
43155
  }
42839
43156
  async function applyJavaScript(db, id) {
42840
43157
  const dbInterface = {
42841
- runQuery: (query, params, fetchAll) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.runQuery(db, query, params, fetchAll),
42842
- execQuery: (query) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.execQuery(db, query),
42843
- transaction: (func) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.transaction(db, func)
43158
+ runQuery: (query, params, fetchAll) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.runQuery(db, query, params, fetchAll),
43159
+ execQuery: (query) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.execQuery(db, query),
43160
+ transaction: (func) => _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.transaction(db, func)
42844
43161
  };
42845
43162
  if (javascriptMigrations[id] == null) {
42846
43163
  throw new Error('Could not find JS migration code to run for ' + id);
42847
43164
  }
42848
43165
  const run = javascriptMigrations[id];
42849
- return run(dbInterface, () => (0, uuid__WEBPACK_IMPORTED_MODULE_5__["default"])());
43166
+ return run(dbInterface, {
43167
+ fs: _platform_server_fs__WEBPACK_IMPORTED_MODULE_4__,
43168
+ fileId: _prefs__WEBPACK_IMPORTED_MODULE_6__.getPrefs()?.id
43169
+ });
42850
43170
  }
42851
43171
  async function applySql(db, sql) {
42852
43172
  try {
42853
- await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.execQuery(db, sql);
43173
+ await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.execQuery(db, sql);
42854
43174
  }
42855
43175
  catch (e) {
42856
43176
  console.log('Error applying sql:', sql);
@@ -42858,14 +43178,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42858
43178
  }
42859
43179
  }
42860
43180
  async function applyMigration(db, name, migrationsDir) {
42861
- const code = await _platform_server_fs__WEBPACK_IMPORTED_MODULE_3__.readFile(_platform_server_fs__WEBPACK_IMPORTED_MODULE_3__.join(migrationsDir, name));
43181
+ const code = await _platform_server_fs__WEBPACK_IMPORTED_MODULE_4__.readFile(_platform_server_fs__WEBPACK_IMPORTED_MODULE_4__.join(migrationsDir, name));
42862
43182
  if (name.match(/\.js$/)) {
42863
43183
  await applyJavaScript(db, getMigrationId(name));
42864
43184
  }
42865
43185
  else {
42866
43186
  await applySql(db, code);
42867
43187
  }
42868
- await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_4__.runQuery(db, 'INSERT INTO __migrations__ (id) VALUES (?)', [
43188
+ await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_5__.runQuery(db, 'INSERT INTO __migrations__ (id) VALUES (?)', [
42869
43189
  getMigrationId(name)
42870
43190
  ]);
42871
43191
  }
@@ -43133,12 +43453,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43133
43453
  /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
43134
43454
  /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
43135
43455
  const app = (0, _app__WEBPACK_IMPORTED_MODULE_0__.createApp)();
43136
- app.method('notes-save', async ({ id, note }) => {
43456
+ async function updateNotes({ id, note }) {
43137
43457
  await _db__WEBPACK_IMPORTED_MODULE_1__.update('notes', {
43138
43458
  id,
43139
43459
  note
43140
43460
  });
43141
- });
43461
+ }
43462
+ app.method('notes-save', updateNotes);
43142
43463
  /***/
43143
43464
  }),
43144
43465
  /***/ "./packages/loot-core/src/server/platform.ts":
@@ -43266,6 +43587,31 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43266
43587
  }
43267
43588
  /***/
43268
43589
  }),
43590
+ /***/ "./packages/loot-core/src/server/preferences/app.ts":
43591
+ /*!**********************************************************!*\
43592
+ !*** ./packages/loot-core/src/server/preferences/app.ts ***!
43593
+ \**********************************************************/
43594
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
43595
+ "use strict";
43596
+ __webpack_require__.r(__webpack_exports__);
43597
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
43598
+ /* harmony export */ app: () => ( /* binding */app)
43599
+ /* harmony export */
43600
+ });
43601
+ /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
43602
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
43603
+ /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
43604
+ /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
43605
+ const app = (0, _app__WEBPACK_IMPORTED_MODULE_0__.createApp)();
43606
+ const savePreferences = async ({ id, value }) => {
43607
+ await _db__WEBPACK_IMPORTED_MODULE_1__.update('preferences', {
43608
+ id,
43609
+ value
43610
+ });
43611
+ };
43612
+ app.method('preferences/save', (0, _mutators__WEBPACK_IMPORTED_MODULE_2__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_3__.undoable)(savePreferences)));
43613
+ /***/
43614
+ }),
43269
43615
  /***/ "./packages/loot-core/src/server/prefs.ts":
43270
43616
  /*!************************************************!*\
43271
43617
  !*** ./packages/loot-core/src/server/prefs.ts ***!
@@ -43307,19 +43653,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43307
43653
  budgetName: id
43308
43654
  };
43309
43655
  }
43310
- // delete released feature flags
43311
- const releasedFeatures = [
43312
- 'syncAccount'
43313
- ];
43314
- for (const feature of releasedFeatures) {
43315
- delete prefs[`flags.${feature}`];
43316
- }
43317
- // delete legacy notifications
43318
- for (const key of Object.keys(prefs)) {
43319
- if (key.startsWith('notifications.')) {
43320
- delete prefs[key];
43321
- }
43322
- }
43323
43656
  // No matter what is in `id` field, force it to be the current id.
43324
43657
  // This makes it resilient to users moving around folders, etc
43325
43658
  prefs.id = id;
@@ -43330,7 +43663,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43330
43663
  if (!avoidSync) {
43331
43664
  // Sync whitelisted prefs
43332
43665
  const messages = Object.keys(prefsToSet).map((key) => {
43333
- if (key === 'budgetType' || key === 'budgetName') {
43666
+ if (key === 'budgetName') {
43334
43667
  return {
43335
43668
  dataset: 'prefs',
43336
43669
  row: key,
@@ -43514,14 +43847,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43514
43847
  /* harmony export */ app: () => ( /* binding */app)
43515
43848
  /* harmony export */
43516
43849
  });
43517
- /* harmony import */ var _shared_rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/rules */ "./packages/loot-core/src/shared/rules.ts");
43518
- /* harmony import */ var _accounts_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../accounts/rules */ "./packages/loot-core/src/server/accounts/rules.ts");
43519
- /* harmony import */ var _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../accounts/transaction-rules */ "./packages/loot-core/src/server/accounts/transaction-rules.ts");
43520
- /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
43521
- /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
43522
- /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
43523
- /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
43524
- /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
43850
+ /* harmony import */ var _accounts_rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../accounts/rules */ "./packages/loot-core/src/server/accounts/rules.ts");
43851
+ /* harmony import */ var _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../accounts/transaction-rules */ "./packages/loot-core/src/server/accounts/transaction-rules.ts");
43852
+ /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
43853
+ /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
43854
+ /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
43855
+ /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
43856
+ /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
43525
43857
  // @ts-strict-ignore
43526
43858
  function validateRule(rule) {
43527
43859
  // Returns an array of errors, the array is the same link as the
@@ -43532,7 +43864,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43532
43864
  validate(item);
43533
43865
  }
43534
43866
  catch (e) {
43535
- if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_4__.RuleError) {
43867
+ if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_3__.RuleError) {
43536
43868
  console.warn('Invalid rule', e);
43537
43869
  return e.type;
43538
43870
  }
@@ -43542,8 +43874,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43542
43874
  });
43543
43875
  return result.filter((res) => typeof res === 'string').length ? result : null;
43544
43876
  }
43545
- const conditionErrors = runValidation(rule.conditions, (cond) => new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Condition(cond.op, cond.field, cond.value, cond.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES));
43546
- const actionErrors = runValidation(rule.actions, (action) => action.op === 'set-split-amount' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : action.op === 'link-schedule' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : action.op === 'prepend-notes' || action.op === 'append-notes' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES));
43877
+ const conditionErrors = runValidation(rule.conditions, (cond) => new _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.Condition(cond.op, cond.field, cond.value, cond.options));
43878
+ const actionErrors = runValidation(rule.actions, (action) => action.op === 'set-split-amount' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.Action(action.op, null, action.value, action.options) : action.op === 'link-schedule' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.Action(action.op, null, action.value, null) : action.op === 'prepend-notes' || action.op === 'append-notes' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.Action(action.op, null, action.value, null) : new _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.Action(action.op, action.field, action.value, action.options));
43547
43879
  if (conditionErrors || actionErrors) {
43548
43880
  return {
43549
43881
  conditionErrors,
@@ -43553,44 +43885,44 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43553
43885
  return null;
43554
43886
  }
43555
43887
  // Expose functions to the client
43556
- const app = (0, _app__WEBPACK_IMPORTED_MODULE_3__.createApp)();
43888
+ const app = (0, _app__WEBPACK_IMPORTED_MODULE_2__.createApp)();
43557
43889
  app.method('rule-validate', async function (rule) {
43558
43890
  const error = validateRule(rule);
43559
43891
  return {
43560
43892
  error
43561
43893
  };
43562
43894
  });
43563
- app.method('rule-add', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function (rule) {
43895
+ app.method('rule-add', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)(async function (rule) {
43564
43896
  const error = validateRule(rule);
43565
43897
  if (error) {
43566
43898
  return {
43567
43899
  error
43568
43900
  };
43569
43901
  }
43570
- const id = await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.insertRule(rule);
43902
+ const id = await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.insertRule(rule);
43571
43903
  return {
43572
43904
  id,
43573
43905
  ...rule
43574
43906
  };
43575
43907
  }));
43576
- app.method('rule-update', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function (rule) {
43908
+ app.method('rule-update', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)(async function (rule) {
43577
43909
  const error = validateRule(rule);
43578
43910
  if (error) {
43579
43911
  return {
43580
43912
  error
43581
43913
  };
43582
43914
  }
43583
- await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.updateRule(rule);
43915
+ await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.updateRule(rule);
43584
43916
  return rule;
43585
43917
  }));
43586
- app.method('rule-delete', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function (id) {
43587
- return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.deleteRule(id);
43918
+ app.method('rule-delete', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)(async function (id) {
43919
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.deleteRule(id);
43588
43920
  }));
43589
- app.method('rule-delete-all', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function (ids) {
43921
+ app.method('rule-delete-all', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)(async function (ids) {
43590
43922
  let someDeletionsFailed = false;
43591
- await (0, _sync__WEBPACK_IMPORTED_MODULE_6__.batchMessages)(async () => {
43923
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
43592
43924
  for (const id of ids) {
43593
- const res = await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.deleteRule(id);
43925
+ const res = await _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.deleteRule(id);
43594
43926
  if (res === false) {
43595
43927
  someDeletionsFailed = true;
43596
43928
  }
@@ -43600,21 +43932,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43600
43932
  someDeletionsFailed
43601
43933
  };
43602
43934
  }));
43603
- app.method('rule-apply-actions', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_7__.undoable)(async function ({ transactions, actions }) {
43604
- return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.applyActions(transactions, actions);
43935
+ app.method('rule-apply-actions', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_6__.undoable)(async function ({ transactions, actions }) {
43936
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.applyActions(transactions, actions);
43605
43937
  })));
43606
- app.method('rule-add-payee-rename', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function ({ fromNames, to }) {
43607
- return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.updatePayeeRenameRule(fromNames, to);
43938
+ app.method('rule-add-payee-rename', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)(async function ({ fromNames, to }) {
43939
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.updatePayeeRenameRule(fromNames, to);
43608
43940
  }));
43609
43941
  app.method('rules-get', async function () {
43610
- return (0, _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.rankRules)(_accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.getRules()).map((rule) => rule.serialize());
43942
+ return (0, _accounts_rules__WEBPACK_IMPORTED_MODULE_0__.rankRules)(_accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.getRules()).map((rule) => rule.serialize());
43611
43943
  });
43612
43944
  app.method('rule-get', async function ({ id }) {
43613
- const rule = _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.getRules().find((rule) => rule.id === id);
43945
+ const rule = _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.getRules().find((rule) => rule.id === id);
43614
43946
  return rule ? rule.serialize() : null;
43615
43947
  });
43616
43948
  app.method('rules-run', async function ({ transaction }) {
43617
- return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.runRules(transaction);
43949
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_1__.runRules(transaction);
43618
43950
  });
43619
43951
  /***/
43620
43952
  }),
@@ -43688,9 +44020,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43688
44020
  }
43689
44021
  function getNextDate(dateCond, start = new Date((0, _shared_months__WEBPACK_IMPORTED_MODULE_3__.currentDay)()), noSkipWeekend = false) {
43690
44022
  start = date_fns__WEBPACK_IMPORTED_MODULE_19__["default"](start);
43691
- const cond = new _accounts_rules__WEBPACK_IMPORTED_MODULE_6__.Condition(dateCond.op, 'date', dateCond.value, null, new Map(Object.entries({
43692
- date: 'date'
43693
- })));
44023
+ const cond = new _accounts_rules__WEBPACK_IMPORTED_MODULE_6__.Condition(dateCond.op, 'date', dateCond.value, null);
43694
44024
  const value = cond.getValue();
43695
44025
  if (value.type === 'date') {
43696
44026
  return value.date;
@@ -43936,12 +44266,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43936
44266
  async function getUpcomingDates({ config, count }) {
43937
44267
  const rules = (0, _shared_schedules__WEBPACK_IMPORTED_MODULE_5__.recurConfigToRSchedule)(config);
43938
44268
  try {
43939
- // @ts-expect-error fix me
43940
44269
  const schedule = new _util_rschedule__WEBPACK_IMPORTED_MODULE_17__.Schedule({
43941
44270
  rrules: rules
43942
44271
  });
43943
- return schedule // @ts-expect-error fix me
43944
- .occurrences({
44272
+ return schedule.occurrences({
43945
44273
  start: date_fns__WEBPACK_IMPORTED_MODULE_19__["default"](new Date()),
43946
44274
  take: count
43947
44275
  }).toArray().map((date) => config.skipWeekend ? getDateWithSkippedWeekend(date.date, config.weekendSolveMode) : date.date).map((date) => (0, _shared_months__WEBPACK_IMPORTED_MODULE_3__.dayFromDate)(date));
@@ -44157,12 +44485,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44157
44485
  /* harmony import */ var _util_rschedule__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../util/rschedule */ "./packages/loot-core/src/server/util/rschedule.ts");
44158
44486
  // @ts-strict-ignore
44159
44487
  function takeDates(config) {
44160
- // @ts-expect-error fix me
44161
44488
  const schedule = new _util_rschedule__WEBPACK_IMPORTED_MODULE_9__.Schedule({
44162
44489
  rrules: (0, _shared_schedules__WEBPACK_IMPORTED_MODULE_3__.recurConfigToRSchedule)(config)
44163
44490
  });
44164
- return schedule // @ts-expect-error fix me
44165
- .occurrences({
44491
+ return schedule.occurrences({
44166
44492
  take: 3
44167
44493
  }).toArray().map((d) => d.date);
44168
44494
  }
@@ -44549,9 +44875,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44549
44875
  /* harmony import */ var _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../platform/server/sqlite */ "./packages/loot-core/src/platform/server/sqlite/index.electron.ts");
44550
44876
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../shared/months */ "./packages/loot-core/src/shared/months.ts");
44551
44877
  /* harmony import */ var _platform__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./platform */ "./packages/loot-core/src/server/platform.ts");
44552
- /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./prefs */ "./packages/loot-core/src/server/prefs.ts");
44553
- /* harmony import */ var _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./spreadsheet/spreadsheet */ "./packages/loot-core/src/server/spreadsheet/spreadsheet.ts");
44554
- /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
44878
+ /* harmony import */ var _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./spreadsheet/spreadsheet */ "./packages/loot-core/src/server/spreadsheet/spreadsheet.ts");
44879
+ /* harmony import */ var _spreadsheet_util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./spreadsheet/util */ "./packages/loot-core/src/server/spreadsheet/util.ts");
44555
44880
  // @ts-strict-ignore
44556
44881
  let globalSheet;
44557
44882
  let globalOnChange;
@@ -44629,10 +44954,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44629
44954
  }
44630
44955
  let sheet;
44631
44956
  if (cacheEnabled) {
44632
- sheet = new _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_5__.Spreadsheet(updateSpreadsheetCache.bind(null, cacheDb), setCacheStatus.bind(null, mainDb, cacheDb));
44957
+ sheet = new _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_4__.Spreadsheet(updateSpreadsheetCache.bind(null, cacheDb), setCacheStatus.bind(null, mainDb, cacheDb));
44633
44958
  }
44634
44959
  else {
44635
- sheet = new _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_5__.Spreadsheet();
44960
+ sheet = new _spreadsheet_spreadsheet__WEBPACK_IMPORTED_MODULE_4__.Spreadsheet();
44636
44961
  }
44637
44962
  (0, _platform_exceptions__WEBPACK_IMPORTED_MODULE_0__.captureBreadcrumb)({
44638
44963
  message: 'loading spreaadsheet',
@@ -44682,7 +45007,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44682
45007
  const sheet = globalSheet;
44683
45008
  // TODO: Clear out the cache here so make sure future loads of the app
44684
45009
  // don't load any extra values that aren't set here
44685
- const { budgetType } = _prefs__WEBPACK_IMPORTED_MODULE_4__.getPrefs() || {};
45010
+ const { value: budgetType = 'rollover' } = await db.first('SELECT value from preferences WHERE id = ?', [
45011
+ 'budgetType'
45012
+ ]) ?? {};
44686
45013
  const table = budgetType === 'report' ? 'reflect_budgets' : 'zero_budgets';
44687
45014
  const budgets = await db.all(`
44688
45015
  SELECT * FROM ${table} b
@@ -44711,10 +45038,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44711
45038
  sheet.endTransaction();
44712
45039
  }
44713
45040
  function getCell(sheet, name) {
44714
- return globalSheet._getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_6__.resolveName)(sheet, name));
45041
+ return globalSheet._getNode((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_5__.resolveName)(sheet, name));
44715
45042
  }
44716
45043
  function getCellValue(sheet, name) {
44717
- return globalSheet.getValue((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_6__.resolveName)(sheet, name));
45044
+ return globalSheet.getValue((0, _spreadsheet_util__WEBPACK_IMPORTED_MODULE_5__.resolveName)(sheet, name));
44718
45045
  }
44719
45046
  function startTransaction() {
44720
45047
  if (globalSheet) {
@@ -45822,6 +46149,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
45822
46149
  ]);
45823
46150
  currentMerkle = _actual_app_crdt__WEBPACK_IMPORTED_MODULE_0__.merkle.insert(currentMerkle, timestamp);
45824
46151
  }
46152
+ // Special treatment for some synced prefs
46153
+ if (dataset === 'preferences' && row === 'budgetType') {
46154
+ (0, _budget_base__WEBPACK_IMPORTED_MODULE_7__.setType)(value);
46155
+ }
45825
46156
  }
45826
46157
  if (checkSyncingMode('enabled')) {
45827
46158
  currentMerkle = _actual_app_crdt__WEBPACK_IMPORTED_MODULE_0__.merkle.prune(currentMerkle);
@@ -45845,9 +46176,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
45845
46176
  _prefs__WEBPACK_IMPORTED_MODULE_13__.savePrefs(prefsToSet, {
45846
46177
  avoidSync: true
45847
46178
  });
45848
- if (prefsToSet.budgetType) {
45849
- (0, _budget_base__WEBPACK_IMPORTED_MODULE_7__.setType)(prefsToSet.budgetType);
45850
- }
45851
46179
  _platform_server_connection__WEBPACK_IMPORTED_MODULE_3__.send('prefs-updated');
45852
46180
  }
45853
46181
  const newData = await fetchData();
@@ -46144,11 +46472,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
46144
46472
  localTimeChanged ? 0 : count + 1, diffTime));
46145
46473
  }
46146
46474
  else {
46147
- // All synced up, store the current time as a simple optimization
46148
- // for the next sync
46149
- await _prefs__WEBPACK_IMPORTED_MODULE_13__.savePrefs({
46150
- lastSyncedTimestamp: (0, _actual_app_crdt__WEBPACK_IMPORTED_MODULE_0__.getClock)().timestamp.toString()
46151
- });
46475
+ // All synced up, store the current time as a simple optimization for the next sync
46476
+ const requiresUpdate = (0, _actual_app_crdt__WEBPACK_IMPORTED_MODULE_0__.getClock)().timestamp.toString() !== lastSyncedTimestamp;
46477
+ if (requiresUpdate) {
46478
+ await _prefs__WEBPACK_IMPORTED_MODULE_13__.savePrefs({
46479
+ lastSyncedTimestamp: (0, _actual_app_crdt__WEBPACK_IMPORTED_MODULE_0__.getClock)().timestamp.toString()
46480
+ });
46481
+ }
46152
46482
  }
46153
46483
  return receivedMessages;
46154
46484
  }
@@ -46812,66 +47142,65 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
46812
47142
  "use strict";
46813
47143
  __webpack_require__.r(__webpack_exports__);
46814
47144
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
46815
- /* harmony export */ AddOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.AddOperator),
46816
- /* harmony export */ ArgumentError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.ArgumentError),
46817
- /* harmony export */ Calendar: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Calendar),
46818
- /* harmony export */ Collection: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Collection),
46819
- /* harmony export */ CollectionIterator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.CollectionIterator),
46820
- /* harmony export */ DateAdapter: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.DateAdapter),
46821
- /* harmony export */ DateAdapterBase: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.DateAdapterBase),
46822
- /* harmony export */ DateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.DateTime),
46823
- /* harmony export */ Dates: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Dates),
46824
- /* harmony export */ InfiniteLoopError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.InfiniteLoopError),
46825
- /* harmony export */ IntersectionOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.IntersectionOperator),
46826
- /* harmony export */ InvalidDateAdapterError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.InvalidDateAdapterError),
46827
- /* harmony export */ InvalidDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.InvalidDateTime),
46828
- /* harmony export */ InvalidDateTimeError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.InvalidDateTimeError),
46829
- /* harmony export */ MergeDurationOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.MergeDurationOperator),
46830
- /* harmony export */ MergeDurationOperatorError: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.MergeDurationOperatorError),
46831
- /* harmony export */ OccurrenceGenerator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.OccurrenceGenerator),
46832
- /* harmony export */ OccurrenceIterator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.OccurrenceIterator),
46833
- /* harmony export */ Operator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Operator),
46834
- /* harmony export */ RecurrenceRuleError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.RecurrenceRuleError),
46835
- /* harmony export */ RecurrenceRulesIterator: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.RecurrenceRulesIterator),
46836
- /* harmony export */ Rule: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Rule),
46837
- /* harmony export */ RuleBase: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.RuleBase),
46838
- /* harmony export */ RuleOptionError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.RuleOptionError),
46839
- /* harmony export */ Schedule: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.Schedule),
46840
- /* harmony export */ ScheduleBase: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.ScheduleBase),
46841
- /* harmony export */ SplitDurationOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.SplitDurationOperator),
46842
- /* harmony export */ SplitDurationOperatorError: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.SplitDurationOperatorError),
46843
- /* harmony export */ StandardDateAdapter: () => ( /* reexport safe */_rschedule_standard_date_adapter__WEBPACK_IMPORTED_MODULE_2__.StandardDateAdapter),
46844
- /* harmony export */ SubtractOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.SubtractOperator),
46845
- /* harmony export */ UniqueOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.UniqueOperator),
46846
- /* harmony export */ ValidDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.ValidDateTime),
46847
- /* harmony export */ add: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.add),
46848
- /* harmony export */ cloneJSON: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.cloneJSON),
46849
- /* harmony export */ cloneRuleOptions: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.cloneRuleOptions),
46850
- /* harmony export */ dateInputToDateAdapter: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.dateInputToDateAdapter),
46851
- /* harmony export */ dateInputToDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.dateInputToDateTime),
46852
- /* harmony export */ dateTimeSortComparer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.dateTimeSortComparer),
46853
- /* harmony export */ freqToGranularity: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.freqToGranularity),
46854
- /* harmony export */ getDaysInYear: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.getDaysInYear),
46855
- /* harmony export */ getDifferenceBetweenWeekdays: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.getDifferenceBetweenWeekdays),
46856
- /* harmony export */ intersection: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.intersection),
46857
- /* harmony export */ isLeapYear: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.isLeapYear),
46858
- /* harmony export */ mergeDuration: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.mergeDuration),
46859
- /* harmony export */ normalizeDateTimeTimezone: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.normalizeDateTimeTimezone),
46860
- /* harmony export */ normalizeRuleOptions: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.normalizeRuleOptions),
46861
- /* harmony export */ numberSortComparer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.numberSortComparer),
46862
- /* harmony export */ orderedWeekdays: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.orderedWeekdays),
46863
- /* harmony export */ recurrenceRulesReducer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.recurrenceRulesReducer),
46864
- /* harmony export */ splitDuration: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.splitDuration),
46865
- /* harmony export */ subtract: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.subtract),
46866
- /* harmony export */ uniqDateTimes: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_3__.uniqDateTimes),
46867
- /* harmony export */ unique: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__.unique)
47145
+ /* harmony export */ AddOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.AddOperator),
47146
+ /* harmony export */ ArgumentError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.ArgumentError),
47147
+ /* harmony export */ Calendar: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Calendar),
47148
+ /* harmony export */ Collection: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Collection),
47149
+ /* harmony export */ CollectionIterator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.CollectionIterator),
47150
+ /* harmony export */ DateAdapter: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateAdapter),
47151
+ /* harmony export */ DateAdapterBase: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateAdapterBase),
47152
+ /* harmony export */ DateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.DateTime),
47153
+ /* harmony export */ Dates: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Dates),
47154
+ /* harmony export */ InfiniteLoopError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.InfiniteLoopError),
47155
+ /* harmony export */ IntersectionOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.IntersectionOperator),
47156
+ /* harmony export */ InvalidDateAdapterError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.InvalidDateAdapterError),
47157
+ /* harmony export */ InvalidDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.InvalidDateTime),
47158
+ /* harmony export */ InvalidDateTimeError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.InvalidDateTimeError),
47159
+ /* harmony export */ MergeDurationOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.MergeDurationOperator),
47160
+ /* harmony export */ MergeDurationOperatorError: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.MergeDurationOperatorError),
47161
+ /* harmony export */ OccurrenceGenerator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.OccurrenceGenerator),
47162
+ /* harmony export */ OccurrenceIterator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.OccurrenceIterator),
47163
+ /* harmony export */ Operator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Operator),
47164
+ /* harmony export */ RecurrenceRuleError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.RecurrenceRuleError),
47165
+ /* harmony export */ RecurrenceRulesIterator: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.RecurrenceRulesIterator),
47166
+ /* harmony export */ Rule: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Rule),
47167
+ /* harmony export */ RuleBase: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.RuleBase),
47168
+ /* harmony export */ RuleOptionError: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.RuleOptionError),
47169
+ /* harmony export */ Schedule: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.Schedule),
47170
+ /* harmony export */ ScheduleBase: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.ScheduleBase),
47171
+ /* harmony export */ SplitDurationOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.SplitDurationOperator),
47172
+ /* harmony export */ SplitDurationOperatorError: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.SplitDurationOperatorError),
47173
+ /* harmony export */ StandardDateAdapter: () => ( /* reexport safe */_rschedule_standard_date_adapter__WEBPACK_IMPORTED_MODULE_1__.StandardDateAdapter),
47174
+ /* harmony export */ SubtractOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.SubtractOperator),
47175
+ /* harmony export */ UniqueOperator: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.UniqueOperator),
47176
+ /* harmony export */ ValidDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.ValidDateTime),
47177
+ /* harmony export */ add: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.add),
47178
+ /* harmony export */ cloneJSON: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.cloneJSON),
47179
+ /* harmony export */ cloneRuleOptions: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.cloneRuleOptions),
47180
+ /* harmony export */ dateInputToDateAdapter: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.dateInputToDateAdapter),
47181
+ /* harmony export */ dateInputToDateTime: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.dateInputToDateTime),
47182
+ /* harmony export */ dateTimeSortComparer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.dateTimeSortComparer),
47183
+ /* harmony export */ freqToGranularity: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.freqToGranularity),
47184
+ /* harmony export */ getDaysInYear: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.getDaysInYear),
47185
+ /* harmony export */ getDifferenceBetweenWeekdays: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.getDifferenceBetweenWeekdays),
47186
+ /* harmony export */ intersection: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.intersection),
47187
+ /* harmony export */ isLeapYear: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.isLeapYear),
47188
+ /* harmony export */ mergeDuration: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.mergeDuration),
47189
+ /* harmony export */ normalizeDateTimeTimezone: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.normalizeDateTimeTimezone),
47190
+ /* harmony export */ normalizeRuleOptions: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.normalizeRuleOptions),
47191
+ /* harmony export */ numberSortComparer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.numberSortComparer),
47192
+ /* harmony export */ orderedWeekdays: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.orderedWeekdays),
47193
+ /* harmony export */ recurrenceRulesReducer: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.recurrenceRulesReducer),
47194
+ /* harmony export */ splitDuration: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.splitDuration),
47195
+ /* harmony export */ subtract: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.subtract),
47196
+ /* harmony export */ uniqDateTimes: () => ( /* reexport safe */_rschedule_core__WEBPACK_IMPORTED_MODULE_2__.uniqDateTimes),
47197
+ /* harmony export */ unique: () => ( /* reexport safe */_rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__.unique)
46868
47198
  /* harmony export */
46869
47199
  });
46870
47200
  /* harmony import */ var _rschedule_standard_date_adapter_setup__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @rschedule/standard-date-adapter/setup */ "./node_modules/@rschedule/standard-date-adapter/es2015/setup.js");
46871
- /* harmony import */ var _rschedule_json_tools_Schedule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @rschedule/json-tools/Schedule */ "./node_modules/@rschedule/json-tools/es2015/Schedule.js");
46872
- /* harmony import */ var _rschedule_standard_date_adapter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @rschedule/standard-date-adapter */ "./node_modules/@rschedule/standard-date-adapter/es2015/main.js");
46873
- /* harmony import */ var _rschedule_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @rschedule/core */ "./node_modules/@rschedule/core/es2015/main.js");
46874
- /* harmony import */ var _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @rschedule/core/generators */ "./node_modules/@rschedule/core/es2015/generators.js");
47201
+ /* harmony import */ var _rschedule_standard_date_adapter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @rschedule/standard-date-adapter */ "./node_modules/@rschedule/standard-date-adapter/es2015/main.js");
47202
+ /* harmony import */ var _rschedule_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @rschedule/core */ "./node_modules/@rschedule/core/es2015/main.js");
47203
+ /* harmony import */ var _rschedule_core_generators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @rschedule/core/generators */ "./node_modules/@rschedule/core/es2015/generators.js");
46875
47204
  /***/
46876
47205
  }),
46877
47206
  /***/ "./packages/loot-core/src/shared/async.ts":
@@ -47091,13 +47420,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47091
47420
  return error.message || 'We had an unknown problem syncing the account.';
47092
47421
  }
47093
47422
  class LazyLoadFailedError extends Error {
47094
- constructor(name) {
47423
+ constructor(name, cause) {
47095
47424
  super(`Error: failed loading lazy-loaded module ${name}`);
47096
47425
  this.type = 'app-init-failure';
47097
47426
  this.meta = {};
47098
47427
  this.meta = {
47099
47428
  name
47100
47429
  };
47430
+ this.cause = cause;
47101
47431
  }
47102
47432
  }
47103
47433
  /***/
@@ -47130,6 +47460,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47130
47460
  /* harmony export */ dayRangeInclusive: () => ( /* binding */dayRangeInclusive),
47131
47461
  /* harmony export */ differenceInCalendarDays: () => ( /* binding */differenceInCalendarDays),
47132
47462
  /* harmony export */ differenceInCalendarMonths: () => ( /* binding */differenceInCalendarMonths),
47463
+ /* harmony export */ firstDayOfMonth: () => ( /* binding */firstDayOfMonth),
47133
47464
  /* harmony export */ format: () => ( /* binding */format),
47134
47465
  /* harmony export */ getDateFormatRegex: () => ( /* binding */getDateFormatRegex),
47135
47466
  /* harmony export */ getDay: () => ( /* binding */getDay),
@@ -47150,6 +47481,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47150
47481
  /* harmony export */ isAfter: () => ( /* binding */isAfter),
47151
47482
  /* harmony export */ isBefore: () => ( /* binding */isBefore),
47152
47483
  /* harmony export */ isCurrentMonth: () => ( /* binding */isCurrentMonth),
47484
+ /* harmony export */ lastDayOfMonth: () => ( /* binding */lastDayOfMonth),
47153
47485
  /* harmony export */ monthFromDate: () => ( /* binding */monthFromDate),
47154
47486
  /* harmony export */ nameForMonth: () => ( /* binding */nameForMonth),
47155
47487
  /* harmony export */ nextMonth: () => ( /* binding */nextMonth),
@@ -47171,21 +47503,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47171
47503
  });
47172
47504
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/format/index.js");
47173
47505
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfWeek/index.js");
47174
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parse/index.js");
47175
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addMonths/index.js");
47176
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subMonths/index.js");
47177
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addYears/index.js");
47178
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addWeeks/index.js");
47179
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarMonths/index.js");
47180
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarDays/index.js");
47181
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subWeeks/index.js");
47182
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subYears/index.js");
47183
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
47184
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
47185
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isBefore/index.js");
47186
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isAfter/index.js");
47187
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfMonth/index.js");
47188
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfMonth/index.js");
47506
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/startOfMonth/index.js");
47507
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfMonth/index.js");
47508
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parse/index.js");
47509
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addMonths/index.js");
47510
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subMonths/index.js");
47511
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addYears/index.js");
47512
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addWeeks/index.js");
47513
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarMonths/index.js");
47514
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInCalendarDays/index.js");
47515
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subWeeks/index.js");
47516
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subYears/index.js");
47517
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
47518
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
47519
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isBefore/index.js");
47520
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isAfter/index.js");
47189
47521
  /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/endOfWeek/index.js");
47190
47522
  /* harmony import */ var memoize_one__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! memoize-one */ "./node_modules/memoize-one/dist/memoize-one.esm.js");
47191
47523
  /* harmony import */ var _client_platform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../client/platform */ "./packages/loot-core/src/client/platform.electron.ts");
@@ -47274,6 +47606,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47274
47606
  weekStartsOn: converted
47275
47607
  })), 'yyyy-MM-dd');
47276
47608
  }
47609
+ function firstDayOfMonth(date) {
47610
+ return dayFromDate(date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](_parse(date)));
47611
+ }
47612
+ function lastDayOfMonth(date) {
47613
+ return dayFromDate(date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(date)));
47614
+ }
47277
47615
  function dayFromDate(date) {
47278
47616
  return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](_parse(date), 'yyyy-MM-dd');
47279
47617
  }
@@ -47306,7 +47644,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47306
47644
  }
47307
47645
  function currentDate() {
47308
47646
  if (global.IS_TESTING || _client_platform__WEBPACK_IMPORTED_MODULE_0__.isPlaywright) {
47309
- return date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](currentDay(), 'yyyy-MM-dd', new Date());
47647
+ return date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](currentDay(), 'yyyy-MM-dd', new Date());
47310
47648
  }
47311
47649
  return new Date();
47312
47650
  }
@@ -47319,49 +47657,49 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47319
47657
  }
47320
47658
  }
47321
47659
  function nextMonth(month) {
47322
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), 1), 'yyyy-MM');
47660
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](_parse(month), 1), 'yyyy-MM');
47323
47661
  }
47324
47662
  function prevYear(month) {
47325
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), 12), 'yyyy-MM');
47663
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(month), 12), 'yyyy-MM');
47326
47664
  }
47327
47665
  function prevMonth(month) {
47328
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), 1), 'yyyy-MM');
47666
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(month), 1), 'yyyy-MM');
47329
47667
  }
47330
47668
  function addYears(year, n) {
47331
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](_parse(year), n), 'yyyy');
47669
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](_parse(year), n), 'yyyy');
47332
47670
  }
47333
47671
  function addMonths(month, n) {
47334
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month), n), 'yyyy-MM');
47672
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](_parse(month), n), 'yyyy-MM');
47335
47673
  }
47336
47674
  function addWeeks(date, n) {
47337
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(date), n), 'yyyy-MM-dd');
47675
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](_parse(date), n), 'yyyy-MM-dd');
47338
47676
  }
47339
47677
  function differenceInCalendarMonths(month1, month2) {
47340
- return date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](_parse(month1), _parse(month2));
47678
+ return date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(month1), _parse(month2));
47341
47679
  }
47342
47680
  function differenceInCalendarDays(month1, month2) {
47343
- return date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](_parse(month1), _parse(month2));
47681
+ return date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](_parse(month1), _parse(month2));
47344
47682
  }
47345
47683
  function subMonths(month, n) {
47346
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_5__["default"](_parse(month), n), 'yyyy-MM');
47684
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](_parse(month), n), 'yyyy-MM');
47347
47685
  }
47348
47686
  function subWeeks(date, n) {
47349
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](_parse(date), n), 'yyyy-MM-dd');
47687
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_12__["default"](_parse(date), n), 'yyyy-MM-dd');
47350
47688
  }
47351
47689
  function subYears(year, n) {
47352
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](_parse(year), n), 'yyyy');
47690
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_13__["default"](_parse(year), n), 'yyyy');
47353
47691
  }
47354
47692
  function addDays(day, n) {
47355
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_12__["default"](_parse(day), n), 'yyyy-MM-dd');
47693
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(day), n), 'yyyy-MM-dd');
47356
47694
  }
47357
47695
  function subDays(day, n) {
47358
- return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_13__["default"](_parse(day), n), 'yyyy-MM-dd');
47696
+ return date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_parse(day), n), 'yyyy-MM-dd');
47359
47697
  }
47360
47698
  function isBefore(month1, month2) {
47361
- return date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month1), _parse(month2));
47699
+ return date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(month1), _parse(month2));
47362
47700
  }
47363
47701
  function isAfter(month1, month2) {
47364
- return date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_parse(month1), _parse(month2));
47702
+ return date_fns__WEBPACK_IMPORTED_MODULE_17__["default"](_parse(month1), _parse(month2));
47365
47703
  }
47366
47704
  function isCurrentMonth(month) {
47367
47705
  return month === currentMonth();
@@ -47370,15 +47708,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47370
47708
  // probably live elsewhere
47371
47709
  function bounds(month) {
47372
47710
  return {
47373
- start: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(month)), 'yyyyMMdd')),
47374
- end: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_17__["default"](_parse(month)), 'yyyyMMdd'))
47711
+ start: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_3__["default"](_parse(month)), 'yyyyMMdd')),
47712
+ end: parseInt(date_fns__WEBPACK_IMPORTED_MODULE_1__["default"](date_fns__WEBPACK_IMPORTED_MODULE_4__["default"](_parse(month)), 'yyyyMMdd'))
47375
47713
  };
47376
47714
  }
47377
47715
  function _yearRange(start, end, inclusive = false) {
47378
47716
  const years = [];
47379
47717
  let year = yearFromDate(start);
47380
47718
  const endYear = yearFromDate(end);
47381
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(year), _parse(endYear))) {
47719
+ while (date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(year), _parse(endYear))) {
47382
47720
  years.push(year);
47383
47721
  year = addYears(year, 1);
47384
47722
  }
@@ -47394,7 +47732,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47394
47732
  const weeks = [];
47395
47733
  let week = weekFromDate(start, firstDayOfWeekIdx);
47396
47734
  const endWeek = weekFromDate(end, firstDayOfWeekIdx);
47397
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(week), _parse(endWeek))) {
47735
+ while (date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(week), _parse(endWeek))) {
47398
47736
  weeks.push(week);
47399
47737
  week = addWeeks(week, 1);
47400
47738
  }
@@ -47410,7 +47748,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47410
47748
  const months = [];
47411
47749
  let month = monthFromDate(start);
47412
47750
  const endMonth = monthFromDate(end);
47413
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month), _parse(endMonth))) {
47751
+ while (date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(month), _parse(endMonth))) {
47414
47752
  months.push(month);
47415
47753
  month = addMonths(month, 1);
47416
47754
  }
@@ -47428,7 +47766,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47428
47766
  function _dayRange(start, end, inclusive = false) {
47429
47767
  const days = [];
47430
47768
  let day = start;
47431
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(day), _parse(end))) {
47769
+ while (date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](_parse(day), _parse(end))) {
47432
47770
  days.push(dayFromDate(day));
47433
47771
  day = addDays(day, 1);
47434
47772
  }
@@ -47701,11 +48039,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47701
48039
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
47702
48040
  /* harmony export */ ALLOCATION_METHODS: () => ( /* binding */ALLOCATION_METHODS),
47703
48041
  /* harmony export */ FIELD_TYPES: () => ( /* binding */FIELD_TYPES),
47704
- /* harmony export */ TYPE_INFO: () => ( /* binding */TYPE_INFO),
47705
48042
  /* harmony export */ deserializeField: () => ( /* binding */deserializeField),
47706
48043
  /* harmony export */ friendlyOp: () => ( /* binding */friendlyOp),
47707
48044
  /* harmony export */ getApproxNumberThreshold: () => ( /* binding */getApproxNumberThreshold),
47708
48045
  /* harmony export */ getFieldError: () => ( /* binding */getFieldError),
48046
+ /* harmony export */ getValidOps: () => ( /* binding */getValidOps),
48047
+ /* harmony export */ isValidOp: () => ( /* binding */isValidOp),
47709
48048
  /* harmony export */ makeValue: () => ( /* binding */makeValue),
47710
48049
  /* harmony export */ mapField: () => ( /* binding */mapField),
47711
48050
  /* harmony export */ parse: () => ( /* binding */parse),
@@ -47759,18 +48098,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47759
48098
  ],
47760
48099
  nullable: true
47761
48100
  },
47762
- imported_payee: {
47763
- ops: [
47764
- 'is',
47765
- 'contains',
47766
- 'matches',
47767
- 'oneOf',
47768
- 'isNot',
47769
- 'doesNotContain',
47770
- 'notOneOf'
47771
- ],
47772
- nullable: true
47773
- },
47774
48101
  number: {
47775
48102
  ops: [
47776
48103
  'is',
@@ -47790,20 +48117,60 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47790
48117
  nullable: false
47791
48118
  }
47792
48119
  };
47793
- const FIELD_TYPES = new Map(Object.entries({
47794
- imported_payee: 'imported_payee',
47795
- payee: 'id',
47796
- date: 'date',
47797
- notes: 'string',
47798
- amount: 'number',
47799
- amountInflow: 'number',
47800
- amountOutfow: 'number',
47801
- category: 'id',
47802
- account: 'id',
47803
- cleared: 'boolean',
47804
- reconciled: 'boolean',
47805
- saved: 'saved'
47806
- }));
48120
+ const FIELD_INFO = {
48121
+ imported_payee: {
48122
+ type: 'string',
48123
+ disallowedOps: new Set([
48124
+ 'hasTags'
48125
+ ])
48126
+ },
48127
+ payee: {
48128
+ type: 'id'
48129
+ },
48130
+ date: {
48131
+ type: 'date'
48132
+ },
48133
+ notes: {
48134
+ type: 'string'
48135
+ },
48136
+ amount: {
48137
+ type: 'number'
48138
+ },
48139
+ category: {
48140
+ type: 'id'
48141
+ },
48142
+ account: {
48143
+ type: 'id'
48144
+ },
48145
+ cleared: {
48146
+ type: 'boolean'
48147
+ },
48148
+ reconciled: {
48149
+ type: 'boolean'
48150
+ },
48151
+ saved: {
48152
+ type: 'saved'
48153
+ }
48154
+ };
48155
+ const fieldInfo = FIELD_INFO;
48156
+ const FIELD_TYPES = new Map(Object.entries(FIELD_INFO).map(([field, info]) => [
48157
+ field,
48158
+ info.type
48159
+ ]));
48160
+ function isValidOp(field, op) {
48161
+ const type = FIELD_TYPES.get(field);
48162
+ if (!type) {
48163
+ return false;
48164
+ }
48165
+ return TYPE_INFO[type].ops.includes(op) && !fieldInfo[field].disallowedOps?.has(op);
48166
+ }
48167
+ function getValidOps(field) {
48168
+ const type = FIELD_TYPES.get(field);
48169
+ if (!type) {
48170
+ return [];
48171
+ }
48172
+ return TYPE_INFO[type].ops.filter((op) => !fieldInfo[field].disallowedOps?.has(op));
48173
+ }
47807
48174
  const ALLOCATION_METHODS = {
47808
48175
  'fixed-amount': 'a fixed amount',
47809
48176
  'fixed-percent': 'a fixed percent of the remainder',
@@ -47925,6 +48292,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
47925
48292
  case 'no-empty-array':
47926
48293
  case 'no-empty-string':
47927
48294
  return 'Value cannot be empty';
48295
+ case 'not-string':
48296
+ return 'Value must be a string';
48297
+ case 'not-boolean':
48298
+ return 'Value must be a boolean';
47928
48299
  case 'not-number':
47929
48300
  return 'Value must be a number';
47930
48301
  case 'invalid-field':
@@ -48722,6 +49093,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48722
49093
  /* harmony export */ hasFieldsChanged: () => ( /* binding */hasFieldsChanged),
48723
49094
  /* harmony export */ integerToAmount: () => ( /* binding */integerToAmount),
48724
49095
  /* harmony export */ integerToCurrency: () => ( /* binding */integerToCurrency),
49096
+ /* harmony export */ isNumberFormat: () => ( /* binding */isNumberFormat),
48725
49097
  /* harmony export */ last: () => ( /* binding */last),
48726
49098
  /* harmony export */ looselyParseAmount: () => ( /* binding */looselyParseAmount),
48727
49099
  /* harmony export */ numberFormats: () => ( /* binding */numberFormats),
@@ -48916,6 +49288,17 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48916
49288
  }
48917
49289
  return amountToCurrency(currencyToAmount(result));
48918
49290
  }
49291
+ const NUMBER_FORMATS = [
49292
+ 'comma-dot',
49293
+ 'dot-comma',
49294
+ 'space-comma',
49295
+ 'apostrophe-dot',
49296
+ 'comma-dot',
49297
+ 'comma-dot-in'
49298
+ ];
49299
+ function isNumberFormat(input = '') {
49300
+ return NUMBER_FORMATS.includes(input);
49301
+ }
48919
49302
  const numberFormats = [
48920
49303
  {
48921
49304
  value: 'comma-dot',