mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-28 10:33:02 -05:00
Remove some any types from the API (#3238)
* Remove some `any` types from the API * Add release notes * No backwards-incompatible changes * Update tests to reflect API changes * PR feedback: standardize on id for deletes * PR feedback: restore partial updates
This commit is contained in:
committed by
GitHub
parent
63ad6dadf2
commit
d9066a49c4
@@ -81,28 +81,22 @@ describe('API CRUD operations', () => {
|
||||
expect(groups).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
hidden: 0,
|
||||
hidden: false,
|
||||
id: 'fc3825fd-b982-4b72-b768-5b30844cf832',
|
||||
is_income: 0,
|
||||
is_income: false,
|
||||
name: 'Usual Expenses',
|
||||
sort_order: 16384,
|
||||
tombstone: 0,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
hidden: 0,
|
||||
hidden: false,
|
||||
id: 'a137772f-cf2f-4089-9432-822d2ddc1466',
|
||||
is_income: 0,
|
||||
is_income: false,
|
||||
name: 'Investments and Savings',
|
||||
sort_order: 32768,
|
||||
tombstone: 0,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
hidden: 0,
|
||||
hidden: false,
|
||||
id: '2E1F5BDB-209B-43F9-AF2C-3CE28E380C00',
|
||||
is_income: 1,
|
||||
is_income: true,
|
||||
name: 'Income',
|
||||
sort_order: 32768,
|
||||
tombstone: 0,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
@@ -563,10 +557,10 @@ describe('API CRUD operations', () => {
|
||||
);
|
||||
|
||||
// delete rules
|
||||
await api.deleteRule(rules[1]);
|
||||
await api.deleteRule(rules[1].id);
|
||||
expect(await api.getRules()).toHaveLength(1);
|
||||
|
||||
await api.deleteRule(rules[0]);
|
||||
await api.deleteRule(rules[0].id);
|
||||
expect(await api.getRules()).toHaveLength(0);
|
||||
});
|
||||
|
||||
|
||||
@@ -205,8 +205,8 @@ export function updateRule(rule) {
|
||||
return send('api/rule-update', { rule });
|
||||
}
|
||||
|
||||
export function deleteRule(id) {
|
||||
return send('api/rule-delete', { id });
|
||||
export function deleteRule(id: string) {
|
||||
return send('api/rule-delete', id);
|
||||
}
|
||||
|
||||
export function holdBudgetForNextMonth(month, amount) {
|
||||
|
||||
@@ -209,7 +209,7 @@ describe('Transaction rules', () => {
|
||||
expect(transaction.payee).toBe('Kroger');
|
||||
expect(transaction.category).toBe('food');
|
||||
|
||||
await deleteRule({ id });
|
||||
await deleteRule(id);
|
||||
expect(getRules().length).toBe(0);
|
||||
transaction = runRules({
|
||||
payee: 'Kroger',
|
||||
|
||||
@@ -223,16 +223,17 @@ export async function updateRule(rule) {
|
||||
return db.update('rules', ruleModel.fromJS(rule));
|
||||
}
|
||||
|
||||
export async function deleteRule<T extends { id: string }>(rule: T) {
|
||||
export async function deleteRule(id: string) {
|
||||
const schedule = await db.first('SELECT id FROM schedules WHERE rule = ?', [
|
||||
rule.id,
|
||||
id,
|
||||
]);
|
||||
|
||||
if (schedule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return db.delete_('rules', rule.id);
|
||||
await db.delete_('rules', id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sync projections
|
||||
|
||||
@@ -44,12 +44,14 @@ let IMPORT_MODE = false;
|
||||
// we also need to notify the UI manually if stuff has changed (if
|
||||
// they are connecting to an already running instance, the UI should
|
||||
// update). The wrapper handles that.
|
||||
function withMutation(handler) {
|
||||
return args => {
|
||||
function withMutation<Params extends Array<unknown>, ReturnType>(
|
||||
handler: (...args: Params) => Promise<ReturnType>,
|
||||
) {
|
||||
return (...args: Params) => {
|
||||
return runMutator(
|
||||
async () => {
|
||||
const latestTimestamp = getClock().timestamp.toString();
|
||||
const result = await handler(args);
|
||||
const result = await handler(...args);
|
||||
|
||||
const rows = await db.all(
|
||||
'SELECT DISTINCT dataset FROM messages_crdt WHERE timestamp > ?',
|
||||
@@ -464,7 +466,7 @@ handlers['api/transactions-add'] = withMutation(async function ({
|
||||
runTransfers,
|
||||
learnCategories,
|
||||
});
|
||||
return 'ok';
|
||||
return 'ok' as const;
|
||||
});
|
||||
|
||||
handlers['api/transactions-get'] = async function ({
|
||||
@@ -503,7 +505,7 @@ handlers['api/transaction-update'] = withMutation(async function ({
|
||||
}
|
||||
|
||||
const { diff } = updateTransaction(transactions, { id, ...fields });
|
||||
return handlers['transactions-batch-update'](diff);
|
||||
return handlers['transactions-batch-update'](diff)['updated'];
|
||||
});
|
||||
|
||||
handlers['api/transaction-delete'] = withMutation(async function ({ id }) {
|
||||
@@ -518,7 +520,7 @@ handlers['api/transaction-delete'] = withMutation(async function ({ id }) {
|
||||
}
|
||||
|
||||
const { diff } = deleteTransaction(transactions, id);
|
||||
return handlers['transactions-batch-update'](diff);
|
||||
return handlers['transactions-batch-update'](diff)['deleted'];
|
||||
});
|
||||
|
||||
handlers['api/accounts-get'] = async function () {
|
||||
@@ -590,7 +592,8 @@ handlers['api/categories-get'] = async function ({
|
||||
|
||||
handlers['api/category-groups-get'] = async function () {
|
||||
checkFileOpen();
|
||||
return handlers['get-category-groups']();
|
||||
const groups = await handlers['get-category-groups']();
|
||||
return groups.map(categoryGroupModel.toExternal);
|
||||
};
|
||||
|
||||
handlers['api/category-group-create'] = withMutation(async function ({
|
||||
@@ -711,7 +714,7 @@ handlers['api/rule-create'] = withMutation(async function ({ rule }) {
|
||||
|
||||
handlers['api/rule-update'] = withMutation(async function ({ rule }) {
|
||||
checkFileOpen();
|
||||
const updatedRule = handlers['rule-update'](rule);
|
||||
const updatedRule = await handlers['rule-update'](rule);
|
||||
|
||||
if ('error' in updatedRule) {
|
||||
throw APIError('Failed updating the rule', updatedRule.error);
|
||||
@@ -720,7 +723,7 @@ handlers['api/rule-update'] = withMutation(async function ({ rule }) {
|
||||
return updatedRule;
|
||||
});
|
||||
|
||||
handlers['api/rule-delete'] = withMutation(async function ({ id }) {
|
||||
handlers['api/rule-delete'] = withMutation(async function (id) {
|
||||
checkFileOpen();
|
||||
return handlers['rule-delete'](id);
|
||||
});
|
||||
|
||||
@@ -111,8 +111,8 @@ app.method(
|
||||
|
||||
app.method(
|
||||
'rule-delete',
|
||||
mutator(async function (rule) {
|
||||
return rules.deleteRule(rule);
|
||||
mutator(async function (id) {
|
||||
return rules.deleteRule(id);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -123,7 +123,7 @@ app.method(
|
||||
|
||||
await batchMessages(async () => {
|
||||
for (const id of ids) {
|
||||
const res = await rules.deleteRule({ id });
|
||||
const res = await rules.deleteRule(id);
|
||||
if (res === false) {
|
||||
someDeletionsFailed = true;
|
||||
}
|
||||
|
||||
@@ -18,13 +18,16 @@ export interface RulesHandlers {
|
||||
|
||||
'rule-add': (
|
||||
rule: Omit<RuleEntity, 'id'>,
|
||||
) => Promise<{ error: ValidationError } | { id: string }>;
|
||||
) => Promise<{ error: ValidationError } | RuleEntity>;
|
||||
|
||||
'rule-update': (
|
||||
rule: Partial<RuleEntity>,
|
||||
) => Promise<{ error: ValidationError } | object>;
|
||||
'rule-update': <
|
||||
PartialRule extends Partial<Omit<RuleEntity, 'id'>> &
|
||||
Pick<RuleEntity, 'id'>,
|
||||
>(
|
||||
rule: PartialRule,
|
||||
) => Promise<{ error: ValidationError } | PartialRule>;
|
||||
|
||||
'rule-delete': (rule: Required<RuleEntity>) => Promise<false | void>;
|
||||
'rule-delete': (id: string) => Promise<boolean>;
|
||||
|
||||
'rule-delete-all': (
|
||||
ids: string[],
|
||||
|
||||
12
packages/loot-core/src/types/api-handlers.d.ts
vendored
12
packages/loot-core/src/types/api-handlers.d.ts
vendored
@@ -66,7 +66,7 @@ export interface ApiHandlers {
|
||||
'api/budget-hold-for-next-month': (arg: {
|
||||
month: string;
|
||||
amount: number;
|
||||
}) => Promise<void>;
|
||||
}) => Promise<boolean>;
|
||||
|
||||
'api/budget-reset-hold': (arg: { month: string }) => Promise<void>;
|
||||
|
||||
@@ -76,7 +76,11 @@ export interface ApiHandlers {
|
||||
payees;
|
||||
}) => Promise<unknown>;
|
||||
|
||||
'api/transactions-import': (arg: { accountId; transactions }) => Promise<{
|
||||
'api/transactions-import': (arg: {
|
||||
accountId;
|
||||
transactions;
|
||||
isPreview?;
|
||||
}) => Promise<{
|
||||
errors?: { message: string }[];
|
||||
added;
|
||||
updated;
|
||||
@@ -102,7 +106,7 @@ export interface ApiHandlers {
|
||||
|
||||
'api/transaction-delete': (arg: {
|
||||
id;
|
||||
}) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>['updated']>;
|
||||
}) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>['deleted']>;
|
||||
|
||||
'api/sync': () => Promise<void>;
|
||||
|
||||
@@ -176,5 +180,5 @@ export interface ApiHandlers {
|
||||
|
||||
'api/rule-update': (arg: { rule: RuleEntity }) => Promise<RuleEntity>;
|
||||
|
||||
'api/rule-delete': (arg: { id: string }) => Promise<boolean>;
|
||||
'api/rule-delete': (id: string) => Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ export interface ServerHandlers {
|
||||
|
||||
'payees-get-rule-counts': () => Promise<unknown>;
|
||||
|
||||
'payees-merge': (arg: { targetId; mergeIds }) => Promise<unknown>;
|
||||
'payees-merge': (arg: { targetId; mergeIds }) => Promise<void>;
|
||||
|
||||
'payees-batch-change': (arg: {
|
||||
added?;
|
||||
|
||||
6
upcoming-release-notes/3238.md
Normal file
6
upcoming-release-notes/3238.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Maintenance
|
||||
authors: [jfdoming]
|
||||
---
|
||||
|
||||
Remove some `any` types from the API
|
||||
Reference in New Issue
Block a user