From 6c028f6e776f9eacddd8c74cc7892f812a901e37 Mon Sep 17 00:00:00 2001 From: Julian Dominguez-Schatz Date: Mon, 20 Jan 2025 17:09:27 -0500 Subject: [PATCH] Fix `send` types in a number of places (2/2) (#4147) * Fix `send` types in a number of places * Add release notes * PR feedback --- .../src/components/accounts/Account.tsx | 16 +++++++++++---- .../src/components/modals/EditUser.tsx | 8 ++++---- .../src/components/reports/Overview.tsx | 2 +- .../select/RecurringSchedulePicker.tsx | 10 ++++++++-- .../loot-core/src/client/actions/budgets.ts | 7 ++----- .../loot-core/src/client/actions/prefs.ts | 2 +- .../src/client/data-hooks/transactions.ts | 2 +- .../loot-core/src/client/query-helpers.ts | 4 ++-- .../src/platform/client/fetch/index.d.ts | 3 ++- .../src/server/admin/types/handlers.ts | 8 +++++--- packages/loot-core/src/server/aql/compiler.ts | 5 ++--- .../src/server/rules/types/handlers.ts | 8 ++++---- .../loot-core/src/server/schedules/app.ts | 2 ++ .../src/server/schedules/types/handlers.ts | 14 ++++++++----- .../loot-core/src/types/models/simplefin.d.ts | 2 ++ .../loot-core/src/types/server-handlers.d.ts | 20 +++++++++++++------ upcoming-release-notes/4147.md | 6 ++++++ 17 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 upcoming-release-notes/4147.md diff --git a/packages/desktop-client/src/components/accounts/Account.tsx b/packages/desktop-client/src/components/accounts/Account.tsx index 26b38aa121b..800152be777 100644 --- a/packages/desktop-client/src/components/accounts/Account.tsx +++ b/packages/desktop-client/src/components/accounts/Account.tsx @@ -480,7 +480,11 @@ class AccountInternal extends PureComponent< } fetchAllIds = async () => { - const { data } = await runQuery(this.paged?.query.select('id')); + if (!this.paged) { + return []; + } + + const { data } = await runQuery(this.paged.query.select('id')); // Remember, this is the `grouped` split type so we need to deal // with the `subtransactions` property return data.reduce((arr: string[], t: TransactionEntity) => { @@ -709,12 +713,12 @@ class AccountInternal extends PureComponent< }; async calculateBalances() { - if (!this.canCalculateBalance()) { + if (!this.canCalculateBalance() || !this.paged) { return null; } const { data } = await runQuery( - this.paged?.query + this.paged.query .options({ splits: 'none' }) .select([{ balance: { $sumOver: '$amount' } }]), ); @@ -930,8 +934,12 @@ class AccountInternal extends PureComponent< } getFilteredAmount = async () => { + if (!this.paged) { + return 0; + } + const { data: amount } = await runQuery( - this.paged?.query.calculate({ $sum: '$amount' }), + this.paged.query.calculate({ $sum: '$amount' }), ); return amount; }; diff --git a/packages/desktop-client/src/components/modals/EditUser.tsx b/packages/desktop-client/src/components/modals/EditUser.tsx index 5fdb1d71a30..5fff56987fc 100644 --- a/packages/desktop-client/src/components/modals/EditUser.tsx +++ b/packages/desktop-client/src/components/modals/EditUser.tsx @@ -83,14 +83,14 @@ function useSaveUser() { user: User, setError: (error: string) => void, ): Promise { - const res = (await send(method, user)) || {}; - if (!res['error']) { - const newId = res['id']; + const res = await send(method, user); + if (!('error' in res)) { + const newId = res.id; if (newId) { user.id = newId; } } else { - const error = res['error']; + const error = res.error; setError(getUserDirectoryErrors(error)); if (error === 'token-expired') { dispatch( diff --git a/packages/desktop-client/src/components/reports/Overview.tsx b/packages/desktop-client/src/components/reports/Overview.tsx index f3e467c7473..61a9ab1c944 100644 --- a/packages/desktop-client/src/components/reports/Overview.tsx +++ b/packages/desktop-client/src/components/reports/Overview.tsx @@ -247,7 +247,7 @@ export function Overview() { const res = await send('dashboard-import', { filepath }); setIsImporting(false); - if (res.error) { + if ('error' in res) { switch (res.error) { case 'json-parse-error': dispatch( diff --git a/packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx b/packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx index eaae2bfb8de..b95969135d9 100644 --- a/packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx +++ b/packages/desktop-client/src/components/select/RecurringSchedulePicker.tsx @@ -234,7 +234,11 @@ function reducer(state: ReducerState, action: ReducerAction): ReducerState { } } -function SchedulePreview({ previewDates }: { previewDates: Date[] }) { +function SchedulePreview({ + previewDates, +}: { + previewDates: string[] | string; +}) { const dateFormat = (useDateFormat() || 'MM/dd/yyyy') .replace('MM', 'M') .replace('dd', 'd'); @@ -369,7 +373,9 @@ function RecurringScheduleTooltip({ onSave: (config: RecurConfig) => void; }) { const { t } = useTranslation(); - const [previewDates, setPreviewDates] = useState(null); + const [previewDates, setPreviewDates] = useState( + null, + ); const { FREQUENCY_OPTIONS } = useFrequencyOptions(); diff --git a/packages/loot-core/src/client/actions/budgets.ts b/packages/loot-core/src/client/actions/budgets.ts index f84aae3a94a..e5eab6e3f50 100644 --- a/packages/loot-core/src/client/actions/budgets.ts +++ b/packages/loot-core/src/client/actions/budgets.ts @@ -148,14 +148,11 @@ export function createBudget({ testMode = false, demoMode = false } = {}) { }; } -export function validateBudgetName(name: string): { - valid: boolean; - message?: string; -} { +export function validateBudgetName(name: string) { return send('validate-budget-name', { name }); } -export function uniqueBudgetName(name: string): string { +export function uniqueBudgetName(name: string) { return send('unique-budget-name', { name }); } diff --git a/packages/loot-core/src/client/actions/prefs.ts b/packages/loot-core/src/client/actions/prefs.ts index 137010a18fc..713c66bd51b 100644 --- a/packages/loot-core/src/client/actions/prefs.ts +++ b/packages/loot-core/src/client/actions/prefs.ts @@ -43,7 +43,7 @@ export function loadPrefs() { ); // We need to load translations before the app renders - setI18NextLanguage(globalPrefs.language); + setI18NextLanguage(globalPrefs.language ?? ''); return prefs; }; diff --git a/packages/loot-core/src/client/data-hooks/transactions.ts b/packages/loot-core/src/client/data-hooks/transactions.ts index 8c76510a45f..dd35d0de227 100644 --- a/packages/loot-core/src/client/data-hooks/transactions.ts +++ b/packages/loot-core/src/client/data-hooks/transactions.ts @@ -248,7 +248,7 @@ export function usePreviewTransactions(): UsePreviewTransactionsResult { if (!isUnmounted) { const withDefaults = newTrans.map(t => ({ ...t, - category: statuses.get(t.schedule), + category: t.schedule != null ? statuses.get(t.schedule) : undefined, schedule: t.schedule, subtransactions: t.subtransactions?.map( (st: TransactionEntity) => ({ diff --git a/packages/loot-core/src/client/query-helpers.ts b/packages/loot-core/src/client/query-helpers.ts index 7df1646109d..1f5ebed926b 100644 --- a/packages/loot-core/src/client/query-helpers.ts +++ b/packages/loot-core/src/client/query-helpers.ts @@ -3,7 +3,7 @@ import { listen, send } from '../platform/client/fetch'; import { once } from '../shared/async'; import { getPrimaryOrderBy, type Query } from '../shared/query'; -export async function runQuery(query) { +export async function runQuery(query: Query) { return send('query', query.serialize()); } @@ -207,7 +207,7 @@ export class LiveQuery { protected fetchData = async ( runQuery: () => Promise<{ data: Data; - dependencies: Set; + dependencies: string[]; }>, ) => { // TODO: precompile queries, or cache compilation results on the diff --git a/packages/loot-core/src/platform/client/fetch/index.d.ts b/packages/loot-core/src/platform/client/fetch/index.d.ts index 417f4f917d9..d6e4d4a31cd 100644 --- a/packages/loot-core/src/platform/client/fetch/index.d.ts +++ b/packages/loot-core/src/platform/client/fetch/index.d.ts @@ -41,7 +41,8 @@ export type Unlisten = typeof unlisten; /** Mock functions */ export function initServer(handlers: { query: (query: { table: string; selectExpressions: unknown }) => Promise<{ - data: unknown; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data: any; dependencies: string[]; }>; getCell?: () => { value: number }; diff --git a/packages/loot-core/src/server/admin/types/handlers.ts b/packages/loot-core/src/server/admin/types/handlers.ts index ec99a415925..359471820b8 100644 --- a/packages/loot-core/src/server/admin/types/handlers.ts +++ b/packages/loot-core/src/server/admin/types/handlers.ts @@ -6,15 +6,17 @@ export interface AdminHandlers { 'user-delete-all': ( ids: string[], - ) => Promise<{ someDeletionsFailed: boolean; ids?: number[] }>; + ) => Promise< + { someDeletionsFailed: boolean; ids?: number[] } | { error: string } + >; 'user-add': ( user: Omit, - ) => Promise<{ error?: string } | { id: string }>; + ) => Promise<{ error: string } | { id: string }>; 'user-update': ( user: Omit, - ) => Promise<{ error?: string } | { id: string }>; + ) => Promise<{ error: string } | { id: string }>; 'access-add': ( user: NewUserAccessEntity, diff --git a/packages/loot-core/src/server/aql/compiler.ts b/packages/loot-core/src/server/aql/compiler.ts index 61c0a875caa..02ae4ffdd15 100644 --- a/packages/loot-core/src/server/aql/compiler.ts +++ b/packages/loot-core/src/server/aql/compiler.ts @@ -1,4 +1,5 @@ import { getNormalisedString } from '../../shared/normalisation'; +import { QueryState } from '../../shared/query'; // @ts-strict-ignore let _uid = 0; @@ -1005,9 +1006,7 @@ export type SchemaConfig = { | Record | ((name: string, config: { withDead; isJoin; tableOptions }) => unknown); tableFilters?: (name: string) => unknown[]; - customizeQuery?: ( - queryString: T, - ) => T; + customizeQuery?: (queryString: QueryState) => QueryState; views?: Record< string, { diff --git a/packages/loot-core/src/server/rules/types/handlers.ts b/packages/loot-core/src/server/rules/types/handlers.ts index 7884f6e4cd8..766c45f2be5 100644 --- a/packages/loot-core/src/server/rules/types/handlers.ts +++ b/packages/loot-core/src/server/rules/types/handlers.ts @@ -45,9 +45,9 @@ export interface RulesHandlers { 'rules-get': () => Promise; - // TODO: change return value to `RuleEntity` - 'rule-get': (arg: { id: string }) => Promise; + 'rule-get': (arg: { id: RuleEntity['id'] }) => Promise; - // TODO: change types to `TransactionEntity` - 'rules-run': (arg: { transaction }) => Promise; + 'rules-run': (arg: { + transaction: TransactionEntity; + }) => Promise; } diff --git a/packages/loot-core/src/server/schedules/app.ts b/packages/loot-core/src/server/schedules/app.ts index a61f762cbc2..7016d6f627a 100644 --- a/packages/loot-core/src/server/schedules/app.ts +++ b/packages/loot-core/src/server/schedules/app.ts @@ -306,6 +306,8 @@ export async function updateSchedule({ await db.updateWithSchema('schedules', schedule); }); + + return schedule.id; } export async function deleteSchedule({ id }) { diff --git a/packages/loot-core/src/server/schedules/types/handlers.ts b/packages/loot-core/src/server/schedules/types/handlers.ts index 3cfa706d138..42218e1bd93 100644 --- a/packages/loot-core/src/server/schedules/types/handlers.ts +++ b/packages/loot-core/src/server/schedules/types/handlers.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { DiscoverScheduleEntity } from '../../../types/models'; +import { DiscoverScheduleEntity, ScheduleEntity } from '../../../types/models'; export interface SchedulesHandlers { 'schedule/create': (arg: { @@ -15,13 +15,17 @@ export interface SchedulesHandlers { schedule; conditions?; resetNextDate?: boolean; - }) => Promise; + }) => Promise; - 'schedule/delete': (arg: { id: string }) => Promise; + 'schedule/delete': (arg: { id: ScheduleEntity['id'] }) => Promise; - 'schedule/skip-next-date': (arg: { id: string }) => Promise; + 'schedule/skip-next-date': (arg: { + id: ScheduleEntity['id']; + }) => Promise; - 'schedule/post-transaction': (arg: { id: string }) => Promise; + 'schedule/post-transaction': (arg: { + id: ScheduleEntity['id']; + }) => Promise; 'schedule/force-run-service': () => Promise; diff --git a/packages/loot-core/src/types/models/simplefin.d.ts b/packages/loot-core/src/types/models/simplefin.d.ts index c4c7f97579a..cd76cb7ba14 100644 --- a/packages/loot-core/src/types/models/simplefin.d.ts +++ b/packages/loot-core/src/types/models/simplefin.d.ts @@ -2,6 +2,7 @@ import { AccountEntity } from './account'; import { BankSyncResponse } from './bank-sync'; export type SimpleFinOrganization = { + id: string; name: string; domain: string; }; @@ -9,6 +10,7 @@ export type SimpleFinOrganization = { export type SimpleFinAccount = { id: string; name: string; + balance: number; org: SimpleFinOrganization; }; diff --git a/packages/loot-core/src/types/server-handlers.d.ts b/packages/loot-core/src/types/server-handlers.d.ts index 3007a8735a0..7156ce2eb6f 100644 --- a/packages/loot-core/src/types/server-handlers.d.ts +++ b/packages/loot-core/src/types/server-handlers.d.ts @@ -52,7 +52,7 @@ export interface ServerHandlers { payees; }) => Promise; - 'transactions-export-query': (arg: { query: QueryState }) => Promise; + 'transactions-export-query': (arg: { query: QueryState }) => Promise; 'get-categories': () => Promise<{ grouped: Array; @@ -109,7 +109,7 @@ export interface ServerHandlers { 'payees-get': () => Promise; - 'payees-get-rule-counts': () => Promise; + 'payees-get-rule-counts': () => Promise>; 'payees-merge': (arg: { targetId; mergeIds }) => Promise; @@ -141,7 +141,8 @@ export interface ServerHandlers { 'create-query': (arg: { sheetName; name; query }) => Promise; - query: (query: Query) => Promise<{ data: unknown; dependencies }>; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + query: (query: Query) => Promise<{ data: any; dependencies: string[] }>; 'account-update': (arg: { id; name }) => Promise; @@ -182,7 +183,10 @@ export interface ServerHandlers { 'account-move': (arg: { id; targetId }) => Promise; - 'secret-set': (arg: { name: string; value: string | null }) => Promise; + 'secret-set': (arg: { + name: string; + value: string | null; + }) => Promise<{ error?: string; reason?: string }>; 'secret-check': (arg: string) => Promise; 'gocardless-poll-web-token': (arg: { @@ -196,7 +200,11 @@ export interface ServerHandlers { 'simplefin-status': () => Promise<{ configured: boolean }>; - 'simplefin-accounts': () => Promise<{ accounts: SimpleFinAccount[] }>; + 'simplefin-accounts': () => Promise<{ + accounts?: SimpleFinAccount[]; + error_code?: string; + reason?: string; + }>; 'simplefin-batch-sync': ({ ids }: { ids: string[] }) => Promise< { @@ -326,7 +334,7 @@ export interface ServerHandlers { return_url; loginMethod?: 'openid'; }, - ) => Promise<{ error?: string }>; + ) => Promise<{ error?: string; redirect_url?: string }>; 'subscribe-sign-out': () => Promise<'ok'>; diff --git a/upcoming-release-notes/4147.md b/upcoming-release-notes/4147.md new file mode 100644 index 00000000000..7dc1a4012e2 --- /dev/null +++ b/upcoming-release-notes/4147.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [jfdoming] +--- + +Fix `send` types in a number of places (2/2)