fix: make backend local verification safe
This commit is contained in:
@@ -7,11 +7,20 @@ NestJS API WealthLedger. Все функциональные изменения
|
|||||||
## Проверка
|
## Проверка
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
npm ci
|
||||||
npm run lint
|
npm run lint
|
||||||
npm test
|
npm run typecheck:app
|
||||||
npm run build
|
npm run typecheck:test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Node 22 обязателен. `npm run lint` и `npm run lint:check` не изменяют
|
||||||
|
versioned-файлы; `npm run lint:fix` — явная записывающая команда. Текущий
|
||||||
|
`npm run test:e2e` временно не является надёжным gate: WL-P2-05 отложен из-за
|
||||||
|
Prisma schema-engine failure; статус и trigger пересмотра указаны в
|
||||||
|
`../docs/development/audit-remediation.md`.
|
||||||
|
Для read-only сверки runtime OpenAPI с frontend snapshot под Node 22 запускать
|
||||||
|
из workspace `bash specs/scripts/verify-runtime-openapi.sh`.
|
||||||
|
|
||||||
## Границы
|
## Границы
|
||||||
|
|
||||||
- Публичный HTTP API версионируется как `/api/v1`; OpenAPI из backend - источник контракта для frontend.
|
- Публичный HTTP API версионируется как `/api/v1`; OpenAPI из backend - источник контракта для frontend.
|
||||||
|
|||||||
@@ -21,16 +21,31 @@
|
|||||||
<!--[](https://opencollective.com/nest#backer)
|
<!--[](https://opencollective.com/nest#backer)
|
||||||
[](https://opencollective.com/nest#sponsor)-->
|
[](https://opencollective.com/nest#sponsor)-->
|
||||||
|
|
||||||
## Description
|
## WealthLedger backend
|
||||||
|
|
||||||
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
NestJS API WealthLedger. Требуется Node 22. Перед первой локальной проверкой
|
||||||
|
установите зависимости строго из lockfile:
|
||||||
## Project setup
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ npm install
|
npm ci
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Проверки, не изменяющие исходники:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint
|
||||||
|
npm run typecheck:app
|
||||||
|
npm run typecheck:test
|
||||||
|
```
|
||||||
|
|
||||||
|
Для явного исправления форматирования используйте `npm run lint:fix`.
|
||||||
|
`npm run test:e2e` пока не является надёжным local gate: Prisma 7.9.1
|
||||||
|
останавливает migration до Jest; запись WL-P2-05 в
|
||||||
|
`../docs/development/audit-remediation.md` фиксирует rationale и trigger
|
||||||
|
пересмотра.
|
||||||
|
|
||||||
|
## Запуск приложения
|
||||||
|
|
||||||
## Compile and run the project
|
## Compile and run the project
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+8
-1
@@ -5,6 +5,9 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
|
"engines": {
|
||||||
|
"node": "22.x"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "prisma generate && nest build",
|
"build": "prisma generate && nest build",
|
||||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
@@ -12,7 +15,11 @@
|
|||||||
"start:dev": "NODE_ENV=development nest start --watch",
|
"start:dev": "NODE_ENV=development nest start --watch",
|
||||||
"start:debug": "nest start --debug --watch",
|
"start:debug": "nest start --debug --watch",
|
||||||
"start:prod": "node dist/src/main.js",
|
"start:prod": "node dist/src/main.js",
|
||||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
"lint": "npm run lint:check",
|
||||||
|
"lint:check": "eslint \"{src,apps,libs,test}/**/*.ts\" --max-warnings=0",
|
||||||
|
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"typecheck:app": "tsc --project tsconfig.typecheck.app.json",
|
||||||
|
"typecheck:test": "tsc --project tsconfig.typecheck.test.json",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ jest.mock('../prisma/prisma.service', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
import { TbankConnectionService } from './tbank-connection.service';
|
import { TbankConnectionService } from './tbank-connection.service';
|
||||||
|
import type { TbankClient } from './tbank.client';
|
||||||
|
|
||||||
describe('TbankConnectionService', () => {
|
describe('TbankConnectionService', () => {
|
||||||
const prisma = {
|
const prisma = {
|
||||||
@@ -17,7 +18,9 @@ describe('TbankConnectionService', () => {
|
|||||||
const config = {
|
const config = {
|
||||||
getOrThrow: jest.fn(() => 'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY='),
|
getOrThrow: jest.fn(() => 'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY='),
|
||||||
};
|
};
|
||||||
const tbank = { validateToken: jest.fn() };
|
const tbank: jest.Mocked<Pick<TbankClient, 'validateToken'>> = {
|
||||||
|
validateToken: jest.fn(),
|
||||||
|
};
|
||||||
const portfolio = { invalidate: jest.fn() };
|
const portfolio = { invalidate: jest.fn() };
|
||||||
const service = new TbankConnectionService(
|
const service = new TbankConnectionService(
|
||||||
prisma as never,
|
prisma as never,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { Environment } from '../config/env.validation';
|
import { Environment } from '../config/env.validation';
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
@@ -6,6 +6,8 @@ import { TbankClient } from './tbank.client';
|
|||||||
import { TbankCrypto } from './tbank.crypto';
|
import { TbankCrypto } from './tbank.crypto';
|
||||||
import { PortfolioService } from './portfolio.service';
|
import { PortfolioService } from './portfolio.service';
|
||||||
|
|
||||||
|
type TbankTokenValidator = Pick<TbankClient, 'validateToken'>;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TbankConnectionService {
|
export class TbankConnectionService {
|
||||||
private readonly crypto: TbankCrypto;
|
private readonly crypto: TbankCrypto;
|
||||||
@@ -13,7 +15,7 @@ export class TbankConnectionService {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
config: ConfigService<Environment, true>,
|
config: ConfigService<Environment, true>,
|
||||||
private readonly tbank: TbankClient,
|
@Inject(TbankClient) private readonly tbank: TbankTokenValidator,
|
||||||
private readonly portfolio: PortfolioService,
|
private readonly portfolio: PortfolioService,
|
||||||
) {
|
) {
|
||||||
this.crypto = TbankCrypto.fromBase64(
|
this.crypto = TbankCrypto.fromBase64(
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ const instrumentCacheTtlMs = 24 * 60 * 60_000;
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class UpcomingEventsService {
|
export class UpcomingEventsService {
|
||||||
private readonly crypto: TbankCrypto;
|
private readonly crypto: TbankCrypto;
|
||||||
private readonly dividendCache = new Map<string, CachedEntry<TbankDividend[]>>();
|
private readonly dividendCache = new Map<
|
||||||
|
string,
|
||||||
|
CachedEntry<TbankDividend[]>
|
||||||
|
>();
|
||||||
private readonly instrumentCache = new Map<
|
private readonly instrumentCache = new Map<
|
||||||
string,
|
string,
|
||||||
CachedEntry<TbankInstrument | null>
|
CachedEntry<TbankInstrument | null>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"incremental": false,
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["src/**/*.spec.ts", "test", "node_modules", "dist"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"incremental": false,
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "test/**/*.ts"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user