diff --git a/apps/api/src/app/endpoints/ai/ai.service.ts b/apps/api/src/app/endpoints/ai/ai.service.ts index 7141c9618..33a7839d9 100644 --- a/apps/api/src/app/endpoints/ai/ai.service.ts +++ b/apps/api/src/app/endpoints/ai/ai.service.ts @@ -1,3 +1,5 @@ +import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PROPERTY_API_KEY_OPENROUTER, PROPERTY_OPENROUTER_MODEL @@ -8,9 +10,7 @@ import type { AiPromptMode } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; import { createOpenRouter } from '@openrouter/ai-sdk-provider'; import { generateText } from 'ai'; - -import { PropertyService } from '../../../services/property/property.service'; -import { PortfolioService } from '../../portfolio/portfolio.service'; +import { tablemark } from 'tablemark'; @Injectable() export class AiService { @@ -59,9 +59,20 @@ export class AiService { userId }); + const holdingsTableColumns = [ + { name: 'Name' }, + { name: 'Symbol' }, + { name: 'Currency' }, + { name: 'Asset Class' }, + { name: 'Asset Sub Class' }, + { name: 'Allocation in Percentage', align: 'right' as const } + ]; + // Build rows for tablemark const rows = Object.values(holdings) - .sort((a, b) => b.allocationInPercentage - a.allocationInPercentage) + .sort((a, b) => { + return b.allocationInPercentage - a.allocationInPercentage; + }) .map( ({ allocationInPercentage, @@ -82,33 +93,10 @@ export class AiService { } ); - // Render Markdown table using tablemark, with safe fallback - let holdingsTableString = ''; - try { - const tablemarkModule: any = await import('tablemark'); - const tablemark = tablemarkModule?.default ?? tablemarkModule; - holdingsTableString = tablemark(rows, { - columns: [ - { name: 'Name' }, - { name: 'Symbol' }, - { name: 'Currency' }, - { name: 'Asset Class' }, - { name: 'Asset Sub Class' }, - { name: 'Allocation in Percentage', align: 'right' } - ] - }); - } catch { - // Fallback to manual rendering if tablemark is unavailable at runtime - const manual = [ - '| Name | Symbol | Currency | Asset Class | Asset Sub Class | Allocation in Percentage |', - '| --- | --- | --- | --- | --- | --- |', - ...rows.map( - (r) => - `| ${r['Name']} | ${r['Symbol']} | ${r['Currency']} | ${r['Asset Class']} | ${r['Asset Sub Class']} | ${r['Allocation in Percentage']} |` - ) - ]; - holdingsTableString = manual.join('\n'); - } + // Render Markdown table using tablemark + const holdingsTableString = tablemark(rows, { + columns: holdingsTableColumns + }); if (mode === 'portfolio') { return holdingsTableString; diff --git a/apps/api/src/types/tablemark.d.ts b/apps/api/src/types/tablemark.d.ts deleted file mode 100644 index ce70b02ec..000000000 --- a/apps/api/src/types/tablemark.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare module 'tablemark' { - interface TablemarkColumnOption { - name: string; - align?: 'left' | 'center' | 'right'; - } - - interface TablemarkOptions { - columns?: (string | TablemarkColumnOption)[]; - } - - function tablemark( - rows: Record[], - options?: TablemarkOptions - ): string; - export = tablemark; -} diff --git a/package-lock.json b/package-lock.json index f3d4bca22..5936a1c41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,7 +90,7 @@ "rxjs": "7.8.1", "stripe": "18.5.0", "svgmap": "2.12.2", - "tablemark": "^4.1.0", + "tablemark": "4.1.0", "twitter-api-v2": "1.23.0", "uuid": "11.1.0", "yahoo-finance2": "3.10.0", diff --git a/package.json b/package.json index c0d951ee7..f849ba9f1 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "rxjs": "7.8.1", "stripe": "18.5.0", "svgmap": "2.12.2", - "tablemark": "^4.1.0", + "tablemark": "4.1.0", "twitter-api-v2": "1.23.0", "uuid": "11.1.0", "yahoo-finance2": "3.10.0",