Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ (typescript) fixing strictNullChecks=true issues #2212

Merged
merged 4 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/crdt/src/crdt/merkle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function diff(trie1: TrieNode, trie2: TrieNode): number | null {
const keys = [...keyset.values()];
keys.sort();

let diffkey = null;
let diffkey: null | '0' | '1' | '2' = null;

// Traverse down the trie through keys that aren't the same. We
// traverse down the keys in order. Stop in two cases: either one
Expand Down
3 changes: 2 additions & 1 deletion packages/loot-core/src/client/actions/queries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import throttle from 'throttleit';

import { send } from '../../platform/client/fetch';
import { type AccountEntity } from '../../types/models';
import * as constants from '../constants';

import { pushModal } from './modals';
Expand Down Expand Up @@ -260,7 +261,7 @@ export function getAccounts() {
};
}

export function updateAccount(account) {
export function updateAccount(account: AccountEntity) {
return async (dispatch: Dispatch) => {
dispatch({ type: constants.UPDATE_ACCOUNT, account });
await send('account-update', account);
Expand Down
33 changes: 19 additions & 14 deletions packages/loot-core/src/client/reducers/queries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import memoizeOne from 'memoize-one';

import { groupById } from '../../shared/util';
import { type AccountEntity, type PayeeEntity } from '../../types/models';
import * as constants from '../constants';
import type { Action } from '../state-types';
import type { QueriesState } from '../state-types/queries';
Expand Down Expand Up @@ -59,9 +60,7 @@ export function update(state = initialState, action: Action): QueriesState {
return {
...state,
accounts: state.accounts.map(account => {
// @ts-expect-error Not typed yet
if (account.id === action.account.id) {
// @ts-expect-error Not typed yet
return { ...account, ...action.account };
}
return account;
Expand All @@ -83,8 +82,12 @@ export function update(state = initialState, action: Action): QueriesState {
return state;
}

export const getAccountsById = memoizeOne(accounts => groupById(accounts));
export const getPayeesById = memoizeOne(payees => groupById(payees));
export const getAccountsById = memoizeOne((accounts: AccountEntity[]) =>
groupById(accounts),
);
export const getPayeesById = memoizeOne((payees: PayeeEntity[]) =>
groupById(payees),
);
export const getCategoriesById = memoizeOne(categoryGroups => {
const res = {};
categoryGroups.forEach(group => {
Expand All @@ -95,14 +98,16 @@ export const getCategoriesById = memoizeOne(categoryGroups => {
return res;
});

export const getActivePayees = memoizeOne((payees, accounts) => {
const accountsById = getAccountsById(accounts);
export const getActivePayees = memoizeOne(
(payees: PayeeEntity[], accounts: AccountEntity[]) => {
const accountsById = getAccountsById(accounts);

return payees.filter(payee => {
if (payee.transfer_acct) {
const account = accountsById[payee.transfer_acct];
return account != null && !account.closed;
}
return true;
});
});
return payees.filter(payee => {
if (payee.transfer_acct) {
const account = accountsById[payee.transfer_acct];
return account != null && !account.closed;
}
return true;
});
},
);
3 changes: 2 additions & 1 deletion packages/loot-core/src/client/state-types/queries.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Handlers } from '../../types/handlers';
import { type AccountEntity } from '../../types/models';
import type * as constants from '../constants';

export type QueriesState = {
Expand Down Expand Up @@ -41,7 +42,7 @@ type LoadAccountsAction = {

type UpdateAccountAction = {
type: typeof constants.UPDATE_ACCOUNT;
account: unknown;
account: AccountEntity;
};

type LoadCategoriesAction = {
Expand Down
4 changes: 2 additions & 2 deletions packages/loot-core/src/mocks/budget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import { q } from '../shared/query';
import type { Handlers } from '../types/handlers';
import type {
CategoryGroupEntity,
PayeeEntity,
NewPayeeEntity,
NewTransactionEntity,
} from '../types/models';

import { random } from './random';

type MockPayeeEntity = PayeeEntity & { bill?: boolean };
type MockPayeeEntity = NewPayeeEntity & { bill?: boolean };

function pickRandom<T>(list: T[]): T {
return list[Math.floor(random() * list.length) % list.length];
Expand Down
11 changes: 8 additions & 3 deletions packages/loot-core/src/server/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { v4 as uuidv4 } from 'uuid';
import * as fs from '../../platform/server/fs';
import * as sqlite from '../../platform/server/sqlite';
import { groupById } from '../../shared/util';
import { CategoryEntity, CategoryGroupEntity } from '../../types/models';
import {
CategoryEntity,
CategoryGroupEntity,
PayeeEntity,
} from '../../types/models';
import {
schema,
schemaConfig,
Expand Down Expand Up @@ -478,9 +482,10 @@ export function updatePayee(payee) {
return update('payees', payee);
}

export async function mergePayees(target, ids) {
export async function mergePayees(target: string, ids: string[]) {
// Load in payees so we can check some stuff
const payees = groupById(await all('SELECT * FROM payees'));
const dbPayees: PayeeEntity[] = await all('SELECT * FROM payees');
const payees = groupById(dbPayees);

// Filter out any transfer payees
if (payees[target].transfer_acct != null) {
Expand Down
58 changes: 37 additions & 21 deletions packages/loot-core/src/shared/transactions.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { v4 as uuidv4 } from 'uuid';

import { TransactionEntity } from '../types/models';

import {
splitTransaction,
updateTransaction,
Expand All @@ -8,16 +10,26 @@ import {
makeChild,
} from './transactions';

// const data = {
// splitTransactions: generateTransaction({ amount: -5000, acct: 2 }, -2000)
// };

function makeTransaction(data) {
function makeTransaction(data: Partial<TransactionEntity>): TransactionEntity {
return {
id: uuidv4(),
amount: 2422,
date: '2020-01-05',
account: 'acct1',
account: {
id: 'acc-id-1',
name: 'account-1',
offbudget: 0,
closed: 0,
sort_order: 1,
tombstone: 0,
account_id: null,
bank: null,
mask: null,
official_name: null,
balance_current: null,
balance_available: null,
balance_limit: null,
},
...data,
};
}
Expand All @@ -27,7 +39,7 @@ function makeSplitTransaction(data, children) {
return [parent, ...children.map(t => makeChild(parent, t))];
}

function splitError(amount) {
function splitError(amount: number) {
return { difference: amount, type: 'SplitTransactionError', version: 1 };
}

Expand All @@ -38,15 +50,18 @@ describe('Transactions', () => {
makeTransaction({ id: 't1', amount: 4000 }),
makeTransaction({ amount: 3000 }),
];
const { data, diff } = updateTransaction(transactions, {
id: 't1',
amount: 5000,
});
const { data, diff } = updateTransaction(
transactions,
makeTransaction({
id: 't1',
amount: 5000,
}),
);
expect(data.find(d => d.subtransactions)).toBeFalsy();
expect(diff).toEqual({
added: [],
deleted: [],
updated: [{ id: 't1', amount: 5000 }],
updated: [expect.objectContaining({ id: 't1', amount: 5000 })],
});
expect(data.map(t => ({ id: t.id, amount: t.amount })).sort()).toEqual([
{ id: expect.any(String), amount: 5000 },
Expand All @@ -56,14 +71,12 @@ describe('Transactions', () => {
});

test('updating does nothing if value not changed', () => {
const updatedTransaction = makeTransaction({ id: 't1', amount: 5000 });
const transactions = [
makeTransaction({ id: 't1', amount: 5000 }),
updatedTransaction,
makeTransaction({ amount: 3000 }),
];
const { data, diff } = updateTransaction(transactions, {
id: 't1',
amount: 5000,
});
const { data, diff } = updateTransaction(transactions, updatedTransaction);
expect(diff).toEqual({ added: [], deleted: [], updated: [] });
expect(data.map(t => ({ id: t.id, amount: t.amount })).sort()).toEqual([
{ id: expect.any(String), amount: 5000 },
Expand Down Expand Up @@ -160,10 +173,13 @@ describe('Transactions', () => {
]),
makeTransaction({ amount: 3002 }),
];
const { data, diff } = updateTransaction(transactions, {
id: 't2',
amount: 2200,
});
const { data, diff } = updateTransaction(
transactions,
makeTransaction({
id: 't2',
amount: 2200,
}),
);
expect(data.find(d => d.subtransactions)).toBeFalsy();
expect(diff).toEqual({
added: [],
Expand Down
31 changes: 21 additions & 10 deletions packages/loot-core/src/shared/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ export function applyTransactionDiff(
groupedTrans: Parameters<typeof ungroupTransaction>[0],
diff: Parameters<typeof applyChanges>[0],
) {
return groupTransaction(applyChanges(diff, ungroupTransaction(groupedTrans)));
return groupTransaction(
applyChanges(diff, ungroupTransaction(groupedTrans) || []),
);
}

function replaceTransactions(
Expand All @@ -131,7 +133,7 @@ function replaceTransactions(
const parentIndex = findParentIndex(transactions, idx);
if (parentIndex == null) {
console.log('Cannot find parent index');
return { diff: { deleted: [], updated: [] } };
return { data: [], diff: { deleted: [], updated: [] } };
}

const split = getSplit(transactions, parentIndex);
Expand Down Expand Up @@ -177,8 +179,8 @@ export function addSplitTransaction(
if (!trans.is_parent) {
return trans;
}
const prevSub = last(trans.subtransactions);
trans.subtransactions.push(
const prevSub = last(trans.subtransactions || []);
trans.subtransactions?.push(
makeChild(trans, {
amount: 0,
sort_order: num(prevSub && prevSub.sort_order) - 1,
Expand All @@ -188,11 +190,14 @@ export function addSplitTransaction(
});
}

export function updateTransaction(transactions, transaction) {
export function updateTransaction(
transactions: TransactionEntity[],
transaction: TransactionEntity,
) {
return replaceTransactions(transactions, transaction.id, trans => {
if (trans.is_parent) {
const parent = trans.id === transaction.id ? transaction : trans;
const sub = trans.subtransactions.map(t => {
const sub = trans.subtransactions?.map(t => {
// Make sure to update the children to reflect the updated
// properties (if the parent updated)

Expand All @@ -216,20 +221,23 @@ export function updateTransaction(transactions, transaction) {
});
}

export function deleteTransaction(transactions, id) {
export function deleteTransaction(
transactions: TransactionEntity[],
id: string,
) {
return replaceTransactions(transactions, id, trans => {
if (trans.is_parent) {
if (trans.id === id) {
return null;
} else if (trans.subtransactions.length === 1) {
} else if (trans.subtransactions?.length === 1) {
return {
...trans,
subtransactions: null,
is_parent: false,
error: null,
};
} else {
const sub = trans.subtransactions.filter(t => t.id !== id);
const sub = trans.subtransactions?.filter(t => t.id !== id);
return recalculateSplit({ ...trans, subtransactions: sub });
}
} else {
Expand All @@ -238,7 +246,10 @@ export function deleteTransaction(transactions, id) {
});
}

export function splitTransaction(transactions, id) {
export function splitTransaction(
transactions: TransactionEntity[],
id: string,
) {
return replaceTransactions(transactions, id, trans => {
if (trans.is_parent || trans.is_child) {
return trans;
Expand Down
Loading