From ca4a8b35f320b64a1def9b5d274e3fe3cfaab99e Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sun, 14 Jun 2026 09:22:02 +0300 Subject: [PATCH] fix: null safety for market data components and backend CI --- apps/backend/package.json | 3 ++- apps/frontend/src/api/responses.ts | 14 +++++++------- apps/frontend/src/components/BondDetails.tsx | 8 +++++--- apps/frontend/src/components/StockDetails.tsx | 8 ++++---- package-lock.json | 1 + 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/apps/backend/package.json b/apps/backend/package.json index 292b1c5..1d8a57e 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -3,11 +3,12 @@ "version": "0.0.1", "private": true, "scripts": { + "postinstall": "prisma generate", "build": "nest build", "start:dev": "nest start --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,test}/**/*.ts\"", - "test": "vitest run", + "test": "VITE_CJS_IGNORE_WARNING=1 vitest run", "test:watch": "vitest" }, "dependencies": { diff --git a/apps/frontend/src/api/responses.ts b/apps/frontend/src/api/responses.ts index a7da5ea..c2da5c1 100644 --- a/apps/frontend/src/api/responses.ts +++ b/apps/frontend/src/api/responses.ts @@ -9,10 +9,10 @@ export interface ApiEnvelope { } export interface StockMarketData { - price: number; - change: number; - changePercent: number; - open: number; + price: number | null; + change: number | null; + changePercent: number | null; + open: number | null; high: number | null; low: number | null; volume: number; @@ -52,11 +52,11 @@ export interface ShareHistoryItem { } export interface BondMarketData { - price: number; + price: number | null; yieldToMaturity: number | null; duration: number | null; - accruedInt: number; - couponValue: number; + accruedInt: number | null; + couponValue: number | null; couponPercent: number | null; nextCouponDate: string | null; open: number; diff --git a/apps/frontend/src/components/BondDetails.tsx b/apps/frontend/src/components/BondDetails.tsx index ae3cf9f..07f8f90 100644 --- a/apps/frontend/src/components/BondDetails.tsx +++ b/apps/frontend/src/components/BondDetails.tsx @@ -28,7 +28,9 @@ export function BondDetails({ bond }: BondDetailsProps) {
{bond.isin}
-
{md.price.toFixed(2)}%
+
+ {md.price?.toFixed(2) ?? '—'}% +
@@ -44,7 +46,7 @@ export function BondDetails({ bond }: BondDetailsProps) {
Купон - {md.couponValue} ₽ {md.couponPercent != null ? `(${md.couponPercent}%)` : ''} + {md.couponValue ?? '—'} ₽ {md.couponPercent != null ? `(${md.couponPercent}%)` : ''}
@@ -57,7 +59,7 @@ export function BondDetails({ bond }: BondDetailsProps) {
НКД - {md.accruedInt.toFixed(2)} ₽ + {md.accruedInt?.toFixed(2) ?? '—'} ₽
Доходность к погашению diff --git a/apps/frontend/src/components/StockDetails.tsx b/apps/frontend/src/components/StockDetails.tsx index 2f4a177..0d4ba4b 100644 --- a/apps/frontend/src/components/StockDetails.tsx +++ b/apps/frontend/src/components/StockDetails.tsx @@ -13,7 +13,7 @@ const rowStyle: React.CSSProperties = { export function StockDetails({ stock }: StockDetailsProps) { const md = stock.marketData; - const isPositive = md.change >= 0; + const isPositive = (md.change ?? 0) >= 0; return (
- {md.price.toLocaleString('ru-RU', { minimumFractionDigits: 2 })}{' '} + {md.price?.toLocaleString('ru-RU', { minimumFractionDigits: 2 }) ?? '—'}{' '} {isPositive ? '+' : ''} - {md.change.toFixed(2)} ({md.changePercent.toFixed(2)}%) + {(md.change ?? 0).toFixed(2)} ({(md.changePercent ?? 0).toFixed(2)}%)
Открытие - {md.open.toFixed(2)} + {md.open?.toFixed(2) ?? '—'}
Максимум diff --git a/package-lock.json b/package-lock.json index cdbe94c..ab095fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "apps/backend": { "name": "@moex-vibe/backend", "version": "0.0.1", + "hasInstallScript": true, "dependencies": { "@libsql/client": "^0.17.3", "@nestjs/axios": "^3.0.0",