diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c32b6fb10ba746d9ae829a6560970b1f51b8704
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,10 @@
+module.exports = {
+  plugins: ["prettier"],
+  extends: ["react-app"],
+  rules: {
+    "prettier/prettier": "error",
+    "no-unused-vars": "off",
+    "no-loop-func": "off",
+    "no-restricted-globals": "off"
+  }
+};
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..f62e834cd8f2df1a7e295d5fd465a2e5dd1fe459
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,4 @@
+{
+    "singleQuote": true,
+    "trailingComma": "none"
+}
diff --git a/package.json b/package.json
index 64025a752580e2ef158039c48bf66a41e04c0b9c..4a05b1ee1274174043a0e615087fa032600c381a 100644
--- a/package.json
+++ b/package.json
@@ -44,18 +44,6 @@
     "shelljs": "^0.8.2",
     "source-map-support": "^0.5.21"
   },
-  "eslintConfig": {
-    "extends": "react-app",
-    "rules": {
-      "no-unused-vars": "off",
-      "no-loop-func": "off",
-      "no-restricted-globals": "off"
-    }
-  },
-  "prettier": {
-    "singleQuote": true,
-    "trailingComma": "none"
-  },
   "resolutions": {
     "@babel/preset-env": "^7.15.1",
     "@babel/core": "^7.15.1",
diff --git a/packages/desktop-client/src/components/Box.js b/packages/desktop-client/src/components/Box.js
index 6360eb13f738d00b375ffc46aab08e59c2272e25..0649804b387b45b34857edb0e6c2a37a0512b3ce 100644
--- a/packages/desktop-client/src/components/Box.js
+++ b/packages/desktop-client/src/components/Box.js
@@ -9,14 +9,18 @@ function getFlex(flex) {
 }
 
 function Box({ flex, children, direction, style }) {
-  return <div
+  return (
+    <div
       style={{
         ...style,
         flex: getFlex(flex),
         display: 'flex',
         flexDirection: direction || 'column'
       }}
-    >{children}</div>;
+    >
+      {children}
+    </div>
+  );
 }
 
 export default Box;
diff --git a/packages/desktop-client/src/components/Debugger.js b/packages/desktop-client/src/components/Debugger.js
index f65899790b43040d1ca58c9cd122ccfd1b987d58..e91d931af64c3467ec6a7d6b9c7287f57facd82d 100644
--- a/packages/desktop-client/src/components/Debugger.js
+++ b/packages/desktop-client/src/components/Debugger.js
@@ -206,7 +206,7 @@ class Debugger extends React.Component {
                   height: 10,
                   backgroundColor: '#303030',
                   marginRight: 10,
-                  borderRadius: 10,
+                  borderRadius: 10
                 }}
               />
               <Button onClick={this.toggleRecord} style={{ marginRight: 10 }}>
diff --git a/packages/desktop-client/src/components/FatalError.js b/packages/desktop-client/src/components/FatalError.js
index 25b5489c697ecda67a67899218eb6af02825b956..48dd267787f209bfda1410865ceed10a236175f0 100644
--- a/packages/desktop-client/src/components/FatalError.js
+++ b/packages/desktop-client/src/components/FatalError.js
@@ -99,7 +99,9 @@ class FatalError extends React.Component {
               .
             </P>
             <P>
-              <Button onClick={() => window.Actual.relaunch()}>{buttonText}</Button>
+              <Button onClick={() => window.Actual.relaunch()}>
+                {buttonText}
+              </Button>
             </P>
             <P isLast={true} style={{ fontSize: 11 }}>
               <Link
diff --git a/packages/desktop-client/src/components/FinancesApp.js b/packages/desktop-client/src/components/FinancesApp.js
index 65486b468fb024678fb131379c73e47c8050f3e7..4f2be90d7c889d64d69f49da0442d379f136b76e 100644
--- a/packages/desktop-client/src/components/FinancesApp.js
+++ b/packages/desktop-client/src/components/FinancesApp.js
@@ -277,7 +277,4 @@ function FinancesAppWithContext(props) {
   );
 }
 
-export default connect(
-  null,
-  actions
-)(FinancesAppWithContext);
+export default connect(null, actions)(FinancesAppWithContext);
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index 4a13dff7c90280de04631e346604e6d7329e33b9..e17fd8a97962b217b0e11a6a0b31990927a0dc82 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -642,7 +642,7 @@ const AccountHeader = React.memo(
     let searchInput = useRef(null);
     let splitsExpanded = useSplitsExpanded();
 
-    let canSync = syncEnabled && (account && account.account_id);
+    let canSync = syncEnabled && account && account.account_id;
     if (!account) {
       // All accounts - check for any syncable account
       canSync = !!accounts.find(account => !!account.account_id);
@@ -1701,9 +1701,9 @@ class AccountInternal extends React.PureComponent {
                     }
                     showAccount={
                       !accountId ||
-                      (accountId === 'offbudget' ||
-                        accountId === 'budgeted' ||
-                        accountId === 'uncategorized')
+                      accountId === 'offbudget' ||
+                      accountId === 'budgeted' ||
+                      accountId === 'uncategorized'
                     }
                     isAdding={this.state.isAdding}
                     isNew={this.isNew}
diff --git a/packages/desktop-client/src/components/accounts/Filters.js b/packages/desktop-client/src/components/accounts/Filters.js
index 44c0bf49aed27025e8816309500899dfa5e402bc..1ac95080504b239f70b8f0eb396a3f3c04e5ee6e 100644
--- a/packages/desktop-client/src/components/accounts/Filters.js
+++ b/packages/desktop-client/src/components/accounts/Filters.js
@@ -149,7 +149,11 @@ function ConfigureField({ field, op, value, dispatch, onApply }) {
                       ['amount-outflow', 'Amount (outflow)']
                     ]
                   : field === 'date'
-                  ? [['date', 'Date'], ['month', 'Month'], ['year', 'Year']]
+                  ? [
+                      ['date', 'Date'],
+                      ['month', 'Month'],
+                      ['year', 'Year']
+                    ]
                   : null
               }
               value={subfield}
diff --git a/packages/desktop-client/src/components/manager/ManagementApp.js b/packages/desktop-client/src/components/manager/ManagementApp.js
index bbf702ae13dc23c9b70590f678cf8ddc5071113d..cc737890c7743e0fa31c164240fc987453683f20 100644
--- a/packages/desktop-client/src/components/manager/ManagementApp.js
+++ b/packages/desktop-client/src/components/manager/ManagementApp.js
@@ -230,17 +230,14 @@ class ManagementApp extends React.Component {
   }
 }
 
-export default connect(
-  state => {
-    let { modalStack } = state.modals;
-
-    return {
-      files: state.budgets.allFiles,
-      userData: state.user.data,
-      managerHasInitialized: state.app.managerHasInitialized,
-      loadingText: state.app.loadingText,
-      currentModals: modalStack.map(modal => modal.name)
-    };
-  },
-  actions
-)(ManagementApp);
+export default connect(state => {
+  let { modalStack } = state.modals;
+
+  return {
+    files: state.budgets.allFiles,
+    userData: state.user.data,
+    managerHasInitialized: state.app.managerHasInitialized,
+    loadingText: state.app.loadingText,
+    currentModals: modalStack.map(modal => modal.name)
+  };
+}, actions)(ManagementApp);
diff --git a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.js b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.js
index cc50b4e9d38c0e0c094a7dea507ce30eaaccaa6f..80601fe198c63751786e34ba1233760f2da6ea07 100644
--- a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.js
+++ b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.js
@@ -69,10 +69,7 @@ export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) {
         </label>
         <View style={{ flex: 1 }} />
         {buttons}
-        <ButtonWithLoading
-          primary
-          loading={loading}
-        >
+        <ButtonWithLoading primary loading={loading}>
           OK
         </ButtonWithLoading>
       </View>
diff --git a/packages/desktop-client/src/components/modals/WelcomeScreen.js b/packages/desktop-client/src/components/modals/WelcomeScreen.js
index 772f36199b271f185715b54653a59a9315390f69..bc2094db6e6d6a012ddc61ac9164ab3738682245 100644
--- a/packages/desktop-client/src/components/modals/WelcomeScreen.js
+++ b/packages/desktop-client/src/components/modals/WelcomeScreen.js
@@ -70,7 +70,4 @@ function WelcomeScreen({ modalProps, actions }) {
   );
 }
 
-export default connect(
-  null,
-  actions
-)(WelcomeScreen);
+export default connect(null, actions)(WelcomeScreen);
diff --git a/packages/desktop-client/src/components/reports/Change.js b/packages/desktop-client/src/components/reports/Change.js
index 21b3aab3cf20ae58165fecc3c7b4f35c8550d6d6..61e9a373d96801194b27beeec2ecda8fe7bbbb0d 100644
--- a/packages/desktop-client/src/components/reports/Change.js
+++ b/packages/desktop-client/src/components/reports/Change.js
@@ -2,7 +2,7 @@ import React from 'react';
 import { styles } from 'loot-design/src/style';
 import { integerToCurrency } from 'loot-core/src/shared/util';
 import { Block } from 'loot-design/src/components/common';
-import { colors } from 'loot-design/src/style'
+import { colors } from 'loot-design/src/style';
 
 function Change({ amount, style }) {
   return (
diff --git a/packages/desktop-client/src/components/reports/Overview.js b/packages/desktop-client/src/components/reports/Overview.js
index 5e2ba9313a9889f510e92c658b821a73bd2c6f86..2366656130d67e4e1c25a647dcb9c28102140811 100644
--- a/packages/desktop-client/src/components/reports/Overview.js
+++ b/packages/desktop-client/src/components/reports/Overview.js
@@ -110,7 +110,10 @@ function CashFlowCard() {
   const end = monthUtils.currentDay();
   const start = monthUtils.currentMonth() + '-01';
 
-  const data = useReport('cash_flow_simple', useArgsMemo(simpleCashFlow)(start, end));
+  const data = useReport(
+    'cash_flow_simple',
+    useArgsMemo(simpleCashFlow)(start, end)
+  );
   if (!data) {
     return null;
   }
@@ -218,9 +221,9 @@ function CashFlowCard() {
 function Overview({ accounts }) {
   return (
     <View
-    style={[
-      styles.page,
-      { paddingLeft: 40, paddingRight: 40, minWidth: 700 }
+      style={[
+        styles.page,
+        { paddingLeft: 40, paddingRight: 40, minWidth: 700 }
       ]}
     >
       <View
diff --git a/packages/desktop-client/src/components/tutorial/BudgetInitial.js b/packages/desktop-client/src/components/tutorial/BudgetInitial.js
index 1b07883c9fac7c7153ee1999349d4f19530cba72..4e1b577b6292cbfde3c2354bd5d1a8f4882b3a3d 100644
--- a/packages/desktop-client/src/components/tutorial/BudgetInitial.js
+++ b/packages/desktop-client/src/components/tutorial/BudgetInitial.js
@@ -15,9 +15,9 @@ function BudgetInitial({ accounts, navigationProps }) {
       {!minimized && (
         <React.Fragment>
           <P>
-            You should see all of your current accounts' balance available
-            to budget. Click on the budgeted column for a category create a
-            budget. Keep doing this until your "To Budget" amount is zero.
+            You should see all of your current accounts' balance available to
+            budget. Click on the budgeted column for a category create a budget.
+            Keep doing this until your "To Budget" amount is zero.
           </P>
           <P>
             Don't worry too much about your initial budget. Just guess. You'll
diff --git a/packages/desktop-client/src/components/tutorial/BudgetNextMonth.js b/packages/desktop-client/src/components/tutorial/BudgetNextMonth.js
index 60904aea59a6b452369fd859b82870ca7df1952b..089ac9be920ebbe7016302a73b44cc953c48e83a 100644
--- a/packages/desktop-client/src/components/tutorial/BudgetNextMonth.js
+++ b/packages/desktop-client/src/components/tutorial/BudgetNextMonth.js
@@ -61,7 +61,6 @@ function BudgetNextMonth({ stepTwo, navigationProps }) {
   );
 }
 
-export default connect(
-  null,
-  dispatch => bindActionCreators(actions, dispatch)
-)(BudgetNextMonth);
+export default connect(null, dispatch => bindActionCreators(actions, dispatch))(
+  BudgetNextMonth
+);
diff --git a/packages/desktop-client/src/components/tutorial/CategoryBalance.js b/packages/desktop-client/src/components/tutorial/CategoryBalance.js
index 76d983570802b2218fb8060d2c49f4a4f503dab7..5a3da2235ef1fe3f507e23976aa3c2a79d0c6dcb 100644
--- a/packages/desktop-client/src/components/tutorial/CategoryBalance.js
+++ b/packages/desktop-client/src/components/tutorial/CategoryBalance.js
@@ -5,7 +5,7 @@ import { styles, colors } from 'loot-design/src/style';
 import { Standalone, Title, useMinimized } from './common';
 
 function CategoryBalance({ targetRect, navigationProps }) {
-  let [minimized, toggle] = useMinimized()
+  let [minimized, toggle] = useMinimized();
 
   return (
     <Standalone>
diff --git a/packages/desktop-client/src/components/tutorial/Overspending.js b/packages/desktop-client/src/components/tutorial/Overspending.js
index a1e3bef5783f4ef87cbc60f189d47f957e77e3a8..68f4188670d8091a43e84dfca3eae0c339bb94b3 100644
--- a/packages/desktop-client/src/components/tutorial/Overspending.js
+++ b/packages/desktop-client/src/components/tutorial/Overspending.js
@@ -96,7 +96,6 @@ function Overspending({ navigationProps, stepTwo }) {
   );
 }
 
-export default connect(
-  null,
-  dispatch => bindActionCreators(actions, dispatch)
-)(Overspending);
+export default connect(null, dispatch => bindActionCreators(actions, dispatch))(
+  Overspending
+);
diff --git a/packages/desktop-client/src/components/tutorial/TransactionAdd.js b/packages/desktop-client/src/components/tutorial/TransactionAdd.js
index e812656b9741242a79cf9515ab5e5a6d83af47f9..99738c3ef48acad04d19ac83ec0bfb093c37645d 100644
--- a/packages/desktop-client/src/components/tutorial/TransactionAdd.js
+++ b/packages/desktop-client/src/components/tutorial/TransactionAdd.js
@@ -33,8 +33,8 @@ function TransactionAdd({ targetRect, navigationProps }) {
         </P>
 
         <P isLast={true}>
-          Try <strong>clicking "Add New"</strong> to see how adding
-          transactions affects your budget.
+          Try <strong>clicking "Add New"</strong> to see how adding transactions
+          affects your budget.
         </P>
 
         <Navigation {...navigationProps} showBack={false} />
diff --git a/packages/desktop-client/src/components/tutorial/TransactionFinalize.js b/packages/desktop-client/src/components/tutorial/TransactionFinalize.js
index b702edf1ce2a4124a14d6bdf4e779121ff9d4de7..0a27f7fca0b740b022c1347043ed151f2d38ea1c 100644
--- a/packages/desktop-client/src/components/tutorial/TransactionFinalize.js
+++ b/packages/desktop-client/src/components/tutorial/TransactionFinalize.js
@@ -3,7 +3,7 @@ import { P } from 'loot-design/src/components/common';
 import { css } from 'glamor';
 import Navigation from './Navigation';
 import * as monthUtils from 'loot-core/src/shared/months';
-import {Standalone} from './common';
+import { Standalone } from './common';
 
 function TransactionFinalize({ navigationProps }) {
   return (
diff --git a/packages/loot-core/package.json b/packages/loot-core/package.json
index ab0eb87b729f8ac25480f69ce07c16a04135be97..e2784effd3fd132c6778b8515cf4271f71e58368 100644
--- a/packages/loot-core/package.json
+++ b/packages/loot-core/package.json
@@ -47,6 +47,7 @@
     "damerau-levenshtein": "^1.0.4",
     "date-fns": "2.0.0-alpha.27",
     "eslint": "5.6.0",
+    "eslint-plugin-prettier": "^3.1.4",
     "esm": "^3.0.82",
     "fake-indexeddb": "^3.1.3",
     "fast-check": "^2.11.0",
@@ -60,6 +61,7 @@
     "mockdate": "^3.0.5",
     "murmurhash": "^0.0.2",
     "perf-deets": "^1.0.15",
+    "prettier": "^1.19.1",
     "sanitize-filename": "^1.6.1",
     "search-query-parser": "^1.3.0",
     "snapshot-diff": "^0.2.2",
diff --git a/packages/loot-core/src/client/actions/debug.js b/packages/loot-core/src/client/actions/debug.js
index e4cda0d9a6c6565b990786da4b6a28b453295592..afa90415e997eeb681bbc919dbbc71773274a7f5 100644
--- a/packages/loot-core/src/client/actions/debug.js
+++ b/packages/loot-core/src/client/actions/debug.js
@@ -5,5 +5,5 @@ export function debugCell(sheet, name) {
     type: constants.DEBUG_CELL,
     sheet,
     name
-  }
+  };
 }
diff --git a/packages/loot-core/src/mocks/budget.js b/packages/loot-core/src/mocks/budget.js
index 7de8781efbe2ef01e28238b7eb1f7646e94162fc..5e03bf4e6079221335643e9d4baf8824307b94b9 100644
--- a/packages/loot-core/src/mocks/budget.js
+++ b/packages/loot-core/src/mocks/budget.js
@@ -439,15 +439,19 @@ async function fillOther(handlers, account, payees, groups) {
 
 async function createBudget(accounts, payees, groups) {
   let primaryAccount = accounts.find(a => (a.name = 'Bank of America'));
-  let earliestDate = (await db.first(
-    `SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
+  let earliestDate = (
+    await db.first(
+      `SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
        WHERE a.offbudget = 0 AND t.is_child = 0 ORDER BY date ASC LIMIT 1`
-  )).date;
-  let earliestPrimaryDate = (await db.first(
-    `SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
+    )
+  ).date;
+  let earliestPrimaryDate = (
+    await db.first(
+      `SELECT * FROM v_transactions t LEFT JOIN accounts a ON t.account = a.id
        WHERE a.id = ? AND a.offbudget = 0 AND t.is_child = 0 ORDER BY date ASC LIMIT 1`,
-    [primaryAccount.id]
-  )).date;
+      [primaryAccount.id]
+    )
+  ).date;
 
   let start = monthUtils.monthFromDate(db.fromDateRepr(earliestDate));
   let end = monthUtils.currentMonth();
diff --git a/packages/loot-core/src/platform/client/fetch/index.browser.js b/packages/loot-core/src/platform/client/fetch/index.browser.js
index 32f445c757c26d414efdecde2447666dd713a5bb..a375a3a0ce9b7010e03d0ccf5121230a0e146a38 100644
--- a/packages/loot-core/src/platform/client/fetch/index.browser.js
+++ b/packages/loot-core/src/platform/client/fetch/index.browser.js
@@ -172,7 +172,10 @@ module.exports.listen = function listen(name, cb) {
 
   return () => {
     let arr = listeners.get(name);
-    listeners.set(name, arr.filter(cb_ => cb_ !== cb));
+    listeners.set(
+      name,
+      arr.filter(cb_ => cb_ !== cb)
+    );
   };
 };
 
diff --git a/packages/loot-core/src/platform/client/fetch/index.mobile.js b/packages/loot-core/src/platform/client/fetch/index.mobile.js
index 14df5f4d855e0cd2c0c2f99f8cecce295b6e543a..133a09037ab6025311bb271eba178e3c050f5859 100644
--- a/packages/loot-core/src/platform/client/fetch/index.mobile.js
+++ b/packages/loot-core/src/platform/client/fetch/index.mobile.js
@@ -82,7 +82,10 @@ function listen(name, cb) {
 
   return () => {
     let arr = listeners.get(name);
-    listeners.set(name, arr.filter(cb_ => cb_ !== cb));
+    listeners.set(
+      name,
+      arr.filter(cb_ => cb_ !== cb)
+    );
   };
 }
 
diff --git a/packages/loot-core/src/platform/client/fetch/index.testing.js b/packages/loot-core/src/platform/client/fetch/index.testing.js
index 7664d5b4355c78da3f0fd25d17af9f48994adeee..bef3633b8e91b7fa198c1abe522f9dfb36629e68 100644
--- a/packages/loot-core/src/platform/client/fetch/index.testing.js
+++ b/packages/loot-core/src/platform/client/fetch/index.testing.js
@@ -56,6 +56,9 @@ module.exports.listen = function listen(name, cb) {
 
   return () => {
     let arr = listeners.get(name);
-    listeners.set(name, arr.filter(cb_ => cb_ !== cb));
+    listeners.set(
+      name,
+      arr.filter(cb_ => cb_ !== cb)
+    );
   };
 };
diff --git a/packages/loot-core/src/platform/client/fetch/index.web.js b/packages/loot-core/src/platform/client/fetch/index.web.js
index d50b8f093f407a29776209f4ea51baf7d7e9c83b..37d8880edeb16b2a5634c00a24108fbe3140c854 100644
--- a/packages/loot-core/src/platform/client/fetch/index.web.js
+++ b/packages/loot-core/src/platform/client/fetch/index.web.js
@@ -117,7 +117,10 @@ module.exports.listen = function listen(name, cb) {
   return () => {
     let arr = listeners.get(name);
     if (arr) {
-      listeners.set(name, arr.filter(cb_ => cb_ !== cb));
+      listeners.set(
+        name,
+        arr.filter(cb_ => cb_ !== cb)
+      );
     }
   };
 };
diff --git a/packages/loot-core/src/platform/exceptions/index.testing.js b/packages/loot-core/src/platform/exceptions/index.testing.js
index 670d02154e295e2bd369b2e15e8f889a0c72e794..cc1a66bfacd5e71666b8a5eac248b958d5a69a84 100644
--- a/packages/loot-core/src/platform/exceptions/index.testing.js
+++ b/packages/loot-core/src/platform/exceptions/index.testing.js
@@ -1,5 +1,3 @@
-export function captureException(exc) {
-}
+export function captureException(exc) {}
 
-export function captureBreadcrumb(info) {
-}
+export function captureBreadcrumb(info) {}
diff --git a/packages/loot-core/src/platform/server/fs/index.web.js b/packages/loot-core/src/platform/server/fs/index.web.js
index a819f0ec6aa32d7f4acf3426c0b48fe6d54f9ed1..591824f745c1bab5501780511b378ecdb20b9c07 100644
--- a/packages/loot-core/src/platform/server/fs/index.web.js
+++ b/packages/loot-core/src/platform/server/fs/index.web.js
@@ -167,9 +167,9 @@ async function _removeFile(filepath) {
 
 // Load files from the server that should exist by default
 async function populateDefaultFilesystem() {
-  let index = await (await fetch(
-    process.env.PUBLIC_URL + 'data-file-index.txt'
-  )).text();
+  let index = await (
+    await fetch(process.env.PUBLIC_URL + 'data-file-index.txt')
+  ).text();
   let files = index
     .split('\n')
     .map(name => name.trim())
diff --git a/packages/loot-core/src/server/accounts/link.js b/packages/loot-core/src/server/accounts/link.js
index 9d65b416ec15b3f298e31ca6c1a7bbc1c2349970..7f97be6b1754a68286e5990aaf9a6b3653192ebd 100644
--- a/packages/loot-core/src/server/accounts/link.js
+++ b/packages/loot-core/src/server/accounts/link.js
@@ -1,6 +1,6 @@
 import asyncStorage from '../../platform/server/asyncStorage';
 import * as db from '../db';
-import { getServer  } from '../server-config';
+import { getServer } from '../server-config';
 import * as bankSync from './sync';
 import { fromPlaidAccountType } from '../../shared/accounts';
 import { amountToInteger } from '../../shared/util';
diff --git a/packages/loot-core/src/server/accounts/title/lower-case.js b/packages/loot-core/src/server/accounts/title/lower-case.js
index 3ad022ef5ad6a8956934070995f1382df18d4770..ab90383dd290cb129562bf1043573060cf1bf81f 100644
--- a/packages/loot-core/src/server/accounts/title/lower-case.js
+++ b/packages/loot-core/src/server/accounts/title/lower-case.js
@@ -1,18 +1,18 @@
 const conjunctions = [
-  'for',
+  'for', //
   'and',
   'nor',
   'but',
   'or',
   'yet',
   'so'
-]
+];
 
 const articles = [
-  'a',
+  'a', //
   'an',
   'the'
-]
+];
 
 const prepositions = [
   'aboard',
@@ -84,10 +84,6 @@ const prepositions = [
   'with',
   'within',
   'without'
-]
+];
 
-module.exports = new Set([
-  ...conjunctions,
-  ...articles,
-  ...prepositions
-])
+module.exports = new Set([...conjunctions, ...articles, ...prepositions]);
diff --git a/packages/loot-core/src/server/accounts/transactions.js b/packages/loot-core/src/server/accounts/transactions.js
index 235d54cb032cf76fca200a9de6e60429d586d4af..092379e5286f520e82e938e94ae6e5bc992139a6 100644
--- a/packages/loot-core/src/server/accounts/transactions.js
+++ b/packages/loot-core/src/server/accounts/transactions.js
@@ -116,9 +116,9 @@ export async function batchUpdateTransactions({
     await Promise.all(allAdded.map(t => transfer.onInsert(t)));
 
     // Return any updates from here
-    resultUpdated = (await Promise.all(
-      allUpdated.map(t => transfer.onUpdate(t))
-    )).filter(Boolean);
+    resultUpdated = (
+      await Promise.all(allUpdated.map(t => transfer.onUpdate(t)))
+    ).filter(Boolean);
 
     await Promise.all(allDeleted.map(t => transfer.onDelete(t)));
   });
diff --git a/packages/loot-core/src/server/accounts/transfer.js b/packages/loot-core/src/server/accounts/transfer.js
index 19228da6a23496dd7bbf6e88fdc53ec3d9add5d1..716c8fe40034547e0820137d5ae55d9e6d782c1d 100644
--- a/packages/loot-core/src/server/accounts/transfer.js
+++ b/packages/loot-core/src/server/accounts/transfer.js
@@ -6,24 +6,28 @@ async function getPayee(acct) {
 
 async function getTransferredAccount(transaction) {
   if (transaction.payee) {
-    let { transfer_acct, id } = await db.first(
-      'SELECT id, transfer_acct FROM v_payees WHERE id = ?',
-      [transaction.payee]
-    );
+    let {
+      transfer_acct,
+      id
+    } = await db.first('SELECT id, transfer_acct FROM v_payees WHERE id = ?', [
+      transaction.payee
+    ]);
     return transfer_acct;
   }
   return null;
 }
 
 async function clearCategory(transaction, transferAcct) {
-  const { offbudget: fromOffBudget } = await db.first(
-    'SELECT offbudget FROM accounts WHERE id = ?',
-    [transaction.account]
-  );
-  const { offbudget: toOffBudget } = await db.first(
-    'SELECT offbudget FROM accounts WHERE id = ?',
-    [transferAcct]
-  );
+  const {
+    offbudget: fromOffBudget
+  } = await db.first('SELECT offbudget FROM accounts WHERE id = ?', [
+    transaction.account
+  ]);
+  const {
+    offbudget: toOffBudget
+  } = await db.first('SELECT offbudget FROM accounts WHERE id = ?', [
+    transferAcct
+  ]);
 
   // We should clear the category to make sure it's not being
   // accounted for in the budget, unless it should be in the case of
@@ -36,10 +40,11 @@ async function clearCategory(transaction, transferAcct) {
 }
 
 export async function addTransfer(transaction, transferredAccount) {
-  let { id: fromPayee } = await db.first(
-    'SELECT id FROM payees WHERE transfer_acct = ?',
-    [transaction.account]
-  );
+  let {
+    id: fromPayee
+  } = await db.first('SELECT id FROM payees WHERE transfer_acct = ?', [
+    transaction.account
+  ]);
 
   // We need to enforce certain constraints with child transaction transfers
   if (transaction.parent_id) {
diff --git a/packages/loot-core/src/server/aql/exec.test.js b/packages/loot-core/src/server/aql/exec.test.js
index c447ac3911d5187cbddc3c68f696d8254296d062..f64ab128c6c31ef27f386a3231a7ab71dbd5f24d 100644
--- a/packages/loot-core/src/server/aql/exec.test.js
+++ b/packages/loot-core/src/server/aql/exec.test.js
@@ -81,28 +81,34 @@ describe('runQuery', () => {
     expect(data[0].date).toBe('2020-01-04');
 
     // date-month
-    data = (await runQuery(
-      query('transactions')
-        .select({ month: { $month: '$date' } })
-        .serialize()
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .select({ month: { $month: '$date' } })
+          .serialize()
+      )
+    ).data;
     expect(data[0].month).toBe('2020-01');
 
     // date-year
-    data = (await runQuery(
-      query('transactions')
-        .select({ year: { $year: '$date' } })
-        .serialize()
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .select({ year: { $year: '$date' } })
+          .serialize()
+      )
+    ).data;
     expect(data[0].year).toBe('2020');
 
     // boolean
-    data = (await runQuery(
-      query('transactions')
-        .select(['is_child', 'is_parent'])
-        .raw()
-        .serialize()
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .select(['is_child', 'is_parent'])
+          .raw()
+          .serialize()
+      )
+    ).data;
     expect(data[0].is_child).toBe(false);
     expect(data[0].is_parent).toBe(true);
     expect(data[1].is_child).toBe(true);
@@ -128,31 +134,37 @@ describe('runQuery', () => {
     );
     expect(data[0].id).toBe(transId);
 
-    data = (await runQuery(
-      query('transactions')
-        .filter({ date: { $transform: '$month', $eq: { $month: ':month' } } })
-        .select('date')
-        .serialize(),
-      { params: { month: '2020-01-02' } }
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .filter({ date: { $transform: '$month', $eq: { $month: ':month' } } })
+          .select('date')
+          .serialize(),
+        { params: { month: '2020-01-02' } }
+      )
+    ).data;
     expect(data[0].id).toBe(transId);
 
-    data = (await runQuery(
-      query('transactions')
-        .filter({ date: { $transform: '$year', $eq: { $year: ':month' } } })
-        .select('date')
-        .serialize(),
-      { params: { month: '2020-01-02' } }
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .filter({ date: { $transform: '$year', $eq: { $year: ':month' } } })
+          .select('date')
+          .serialize(),
+        { params: { month: '2020-01-02' } }
+      )
+    ).data;
     expect(data[0].id).toBe(transId);
 
-    data = (await runQuery(
-      query('transactions')
-        .filter({ cleared: ':cleared' })
-        .select('date')
-        .serialize(),
-      { params: { cleared: true } }
-    )).data;
+    data = (
+      await runQuery(
+        query('transactions')
+          .filter({ cleared: ':cleared' })
+          .select('date')
+          .serialize(),
+        { params: { cleared: true } }
+      )
+    ).data;
     expect(data[0].id).toBe(transId);
   });
 
diff --git a/packages/loot-core/src/server/aql/schema/executors.js b/packages/loot-core/src/server/aql/schema/executors.js
index 8df751b7c7e488187be1ad63d58a330582171cf7..5ab925f9c97f5cc1b638d5e6404d07a28b4850be 100644
--- a/packages/loot-core/src/server/aql/schema/executors.js
+++ b/packages/loot-core/src/server/aql/schema/executors.js
@@ -142,7 +142,10 @@ async function execTransactionsGrouped(
 
     rows = await db.all(rowSql, params);
     matched = new Set(
-      [].concat.apply([], rows.map(row => row.matched.split(',')))
+      [].concat.apply(
+        [],
+        rows.map(row => row.matched.split(','))
+      )
     );
   }
 
diff --git a/packages/loot-core/src/server/aql/schema/index.test.js b/packages/loot-core/src/server/aql/schema/index.test.js
index 2704b76b037ad16a5aa68e3eeb28c71837b89879..8b543e3a5ca167961def9f7ecb3d334b686690ed 100644
--- a/packages/loot-core/src/server/aql/schema/index.test.js
+++ b/packages/loot-core/src/server/aql/schema/index.test.js
@@ -10,7 +10,7 @@ describe('schema', () => {
   test('never returns transactions without a date', async () => {
     expect((await db.all('SELECT * FROM transactions')).length).toBe(0);
     expect((await db.all('SELECT * FROM v_transactions')).length).toBe(0);
-    await db.runQuery('INSERT INTO transactions (acct) VALUES (?)', ["foo"]);
+    await db.runQuery('INSERT INTO transactions (acct) VALUES (?)', ['foo']);
     expect((await db.all('SELECT * FROM transactions')).length).toBe(1);
     expect((await db.all('SELECT * FROM v_transactions')).length).toBe(0);
   });
@@ -28,7 +28,7 @@ describe('schema', () => {
     expect((await db.all('SELECT * FROM v_transactions')).length).toBe(0);
     await db.runQuery(
       'INSERT INTO transactions (date, acct, isChild) VALUES (?, ?, ?)',
-      [20200101, "foo", 1]
+      [20200101, 'foo', 1]
     );
     expect((await db.all('SELECT * FROM transactions')).length).toBe(1);
     expect((await db.all('SELECT * FROM v_transactions')).length).toBe(0);
diff --git a/packages/loot-core/src/server/budget/app.js b/packages/loot-core/src/server/budget/app.js
index 3867ea3b9dbf41de63212d1b434c523f57fcaa2b..2ef9ea936902ae1becbbe81208098d51ee6dc689 100644
--- a/packages/loot-core/src/server/budget/app.js
+++ b/packages/loot-core/src/server/budget/app.js
@@ -3,7 +3,6 @@ import { mutator } from '../mutators';
 import { undoable } from '../undo';
 import * as actions from './actions';
 
-
 let app = createApp();
 
 app.method('budget/budget-amount', mutator(undoable(actions.setBudget)));
diff --git a/packages/loot-core/src/server/budget/util.js b/packages/loot-core/src/server/budget/util.js
index 8cc208c3d1968e7dc24dea55e6f142e5cd320deb..ae1a2887e0a717c3b5515a27d4fcb4170fe15429 100644
--- a/packages/loot-core/src/server/budget/util.js
+++ b/packages/loot-core/src/server/budget/util.js
@@ -19,4 +19,3 @@ export function unflatten2(arr) {
   }
   return res;
 }
-
diff --git a/packages/loot-core/src/server/crdt/index.js b/packages/loot-core/src/server/crdt/index.js
index a62ee7991c6fc2eb612b9588d3f8e43e0fdc3b8a..ce714a60b95365bab9ea3b857c67a14864d0d3a5 100644
--- a/packages/loot-core/src/server/crdt/index.js
+++ b/packages/loot-core/src/server/crdt/index.js
@@ -1,4 +1,12 @@
-import * as merkle from "./merkle";
+import * as merkle from './merkle';
 
 export { merkle };
-export { getClock, setClock, makeClock, makeClientId, serializeClock, deserializeClock, Timestamp } from "./timestamp"
+export {
+  getClock,
+  setClock,
+  makeClock,
+  makeClientId,
+  serializeClock,
+  deserializeClock,
+  Timestamp
+} from './timestamp';
diff --git a/packages/loot-core/src/server/main.js b/packages/loot-core/src/server/main.js
index cbda0e7fb24dd311b5691153cf9f678cc5b6c2df..ac80260f6fb17fb5443d8ea90ee65cf39854cbbd 100644
--- a/packages/loot-core/src/server/main.js
+++ b/packages/loot-core/src/server/main.js
@@ -30,7 +30,16 @@ import * as bankSync from './accounts/sync';
 import * as link from './accounts/link';
 import { uniqueFileName, idFromFileName } from './util/budget-name';
 import { mutator, runHandler } from './mutators';
-import { getClock, setClock, makeClock, makeClientId, serializeClock, deserializeClock, Timestamp, merkle } from './crdt';
+import {
+  getClock,
+  setClock,
+  makeClock,
+  makeClientId,
+  serializeClock,
+  deserializeClock,
+  Timestamp,
+  merkle
+} from './crdt';
 import {
   initialFullSync,
   fullSync,
@@ -414,7 +423,10 @@ handlers['category-group-delete'] = mutator(async function({ id, transferId }) {
 
     return batchMessages(async () => {
       if (transferId) {
-        await budget.doTransfer(groupCategories.map(c => c.id), transferId);
+        await budget.doTransfer(
+          groupCategories.map(c => c.id),
+          transferId
+        );
       }
       await db.deleteCategoryGroup({ id }, transferId);
     });
@@ -759,11 +771,15 @@ handlers['accounts-get'] = async function() {
 };
 
 handlers['account-properties'] = async function({ id }) {
-  const { balance } = await db.first(
+  const {
+    balance
+  } = await db.first(
     'SELECT sum(amount) as balance FROM transactions WHERE acct = ? AND isParent = 0 AND tombstone = 0',
     [id]
   );
-  const { count } = await db.first(
+  const {
+    count
+  } = await db.first(
     'SELECT count(id) as count FROM transactions WHERE acct = ? AND tombstone = 0',
     [id]
   );
@@ -902,10 +918,9 @@ handlers['account-close'] = mutator(async function({
         true
       );
 
-      let { id: payeeId } = await db.first(
-        'SELECT id FROM payees WHERE transfer_acct = ?',
-        [id]
-      );
+      let {
+        id: payeeId
+      } = await db.first('SELECT id FROM payees WHERE transfer_acct = ?', [id]);
 
       await batchMessages(() => {
         // TODO: what this should really do is send a special message that
@@ -939,10 +954,11 @@ handlers['account-close'] = mutator(async function({
       // If there is a balance we need to transfer it to the specified
       // account (and possibly categorize it)
       if (balance !== 0) {
-        let { id: payeeId } = await db.first(
-          'SELECT id FROM payees WHERE transfer_acct = ?',
-          [transferAccountId]
-        );
+        let {
+          id: payeeId
+        } = await db.first('SELECT id FROM payees WHERE transfer_acct = ?', [
+          transferAccountId
+        ]);
 
         await handlers['transaction-add']({
           id: uuid.v4Sync(),
@@ -1082,9 +1098,7 @@ handlers['accounts-sync'] = async function({ id }) {
         } else if (err instanceof PostError && err.reason !== 'internal') {
           errors.push({
             accountId: acct.id,
-            message: `Account "${
-              acct.name
-            }" is not linked properly. Please link it again`
+            message: `Account "${acct.name}" is not linked properly. Please link it again`
           });
         } else {
           errors.push({
@@ -1134,10 +1148,9 @@ handlers['transactions-import'] = mutator(function({
 });
 
 handlers['account-unlink'] = mutator(async function({ id }) {
-  let { bank: bankId } = await db.first(
-    'SELECT bank FROM accounts WHERE id = ?',
-    [id]
-  );
+  let {
+    bank: bankId
+  } = await db.first('SELECT bank FROM accounts WHERE id = ?', [id]);
 
   if (!bankId) {
     return 'ok';
@@ -1152,10 +1165,11 @@ handlers['account-unlink'] = mutator(async function({ id }) {
     balance_limit: null
   });
 
-  let { count } = await db.first(
-    'SELECT COUNT(*) as count FROM accounts WHERE bank = ?',
-    [bankId]
-  );
+  let {
+    count
+  } = await db.first('SELECT COUNT(*) as count FROM accounts WHERE bank = ?', [
+    bankId
+  ]);
 
   if (count === 0) {
     // No more accounts are associated with this bank. We can remove
@@ -1545,35 +1559,37 @@ handlers['get-version'] = async function() {
 
 handlers['get-budgets'] = async function() {
   const paths = await fs.listDir(fs.getDocumentDir());
-  const budgets = (await Promise.all(
-    paths.map(async name => {
-      const prefsPath = fs.join(fs.getDocumentDir(), name, 'metadata.json');
-      if (await fs.exists(prefsPath)) {
-        let prefs;
-        try {
-          prefs = JSON.parse(await fs.readFile(prefsPath));
-        } catch (e) {
-          console.log('Error parsing metadata:', e.stack);
-          return;
-        }
+  const budgets = (
+    await Promise.all(
+      paths.map(async name => {
+        const prefsPath = fs.join(fs.getDocumentDir(), name, 'metadata.json');
+        if (await fs.exists(prefsPath)) {
+          let prefs;
+          try {
+            prefs = JSON.parse(await fs.readFile(prefsPath));
+          } catch (e) {
+            console.log('Error parsing metadata:', e.stack);
+            return;
+          }
 
-        // We treat the directory name as the canonical id so that if
-        // the user moves it around/renames/etc, nothing breaks. The
-        // id is stored in prefs just for convenience (and the prefs
-        // will always update to the latest given id)
-        if (name !== DEMO_BUDGET_ID) {
-          return {
-            id: name,
-            cloudFileId: prefs.cloudFileId,
-            groupId: prefs.groupId,
-            name: prefs.budgetName || '(no name)'
-          };
+          // We treat the directory name as the canonical id so that if
+          // the user moves it around/renames/etc, nothing breaks. The
+          // id is stored in prefs just for convenience (and the prefs
+          // will always update to the latest given id)
+          if (name !== DEMO_BUDGET_ID) {
+            return {
+              id: name,
+              cloudFileId: prefs.cloudFileId,
+              groupId: prefs.groupId,
+              name: prefs.budgetName || '(no name)'
+            };
+          }
         }
-      }
 
-      return null;
-    })
-  )).filter(x => x);
+        return null;
+      })
+    )
+  ).filter(x => x);
 
   return budgets;
 };
@@ -2253,7 +2269,13 @@ export const lib = {
   // Expose CRDT mechanisms so server can use them
   merkle,
   timestamp: {
-    getClock, setClock, makeClock, makeClientId, serializeClock, deserializeClock, Timestamp
+    getClock,
+    setClock,
+    makeClock,
+    makeClientId,
+    serializeClock,
+    deserializeClock,
+    Timestamp
   },
   SyncProtoBuf: SyncPb
 };
diff --git a/packages/loot-core/src/server/polyfills.mobile.js b/packages/loot-core/src/server/polyfills.mobile.js
index 2a5bf61b6ce961b8476b29dcd90561fdb8d6b34f..895dd8c7cc5ecd41012b0d0b5cb489b133e454f4 100644
--- a/packages/loot-core/src/server/polyfills.mobile.js
+++ b/packages/loot-core/src/server/polyfills.mobile.js
@@ -1,2 +1,2 @@
 // Mobile needs this
-import 'core-js/modules/es.object.from-entries'
+import 'core-js/modules/es.object.from-entries';
diff --git a/packages/loot-core/src/server/schedules/app.test.js b/packages/loot-core/src/server/schedules/app.test.js
index bf744d9d63b234ea94b11a9a2e219c889987fd58..916244cb568cafee97058e73e861baf7de0ed7eb 100644
--- a/packages/loot-core/src/server/schedules/app.test.js
+++ b/packages/loot-core/src/server/schedules/app.test.js
@@ -71,7 +71,10 @@ describe('schedule app', () => {
           value: {
             start: '2020-12-20',
             frequency: 'monthly',
-            patterns: [{ type: 'day', value: 15 }, { type: 'day', value: 30 }]
+            patterns: [
+              { type: 'day', value: 15 },
+              { type: 'day', value: 30 }
+            ]
           }
         })
       ).toBe('2021-05-30');
@@ -88,7 +91,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 15 }, { type: 'day', value: 30 }]
+              patterns: [
+                { type: 'day', value: 15 },
+                { type: 'day', value: 30 }
+              ]
             }
           }
         ]
@@ -123,7 +129,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 15 }, { type: 'day', value: 30 }]
+              patterns: [
+                { type: 'day', value: 15 },
+                { type: 'day', value: 30 }
+              ]
             }
           }
         ]
@@ -150,7 +159,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 18 }, { type: 'day', value: 29 }]
+              patterns: [
+                { type: 'day', value: 18 },
+                { type: 'day', value: 29 }
+              ]
             }
           }
         ]
@@ -177,7 +189,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 15 }, { type: 'day', value: 30 }]
+              patterns: [
+                { type: 'day', value: 15 },
+                { type: 'day', value: 30 }
+              ]
             }
           }
         ]
@@ -200,7 +215,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 15 }, { type: 'day', value: 30 }]
+              patterns: [
+                { type: 'day', value: 15 },
+                { type: 'day', value: 30 }
+              ]
             }
           }
         ]
@@ -222,7 +240,10 @@ describe('schedule app', () => {
             value: {
               start: '2020-12-20',
               frequency: 'monthly',
-              patterns: [{ type: 'day', value: 18 }, { type: 'day', value: 28 }]
+              patterns: [
+                { type: 'day', value: 18 },
+                { type: 'day', value: 28 }
+              ]
             }
           }
         ]
diff --git a/packages/loot-core/src/server/schedules/find-schedules.js b/packages/loot-core/src/server/schedules/find-schedules.js
index 214e725c2d3ad1739da614658cb35eb7448b7fa1..6432f0b207c000ea939be889228faaf38830ec01 100644
--- a/packages/loot-core/src/server/schedules/find-schedules.js
+++ b/packages/loot-core/src/server/schedules/find-schedules.js
@@ -219,7 +219,10 @@ async function monthly1stor3rd(startDate, accountId) {
       return {
         start,
         frequency: 'monthly',
-        patterns: [{ type: dayValue, value: 1 }, { type: dayValue, value: 3 }]
+        patterns: [
+          { type: dayValue, value: 1 },
+          { type: dayValue, value: 3 }
+        ]
       };
     },
     accountId
@@ -237,7 +240,10 @@ async function monthly2ndor4th(startDate, accountId) {
       return {
         start,
         frequency: 'monthly',
-        patterns: [{ type: dayValue, value: 2 }, { type: dayValue, value: 4 }]
+        patterns: [
+          { type: dayValue, value: 2 },
+          { type: dayValue, value: 4 }
+        ]
       };
     },
     accountId
diff --git a/packages/loot-core/src/server/spreadsheet/new/parser.js b/packages/loot-core/src/server/spreadsheet/new/parser.js
index f190a60472ffe08234edcf4d7224684ead570959..2bf3b04919a4b5b661fd2846f8214c21a484710f 100644
--- a/packages/loot-core/src/server/spreadsheet/new/parser.js
+++ b/packages/loot-core/src/server/spreadsheet/new/parser.js
@@ -363,7 +363,7 @@ function parsePostfix(state, node) {
   while ((tok = nextToken(state))) {
     if (tok.type === types.TOKEN_LEFT_PAREN) {
       pushToken(state, tok);
-      let args = parseArgs(state)
+      let args = parseArgs(state);
       node = new nodes.FunCall(tok.lineno, tok.colno, node, args);
     } else if (tok.type === types.TOKEN_DOT) {
       const val = nextToken(state);
diff --git a/packages/loot-core/src/server/spreadsheet/new/sqlgen.js b/packages/loot-core/src/server/spreadsheet/new/sqlgen.js
index 34eea21778ab34842ba3c8dba928ec66c519c5b3..b076edb82a430c5a7265d3821ae61e13506659b8 100644
--- a/packages/loot-core/src/server/spreadsheet/new/sqlgen.js
+++ b/packages/loot-core/src/server/spreadsheet/new/sqlgen.js
@@ -238,9 +238,7 @@ export default function generate(table, where, groupby, select, deps) {
         joins.push(meta.sql(lookup.tableId));
       } else {
         joins.push(
-          `LEFT JOIN ${meta.table} ${lookup.tableId} ON ${
-            lookup.tableId
-          }.id = ${currentTable.id}.${lookup.field}`
+          `LEFT JOIN ${meta.table} ${lookup.tableId} ON ${lookup.tableId}.id = ${currentTable.id}.${lookup.field}`
         );
       }
 
diff --git a/packages/loot-core/src/server/spreadsheet/new/vm.js b/packages/loot-core/src/server/spreadsheet/new/vm.js
index 20feb5c13ae5a3cb51538160b9604fb247f74f1c..2ddb9026532d9955316ff2318c84afc8bf37a68a 100644
--- a/packages/loot-core/src/server/spreadsheet/new/vm.js
+++ b/packages/loot-core/src/server/spreadsheet/new/vm.js
@@ -74,7 +74,10 @@ export default class VM {
 
   call(callee, args) {
     const func = this.get(callee);
-    this.reg1 = func.apply(null, args.map(arg => this.get(arg)));
+    this.reg1 = func.apply(
+      null,
+      args.map(arg => this.get(arg))
+    );
   }
 
   query(sql, calculated) {
diff --git a/packages/loot-core/src/server/spreadsheet/tests/data-propagation.js b/packages/loot-core/src/server/spreadsheet/tests/data-propagation.js
index 45e73989667ec52b52a4e78877aecb95bb9b0d28..9d8544f45f93c591da8fc5ba570b897b3eb72ba2 100644
--- a/packages/loot-core/src/server/spreadsheet/tests/data-propagation.js
+++ b/packages/loot-core/src/server/spreadsheet/tests/data-propagation.js
@@ -1,10 +1,8 @@
+const expect = require('expect');
+const propagate = require('../data-compute/propagate.js');
 
-
-const expect = require("expect");
-const propagate = require("../data-compute/propagate.js");
-
-describe("data propagation", () => {
-  it("should work", () => {
+describe('data propagation', () => {
+  it('should work', () => {
     expect(true).toExist();
   });
 });
diff --git a/packages/loot-core/src/server/spreadsheet/tests/graph.js b/packages/loot-core/src/server/spreadsheet/tests/graph.js
index dbc8345c15c3715acd1d67138ef80bf5aa1d7e78..c938e09b2e34308d1bdca6f8db2eeb8db54e8c40 100644
--- a/packages/loot-core/src/server/spreadsheet/tests/graph.js
+++ b/packages/loot-core/src/server/spreadsheet/tests/graph.js
@@ -1,308 +1,304 @@
-
 // Unit tests for reactive-property.
-var assert = require("assert");
+var assert = require('assert');
 
 // If using from the NPM package, this line would be
 // var Graph = require("graph-data-structure");
-var Graph = require("../data-compute/graph-data-structure");
+var Graph = require('../data-compute/graph-data-structure');
 
-describe("Graph", function() {
-  describe("Data structure", function() {
-    it("Should add nodes and list them.", function (){
+describe('Graph', function() {
+  describe('Data structure', function() {
+    it('Should add nodes and list them.', function() {
       var graph = Graph();
-      graph.addNode("a");
-      graph.addNode("b");
+      graph.addNode('a');
+      graph.addNode('b');
       assert.equal(graph.nodes().length, 2);
-      assert(contains(graph.nodes(), "a"));
-      assert(contains(graph.nodes(), "b"));
+      assert(contains(graph.nodes(), 'a'));
+      assert(contains(graph.nodes(), 'b'));
     });
 
-    it("Should chain addNode.", function (){
-      var graph = Graph().addNode("a").addNode("b");
+    it('Should chain addNode.', function() {
+      var graph = Graph()
+        .addNode('a')
+        .addNode('b');
       assert.equal(graph.nodes().length, 2);
-      assert(contains(graph.nodes(), "a"));
-      assert(contains(graph.nodes(), "b"));
+      assert(contains(graph.nodes(), 'a'));
+      assert(contains(graph.nodes(), 'b'));
     });
 
-    it("Should remove nodes.", function (){
+    it('Should remove nodes.', function() {
       var graph = Graph();
-      graph.addNode("a");
-      graph.addNode("b");
-      graph.removeNode("a");
-      graph.removeNode("b");
+      graph.addNode('a');
+      graph.addNode('b');
+      graph.removeNode('a');
+      graph.removeNode('b');
       assert.equal(graph.nodes().length, 0);
     });
 
-    it("Should chain removeNode.", function (){
+    it('Should chain removeNode.', function() {
       var graph = Graph()
-        .addNode("a")
-        .addNode("b")
-        .removeNode("a")
-        .removeNode("b");
+        .addNode('a')
+        .addNode('b')
+        .removeNode('a')
+        .removeNode('b');
       assert.equal(graph.nodes().length, 0);
     });
 
-    it("Should add edges and query for adjacent nodes.", function (){
+    it('Should add edges and query for adjacent nodes.', function() {
       var graph = Graph();
-      graph.addNode("a");
-      graph.addNode("b");
-      graph.addEdge("a", "b");
-      assert.equal(graph.adjacent("a").length, 1);
-      assert.equal(graph.adjacent("a")[0], "b");
+      graph.addNode('a');
+      graph.addNode('b');
+      graph.addEdge('a', 'b');
+      assert.equal(graph.adjacent('a').length, 1);
+      assert.equal(graph.adjacent('a')[0], 'b');
     });
 
-    it("Should implicitly add nodes when edges are added.", function (){
+    it('Should implicitly add nodes when edges are added.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      assert.equal(graph.adjacent("a").length, 1);
-      assert.equal(graph.adjacent("a")[0], "b");
+      graph.addEdge('a', 'b');
+      assert.equal(graph.adjacent('a').length, 1);
+      assert.equal(graph.adjacent('a')[0], 'b');
       assert.equal(graph.nodes().length, 2);
-      assert(contains(graph.nodes(), "a"));
-      assert(contains(graph.nodes(), "b"));
+      assert(contains(graph.nodes(), 'a'));
+      assert(contains(graph.nodes(), 'b'));
     });
 
-    it("Should chain addEdge.", function (){
-      var graph = Graph().addEdge("a", "b");
-      assert.equal(graph.adjacent("a").length, 1);
-      assert.equal(graph.adjacent("a")[0], "b");
+    it('Should chain addEdge.', function() {
+      var graph = Graph().addEdge('a', 'b');
+      assert.equal(graph.adjacent('a').length, 1);
+      assert.equal(graph.adjacent('a')[0], 'b');
     });
 
-    it("Should remove edges.", function (){
+    it('Should remove edges.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      graph.removeEdge("a", "b");
-      assert.equal(graph.adjacent("a").length, 0);
+      graph.addEdge('a', 'b');
+      graph.removeEdge('a', 'b');
+      assert.equal(graph.adjacent('a').length, 0);
     });
 
-    it("Should chain removeEdge.", function (){
+    it('Should chain removeEdge.', function() {
       var graph = Graph()
-        .addEdge("a", "b")
-        .removeEdge("a", "b");
-      assert.equal(graph.adjacent("a").length, 0);
+        .addEdge('a', 'b')
+        .removeEdge('a', 'b');
+      assert.equal(graph.adjacent('a').length, 0);
     });
 
-    it("Should not remove nodes when edges are removed.", function (){
+    it('Should not remove nodes when edges are removed.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      graph.removeEdge("a", "b");
+      graph.addEdge('a', 'b');
+      graph.removeEdge('a', 'b');
       assert.equal(graph.nodes().length, 2);
-      assert(contains(graph.nodes(), "a"));
-      assert(contains(graph.nodes(), "b"));
+      assert(contains(graph.nodes(), 'a'));
+      assert(contains(graph.nodes(), 'b'));
     });
 
-    it("Should remove outgoing edges when a node is removed.", function (){
+    it('Should remove outgoing edges when a node is removed.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      graph.removeNode("a");
-      assert.equal(graph.adjacent("a").length, 0);
+      graph.addEdge('a', 'b');
+      graph.removeNode('a');
+      assert.equal(graph.adjacent('a').length, 0);
     });
 
-    it("Should remove incoming edges when a node is removed.", function (){
+    it('Should remove incoming edges when a node is removed.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      graph.removeNode("b");
-      assert.equal(graph.adjacent("a").length, 0);
+      graph.addEdge('a', 'b');
+      graph.removeNode('b');
+      assert.equal(graph.adjacent('a').length, 0);
     });
 
-    it("Should compute indegree.", function (){
+    it('Should compute indegree.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      assert.equal(graph.indegree("a"), 0);
-      assert.equal(graph.indegree("b"), 1);
+      graph.addEdge('a', 'b');
+      assert.equal(graph.indegree('a'), 0);
+      assert.equal(graph.indegree('b'), 1);
 
-      graph.addEdge("c", "b");
-      assert.equal(graph.indegree("b"), 2);
+      graph.addEdge('c', 'b');
+      assert.equal(graph.indegree('b'), 2);
     });
 
-    it("Should compute outdegree.", function (){
+    it('Should compute outdegree.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      assert.equal(graph.outdegree("a"), 1);
-      assert.equal(graph.outdegree("b"), 0);
+      graph.addEdge('a', 'b');
+      assert.equal(graph.outdegree('a'), 1);
+      assert.equal(graph.outdegree('b'), 0);
 
-      graph.addEdge("a", "c");
-      assert.equal(graph.outdegree("a"), 2);
+      graph.addEdge('a', 'c');
+      assert.equal(graph.outdegree('a'), 2);
     });
-
   });
 
-  describe("Algorithms", function() {
-
+  describe('Algorithms', function() {
     // This example is from Cormen et al. "Introduction to Algorithms" page 550
-    it("Should compute topological sort.", function (){
-
+    it('Should compute topological sort.', function() {
       var graph = Graph();
 
       // Shoes depend on socks.
       // Socks need to be put on before shoes.
-      graph.addEdge("socks", "shoes");
+      graph.addEdge('socks', 'shoes');
 
-      graph.addEdge("shirt", "belt");
-      graph.addEdge("shirt", "tie");
-      graph.addEdge("tie", "jacket");
-      graph.addEdge("belt", "jacket");
-      graph.addEdge("pants", "shoes");
-      graph.addEdge("underpants", "pants");
-      graph.addEdge("pants", "belt");
+      graph.addEdge('shirt', 'belt');
+      graph.addEdge('shirt', 'tie');
+      graph.addEdge('tie', 'jacket');
+      graph.addEdge('belt', 'jacket');
+      graph.addEdge('pants', 'shoes');
+      graph.addEdge('underpants', 'pants');
+      graph.addEdge('pants', 'belt');
 
       var sorted = graph.topologicalSort();
 
-      assert(comesBefore(sorted, "pants", "shoes"));
-      assert(comesBefore(sorted, "underpants", "pants"));
-      assert(comesBefore(sorted, "underpants", "shoes"));
-      assert(comesBefore(sorted, "shirt", "jacket"));
-      assert(comesBefore(sorted, "shirt", "belt"));
-      assert(comesBefore(sorted, "belt", "jacket"));
+      assert(comesBefore(sorted, 'pants', 'shoes'));
+      assert(comesBefore(sorted, 'underpants', 'pants'));
+      assert(comesBefore(sorted, 'underpants', 'shoes'));
+      assert(comesBefore(sorted, 'shirt', 'jacket'));
+      assert(comesBefore(sorted, 'shirt', 'belt'));
+      assert(comesBefore(sorted, 'belt', 'jacket'));
 
       assert.equal(sorted.length, 8);
-
     });
 
-    it("Should compute topological sort, excluding source nodes.", function (){
+    it('Should compute topological sort, excluding source nodes.', function() {
       var graph = Graph();
-      graph.addEdge("a", "b");
-      graph.addEdge("b", "c");
-      var sorted = graph.topologicalSort(["a"], false);
+      graph.addEdge('a', 'b');
+      graph.addEdge('b', 'c');
+      var sorted = graph.topologicalSort(['a'], false);
       assert.equal(sorted.length, 2);
-      assert.equal(sorted[0], "b");
-      assert.equal(sorted[1], "c");
+      assert.equal(sorted[0], 'b');
+      assert.equal(sorted[1], 'c');
     });
 
-    it("Should compute topological sort tricky case.", function (){
+    it('Should compute topological sort tricky case.', function() {
+      var graph = Graph(); //      a
+      //     / \
+      graph.addEdge('a', 'b'); //    b   |
+      graph.addEdge('a', 'd'); //    |   d
+      graph.addEdge('b', 'c'); //    c   |
+      graph.addEdge('d', 'e'); //     \ /
+      graph.addEdge('c', 'e'); //      e
 
-      var graph = Graph();     //      a
-                               //     / \
-      graph.addEdge("a", "b"); //    b   |
-      graph.addEdge("a", "d"); //    |   d
-      graph.addEdge("b", "c"); //    c   |
-      graph.addEdge("d", "e"); //     \ /
-      graph.addEdge("c", "e"); //      e
-
-      var sorted = graph.topologicalSort(["a"], false);
+      var sorted = graph.topologicalSort(['a'], false);
       assert.equal(sorted.length, 4);
-      assert(contains(sorted, "b"));
-      assert(contains(sorted, "c"));
-      assert(contains(sorted, "d"));
-      assert.equal(sorted[sorted.length - 1], "e");
-
-      assert(comesBefore(sorted, "b", "c"));
-      assert(comesBefore(sorted, "b", "e"));
-      assert(comesBefore(sorted, "c", "e"));
-      assert(comesBefore(sorted, "d", "e"));
-
+      assert(contains(sorted, 'b'));
+      assert(contains(sorted, 'c'));
+      assert(contains(sorted, 'd'));
+      assert.equal(sorted[sorted.length - 1], 'e');
+
+      assert(comesBefore(sorted, 'b', 'c'));
+      assert(comesBefore(sorted, 'b', 'e'));
+      assert(comesBefore(sorted, 'c', 'e'));
+      assert(comesBefore(sorted, 'd', 'e'));
     });
 
-    it("Should exclude source nodes with a cycle.", function (){
+    it('Should exclude source nodes with a cycle.', function() {
       var graph = Graph()
-        .addEdge("a", "b")
-        .addEdge("b", "c")
-        .addEdge("c", "a");
-      var sorted = graph.topologicalSort(["a"], false);
+        .addEdge('a', 'b')
+        .addEdge('b', 'c')
+        .addEdge('c', 'a');
+      var sorted = graph.topologicalSort(['a'], false);
       assert.equal(sorted.length, 2);
-      assert.equal(sorted[0], "b");
-      assert.equal(sorted[1], "c");
-
+      assert.equal(sorted[0], 'b');
+      assert.equal(sorted[1], 'c');
     });
 
-    it("Should exclude source nodes with multiple cycles.", function (){
+    it('Should exclude source nodes with multiple cycles.', function() {
       var graph = Graph()
+        .addEdge('a', 'b')
+        .addEdge('b', 'a')
 
-        .addEdge("a", "b")
-        .addEdge("b", "a")
+        .addEdge('b', 'c')
+        .addEdge('c', 'b')
 
-        .addEdge("b", "c")
-        .addEdge("c", "b")
+        .addEdge('a', 'c')
+        .addEdge('c', 'a');
 
-        .addEdge("a", "c")
-        .addEdge("c", "a");
-
-      var sorted = graph.topologicalSort(["a", "b"], false);
-      assert(!contains(sorted, "b"));
+      var sorted = graph.topologicalSort(['a', 'b'], false);
+      assert(!contains(sorted, 'b'));
     });
   });
 
-  describe("Edge cases and error handling", function() {
-
-    it("Should return empty array of adjacent nodes for unknown nodes.", function (){
+  describe('Edge cases and error handling', function() {
+    it('Should return empty array of adjacent nodes for unknown nodes.', function() {
       var graph = Graph();
-      assert.equal(graph.adjacent("a").length, 0);
+      assert.equal(graph.adjacent('a').length, 0);
       assert.equal(graph.nodes(), 0);
     });
 
-    it("Should do nothing if removing an edge that does not exist.", function (){
-      assert.doesNotThrow(function (){
+    it('Should do nothing if removing an edge that does not exist.', function() {
+      assert.doesNotThrow(function() {
         var graph = Graph();
-        graph.removeEdge("a", "b");
+        graph.removeEdge('a', 'b');
       });
     });
 
-    it("Should return indegree of 0 for unknown nodes.", function (){
+    it('Should return indegree of 0 for unknown nodes.', function() {
       var graph = Graph();
-      assert.equal(graph.indegree("z"), 0);
+      assert.equal(graph.indegree('z'), 0);
     });
 
-    it("Should return outdegree of 0 for unknown nodes.", function (){
+    it('Should return outdegree of 0 for unknown nodes.', function() {
       var graph = Graph();
-      assert.equal(graph.outdegree("z"), 0);
+      assert.equal(graph.outdegree('z'), 0);
     });
-
   });
 
-  describe("Serialization", function() {
-
+  describe('Serialization', function() {
     var serialized;
 
-    function checkSerialized(graph){
+    function checkSerialized(graph) {
       assert.equal(graph.nodes.length, 3);
       assert.equal(graph.links.length, 2);
 
-      assert.equal(graph.nodes[0].id, "a");
-      assert.equal(graph.nodes[1].id, "b");
-      assert.equal(graph.nodes[2].id, "c");
+      assert.equal(graph.nodes[0].id, 'a');
+      assert.equal(graph.nodes[1].id, 'b');
+      assert.equal(graph.nodes[2].id, 'c');
 
-      assert.equal(graph.links[0].source, "a");
-      assert.equal(graph.links[0].target, "b");
-      assert.equal(graph.links[1].source, "b");
-      assert.equal(graph.links[1].target, "c");
+      assert.equal(graph.links[0].source, 'a');
+      assert.equal(graph.links[0].target, 'b');
+      assert.equal(graph.links[1].source, 'b');
+      assert.equal(graph.links[1].target, 'c');
     }
 
-    it("Should serialize a graph.", function (){
+    it('Should serialize a graph.', function() {
       var graph = Graph()
-        .addEdge("a", "b")
-        .addEdge("b", "c");
+        .addEdge('a', 'b')
+        .addEdge('b', 'c');
       serialized = graph.serialize();
       checkSerialized(serialized);
     });
 
-    it("Should deserialize a graph.", function (){
+    it('Should deserialize a graph.', function() {
       var graph = Graph();
       graph.deserialize(serialized);
       checkSerialized(graph.serialize());
     });
 
-    it("Should chain deserialize a graph.", function (){
+    it('Should chain deserialize a graph.', function() {
       var graph = Graph().deserialize(serialized);
       checkSerialized(graph.serialize());
     });
 
-    it("Should deserialize a graph passed to constructor.", function (){
+    it('Should deserialize a graph passed to constructor.', function() {
       var graph = Graph(serialized);
       checkSerialized(graph.serialize());
     });
   });
 });
 
-function contains(arr, item){
-  return arr.filter(function (d){
-    return d === item;
-  }).length > 0;
+function contains(arr, item) {
+  return (
+    arr.filter(function(d) {
+      return d === item;
+    }).length > 0
+  );
 }
 
-function comesBefore(arr, a, b){
+function comesBefore(arr, a, b) {
   var aIndex, bIndex;
-  arr.forEach(function (d, i){
-    if(d === a){ aIndex = i; }
-    if(d === b){ bIndex = i; }
+  arr.forEach(function(d, i) {
+    if (d === a) {
+      aIndex = i;
+    }
+    if (d === b) {
+      bIndex = i;
+    }
   });
   return aIndex < bIndex;
 }
diff --git a/packages/loot-core/src/server/spreadsheet/usage.js b/packages/loot-core/src/server/spreadsheet/usage.js
index 4b8f12f4aa61e0e670b675e01c4b21642c11fb9c..abe6f8cd1d734fcb47fd75b35b0dee8590ad29dc 100644
--- a/packages/loot-core/src/server/spreadsheet/usage.js
+++ b/packages/loot-core/src/server/spreadsheet/usage.js
@@ -1,12 +1,12 @@
-const sqlite = require("sqlite3");
-const escodegen = require("escodegen");
-const sqlgen = require("./sqlgen");
+const sqlite = require('sqlite3');
+const escodegen = require('escodegen');
+const sqlgen = require('./sqlgen');
 
 // Example usage:
 
-const Spreadsheet = require("./spreadsheet");
+const Spreadsheet = require('./spreadsheet');
 
-const db = new sqlite.Database(__dirname + "/../../db.sqlite");
+const db = new sqlite.Database(__dirname + '/../../db.sqlite');
 const sheet = new Spreadsheet({
   plugins: {
     runQuery: {
@@ -20,22 +20,24 @@ const sheet = new Spreadsheet({
 
         return {
           data: {
-            type: "query",
+            type: 'query',
             query: query,
             sql: sql
           },
 
           ast: {
-            type: "CallExpression",
+            type: 'CallExpression',
             callee: {
-              type: "Identifier",
-              name: "runQuery"
+              type: 'Identifier',
+              name: 'runQuery'
             },
-            arguments: [{
-              type: "Literal",
-              raw: sql,
-              value: sql
-            }]
+            arguments: [
+              {
+                type: 'Literal',
+                raw: sql,
+                value: sql
+              }
+            ]
           }
         };
       },
@@ -43,7 +45,7 @@ const sheet = new Spreadsheet({
         return new Promise(resolve => {
           const start = Date.now();
           db.all(sql, function(err, rows) {
-            if(err) {
+            if (err) {
               throw new Error(err);
             }
             resolve(rows);
@@ -54,11 +56,12 @@ const sheet = new Spreadsheet({
   }
 });
 
-db.on("preupdate", function(type, dbname, table, old, _new, oldId, newId) {
+db.on('preupdate', function(type, dbname, table, old, _new, oldId, newId) {
   sheet.resolve().then(() => {
     const start = Date.now();
     sheet.startTransaction();
-    sheet.getNodesOfType("query")
+    sheet
+      .getNodesOfType('query')
       .filter(node => node.data.query.table === table)
       .forEach(q => {
         sheet.signal(q.name);
diff --git a/packages/loot-core/src/server/sync/sync.property.test.js b/packages/loot-core/src/server/sync/sync.property.test.js
index e267f7ad26b3b7421edf88a602261fadc07c29da..0c798c84077cabc9797c44908c6e5cd0b320c507 100644
--- a/packages/loot-core/src/server/sync/sync.property.test.js
+++ b/packages/loot-core/src/server/sync/sync.property.test.js
@@ -2,13 +2,13 @@ import * as prefs from '../prefs';
 import * as db from '../db';
 import * as sheet from '../sheet';
 import * as sync from './index';
-import { getClock, Timestamp } from '../crdt';
-import { merkle } from '../crdt';
+import { merkle, getClock, Timestamp } from '../crdt';
 import * as encoder from './encoder';
 const jsc = require('jsverify');
-const uuidGenerator = jsc
-  .integer(97, 122)
-  .smap(x => String.fromCharCode(x), x => x.charCodeAt(x));
+const uuidGenerator = jsc.integer(97, 122).smap(
+  x => String.fromCharCode(x),
+  x => x.charCodeAt(x)
+);
 
 const mockSyncServer = require('../tests/mockSyncServer');
 
@@ -126,7 +126,10 @@ Object.keys(schema).forEach(table => {
       generators.push(
         makeGen({
           table,
-          row: jsc.asciinestring.smap(x => 'sheet!' + x, x => x),
+          row: jsc.asciinestring.smap(
+            x => 'sheet!' + x,
+            x => x
+          ),
           field: 'expr',
           value: jsc.constant(JSON.stringify('fooooo'))
         })
diff --git a/packages/loot-core/src/server/tracking/events.js b/packages/loot-core/src/server/tracking/events.js
index 0884a122e61d8e581cd8ce0901c5fd873bdf97ad..fea5dd6e22e0c5d9e542b937c8ceed119639d9ec 100644
--- a/packages/loot-core/src/server/tracking/events.js
+++ b/packages/loot-core/src/server/tracking/events.js
@@ -24,11 +24,9 @@ function isAnonymous(id) {
   return !id.startsWith('user-');
 }
 
-export async function init() {
-}
+export async function init() {}
 
-export async function login(userId) {
-}
+export async function login(userId) {}
 
 let BUFFERING = false;
 let BUFFER = [];
diff --git a/yarn.lock b/yarn.lock
index a9e8b77fe78ecc839da1ce923606061b3ad8be9c..af5a843771378b437683ee8b212358197f59660a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2503,13 +2503,13 @@ __metadata:
   linkType: hard
 
 "@babel/types@npm:^7.8.3":
-  version: 7.18.10
-  resolution: "@babel/types@npm:7.18.10"
+  version: 7.18.13
+  resolution: "@babel/types@npm:7.18.13"
   dependencies:
     "@babel/helper-string-parser": ^7.18.10
     "@babel/helper-validator-identifier": ^7.18.6
     to-fast-properties: ^2.0.0
-  checksum: 11632c9b106e54021937a6498138014ebc9ad6c327a07b2af3ba8700773945aba4055fd136431cbe3a500d0f363cbf9c68eb4d6d38229897c5de9d06e14c85e8
+  checksum: abc3ad1f3b6864df0ea0e778bcdf7d2c5ee2293811192962d50e8a8c05c1aeec90a48275f53b2a45aad882ed8bef9477ae1f8e70ac1d44d039e14930d1388dcc
   languageName: node
   linkType: hard
 
@@ -3104,22 +3104,22 @@ __metadata:
   linkType: hard
 
 "@npmcli/fs@npm:^2.1.0":
-  version: 2.1.1
-  resolution: "@npmcli/fs@npm:2.1.1"
+  version: 2.1.2
+  resolution: "@npmcli/fs@npm:2.1.2"
   dependencies:
     "@gar/promisify": ^1.1.3
     semver: ^7.3.5
-  checksum: 4944a0545d38d3e6e29780eeb3cd4be6059c1e9627509d2c9ced635c53b852d28b37cdc615a2adf815b51ab8673adb6507e370401a20a7e90c8a6dc4fac02389
+  checksum: 405074965e72d4c9d728931b64d2d38e6ea12066d4fad651ac253d175e413c06fe4350970c783db0d749181da8fe49c42d3880bd1cbc12cd68e3a7964d820225
   languageName: node
   linkType: hard
 
 "@npmcli/move-file@npm:^2.0.0":
-  version: 2.0.0
-  resolution: "@npmcli/move-file@npm:2.0.0"
+  version: 2.0.1
+  resolution: "@npmcli/move-file@npm:2.0.1"
   dependencies:
     mkdirp: ^1.0.4
     rimraf: ^3.0.2
-  checksum: 1388777b507b0c592d53f41b9d182e1a8de7763bc625fc07999b8edbc22325f074e5b3ec90af79c89d6987fdb2325bc66d59f483258543c14a43661621f841b0
+  checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380
   languageName: node
   linkType: hard
 
@@ -6826,8 +6826,8 @@ __metadata:
   linkType: hard
 
 "cacache@npm:^16.1.0":
-  version: 16.1.1
-  resolution: "cacache@npm:16.1.1"
+  version: 16.1.2
+  resolution: "cacache@npm:16.1.2"
   dependencies:
     "@npmcli/fs": ^2.1.0
     "@npmcli/move-file": ^2.0.0
@@ -6847,7 +6847,7 @@ __metadata:
     ssri: ^9.0.0
     tar: ^6.1.11
     unique-filename: ^1.1.1
-  checksum: 488524617008b793f0249b0c4ea2c330c710ca997921376e15650cc2415a8054491ae2dee9f01382c2015602c0641f3f977faf2fa7361aa33d2637dcfb03907a
+  checksum: defe1d6f557ddda178204cac111990da27e8a60ed276fcd608dad7109cc1936e7dcd57d7263d22cdb06a80e7ceb76ab5eb05133c7c7f886abf1d870d722abd6c
   languageName: node
   linkType: hard
 
@@ -10175,6 +10175,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-plugin-prettier@npm:^3.1.4":
+  version: 3.4.1
+  resolution: "eslint-plugin-prettier@npm:3.4.1"
+  dependencies:
+    prettier-linter-helpers: ^1.0.0
+  peerDependencies:
+    eslint: ">=5.0.0"
+    prettier: ">=1.13.0"
+  peerDependenciesMeta:
+    eslint-config-prettier:
+      optional: true
+  checksum: fa6a89f0d7cba1cc87064352f5a4a68dc3739448dd279bec2bced1bfa3b704467e603d13b69dcec853f8fa30b286b8b715912898e9da776e1b016cf0ee48bd99
+  languageName: node
+  linkType: hard
+
 "eslint-plugin-react@npm:7.11.1":
   version: 7.11.1
   resolution: "eslint-plugin-react@npm:7.11.1"
@@ -10707,6 +10722,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"fast-diff@npm:^1.1.2":
+  version: 1.2.0
+  resolution: "fast-diff@npm:1.2.0"
+  checksum: 1b5306eaa9e826564d9e5ffcd6ebd881eb5f770b3f977fcbf38f05c824e42172b53c79920e8429c54eb742ce15a0caf268b0fdd5b38f6de52234c4a8368131ae
+  languageName: node
+  linkType: hard
+
 "fast-glob@npm:^2.2.0, fast-glob@npm:^2.2.2":
   version: 2.2.7
   resolution: "fast-glob@npm:2.2.7"
@@ -15303,6 +15325,7 @@ jest-snapshot@test:
     date-fns: 2.0.0-alpha.27
     deep-equal: ^2.0.5
     eslint: 5.6.0
+    eslint-plugin-prettier: ^3.1.4
     esm: ^3.0.82
     fake-indexeddb: ^3.1.3
     fast-check: ^2.11.0
@@ -15321,6 +15344,7 @@ jest-snapshot@test:
     node-fetch: ^1.6.3
     node-libofx: "*"
     perf-deets: ^1.0.15
+    prettier: ^1.19.1
     regenerator-runtime: ^0.13.7
     sanitize-filename: ^1.6.1
     search-query-parser: ^1.3.0
@@ -15433,9 +15457,9 @@ jest-snapshot@test:
   linkType: hard
 
 "lru-cache@npm:^7.7.1":
-  version: 7.13.2
-  resolution: "lru-cache@npm:7.13.2"
-  checksum: dfed24e52bae95edf490d0f28f4f14552319ac7e7dc37ae0b84a72e084949233821b33227271abe81d8361ac079810f9d171a706f316cfdeda135012e4311015
+  version: 7.14.0
+  resolution: "lru-cache@npm:7.14.0"
+  checksum: efdd329f2c1bb790b71d497c6c59272e6bc2d7dd060ba55fc136becd3dd31fc8346edb446275504d94cb60d3c8385dbf5267b79b23789e409b2bdf302d13f0d7
   languageName: node
   linkType: hard
 
@@ -15516,8 +15540,8 @@ jest-snapshot@test:
   linkType: hard
 
 "make-fetch-happen@npm:^10.0.3":
-  version: 10.2.0
-  resolution: "make-fetch-happen@npm:10.2.0"
+  version: 10.2.1
+  resolution: "make-fetch-happen@npm:10.2.1"
   dependencies:
     agentkeepalive: ^4.2.1
     cacache: ^16.1.0
@@ -15535,7 +15559,7 @@ jest-snapshot@test:
     promise-retry: ^2.0.1
     socks-proxy-agent: ^7.0.0
     ssri: ^9.0.0
-  checksum: 2f6c294179972f56fab40fd8618f07841e06550692bb78f6da16e7afaa9dca78c345b08cf44a77a8907ef3948e4dc77e93eb7492b8381f1217d7ac057a7522f8
+  checksum: 2332eb9a8ec96f1ffeeea56ccefabcb4193693597b132cd110734d50f2928842e22b84cfa1508e921b8385cdfd06dda9ad68645fed62b50fff629a580f5fb72c
   languageName: node
   linkType: hard
 
@@ -16249,8 +16273,8 @@ jest-snapshot@test:
   linkType: hard
 
 "minipass-fetch@npm:^2.0.3":
-  version: 2.1.0
-  resolution: "minipass-fetch@npm:2.1.0"
+  version: 2.1.2
+  resolution: "minipass-fetch@npm:2.1.2"
   dependencies:
     encoding: ^0.1.13
     minipass: ^3.1.6
@@ -16259,7 +16283,7 @@ jest-snapshot@test:
   dependenciesMeta:
     encoding:
       optional: true
-  checksum: 1334732859a3f7959ed22589bafd9c40384b885aebb5932328071c33f86b3eb181d54c86919675d1825ab5f1c8e4f328878c863873258d113c29d79a4b0c9c9f
+  checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91
   languageName: node
   linkType: hard
 
@@ -19080,7 +19104,16 @@ jest-snapshot@test:
   languageName: node
   linkType: hard
 
-"prettier@npm:^1.14.2, prettier@npm:^1.18.1":
+"prettier-linter-helpers@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "prettier-linter-helpers@npm:1.0.0"
+  dependencies:
+    fast-diff: ^1.1.2
+  checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392
+  languageName: node
+  linkType: hard
+
+"prettier@npm:^1.14.2, prettier@npm:^1.18.1, prettier@npm:^1.19.1":
   version: 1.19.1
   resolution: "prettier@npm:1.19.1"
   bin: