diff --git a/packages/loot-core/src/mocks/budget.ts b/packages/loot-core/src/mocks/budget.ts index e4d9506030f97ddc350be0fb8b8a5c2dbc3cd965..4aa912cfe511a403d0f1fe4466a285e4f93de4ab 100644 --- a/packages/loot-core/src/mocks/budget.ts +++ b/packages/loot-core/src/mocks/budget.ts @@ -9,6 +9,7 @@ import * as sheet from '../server/sheet'; import { batchMessages, setSyncingMode } from '../server/sync'; import * as monthUtils from '../shared/months'; import { q } from '../shared/query'; +import type { Handlers } from '../types/handlers'; import type { CategoryGroupEntity, PayeeEntity, @@ -566,7 +567,7 @@ async function createBudget(accounts, payees, groups) { await sheet.waitOnSpreadsheet(); } -export async function createTestBudget(handlers) { +export async function createTestBudget(handlers: Handlers) { setSyncingMode('import'); await db.execQuery('PRAGMA journal_mode = OFF'); @@ -577,15 +578,15 @@ export async function createTestBudget(handlers) { await db.runQuery('DELETE FROM categories;'); await db.runQuery('DELETE FROM category_groups'); - const accounts: { name: string; offBudget?: 1; id?: string }[] = [ + const accounts: { name: string; offBudget?: boolean; id?: string }[] = [ { name: 'Bank of America' }, { name: 'Ally Savings' }, { name: 'Capital One Checking' }, { name: 'HSBC' }, - { name: 'Vanguard 401k', offBudget: 1 }, - { name: 'Mortgage', offBudget: 1 }, - { name: 'House Asset', offBudget: 1 }, - { name: 'Roth IRA', offBudget: 1 }, + { name: 'Vanguard 401k', offBudget: true }, + { name: 'Mortgage', offBudget: true }, + { name: 'House Asset', offBudget: true }, + { name: 'Roth IRA', offBudget: true }, ]; await runMutator(() => batchMessages(async () => { @@ -657,7 +658,7 @@ export async function createTestBudget(handlers) { for (const group of categoryGroups) { group.id = await handlers['category-group-create']({ name: group.name, - isIncome: group.is_income ? 1 : 0, + isIncome: group.is_income, }); for (const category of group.categories) { diff --git a/packages/loot-core/src/platform/server/connection/index.web.ts b/packages/loot-core/src/platform/server/connection/index.web.ts index 8b8bcd5b4884d01604ac303ae48b6a56feabe510..c1e3af987fd8530c153cf0287d39d95c003472ee 100644 --- a/packages/loot-core/src/platform/server/connection/index.web.ts +++ b/packages/loot-core/src/platform/server/connection/index.web.ts @@ -47,14 +47,10 @@ export const init: T.Init = function (serverChn, handlers) { if (handlers[name]) { runHandler(handlers[name], args, { undoTag, name }).then( result => { - if (catchErrors) { - result = { data: result, error: null }; - } - serverChannel.postMessage({ type: 'reply', id, - result, + result: catchErrors ? { data: result, error: null } : result, mutated: isMutating(handlers[name]), undoTag, }); diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts index 8d8da4116ecfb0e4aa1ca6d3f11bae9c4f31a2a9..417e417260a34536523bab65529fd404c299069b 100644 --- a/packages/loot-core/src/server/main.ts +++ b/packages/loot-core/src/server/main.ts @@ -1673,14 +1673,11 @@ handlers['set-server-url'] = async function ({ url, validate = true }) { if (validate) { // Validate the server is running - const { error } = await runHandler( - handlers['subscribe-needs-bootstrap'], - { - url, - }, - ); - if (error) { - return { error }; + const result = await runHandler(handlers['subscribe-needs-bootstrap'], { + url, + }); + if ('error' in result) { + return { error: result.error }; } } } @@ -2296,7 +2293,10 @@ export async function init(config) { export const lib = { getDataDir: fs.getDataDir, sendMessage: (msg, args) => connection.send(msg, args), - send: async (name, args) => { + send: async <K extends keyof Handlers, T extends Handlers[K]>( + name: K, + args?: Parameters<T>[0], + ): Promise<Awaited<ReturnType<T>>> => { const res = await runHandler(app.handlers[name], args); return res; }, diff --git a/packages/loot-core/src/server/mutators.ts b/packages/loot-core/src/server/mutators.ts index 3988e5c58f813f806ea8f2bf7f874693f09bfef6..d7b60ea1e1cbc3ebde594df504c2861d8e81a15a 100644 --- a/packages/loot-core/src/server/mutators.ts +++ b/packages/loot-core/src/server/mutators.ts @@ -1,6 +1,6 @@ import { captureException, captureBreadcrumb } from '../platform/exceptions'; import { sequential } from '../shared/async'; -import { type HandlerFunctions } from '../types/handlers'; +import { type HandlerFunctions, type Handlers } from '../types/handlers'; const runningMethods = new Set(); @@ -37,11 +37,11 @@ function wait(time) { return new Promise(resolve => setTimeout(resolve, time)); } -export async function runHandler( - handler, - args?, +export async function runHandler<T extends Handlers[keyof Handlers]>( + handler: T, + args?: Parameters<T>[0], { undoTag, name }: { undoTag?; name? } = {}, -) { +): Promise<ReturnType<T>> { // For debug reasons, track the latest handlers that have been // called _latestHandlerNames.push(name); diff --git a/packages/loot-core/src/server/schedules/types/handlers.ts b/packages/loot-core/src/server/schedules/types/handlers.ts index c15fb1479e887473bc7cac5b7e4adb463ac2cf1c..293fcc24007296e5fb714723fab35a5f15b2d24b 100644 --- a/packages/loot-core/src/server/schedules/types/handlers.ts +++ b/packages/loot-core/src/server/schedules/types/handlers.ts @@ -5,7 +5,7 @@ export interface SchedulesHandlers { schedule: { id?: string; name?: string; - post_transaction?: boolean; + posts_transaction?: boolean; }; conditions: unknown[]; }) => Promise<string>; diff --git a/packages/loot-core/src/types/api-handlers.d.ts b/packages/loot-core/src/types/api-handlers.d.ts index 71bc15306665e3b3579144325ec54458a5f9b976..c4e8c2b11b84df750d7e853b2f1fddfbb27838f3 100644 --- a/packages/loot-core/src/types/api-handlers.d.ts +++ b/packages/loot-core/src/types/api-handlers.d.ts @@ -59,7 +59,12 @@ export interface ApiHandlers { transactions; }) => Promise<unknown>; - 'api/transactions-add': (arg: { accountId; transactions }) => Promise<'ok'>; + 'api/transactions-add': (arg: { + accountId; + transactions; + runTransfers?: boolean; + learnCategories?: boolean; + }) => Promise<'ok'>; 'api/transactions-get': (arg: { accountId; @@ -74,9 +79,11 @@ export interface ApiHandlers { 'api/transaction-delete': (arg: { id }) => Promise<unknown>; - 'api/accounts-get': () => Promise<unknown>; + 'api/sync': () => Promise<unknown>; + + 'api/accounts-get': () => Promise<AccountEntity[]>; - 'api/account-create': (arg: { account; initialBalance }) => Promise<unknown>; + 'api/account-create': (arg: { account; initialBalance? }) => Promise<string>; 'api/account-update': (arg: { id; fields }) => Promise<unknown>; @@ -90,9 +97,11 @@ export interface ApiHandlers { 'api/account-delete': (arg: { id }) => Promise<unknown>; - 'api/categories-get': (arg: { grouped }) => Promise<unknown>; + 'api/categories-get': (arg: { + grouped; + }) => Promise<Array<CategoryGroupEntity> | Array<CategoryEntity>>; - 'api/category-group-create': (arg: { group }) => Promise<unknown>; + 'api/category-group-create': (arg: { group }) => Promise<string>; 'api/category-group-update': (arg: { id; fields }) => Promise<unknown>; @@ -101,15 +110,15 @@ export interface ApiHandlers { transferCategoryId; }) => Promise<unknown>; - 'api/category-create': (arg: { category }) => Promise<unknown>; + 'api/category-create': (arg: { category }) => Promise<string>; 'api/category-update': (arg: { id; fields }) => Promise<unknown>; 'api/category-delete': (arg: { id; transferCategoryId }) => Promise<unknown>; - 'api/payees-get': () => Promise<unknown>; + 'api/payees-get': () => Promise<PayeeEntity[]>; - 'api/payee-create': (arg: { payee }) => Promise<unknown>; + 'api/payee-create': (arg: { payee }) => Promise<string>; 'api/payee-update': (arg: { id; fields }) => Promise<unknown>; diff --git a/packages/loot-core/src/types/server-handlers.d.ts b/packages/loot-core/src/types/server-handlers.d.ts index 5a6487b21abe3e69213cecf067c9209605960306..f5022b44440a5811600fc314ece078733a0fa649 100644 --- a/packages/loot-core/src/types/server-handlers.d.ts +++ b/packages/loot-core/src/types/server-handlers.d.ts @@ -78,20 +78,20 @@ export interface ServerHandlers { 'category-create': (arg: { name; groupId; - isIncome; - hidden: boolean; - }) => Promise<unknown>; + isIncome?; + hidden?: boolean; + }) => Promise<string>; 'category-update': (category) => Promise<unknown>; 'category-move': (arg: { id; groupId; targetId }) => Promise<unknown>; - 'category-delete': (arg: { id; transferId }) => Promise<{ error?: string }>; + 'category-delete': (arg: { id; transferId? }) => Promise<{ error?: string }>; 'category-group-create': (arg: { name; isIncome?: boolean; - }) => Promise<unknown>; + }) => Promise<string>; 'category-group-update': (group) => Promise<unknown>; @@ -101,7 +101,7 @@ export interface ServerHandlers { 'must-category-transfer': (arg: { id }) => Promise<unknown>; - 'payee-create': (arg: { name }) => Promise<unknown>; + 'payee-create': (arg: { name }) => Promise<string>; 'payees-get': () => Promise<PayeeEntity[]>; @@ -165,7 +165,7 @@ export interface ServerHandlers { institution; publicToken; accountIds; - offbudgetIds; + offbudgetIds?; }) => Promise<unknown>; 'gocardless-accounts-connect': (arg: { @@ -177,7 +177,7 @@ export interface ServerHandlers { 'account-create': (arg: { name: string; - balance: number; + balance?: number; offBudget?: boolean; closed?: 0 | 1; }) => Promise<string>; @@ -197,7 +197,7 @@ export interface ServerHandlers { 'poll-web-token-stop': () => Promise<'ok'>; - 'accounts-sync': (arg: { id }) => Promise<{ + 'accounts-sync': (arg: { id? }) => Promise<{ errors: unknown; newTransactions: unknown; matchedTransactions: unknown; diff --git a/upcoming-release-notes/2136.md b/upcoming-release-notes/2136.md new file mode 100644 index 0000000000000000000000000000000000000000..90a5e66c3b61f790a4a9bc2ac12e4ea8fd667d88 --- /dev/null +++ b/upcoming-release-notes/2136.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [twk3] +--- + +TypeScript: Add proper types to runHandler