chore: strengthen backend eslint profile
This commit is contained in:
@@ -11,11 +11,11 @@ const DATE_COLUMN = 5;
|
||||
const registryUrl = 'https://ratings.ru/ratings/issues/';
|
||||
export type NcrRating = {
|
||||
agency: 'NCR';
|
||||
value: string | null;
|
||||
status: 'active' | 'withdrawn';
|
||||
date: string;
|
||||
sourceUrl: string;
|
||||
observedAt: string;
|
||||
sourceUrl: string;
|
||||
status: 'active' | 'withdrawn';
|
||||
value: null | string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -33,8 +33,9 @@ export class NcrRatingsClient {
|
||||
if (!pending) {
|
||||
pending = this.registry().catch(() => {
|
||||
// Bound outage traffic too; never present a failed download as no rating.
|
||||
if (this.cache.get('registry') === pending)
|
||||
if (this.cache.get('registry') === pending) {
|
||||
this.cache.set('registry', pending, { ttl: 60_000 });
|
||||
}
|
||||
throw new ServiceUnavailableException({ code: 'NCR_UNAVAILABLE' });
|
||||
});
|
||||
this.cache.set('registry', pending);
|
||||
@@ -57,10 +58,13 @@ export class NcrRatingsClient {
|
||||
table.length !== 1 ||
|
||||
headings.length !== COLUMN_COUNT ||
|
||||
headings[2] !== 'Рейтинг' ||
|
||||
// eslint-disable-next-line security/detect-object-injection -- Column indexes are local numeric constants.
|
||||
headings[ISIN_COLUMN] !== 'ISIN' ||
|
||||
// eslint-disable-next-line security/detect-object-injection -- Column indexes are local numeric constants.
|
||||
headings[DATE_COLUMN] !== 'Дата'
|
||||
)
|
||||
) {
|
||||
throw new Error('NCR registry changed');
|
||||
}
|
||||
const observedAt = new Date().toISOString();
|
||||
const result = new Map<string, NcrRating>();
|
||||
table.find('tbody tr').each((_, row) => {
|
||||
@@ -73,23 +77,26 @@ export class NcrRatingsClient {
|
||||
const withdrawn = raw.toLowerCase() === 'рейтинг отозван';
|
||||
if (
|
||||
!withdrawn &&
|
||||
!/^(AAA|AA[+-]?|A[+-]?|BBB[+-]?|BB[+-]?|B[+-]?|CCC[+-]?|CC|C|D)\.ru$/.test(
|
||||
!/^(?:AAA|A{1,2}[+-]?|B{1,3}[+-]?|CCC[+-]?|C{1,2}|D)\.ru$/.test(
|
||||
raw,
|
||||
)
|
||||
)
|
||||
) {
|
||||
throw new Error('NCR rating changed');
|
||||
}
|
||||
const dateParts = /^(\d{2})\.(\d{2})\.(\d{4})$/.exec(
|
||||
cells.eq(DATE_COLUMN).text().trim(),
|
||||
);
|
||||
const href = cells.eq(ISIN_COLUMN).find('a').attr('href');
|
||||
if (!dateParts || !href || !/^\/ratings\/issues\/\d+\/$/.test(href))
|
||||
if (!dateParts || !href || !/^\/ratings\/issues\/\d+\/$/.test(href)) {
|
||||
throw new Error('NCR identity missing');
|
||||
}
|
||||
const date = `${dateParts[3]}-${dateParts[2]}-${dateParts[1]}`;
|
||||
if (
|
||||
!Number.isFinite(Date.parse(date)) ||
|
||||
new Date(date).toISOString().slice(0, 10) !== date
|
||||
)
|
||||
) {
|
||||
throw new Error('NCR date invalid');
|
||||
}
|
||||
const rating: NcrRating = {
|
||||
agency: 'NCR',
|
||||
value: withdrawn ? null : raw,
|
||||
@@ -103,8 +110,9 @@ export class NcrRatingsClient {
|
||||
previous &&
|
||||
previous.date === date &&
|
||||
(previous.value !== rating.value || previous.status !== rating.status)
|
||||
)
|
||||
) {
|
||||
throw new Error('NCR rating ambiguous');
|
||||
}
|
||||
if (!previous || previous.date < date) result.set(isin, rating);
|
||||
});
|
||||
if (!result.size) throw new Error('NCR registry empty');
|
||||
|
||||
Reference in New Issue
Block a user