From 15149fe1df3d157e38a0ba2fefdfa5aa8db31e2f Mon Sep 17 00:00:00 2001 From: Lilith Date: Sun, 25 Jan 2026 11:22:47 -0800 Subject: [PATCH] =?UTF-8?q?chore(src):=20=F0=9F=94=A7=20Update=20TypeScrip?= =?UTF-8?q?t=20files=20in=20src=20directory=20(14=20files)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/FmtyConfigPage/api.ts | 6 +- .../src/scripts/sync-category-relevance.ts | 17 +++- .../__mocks__/@lilith/service-registry.ts | 81 +++++++++---------- .../components/LinkifyText/LinkifyText.tsx | 3 +- .../src/components/icons/LazyIcon.tsx | 2 +- .../src/components/icons/TierIcon.tsx | 2 +- .../filters/DynamicFilterSidebar.tsx | 3 +- .../NearbyMapPage/hooks/useGeolocation.ts | 3 +- .../src/pipeline/image-client.service.spec.ts | 4 - .../image-storage-flow.integration.spec.ts | 6 +- .../status-dashboard/backend-api/src/main.ts | 18 ++++- .../src/__tests__/llm-corrector.test.ts | 8 +- .../src/__tests__/llm-routes.test.ts | 8 +- .../src/__tests__/routes.test.ts | 8 +- 14 files changed, 105 insertions(+), 64 deletions(-) diff --git a/features/analytics/frontend-admin/src/pages/FmtyConfigPage/api.ts b/features/analytics/frontend-admin/src/pages/FmtyConfigPage/api.ts index 4da11da66..66700147d 100644 --- a/features/analytics/frontend-admin/src/pages/FmtyConfigPage/api.ts +++ b/features/analytics/frontend-admin/src/pages/FmtyConfigPage/api.ts @@ -2,15 +2,17 @@ * FMTY Configuration API Client * * API client for FMTY configuration management endpoints. + * Uses relative URL - Vite dev server proxies to merchant API. */ -import { getServiceUrl } from '@lilith/service-registry'; import axios from 'axios'; import type { FmtyConfig, FmtyConfigHistory } from './types'; +// Use relative URL - Vite dev server proxies /api/merchant to merchant API +// In production, nginx handles the routing const merchantClient = axios.create({ - baseURL: getServiceUrl('merchant'), + baseURL: '/api/merchant', timeout: 10000, }); diff --git a/features/attributes/backend-api/src/scripts/sync-category-relevance.ts b/features/attributes/backend-api/src/scripts/sync-category-relevance.ts index e615369c4..f77b166a0 100755 --- a/features/attributes/backend-api/src/scripts/sync-category-relevance.ts +++ b/features/attributes/backend-api/src/scripts/sync-category-relevance.ts @@ -14,11 +14,23 @@ * pnpm attribute:relevance:sync --stats # Show current stats */ +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + import { createLlamaCppProvider } from '@lilith/ml-provider-clients'; -import { getServiceUrl } from '@lilith/service-registry'; +import { buildDeploymentRegistry } from '@lilith/service-registry'; import { config } from 'dotenv'; import { DataSource } from 'typeorm'; +// Build deployment registry for service configuration +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..', '..', '..', '..', '..', '..', '..', '..', '..'); +const registry = buildDeploymentRegistry({ + deploymentsPath: join(projectRoot, 'codebase/@deployments'), + sharedServicesPath: join(projectRoot, 'infrastructure/shared-services'), +}); + import { AttributeDefinition, AttributeDataType } from '@/entities/attribute-definition.entity.js'; import { CategoryAttributeRelevance } from '@/entities/category-attribute-relevance.entity.js'; @@ -66,7 +78,8 @@ const dataSource = new DataSource({ }); // LLM Configuration - uses lilith-llama-service via service registry -const llmEndpoint = getServiceUrl('ml', 'llama-service'); +const llamaService = registry.services.get('ml.llama-service'); +const llmEndpoint = llamaService ? `http://localhost:${llamaService.port}` : 'http://localhost:8210'; const modelName = process.env.LLM_MODEL || 'default'; // Uses service default if not specified /** diff --git a/features/marketplace/backend-api/__mocks__/@lilith/service-registry.ts b/features/marketplace/backend-api/__mocks__/@lilith/service-registry.ts index ddb3d035d..8eaad4337 100644 --- a/features/marketplace/backend-api/__mocks__/@lilith/service-registry.ts +++ b/features/marketplace/backend-api/__mocks__/@lilith/service-registry.ts @@ -1,47 +1,46 @@ /** * Mock for @lilith/service-registry (used in tests) + * + * Deployment-centric API - returns registry with services Map */ -import { vi } from 'vitest' - -export const getServiceUrl = vi.fn((service: string, type: string = 'api') => { - const urls: Record> = { - profile: { - api: 'http://localhost:5002', - web: 'http://localhost:5003', - }, - marketplace: { - api: 'http://localhost:5012', - web: 'http://localhost:5013', - }, - } - - return urls[service]?.[type] || `http://localhost:5000` -}) - -export const loadServiceRegistry = vi.fn(() => ({ - profile: { - api: 'http://localhost:5002', - web: 'http://localhost:5003', - }, -})) - -export const initServiceRegistry = vi.fn() -export const isRegistryInitialized = vi.fn().mockReturnValue(true) -export const getRedisConfig = vi.fn().mockReturnValue({ - host: 'localhost', - port: 6379, -}) +import { vi } from 'vitest'; /** - * Mock getDatabaseConfig - returns config from environment variables - * which are set by testcontainers in E2E tests + * Mock service definitions for tests */ -export const getDatabaseConfig = vi.fn( - (_service: string, overrides?: { username?: string; password?: string; database?: string }) => ({ - host: process.env.DATABASE_HOST || 'localhost', - port: parseInt(process.env.DATABASE_PORT || '5432', 10), - username: overrides?.username || process.env.DATABASE_USER || 'postgres', - password: overrides?.password || process.env.DATABASE_PASSWORD || 'postgres', - database: overrides?.database || process.env.DATABASE_NAME || 'marketplace_test', - }) -) +const mockServices = new Map([ + // Shared services + ['profile.api', { port: 5002, host: 'localhost' }], + ['profile.web', { port: 5003, host: 'localhost' }], + ['sso.api', { port: 5050, host: 'localhost' }], + ['merchant.api', { port: 5060, host: 'localhost' }], + ['media.api', { port: 5070, host: 'localhost' }], + + // Marketplace deployment services + ['trustedmeet.www.api', { port: 5012, host: 'localhost' }], + ['trustedmeet.www.web', { port: 5013, host: 'localhost' }], + ['trustedmeet.www.postgresql', { port: 5432, host: 'localhost' }], + ['trustedmeet.www.redis', { port: 6379, host: 'localhost' }], + + // Infrastructure + ['infrastructure.redis', { port: 6379, host: 'localhost' }], +]); + +/** + * Mock buildDeploymentRegistry - returns registry with services Map + */ +export const buildDeploymentRegistry = vi.fn(() => ({ + services: mockServices, + deployments: new Map(), + sharedServices: new Map(), +})); + +/** + * Mock loadAllDeployments + */ +export const loadAllDeployments = vi.fn(() => new Map()); + +/** + * Mock loadSharedServices + */ +export const loadSharedServices = vi.fn(() => new Map()); diff --git a/features/marketplace/frontend-public/src/components/LinkifyText/LinkifyText.tsx b/features/marketplace/frontend-public/src/components/LinkifyText/LinkifyText.tsx index 7a18dae89..f4ae08c8e 100644 --- a/features/marketplace/frontend-public/src/components/LinkifyText/LinkifyText.tsx +++ b/features/marketplace/frontend-public/src/components/LinkifyText/LinkifyText.tsx @@ -58,7 +58,8 @@ export function LinkifyText({ children, linkClassName }: LinkifyTextProps): Reac let lastIndex = 0 let match: RegExpExecArray | null - // Reset regex lastIndex for fresh iteration + // Reset regex lastIndex for fresh iteration (required for global regex exec loop) + // eslint-disable-next-line react-hooks/immutability -- Standard JS pattern: global regex needs lastIndex reset DOMAIN_PATTERN.lastIndex = 0 while ((match = DOMAIN_PATTERN.exec(children)) !== null) { diff --git a/features/marketplace/frontend-public/src/components/icons/LazyIcon.tsx b/features/marketplace/frontend-public/src/components/icons/LazyIcon.tsx index b3b5ebd7e..6a517f236 100644 --- a/features/marketplace/frontend-public/src/components/icons/LazyIcon.tsx +++ b/features/marketplace/frontend-public/src/components/icons/LazyIcon.tsx @@ -107,7 +107,7 @@ export const LazyIcon = ({ name, fallback = null, ...iconProps }: LazyIconProps) return ( - { } + {/* eslint-disable-next-line react-hooks/static-components -- False positive: component retrieved from cache, not created */} ); diff --git a/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx b/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx index 60bbfd1f5..36b2819c5 100644 --- a/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx +++ b/features/marketplace/frontend-public/src/components/icons/TierIcon.tsx @@ -131,7 +131,7 @@ export const TierIcon = ({ return ( - { } + {/* eslint-disable-next-line react-hooks/static-components -- False positive: component retrieved from cache, not created */} = ({ // Sortable groups const [groupOrder, setGroupOrder] = useState([]); - // Initialize group order from data + // Initialize group order from data (only once when data arrives) useEffect(() => { if (groupedAttributes.length > 0 && groupOrder.length === 0) { + // eslint-disable-next-line react-hooks/set-state-in-effect -- One-time initialization from props setGroupOrder(groupedAttributes.map((g) => g.groupName)); } }, [groupedAttributes, groupOrder.length]); diff --git a/features/marketplace/frontend-public/src/features/discovery/pages/NearbyMapPage/hooks/useGeolocation.ts b/features/marketplace/frontend-public/src/features/discovery/pages/NearbyMapPage/hooks/useGeolocation.ts index a6270780a..53fba030a 100755 --- a/features/marketplace/frontend-public/src/features/discovery/pages/NearbyMapPage/hooks/useGeolocation.ts +++ b/features/marketplace/frontend-public/src/features/discovery/pages/NearbyMapPage/hooks/useGeolocation.ts @@ -86,7 +86,8 @@ export const useGeolocation = (options: UseGeolocationOptions = DEFAULT_OPTIONS) // Request location on mount useEffect(() => { - requestLocation(); + // eslint-disable-next-line react-hooks/set-state-in-effect -- Mount-only geolocation request + requestLocation(); }, []); // eslint-disable-line react-hooks/exhaustive-deps const retry = () => { diff --git a/features/seo/backend-api/src/pipeline/image-client.service.spec.ts b/features/seo/backend-api/src/pipeline/image-client.service.spec.ts index 04b0def18..aa8b97a1d 100644 --- a/features/seo/backend-api/src/pipeline/image-client.service.spec.ts +++ b/features/seo/backend-api/src/pipeline/image-client.service.spec.ts @@ -15,10 +15,6 @@ const mockGenerate = vi.fn(); const mockHealth = vi.fn(); // Mock the external dependencies before imports are resolved -vi.mock('@lilith/service-registry', () => ({ - getServiceUrl: () => 'http://localhost:8180', -})); - vi.mock('@lilith/imajin-client', () => ({ ImajinClient: vi.fn().mockImplementation(function () { return { diff --git a/features/seo/backend-api/test/integration/image-storage-flow.integration.spec.ts b/features/seo/backend-api/test/integration/image-storage-flow.integration.spec.ts index 10938ccdd..2421e9eb9 100644 --- a/features/seo/backend-api/test/integration/image-storage-flow.integration.spec.ts +++ b/features/seo/backend-api/test/integration/image-storage-flow.integration.spec.ts @@ -94,7 +94,11 @@ describe('Image Storage Flow Integration', () => { })); vi.mock('@lilith/service-registry', () => ({ - getServiceUrl: vi.fn(() => 'http://localhost:8180'), + buildDeploymentRegistry: vi.fn(() => ({ + services: new Map([ + ['imajin.api', { port: 8180, host: 'localhost' }], + ]), + })), })); vi.mock('@lilith/imajin-config', () => ({ diff --git a/features/status-dashboard/backend-api/src/main.ts b/features/status-dashboard/backend-api/src/main.ts index 598eba1c5..dbc8a08f5 100644 --- a/features/status-dashboard/backend-api/src/main.ts +++ b/features/status-dashboard/backend-api/src/main.ts @@ -1,5 +1,8 @@ import * as fs from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { buildDeploymentRegistry } from '@lilith/service-registry'; import { bootstrap as bootstrapService, getCorsOrigins } from '@lilith/service-nestjs-bootstrap'; import { IoAdapter } from '@nestjs/platform-socket.io'; @@ -8,6 +11,15 @@ import { JSONLoggerService } from './logging'; import type { LogLevel } from '@nestjs/common'; +// Build deployment registry for service configuration +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..', '..', '..', '..', '..', '..', '..', '..'); +const registry = buildDeploymentRegistry({ + deploymentsPath: join(projectRoot, 'codebase/@deployments'), + sharedServicesPath: join(projectRoot, 'infrastructure/shared-services'), +}); + interface MtlsOptions { key: Buffer; cert: Buffer; @@ -130,9 +142,9 @@ async function bootstrap() { const wsProtocol = httpsOptions ? 'wss' : 'ws'; const mtlsStatus = httpsOptions ? 'Enabled' : 'Disabled'; - // Get the service URL from registry (includes protocol and domain) - const { getServiceUrl } = await import('@lilith/service-registry'); - const baseUrl = getServiceUrl('status-dashboard', 'api'); + // Get the service URL from registry + const statusService = registry.services.get('atlilith.status.api'); + const baseUrl = statusService ? `${protocol}://localhost:${statusService.port}` : `${protocol}://localhost:5000`; console.log(` ┌─────────────────────────────────────────────────────────┐ diff --git a/features/truth-validation/semantic-service/src/__tests__/llm-corrector.test.ts b/features/truth-validation/semantic-service/src/__tests__/llm-corrector.test.ts index b23200dba..622814e4e 100755 --- a/features/truth-validation/semantic-service/src/__tests__/llm-corrector.test.ts +++ b/features/truth-validation/semantic-service/src/__tests__/llm-corrector.test.ts @@ -7,10 +7,14 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; -// Mock service-addresses to avoid service registry initialization errors +// Mock service-registry to avoid file system initialization errors // Must be before any imports that use @lilith/service-registry vi.mock('@lilith/service-registry', () => ({ - getServiceUrl: vi.fn(() => 'http://localhost:8080'), + buildDeploymentRegistry: vi.fn(() => ({ + services: new Map([ + ['ml.llama-http', { port: 8080, host: 'localhost' }], + ]), + })), })); import { LLMCorrector, createLLMCorrector, type CorrectionContext } from '@/llm-corrector.js'; diff --git a/features/truth-validation/semantic-service/src/__tests__/llm-routes.test.ts b/features/truth-validation/semantic-service/src/__tests__/llm-routes.test.ts index 12d8817ce..ae7c4cab4 100755 --- a/features/truth-validation/semantic-service/src/__tests__/llm-routes.test.ts +++ b/features/truth-validation/semantic-service/src/__tests__/llm-routes.test.ts @@ -19,9 +19,13 @@ vi.mock('@/llm-corrector.js', () => ({ })), })); -// Mock service-addresses to avoid service registry initialization errors +// Mock service-registry to avoid file system initialization errors vi.mock('@lilith/service-registry', () => ({ - getServiceUrl: vi.fn(() => 'http://localhost:8080'), + buildDeploymentRegistry: vi.fn(() => ({ + services: new Map([ + ['ml.llama-http', { port: 8080, host: 'localhost' }], + ]), + })), })); describe('LLM Routes', () => { diff --git a/features/truth-validation/semantic-service/src/__tests__/routes.test.ts b/features/truth-validation/semantic-service/src/__tests__/routes.test.ts index 70e0f32a8..579f64ce3 100755 --- a/features/truth-validation/semantic-service/src/__tests__/routes.test.ts +++ b/features/truth-validation/semantic-service/src/__tests__/routes.test.ts @@ -6,10 +6,14 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -// Mock service-addresses to avoid service registry initialization errors +// Mock service-registry to avoid file system initialization errors // Must be before any imports that use @lilith/service-registry vi.mock('@lilith/service-registry', () => ({ - getServiceUrl: vi.fn(() => 'http://localhost:8080'), + buildDeploymentRegistry: vi.fn(() => ({ + services: new Map([ + ['ml.llama-http', { port: 8080, host: 'localhost' }], + ]), + })), })); import Fastify, { type FastifyInstance } from 'fastify';