mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-21 15:36:50 -05:00
Enable restrict-template-expressions linting rule (#7181)
* [AI] Promote typescript/restrict-template-expressions to error and fix violations Convert the oxlint rule from "warn" to "error" and fix all 42 violations by wrapping non-string template expressions with String(). This ensures type safety in template literals across the codebase. https://claude.ai/code/session_01Uk8SwFbD6HuUuo3SSMwU9z * Add release notes for PR #7181 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
85e3166495
commit
541df52441
@@ -61,7 +61,7 @@ export class ConfigurationPage {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unrecognized import type: ${type}`);
|
||||
throw new Error(`Unrecognized import type: ${String(type)}`);
|
||||
}
|
||||
|
||||
const fileChooser = await fileChooserPromise;
|
||||
|
||||
@@ -39,7 +39,7 @@ export class CustomReportPage {
|
||||
.click();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized mode: ${mode}`);
|
||||
throw new Error(`Unrecognized mode: ${String(mode)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,7 +779,7 @@ export function useBudgetActions() {
|
||||
});
|
||||
return null;
|
||||
default:
|
||||
throw new Error(`Unknown budget action type: ${type}`);
|
||||
throw new Error(`Unknown budget action type: ${String(type)}`);
|
||||
}
|
||||
},
|
||||
onSuccess: notification => {
|
||||
|
||||
@@ -95,7 +95,7 @@ export const HelpMenu = () => {
|
||||
dispatch(pushModal({ modal: { name: 'goal-templates' } }));
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${item}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(item)}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ export function IncomeMenu({
|
||||
onClose();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
}}
|
||||
items={[
|
||||
|
||||
@@ -68,7 +68,9 @@ export const getInitialState = (template: Template | null): ReducerState => {
|
||||
case 'error':
|
||||
throw new Error('An error occurred while parsing the template');
|
||||
default:
|
||||
throw new Error(`Unknown template type: ${type satisfies undefined}`);
|
||||
throw new Error(
|
||||
`Unknown template type: ${String(type satisfies undefined)}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,7 +170,9 @@ const changeType = (
|
||||
};
|
||||
default:
|
||||
// Make sure we're not missing any cases
|
||||
throw new Error(`Unknown display type: ${visualType satisfies never}`);
|
||||
throw new Error(
|
||||
`Unknown display type: ${String(visualType satisfies never)}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -251,6 +255,6 @@ export const templateReducer = (
|
||||
return mapTemplateTypesForUpdate(state, action.payload);
|
||||
default:
|
||||
// Make sure we're not missing any cases
|
||||
throw new Error(`Unknown display type: ${type satisfies never}`);
|
||||
throw new Error(`Unknown display type: ${String(type satisfies never)}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ export function BalanceMenu({
|
||||
onCarryover?.(!carryover);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
}}
|
||||
items={[
|
||||
|
||||
@@ -506,7 +506,7 @@ function SelectedTransactionsFloatingActionBar({
|
||||
: integerToCurrency(Number(value));
|
||||
break;
|
||||
case 'notes':
|
||||
displayValue = `${mode} with ${value}`;
|
||||
displayValue = `${mode} with ${String(value)}`;
|
||||
break;
|
||||
default:
|
||||
displayValue = value;
|
||||
@@ -514,15 +514,15 @@ function SelectedTransactionsFloatingActionBar({
|
||||
}
|
||||
|
||||
showUndoNotification({
|
||||
message: `Successfully updated ${name} of ${ids.length} transaction${ids.length > 1 ? 's' : ''} to [${displayValue}](#${displayValue}).`,
|
||||
message: `Successfully updated ${name} of ${ids.length} transaction${ids.length > 1 ? 's' : ''} to [${String(displayValue)}](#${String(displayValue)}).`,
|
||||
messageActions: {
|
||||
[String(displayValue)]: () => {
|
||||
switch (name) {
|
||||
case 'account':
|
||||
void navigate(`/accounts/${value}`);
|
||||
void navigate(`/accounts/${String(value)}`);
|
||||
break;
|
||||
case 'category':
|
||||
void navigate(`/categories/${value}`);
|
||||
void navigate(`/categories/${String(value)}`);
|
||||
break;
|
||||
case 'payee':
|
||||
void navigate(`/payees`);
|
||||
|
||||
@@ -295,7 +295,7 @@ function AdditionalAccountMenu({
|
||||
onToggleReconciled?.();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -117,7 +117,7 @@ export function EnvelopeIncomeBalanceMenuModal({
|
||||
onShowActivity?.();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
}}
|
||||
items={[
|
||||
|
||||
@@ -26,7 +26,7 @@ export function SelectField({
|
||||
option,
|
||||
hasHeaderRow
|
||||
? option
|
||||
: `Column ${parseInt(option) + 1} (${firstTransaction[option]})`,
|
||||
: `Column ${parseInt(option) + 1} (${String(firstTransaction[option])})`,
|
||||
] as const,
|
||||
);
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ export function SelectLinkedAccountsModal({
|
||||
externalAccounts: toSort as SyncServerGoCardlessAccount[],
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unrecognized sync source: ${syncSource}`);
|
||||
throw new Error(`Unrecognized sync source: ${String(syncSource)}`);
|
||||
}
|
||||
}, [externalAccounts, syncSource, requisitionId]);
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ export const PayeeTableRow = memo(
|
||||
onCreateRule(id);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
setMenuOpen(false);
|
||||
}}
|
||||
|
||||
@@ -671,7 +671,7 @@ export function Overview({ dashboard }: OverviewProps) {
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
`Unrecognized menu option: ${item}`,
|
||||
`Unrecognized menu option: ${String(item)}`,
|
||||
);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -99,7 +99,7 @@ export const RuleRow = memo(
|
||||
onEditRule(rule);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
setMenuOpen(false);
|
||||
}}
|
||||
|
||||
@@ -137,7 +137,7 @@ export function Value<T>({
|
||||
|
||||
return '…';
|
||||
default:
|
||||
throw new Error(`Unknown field ${field}`);
|
||||
throw new Error(`Unknown field ${String(field)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ export function Schedules() {
|
||||
await send('schedule/delete', { id });
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown action: ${name}`);
|
||||
throw new Error(`Unknown action: ${String(name)}`);
|
||||
}
|
||||
},
|
||||
[],
|
||||
|
||||
@@ -272,7 +272,9 @@ export function Account<FieldName extends SheetFields<'account'>>({
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Unrecognized menu option: ${type}`);
|
||||
throw new Error(
|
||||
`Unrecognized menu option: ${String(type)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
setMenuOpen(false);
|
||||
|
||||
@@ -114,7 +114,7 @@ export const TagRow = memo(
|
||||
deleteTag({ id: tag.id });
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized menu option: ${name}`);
|
||||
throw new Error(`Unrecognized menu option: ${String(name)}`);
|
||||
}
|
||||
setMenuOpen(false);
|
||||
}}
|
||||
|
||||
@@ -400,7 +400,7 @@ expect.extend({
|
||||
} else {
|
||||
return {
|
||||
message: () =>
|
||||
`Expected ${validPayeeListWithFavorite} to have favorite stars`,
|
||||
`Expected ${String(validPayeeListWithFavorite)} to have favorite stars`,
|
||||
pass: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ export function useTransactionBatchActions() {
|
||||
if (name === 'notes') {
|
||||
if (mode === 'prepend') {
|
||||
valueToSet =
|
||||
trans.notes === null ? value : `${value}${trans.notes}`;
|
||||
trans.notes === null ? value : `${String(value)}${trans.notes}`;
|
||||
} else if (mode === 'append') {
|
||||
valueToSet =
|
||||
trans.notes === null ? value : `${trans.notes}${value}`;
|
||||
trans.notes === null ? value : `${trans.notes}${String(value)}`;
|
||||
} else if (mode === 'replace') {
|
||||
valueToSet = value;
|
||||
} else if (
|
||||
|
||||
@@ -323,7 +323,10 @@ async function startSyncServer() {
|
||||
|
||||
return await Promise.race([syncServerPromise, syncServerTimeout]); // Either the server has started or the timeout is reached
|
||||
} catch (error) {
|
||||
logMessage('error', `Sync-Server: Error starting sync server: ${error}`);
|
||||
logMessage(
|
||||
'error',
|
||||
`Sync-Server: Error starting sync server: ${String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +664,7 @@ ipcMain.handle(
|
||||
} catch (error) {
|
||||
logMessage(
|
||||
'error',
|
||||
`There was an error moving your directory: ${error}`,
|
||||
`There was an error moving your directory: ${String(error)}`,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
@@ -687,7 +690,7 @@ ipcMain.handle(
|
||||
// This call needs to succeed to allow the user to continue using the app with the files in the new location.
|
||||
logMessage(
|
||||
'error',
|
||||
`There was an error removing the old directory: ${error}`,
|
||||
`There was an error removing the old directory: ${String(error)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@ const lazyLoadBackend = async (isDev: boolean) => {
|
||||
} catch (error) {
|
||||
console.error('Failed to init the server bundle after all retries:', error);
|
||||
throw new Error(
|
||||
`Failed to init the server bundle after all retries: ${error}`,
|
||||
`Failed to init the server bundle after all retries: ${String(error)}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ export function patchFetchForSqlJS(baseURL: string) {
|
||||
},
|
||||
});
|
||||
}
|
||||
return Promise.reject(new Error(`fetch not mocked for ${url}`));
|
||||
return Promise.reject(new Error(`fetch not mocked for ${String(url)}`));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -944,7 +944,7 @@ handlers['api/schedule-update'] = withMutation(async function ({
|
||||
break;
|
||||
default:
|
||||
throw APIError(
|
||||
`Invalid amount operator: ${value}. Expected: is, isapprox, or isbetween`,
|
||||
`Invalid amount operator: ${String(value)}. Expected: is, isapprox, or isbetween`,
|
||||
);
|
||||
}
|
||||
sched._conditions[amountIndex].op = convertedOp;
|
||||
|
||||
@@ -715,7 +715,11 @@ const compileOp = saveStack('op', (state, fieldRef, opData) => {
|
||||
// Dedupe the ids
|
||||
const ids = [...new Set(right)];
|
||||
|
||||
return `${left} IN (` + ids.map(id => `'${id}'`).join(',') + ')';
|
||||
return (
|
||||
`${String(left)} IN (` +
|
||||
ids.map(id => `'${String(id)}'`).join(',') +
|
||||
')'
|
||||
);
|
||||
}
|
||||
case '$like': {
|
||||
const [left, right] = valArray(state, [lhs, rhs], ['string', 'string']);
|
||||
|
||||
@@ -611,7 +611,7 @@ export class CategoryTemplateContext {
|
||||
monthUtils.addMonths(date, numPeriods * 12);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognized periodic period: ${period}`);
|
||||
throw new Error(`Unrecognized periodic period: ${String(period)}`);
|
||||
}
|
||||
|
||||
//shift the starting date until its in our month or in the future
|
||||
|
||||
@@ -89,7 +89,7 @@ const exportModel = {
|
||||
|
||||
if (!isWidgetType(widget.type)) {
|
||||
throw new ValidationError(
|
||||
`Invalid widget.${idx}.type value ${widget.type}.`,
|
||||
`Invalid widget.${idx}.type value ${String(widget.type)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export const mappingsFromString = (str: string): Mappings => {
|
||||
);
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : e;
|
||||
throw new Error(`Failed to parse mapping: ${message}`);
|
||||
throw new Error(`Failed to parse mapping: ${String(message)}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ export function getDownloadError({
|
||||
default:
|
||||
const info =
|
||||
meta && typeof meta === 'object' && 'fileId' in meta && meta.fileId
|
||||
? `, fileId: ${meta.fileId}`
|
||||
? `, fileId: ${String(meta.fileId)}`
|
||||
: '';
|
||||
return t(
|
||||
'Something went wrong trying to download that file, sorry! Visit https://actualbudget.org/contact/ for support. reason: {{reason}}{{info}}',
|
||||
|
||||
@@ -91,12 +91,12 @@ if (values.config) {
|
||||
|
||||
if (!configExists) {
|
||||
console.log(
|
||||
`Please specify a valid config path. The path ${values.config} does not exist.`,
|
||||
`Please specify a valid config path. The path ${String(values.config)} does not exist.`,
|
||||
);
|
||||
|
||||
process.exit();
|
||||
} else {
|
||||
console.log(`Loading config from ${values.config}`);
|
||||
console.log(`Loading config from ${String(values.config)}`);
|
||||
const configJson = JSON.parse(readFileSync(values.config, 'utf-8'));
|
||||
process.env.ACTUAL_CONFIG_PATH = values.config;
|
||||
setupDataDir(configJson.dataDir);
|
||||
|
||||
@@ -55,7 +55,7 @@ const requestLoggerMiddleware = expressWinston.logger({
|
||||
const { timestamp, level, meta } = args;
|
||||
const { res, req } = meta as { res: Response; req: Request };
|
||||
|
||||
return `${timestamp} ${level}: ${req.method} ${res.statusCode} ${req.url}`;
|
||||
return `${String(timestamp)} ${String(level)}: ${req.method} ${res.statusCode} ${req.url}`;
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user