chore: strengthen backend eslint profile

This commit is contained in:
2026-09-28 16:37:01 +03:00
committed by ksv741
parent 53b2794963
commit a970eaaf7a
179 changed files with 4485 additions and 2716 deletions
+104 -91
View File
@@ -1,58 +1,58 @@
import { planIncomePeriod } from './income/income.api';
import { dateOnlyBounds, moscowDate } from './investment-calendar';
import {
operationIntervals,
type OperationInterval,
operationIntervals,
} from './operations/domain/operations-sync-plan';
export type InvestmentScreen = {
screen:
| 'accounts'
| 'account'
| 'operations'
| 'income'
| 'events'
| 'stocks'
| 'bonds'
| 'stock'
| 'bond';
accountId?: string;
candlePeriod?: 'all' | 'halfYear' | 'month' | 'year';
candleRange?: { from: Date; to: Date };
from?: string;
to?: string;
instrumentUid?: string;
query?: string;
candlePeriod?: 'month' | 'halfYear' | 'year' | 'all';
candleRange?: { from: Date; to: Date };
screen:
| 'account' |
'accounts' |
'bond' |
'bonds' |
'events' |
'income' |
'operations' |
'stock' |
'stocks';
to?: string;
};
const defaultEventDays = 30;
const incomeHistoryYears = 5;
const candleMonths = { month: 1, halfYear: 6, year: 12 };
type Account = { accountId: string; openedOn: string | null };
type Account = { accountId: string; openedOn: null | string };
type Instrument = {
uid: string;
type: 'STOCK' | 'BOND';
historyFrom: Date | null;
type: 'BOND' | 'STOCK';
uid: string;
};
type Source = {
kind:
| 'membership'
| 'portfolio'
| 'operations'
| 'metadata'
| 'catalog'
| 'quote'
| 'company'
| 'metrics'
| 'calendar'
| 'candles';
accountId?: string;
instrumentUid?: string;
instrumentType?: 'STOCK' | 'BOND';
from?: Date;
to?: Date;
instrumentType?: 'BOND' | 'STOCK';
instrumentUid?: string;
kind:
| 'calendar' |
'candles' |
'catalog' |
'company' |
'membership' |
'metadata' |
'metrics' |
'operations' |
'portfolio' |
'quote';
priority: 'discovery' | 'history' | 'screen';
query?: string;
priority: 'discovery' | 'screen' | 'history';
to?: Date;
};
// Expands screen scope, never credentials or arbitrary caller-supplied jobs.
@@ -74,19 +74,19 @@ export function planInvestmentScreen(
screen.accountId === 'all' ||
account.accountId === screen.accountId,
);
const unavailable: { resourceKey: string; reason: string }[] = [];
const unavailable: { reason: string; resourceKey: string }[] = [];
const operations = (from: Date, to: Date, instrumentUid?: string) => {
const targets = accounts.flatMap((account) =>
from < to
? [
from < to ?
[
{
accountId: account.accountId,
from,
to,
...(instrumentUid ? { instrumentUid } : {}),
},
]
: [],
] :
[],
);
sources.push(
...operationIntervals(targets).map((range) => ({
@@ -105,16 +105,18 @@ export function planInvestmentScreen(
})),
);
const knownOpening =
accounts.length && accounts.every((account) => account.openedOn)
? new Date(
accounts.length && accounts.every((account) => account.openedOn) ?
new Date(
// eslint-disable-next-line sonarjs/no-alphabetical-sort -- Code-unit ordering is intentional for canonical keys and ISO dates; locale collation would change persisted bindings.
`${accounts.map((account) => account.openedOn ?? '').sort()[0]}T00:00:00+03:00`,
)
: undefined;
) :
undefined;
if (!context.membershipKnown) return { sources, unavailable, now };
if (
['accounts', 'account', 'events', 'stock', 'bond'].includes(screen.screen)
)
['account', 'accounts', 'bond', 'events', 'stock'].includes(screen.screen)
) {
portfolio();
}
if (
screen.screen === 'operations' ||
screen.screen === 'stock' ||
@@ -137,18 +139,19 @@ export function planInvestmentScreen(
);
for (const range of [
period.selected,
...(screen.screen === 'income'
? [period.previous, ...(period.yearAgo ? [period.yearAgo] : [])]
: []),
...(screen.screen === 'income' ?
[period.previous, ...(period.yearAgo ? [period.yearAgo] : [])] :
[]),
]) {
const bounds = dateOnlyBounds(range, now);
operations(bounds.from, bounds.to);
}
if (screen.screen === 'income' && !period.yearAgo)
if (screen.screen === 'income' && !period.yearAgo) {
unavailable.push({
resourceKey: 'income/yearAgo', // gitleaks:allow public resource identifier
reason: 'calendar_or_account_boundary',
});
}
if (screen.screen === 'account') {
const range = ledgerRange(
screen.from,
@@ -160,13 +163,14 @@ export function planInvestmentScreen(
operations(range.from, range.to);
}
}
if (screen.screen === 'stocks' || screen.screen === 'bonds')
if (screen.screen === 'stocks' || screen.screen === 'bonds') {
sources.push({
kind: 'catalog',
instrumentType: screen.screen === 'stocks' ? 'STOCK' : 'BOND',
query: screen.query?.trim().toUpperCase() ?? '',
priority: 'screen',
});
}
const instruments = context.instruments.filter(
(instrument) =>
!screen.instrumentUid || instrument.uid === screen.instrumentUid,
@@ -175,20 +179,22 @@ export function planInvestmentScreen(
screen.instrumentUid &&
!instruments.length &&
(screen.screen === 'stock' || screen.screen === 'bond')
)
) {
instruments.push({
uid: screen.instrumentUid,
type: screen.screen === 'stock' ? 'STOCK' : 'BOND',
historyFrom: null,
});
}
for (const instrument of instruments) {
const identity = {
instrumentUid: instrument.uid,
instrumentType: instrument.type,
};
sources.push({ ...identity, kind: 'metadata', priority: 'screen' });
if (['stocks', 'bonds', 'stock', 'bond'].includes(screen.screen))
if (['bond', 'bonds', 'stock', 'stocks'].includes(screen.screen)) {
sources.push({ ...identity, kind: 'quote', priority: 'screen' });
}
if (screen.screen === 'stock' || screen.screen === 'bond') {
sources.push({
...identity,
@@ -197,47 +203,51 @@ export function planInvestmentScreen(
});
const from = new Date(now);
const period = screen.candlePeriod ?? 'month';
if (period !== 'all')
if (period !== 'all') {
// eslint-disable-next-line security/detect-object-injection -- The period belongs to the validated candle-period union.
from.setUTCMonth(from.getUTCMonth() - candleMonths[period]);
}
const range =
screen.candleRange ??
(period === 'all'
? instrument.historyFrom
? { from: instrument.historyFrom, to: now }
: null
: { from, to: now });
if (range)
(period === 'all' ?
instrument.historyFrom ?
{ from: instrument.historyFrom, to: now } :
null :
{ from, to: now });
if (range) {
sources.push({
...identity,
kind: 'candles',
...range,
priority: 'screen',
});
else
} else {
unavailable.push({
resourceKey: `candles/${instrument.uid}/all`,
reason: 'history_start_unavailable',
});
}
}
if (['account', 'events', 'stock', 'bond'].includes(screen.screen)) {
if (['account', 'bond', 'events', 'stock'].includes(screen.screen)) {
const day =
screen.screen === 'stock' || screen.screen === 'bond'
? moscowDate(now)
: now.toISOString().slice(0, 10);
screen.screen === 'stock' || screen.screen === 'bond' ?
moscowDate(now) :
now.toISOString().slice(0, 10);
const from =
screen.screen === 'events' && screen.from
? new Date(`${screen.from}T00:00:00Z`)
: new Date(`${day}T00:00:00Z`);
screen.screen === 'events' && screen.from ?
new Date(`${screen.from}T00:00:00Z`) :
new Date(`${day}T00:00:00Z`);
const to =
screen.screen === 'events' && screen.to
? new Date(`${screen.to}T00:00:00Z`)
: new Date(from);
screen.screen === 'events' && screen.to ?
new Date(`${screen.to}T00:00:00Z`) :
new Date(from);
if (
!(screen.screen === 'events' && screen.to) &&
screen.screen !== 'stock' &&
screen.screen !== 'bond'
)
) {
to.setUTCDate(to.getUTCDate() + defaultEventDays);
}
if (screen.screen === 'stock' || screen.screen === 'bond') {
from.setUTCFullYear(from.getUTCFullYear() - incomeHistoryYears);
to.setUTCFullYear(to.getUTCFullYear() + 1);
@@ -252,9 +262,9 @@ export function planInvestmentScreen(
}
if (
!force &&
['account', 'operations', 'income', 'events'].includes(screen.screen)
['account', 'events', 'income', 'operations'].includes(screen.screen)
) {
if (instrument.historyFrom)
if (instrument.historyFrom) {
sources.push({
...identity,
kind: 'candles',
@@ -262,14 +272,15 @@ export function planInvestmentScreen(
to: now,
priority: 'history',
});
else
} else {
unavailable.push({
resourceKey: `candles/${instrument.uid}/all`,
reason: 'history_start_unavailable',
});
}
}
}
if (!force && !['stocks', 'bonds'].includes(screen.screen))
if (!force && !['bonds', 'stocks'].includes(screen.screen)) {
sources.push(
...accountHistory(accounts, now).map((range) => ({
...range,
@@ -277,6 +288,7 @@ export function planInvestmentScreen(
priority: 'history' as const,
})),
);
}
const priorities = { discovery: 0, screen: 1, history: 2 };
sources.sort(
(left, right) => priorities[left.priority] - priorities[right.priority],
@@ -290,9 +302,9 @@ export function accountHistory(
): OperationInterval[] {
return accounts.flatMap((account) => {
const from = new Date(
account.openedOn
? `${account.openedOn}T00:00:00Z`
: '1970-01-01T00:00:00Z',
account.openedOn ?
`${account.openedOn}T00:00:00Z` :
'1970-01-01T00:00:00Z',
);
return from < now ? [{ accountId: account.accountId, from, to: now }] : [];
});
@@ -305,21 +317,22 @@ export function ledgerRange(
accounts: Account[],
now: Date,
) {
const opening = accounts.every((account) => account.openedOn)
? accounts.map((account) => account.openedOn ?? '').sort()[0]
: undefined;
const from = fromValue
? new Date(fromValue)
: instrumentUid
? new Date(opening ? `${opening}T00:00:00Z` : '1970-01-01T00:00:00Z')
: new Date(Date.UTC(now.getUTCFullYear(), 0, 1));
const end = toValue
? new Date(
/^\d{4}-\d{2}-\d{2}$/.test(toValue)
? `${toValue}T23:59:59.999Z`
: toValue,
)
: now;
const opening = accounts.every((account) => account.openedOn) ?
// eslint-disable-next-line sonarjs/no-alphabetical-sort -- Code-unit ordering is intentional for canonical keys and ISO dates; locale collation would change persisted bindings.
accounts.map((account) => account.openedOn ?? '').sort()[0] :
undefined;
const from = fromValue ?
new Date(fromValue) :
instrumentUid ?
new Date(opening ? `${opening}T00:00:00Z` : '1970-01-01T00:00:00Z') :
new Date(Date.UTC(now.getUTCFullYear(), 0, 1));
const end = toValue ?
new Date(
/^\d{4}-\d{2}-\d{2}$/.test(toValue) ?
`${toValue}T23:59:59.999Z` :
toValue,
) :
now;
return {
from,
to: new Date(Math.min(end.valueOf() + (toValue ? 1 : 0), now.valueOf())),