fix: translate permanent invalid-token errors on online entrypoints (WealthLedger/backend#59) (#110)
Backend verify / commits (push) Skipped
Backend verify / commits (pull_request) Failing after 33s
Backend verify / security (pull_request) Skipped
Backend verify / verify (pull_request) Skipped
Backend verify / security (push) Successful in 11s
Backend verify / verify (push) Failing after 6m40s

This commit was merged in pull request #110.
This commit is contained in:
2026-10-16 23:23:12 +03:00
parent e03fad622b
commit 8a6f60d965
8 changed files with 240 additions and 64 deletions
@@ -22,14 +22,16 @@ function share(index: number, overrides: Partial<TbankShare> = {}): TbankShare {
}
describe('StockScreenerService', () => {
const access = { current: jest.fn(), local: jest.fn() };
const access = { online: jest.fn(), local: jest.fn() };
const client = { getAllShares: jest.fn() };
const logger = { event: jest.fn() };
let service: StockScreenerService;
beforeEach(() => {
jest.clearAllMocks();
access.current.mockResolvedValue({ revision, token });
access.online.mockImplementation((_userId: string, run: (connection: { revision: string; token: string }) => Promise<unknown>) =>
run({ revision, token }),
);
access.local.mockResolvedValue({ revision });
client.getAllShares.mockResolvedValue(
Array.from({ length: pageSize + 1 }, (_, index) => share(index)),
@@ -48,8 +48,8 @@ type StockScreenerPage = {
};
type Snapshot = { asOf: string; expiresAt: number; items: StockScreenerItem[]; revision: string; userId: string };
type TbankAccess = {
current(userId: string): Promise<{ revision: string; token: string }>;
local(userId: string): Promise<{ revision: string }>;
online<T>(userId: string, run: (connection: { revision: string; token: string }) => Promise<T>): Promise<T>;
};
@Injectable()
@@ -63,8 +63,10 @@ export class StockScreenerService {
) {}
async search(userId: string, conditions: StockScreenerConditions): Promise<StockScreenerPage> {
const connection = await this.access.current(userId);
const instruments = await this.client.getAllShares(connection.token);
const { instruments, revision } = await this.access.online(userId, async (connection) => ({
instruments: await this.client.getAllShares(connection.token),
revision: connection.revision,
}));
const asOf = new Date().toISOString();
const selected = selectStockScreenerInstruments({ asOf: new Date(asOf), instruments }, conditions)
.instruments.map((instrument) => this.item(instrument));
@@ -74,7 +76,7 @@ export class StockScreenerService {
asOf,
expiresAt: Date.now() + SNAPSHOT_TTL_MS,
items: selected,
revision: connection.revision,
revision,
userId,
});
this.logger.event('info', 'stock.screener.search.completed', { asOf, count: selected.length, operation: 'stock-screener-search' });