diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..f572743
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,113 @@
+# Dependencies
+node_modules
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Production build
+dist
+
+# Environment files
+.env
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# IDE files
+.vscode
+.idea
+*.swp
+*.swo
+*~
+
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# Logs
+logs
+*.log
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Optional npm cache directory
+.npm
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# next.js build output
+.next
+
+# nuxt.js build output
+.nuxt
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# Generated files
+generated/
+
+# Git
+.git
+.gitignore
+
+# Docker
+Dockerfile
+.dockerignore
+docker-compose*.yml
+
+# Documentation
+*.md
+!README.md
+
+# Test files (keep only the Excel files)
+test/**
+!test/*.xlsx
+
+# Uploads (will be created at runtime)
+uploads/
+
+# Temporary files
+.temp
+.tmp
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..253338c
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,179 @@
+# =================================
+# APPLICATION CONFIGURATION
+# =================================
+
+# Environment mode: development, staging, production
+NODE_ENV=development
+
+# Application port
+PORT=3000
+
+# Application host (for binding)
+HOST=localhost
+
+# Application base URL (for CORS and other purposes)
+APP_URL=http://localhost:3000
+
+# =================================
+# DATABASE CONFIGURATION
+# =================================
+
+# PostgreSQL Database URL
+# Format: postgresql://username:password@host:port/database_name
+DATABASE_URL=postgresql://username:password@localhost:5432/claim_guard
+
+# Database connection pool settings
+DB_POOL_MIN=2
+DB_POOL_MAX=10
+
+# =================================
+# CORS CONFIGURATION
+# =================================
+
+# Allowed origins for CORS (comma-separated)
+# Use * for allow all origins (NOT recommended for production)
+# Examples:
+# - Development: http://localhost:3000,http://localhost:3001
+# - Production: https://yourdomain.com,https://www.yourdomain.com
+CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:8080
+
+# Allowed methods for CORS (comma-separated)
+CORS_METHODS=GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS
+
+# Allowed headers for CORS (comma-separated)
+CORS_HEADERS=Content-Type,Accept,Authorization,X-Requested-With
+
+# Allow credentials in CORS requests
+CORS_CREDENTIALS=true
+
+# =================================
+# SECURITY CONFIGURATION
+# =================================
+
+# JWT Secret for authentication (generate strong secret for production)
+JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
+
+# JWT Token expiration time
+JWT_EXPIRES_IN=24h
+
+# JWT Refresh token expiration
+JWT_REFRESH_EXPIRES_IN=7d
+
+# API Rate limiting (requests per minute)
+RATE_LIMIT_MAX=100
+
+# =================================
+# LOGGING CONFIGURATION
+# =================================
+
+# Log level: error, warn, info, debug, verbose
+LOG_LEVEL=info
+
+# Log format: json, simple
+LOG_FORMAT=simple
+
+# Enable request logging
+LOG_REQUESTS=true
+
+# =================================
+# FILE UPLOAD CONFIGURATION
+# =================================
+
+# Maximum file size for uploads (in bytes)
+# 10MB = 10485760, 50MB = 52428800
+MAX_FILE_SIZE=10485760
+
+# Allowed file types for upload (comma-separated)
+ALLOWED_FILE_TYPES=.xlsx,.xls,.csv
+
+# Upload directory path
+UPLOAD_DIR=./uploads
+
+# =================================
+# CACHE CONFIGURATION
+# =================================
+
+# Redis URL for caching (optional)
+# REDIS_URL=redis://localhost:6379
+
+# Cache TTL in seconds (default: 1 hour)
+CACHE_TTL=3600
+
+# =================================
+# EMAIL CONFIGURATION (Optional)
+# =================================
+
+# SMTP configuration for sending emails
+# SMTP_HOST=smtp.gmail.com
+# SMTP_PORT=587
+# SMTP_SECURE=false
+# SMTP_USER=your-email@gmail.com
+# SMTP_PASS=your-email-password
+
+# Email from address
+# EMAIL_FROM=noreply@yourdomain.com
+
+# =================================
+# THIRD-PARTY INTEGRATIONS
+# =================================
+
+# External API keys
+# EXTERNAL_API_KEY=your-api-key
+# EXTERNAL_API_URL=https://api.external-service.com
+
+# =================================
+# DEVELOPMENT SETTINGS
+# =================================
+
+# Enable API documentation (Swagger)
+ENABLE_DOCS=true
+
+# Enable debug mode
+DEBUG=true
+
+# Enable database logging
+DB_LOGGING=true
+
+# =================================
+# PRODUCTION SETTINGS
+# =================================
+
+# When NODE_ENV=production, ensure these are set:
+# - Strong JWT_SECRET
+# - Specific CORS_ORIGINS (not *)
+# - DB_LOGGING=false
+# - DEBUG=false
+# - LOG_LEVEL=warn or error
+
+# Health check endpoint settings
+HEALTH_CHECK_ENABLED=true
+
+# Request timeout in milliseconds
+REQUEST_TIMEOUT=30000
+
+# =================================
+# ICD SPECIFIC CONFIGURATION
+# =================================
+
+# Path to ICD data files
+ICD9_FILE_PATH=./test/[PUBLIC] ICD-9CM e-klaim.xlsx
+ICD10_FILE_PATH=./test/[PUBLIC] ICD-10 e-klaim.xlsx
+
+# ICD import batch size
+ICD_IMPORT_BATCH_SIZE=1000
+
+# =================================
+# MONITORING & METRICS
+# =================================
+
+# Enable application metrics
+METRICS_ENABLED=true
+
+# Metrics endpoint path
+METRICS_PATH=/metrics
+
+# Enable health check endpoint
+HEALTH_CHECK_PATH=/health
+
+OPENAI_API_KEY=xxxxxx
+OPENAI_API_MODEL=text-embedding-ada-002
\ No newline at end of file
diff --git a/README.md b/README.md
index 751530d..f056859 100644
--- a/README.md
+++ b/README.md
@@ -1,194 +1,397 @@
-
-
-
+# π₯ Claim Guard Backend
-[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
-[circleci-url]: https://circleci.com/gh/nestjs/nest
+> **NestJS application for managing ICD-9 and ICD-10 medical codes with Excel import functionality**
- A progressive Node.js framework for building efficient and scalable server-side applications.
-
-
-
-
-
-
-
-
-
-
-
-
-
+[](https://nestjs.com/)
+[](https://www.typescriptlang.org/)
+[](https://www.postgresql.org/)
+[](https://www.docker.com/)
+[](https://www.prisma.io/)
-## Description
+## β¨ Features
-Claim Guard Backend - A NestJS application for managing ICD-9 and ICD-10 medical codes with Excel import functionality.
+- π₯ **ICD Code Management** - Import and manage ICD-9 and ICD-10 medical codes
+- π **Excel Import** - Read data from Excel files and store in PostgreSQL
+- π **Search & Filter** - Search codes by category, code, or display text
+- π **REST API** - Full REST API with Swagger documentation
+- π **Pagination** - Built-in pagination for large datasets
+- π³ **Docker Ready** - PostgreSQL with pgvector extension
+- π **Database Migrations** - Prisma migration system
+- β
**Input Validation** - Type-safe DTOs with validation
+- π **API Documentation** - Interactive Swagger UI
-## Features
+## π Quick Start
-- **ICD Code Management**: Import and manage ICD-9 and ICD-10 medical codes
-- **Excel Import**: Read data from Excel files and store in PostgreSQL database
-- **Search & Filter**: Search codes by category, code, or display text
-- **REST API**: Full REST API endpoints for accessing ICD data
-- **Pagination**: Built-in pagination support for large datasets
+### Prerequisites
-## ICD Service Endpoints
+- Node.js 18+
+- Docker & Docker Compose
+- Git
-### Import Data
-
-```bash
-POST /icd/import
-```
-
-Imports ICD-9 and ICD-10 data from Excel files in the `test/` directory.
-
-### Search Codes
-
-```bash
-GET /icd/search?category=ICD10&search=diabetes&page=1&limit=10
-```
-
-Search ICD codes with optional filters:
-
-- `category`: Filter by ICD9 or ICD10
-- `search`: Search in code or display text
-- `page`: Page number (default: 1)
-- `limit`: Items per page (default: 10)
-
-### Get Statistics
-
-```bash
-GET /icd/statistics
-```
-
-Returns count statistics for ICD codes.
-
-## Database Schema
-
-The application uses PostgreSQL with Prisma ORM. The ICD codes are stored in the `icd_codes` table with the following structure:
-
-```sql
-CREATE TABLE "icd_codes" (
- "id" TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
- "code" TEXT UNIQUE NOT NULL,
- "display" TEXT NOT NULL,
- "version" TEXT NOT NULL,
- "category" TEXT NOT NULL, -- "ICD9" or "ICD10"
- "createdAt" TIMESTAMP DEFAULT NOW(),
- "updatedAt" TIMESTAMP DEFAULT NOW()
-);
-```
-
-**ID Format**: The `id` field now uses UUID (Universal Unique Identifier) format like `550e8400-e29b-41d4-a716-446655440000` instead of CUID.
-
-## Setup Instructions
-
-1. **Install Dependencies**
+### 1. Clone & Install
```bash
+git clone
+cd claim-guard-be
npm install
```
-2. **Database Setup**
- Create a `.env` file with your PostgreSQL connection:
+### 2. Start Database
```bash
-DATABASE_URL="postgresql://username:password@localhost:5432/claim_guard_db?schema=public"
+# Start PostgreSQL with pgvector
+docker-compose up -d
+
+# Verify database is running
+docker-compose ps
```
-3. **Generate Prisma Client**
+### 3. Setup Environment
```bash
+# Copy environment template (edit as needed)
+copy .env.example .env
+
+# Update DATABASE_URL in .env:
+DATABASE_URL=postgresql://postgres:postgres123@localhost:5432/claim_guard
+```
+
+### 4. Run Migrations
+
+```bash
+# Apply database schema
+npx prisma migrate deploy
+
+# Generate Prisma client
npx prisma generate
```
-4. **Run Database Migrations**
+### 5. Start Application
```bash
-npx prisma db push
+# Development mode
+npm run start:dev
+
+# Production mode
+npm run build
+npm run start:prod
```
-5. **Place Excel Files**
- Ensure the following files are in the `test/` directory:
+### 6. Access Services
-- `[PUBLIC] ICD-9CM e-klaim.xlsx`
-- `[PUBLIC] ICD-10 e-klaim.xlsx`
+- **API**: http://localhost:3000
+- **Swagger Docs**: http://localhost:3000/docs
+- **Health Check**: http://localhost:3000/health
-The Excel files should have at least 3 columns:
+## π API Endpoints
-- Column 1: Code
-- Column 2: Display/Description
-- Column 3: Version
+### ICD Management
-## Project setup
+| Method | Endpoint | Description |
+| ------ | ----------------- | -------------------------------- |
+| `POST` | `/icd/import` | Import ICD data from Excel files |
+| `GET` | `/icd/search` | Search ICD codes with filters |
+| `GET` | `/icd/statistics` | Get database statistics |
+
+### Health & Monitoring
+
+| Method | Endpoint | Description |
+| ------ | --------------- | ----------------------------- |
+| `GET` | `/health` | Application health check |
+| `GET` | `/health/ready` | Readiness probe |
+| `GET` | `/health/live` | Liveness probe |
+| `GET` | `/docs` | Interactive API documentation |
+
+### Example Usage
```bash
-$ npm install
+# Import ICD data
+curl -X POST http://localhost:3000/icd/import
+
+# Search for diabetes codes
+curl "http://localhost:3000/icd/search?search=diabetes&page=1&limit=10"
+
+# Get statistics
+curl http://localhost:3000/icd/statistics
+
+# Health check
+curl http://localhost:3000/health
```
-## Compile and run the project
+## π³ Docker Setup
+
+### Database Only (Recommended)
```bash
-# development
-$ npm run start
+# Start PostgreSQL with pgvector
+docker-compose up -d
-# watch mode
-$ npm run start:dev
+# Stop database
+docker-compose down
-# production mode
-$ npm run start:prod
+# Reset database (deletes all data!)
+docker-compose down -v
```
-## Run tests
+### Connection Details
+
+```env
+DATABASE_URL=postgresql://postgres:postgres123@localhost:5432/claim_guard
+Host: localhost
+Port: 5432
+Database: claim_guard
+Username: postgres
+Password: postgres123
+```
+
+### Verify pgvector Extension
```bash
-# unit tests
-$ npm run test
-
-# e2e tests
-$ npm run test:e2e
-
-# test coverage
-$ npm run test:cov
+docker-compose exec postgres psql -U postgres -d claim_guard -c "SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name = 'vector';"
```
-## Deployment
+## ποΈ Database Schema
-When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information.
+### IcdCode Model
-If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps:
+```prisma
+model IcdCode {
+ id String @id @default(uuid())
+ code String @unique
+ display String
+ version String
+ category String // "ICD9" or "ICD10"
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ @@map("icd_codes")
+}
+```
+
+### Migration Commands
```bash
-$ npm install -g @nestjs/mau
-$ mau deploy
+# Check migration status
+npx prisma migrate status
+
+# Create new migration
+npx prisma migrate dev --name description
+
+# Deploy to production
+npx prisma migrate deploy
+
+# Reset database (development)
+npx prisma migrate reset
```
-With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure.
+## βοΈ Environment Configuration
-## Resources
+### Development
-Check out a few resources that may come in handy when working with NestJS:
+```env
+NODE_ENV=development
+PORT=3000
+DATABASE_URL=postgresql://postgres:postgres123@localhost:5432/claim_guard
+CORS_ORIGINS=http://localhost:3000,http://localhost:3001
+ENABLE_DOCS=true
+DEBUG=true
+LOG_LEVEL=debug
+```
-- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
-- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy).
-- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/).
-- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks.
-- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
-- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com).
-- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
-- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
+### Production
-## Support
+```env
+NODE_ENV=production
+PORT=3000
+DATABASE_URL=postgresql://user:pass@host:5432/db
+CORS_ORIGINS=https://yourdomain.com
+ENABLE_DOCS=false
+DEBUG=false
+LOG_LEVEL=warn
+JWT_SECRET=strong-production-secret
+```
-Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
+### Available Variables
-## Stay in touch
+| Variable | Description | Default |
+| -------------- | ---------------------------- | ----------------------- |
+| `NODE_ENV` | Environment mode | `development` |
+| `PORT` | Application port | `3000` |
+| `DATABASE_URL` | PostgreSQL connection string | Required |
+| `CORS_ORIGINS` | Allowed CORS origins | `http://localhost:3000` |
+| `ENABLE_DOCS` | Enable Swagger documentation | `true` |
+| `LOG_LEVEL` | Logging level | `info` |
+| `JWT_SECRET` | JWT signing secret | Required for auth |
-- Author - [Kamil MyΕliwiec](https://twitter.com/kammysliwiec)
-- Website - [https://nestjs.com](https://nestjs.com/)
-- Twitter - [@nestframework](https://twitter.com/nestframework)
+## π§ͺ Testing
-## License
+### API Testing
-Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
+Use the included `icd.http` file with VS Code REST Client extension:
+
+```http
+### Import ICD Data
+POST http://localhost:3000/icd/import
+
+### Search ICD Codes
+GET http://localhost:3000/icd/search?search=diabetes&page=1&limit=10
+
+### Get Statistics
+GET http://localhost:3000/icd/statistics
+```
+
+### Unit Tests
+
+```bash
+# Run tests
+npm run test
+
+# Watch mode
+npm run test:watch
+
+# Coverage
+npm run test:cov
+
+# E2E tests
+npm run test:e2e
+```
+
+## π§ Development
+
+### Project Structure
+
+```
+src/
+βββ main.ts # Application entry point
+βββ app.module.ts # Root module
+βββ icd/ # ICD module
+β βββ icd.controller.ts # REST endpoints
+β βββ icd.service.ts # Business logic
+β βββ icd.module.ts # Module definition
+β βββ dto/ # Data transfer objects
+βββ health/ # Health check module
+βββ prisma/ # Database schema
+```
+
+### Scripts
+
+```bash
+# Development
+npm run start:dev # Start with hot reload
+npm run start:debug # Start with debugger
+
+# Build
+npm run build # Build for production
+npm run start:prod # Start production build
+
+# Database
+npx prisma studio # Open Prisma Studio
+npx prisma db push # Push schema changes (dev only)
+npx prisma generate # Generate Prisma client
+
+# Code Quality
+npm run lint # Run ESLint
+npm run format # Format with Prettier
+```
+
+### Adding New Features
+
+1. **Create DTOs** with validation decorators
+2. **Add Swagger decorators** for API documentation
+3. **Write unit tests** for services and controllers
+4. **Update database schema** if needed
+5. **Create migration** with descriptive name
+
+## π¦ Deployment
+
+### Docker Production
+
+```dockerfile
+# Build stage
+FROM node:18-alpine AS builder
+WORKDIR /app
+COPY package*.json ./
+RUN npm ci --only=production
+COPY . .
+RUN npm run build
+
+# Production stage
+FROM node:18-alpine AS production
+WORKDIR /app
+COPY --from=builder /app/dist ./dist
+COPY --from=builder /app/node_modules ./node_modules
+COPY package*.json ./
+EXPOSE 3000
+CMD ["node", "dist/main"]
+```
+
+### Environment Setup
+
+1. **Production Database**: Use managed PostgreSQL (AWS RDS, Google Cloud SQL)
+2. **Environment Variables**: Set secure values for production
+3. **SSL/TLS**: Enable HTTPS in production
+4. **Monitoring**: Add application monitoring (Prometheus, Grafana)
+5. **Logging**: Configure centralized logging
+
+## π Troubleshooting
+
+### Common Issues
+
+**Port 5432 already in use:**
+
+```bash
+# Check what's using the port
+netstat -ano | findstr :5432
+# Stop local PostgreSQL service
+```
+
+**Database connection failed:**
+
+```bash
+# Check if container is running
+docker-compose ps
+# Check logs
+docker-compose logs
+# Restart database
+docker-compose restart
+```
+
+**Prisma can't connect:**
+
+```bash
+# Verify DATABASE_URL in .env
+# Test connection
+npx prisma db pull
+```
+
+**Build errors:**
+
+```bash
+# Clean install
+rm -rf node_modules package-lock.json
+npm install
+```
+
+## π License
+
+This project is licensed under the MIT License.
+
+## π€ Contributing
+
+1. Fork the repository
+2. Create a feature branch
+3. Make your changes
+4. Add tests
+5. Submit a pull request
+
+## π Support
+
+For questions and support:
+
+- Check the [API documentation](http://localhost:3000/docs)
+- Review the troubleshooting section
+- Create an issue in the repository
+
+---
+
+**Ready to manage ICD codes efficiently!** π
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..4f2b6db
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,25 @@
+services:
+ # PostgreSQL Database with pgvector extension
+ postgres:
+ image: pgvector/pgvector:pg15
+ container_name: claim-guard-postgres
+ restart: unless-stopped
+ environment:
+ POSTGRES_DB: claim_guard
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres123
+ ports:
+ - '5432:5432'
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ - ./docker/postgres/init:/docker-entrypoint-initdb.d
+ healthcheck:
+ test: ['CMD-SHELL', 'pg_isready -U postgres -d claim_guard']
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 30s
+
+volumes:
+ postgres_data:
+ driver: local
diff --git a/docker/postgres/init/01-init.sql b/docker/postgres/init/01-init.sql
new file mode 100644
index 0000000..1cf3e19
--- /dev/null
+++ b/docker/postgres/init/01-init.sql
@@ -0,0 +1,32 @@
+-- =====================================================
+-- Claim Guard Database Initialization Script
+-- =====================================================
+
+-- Create database if it doesn't exist (handled by POSTGRES_DB env var)
+-- But we can create additional databases if needed
+
+-- Enable pgvector extension
+CREATE EXTENSION IF NOT EXISTS vector;
+
+-- Enable other useful extensions
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+CREATE EXTENSION IF NOT EXISTS "pg_trgm";
+CREATE EXTENSION IF NOT EXISTS "btree_gin";
+CREATE EXTENSION IF NOT EXISTS "btree_gist";
+
+-- Create application user if needed (optional)
+-- The main user is already created via POSTGRES_USER
+
+-- Set up database permissions
+GRANT ALL PRIVILEGES ON DATABASE claim_guard TO postgres;
+
+-- Create schema for application (optional, Prisma will use public by default)
+-- CREATE SCHEMA IF NOT EXISTS claim_guard;
+
+-- Log successful initialization
+DO $$
+BEGIN
+ RAISE NOTICE 'Claim Guard database initialized successfully';
+ RAISE NOTICE 'pgvector extension: %', (SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = 'vector'));
+ RAISE NOTICE 'Database ready for Prisma migrations';
+END $$;
diff --git a/docker/scripts/reset-db.bat b/docker/scripts/reset-db.bat
new file mode 100644
index 0000000..c99e745
--- /dev/null
+++ b/docker/scripts/reset-db.bat
@@ -0,0 +1,43 @@
+@echo off
+REM =====================================================
+REM Reset PostgreSQL Database (Windows)
+REM =====================================================
+
+echo ποΈ Resetting PostgreSQL database...
+
+REM Stop services
+docker-compose down
+
+REM Remove volumes (this will delete all data!)
+echo β οΈ WARNING: This will delete ALL database data!
+set /p confirm=Are you sure? (y/N):
+if /i not "%confirm%"=="y" (
+ echo β Operation cancelled
+ exit /b 1
+)
+
+docker-compose down -v
+docker volume rm claim-guard-be_postgres_data 2>nul
+docker volume rm claim-guard-be_pgadmin_data 2>nul
+
+echo β
Database reset complete!
+echo π³ Starting fresh database...
+
+REM Start database again
+docker-compose up -d postgres
+
+echo β³ Waiting for PostgreSQL to be ready...
+
+REM Wait for PostgreSQL to be healthy
+:wait_loop
+docker-compose exec postgres pg_isready -U postgres -d claim_guard >nul 2>&1
+if %errorlevel% neq 0 (
+ echo β³ PostgreSQL is unavailable - sleeping
+ timeout /t 2 /nobreak >nul
+ goto wait_loop
+)
+
+echo β
Fresh database is ready!
+echo π Run 'npx prisma migrate deploy' to setup schema
+
+pause
diff --git a/docker/scripts/start-db.bat b/docker/scripts/start-db.bat
new file mode 100644
index 0000000..a00cd89
--- /dev/null
+++ b/docker/scripts/start-db.bat
@@ -0,0 +1,29 @@
+@echo off
+REM =====================================================
+REM Start PostgreSQL Database Only (Windows)
+REM =====================================================
+
+echo π³ Starting PostgreSQL with pgvector...
+
+REM Start only the database service
+docker-compose up -d postgres
+
+echo β³ Waiting for PostgreSQL to be ready...
+
+REM Wait for PostgreSQL to be healthy
+:wait_loop
+docker-compose exec postgres pg_isready -U postgres -d claim_guard >nul 2>&1
+if %errorlevel% neq 0 (
+ echo β³ PostgreSQL is unavailable - sleeping
+ timeout /t 2 /nobreak >nul
+ goto wait_loop
+)
+
+echo β
PostgreSQL is ready!
+echo π Database URL: postgresql://postgres:postgres123@localhost:5432/claim_guard
+
+REM Show logs
+echo π Database logs:
+docker-compose logs postgres
+
+pause
diff --git a/docker/scripts/start-db.sh b/docker/scripts/start-db.sh
new file mode 100644
index 0000000..13fb03d
--- /dev/null
+++ b/docker/scripts/start-db.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# =====================================================
+# Start PostgreSQL Database Only
+# =====================================================
+
+echo "π³ Starting PostgreSQL with pgvector..."
+
+# Start only the database service
+docker-compose up -d postgres
+
+echo "β³ Waiting for PostgreSQL to be ready..."
+
+# Wait for PostgreSQL to be healthy
+until docker-compose exec postgres pg_isready -U postgres -d claim_guard; do
+ echo "β³ PostgreSQL is unavailable - sleeping"
+ sleep 2
+done
+
+echo "β
PostgreSQL is ready!"
+echo "π Database URL: postgresql://postgres:postgres123@localhost:5432/claim_guard"
+
+# Show logs
+echo "π Database logs:"
+docker-compose logs postgres
diff --git a/package-lock.json b/package-lock.json
index 69d3739..38547d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,12 +9,20 @@
"version": "0.0.1",
"license": "UNLICENSED",
"dependencies": {
+ "@langchain/community": "^0.3.53",
+ "@langchain/openai": "^0.6.9",
"@nestjs/common": "^11.0.1",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
+ "@nestjs/swagger": "^11.2.0",
"@prisma/client": "^6.14.0",
+ "class-transformer": "^0.5.1",
+ "class-validator": "^0.14.2",
+ "langchain": "^0.3.31",
+ "pg": "^8.11.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
+ "swagger-ui-express": "^5.0.1",
"xlsx": "^0.18.5"
},
"devDependencies": {
@@ -203,6 +211,39 @@
"tslib": "^2.1.0"
}
},
+ "node_modules/@anthropic-ai/sdk": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.27.3.tgz",
+ "integrity": "sha512-IjLt0gd3L4jlOfilxVXTifn42FnVffMgDC04RJK1KDZpmkBWLv0XC92MVVmkxrFZNS/7l3xWgP/I3nqtX1sQHw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "^18.11.18",
+ "@types/node-fetch": "^2.6.4",
+ "abort-controller": "^3.0.0",
+ "agentkeepalive": "^4.2.1",
+ "form-data-encoder": "1.7.2",
+ "formdata-node": "^4.3.2",
+ "node-fetch": "^2.6.7"
+ }
+ },
+ "node_modules/@anthropic-ai/sdk/node_modules/@types/node": {
+ "version": "18.19.123",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.123.tgz",
+ "integrity": "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@anthropic-ai/sdk/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -729,6 +770,66 @@
"url": "https://github.com/sponsors/Borewit"
}
},
+ "node_modules/@browserbasehq/sdk": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@browserbasehq/sdk/-/sdk-2.6.0.tgz",
+ "integrity": "sha512-83iXP5D7xMm8Wyn66TUaUrgoByCmAJuoMoZQI3sGg3JAiMlTfnCIMqyVBoNSaItaPIkaCnrsj6LiusmXV2X9YA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "^18.11.18",
+ "@types/node-fetch": "^2.6.4",
+ "abort-controller": "^3.0.0",
+ "agentkeepalive": "^4.2.1",
+ "form-data-encoder": "1.7.2",
+ "formdata-node": "^4.3.2",
+ "node-fetch": "^2.6.7"
+ }
+ },
+ "node_modules/@browserbasehq/sdk/node_modules/@types/node": {
+ "version": "18.19.123",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.123.tgz",
+ "integrity": "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@browserbasehq/sdk/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@browserbasehq/stagehand": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/@browserbasehq/stagehand/-/stagehand-1.14.0.tgz",
+ "integrity": "sha512-Hi/EzgMFWz+FKyepxHTrqfTPjpsuBS4zRy3e9sbMpBgLPv+9c0R+YZEvS7Bw4mTS66QtvvURRT6zgDGFotthVQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@anthropic-ai/sdk": "^0.27.3",
+ "@browserbasehq/sdk": "^2.0.0",
+ "ws": "^8.18.0",
+ "zod-to-json-schema": "^3.23.5"
+ },
+ "peerDependencies": {
+ "@playwright/test": "^1.42.1",
+ "deepmerge": "^4.3.1",
+ "dotenv": "^16.4.5",
+ "openai": "^4.62.1",
+ "zod": "^3.23.8"
+ }
+ },
+ "node_modules/@cfworker/json-schema": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz",
+ "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@colors/colors": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
@@ -952,6 +1053,46 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@graphql-typed-document-node/core": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz",
+ "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz",
+ "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.13",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.15",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
+ "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1018,6 +1159,38 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@ibm-cloud/watsonx-ai": {
+ "version": "1.6.10",
+ "resolved": "https://registry.npmjs.org/@ibm-cloud/watsonx-ai/-/watsonx-ai-1.6.10.tgz",
+ "integrity": "sha512-aZV50/s8VZc7w0t/qcaBw3RLT3WDsAeZUJlP8EbG/csZJF3a8F7alihbGOM4lJFM7R4Z81Lucz3nfHi2KR7J4Q==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "^18.0.0",
+ "extend": "3.0.2",
+ "ibm-cloud-sdk-core": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@ibm-cloud/watsonx-ai/node_modules/@types/node": {
+ "version": "18.19.123",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.123.tgz",
+ "integrity": "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@ibm-cloud/watsonx-ai/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@inquirer/checkbox": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.1.tgz",
@@ -2051,6 +2224,660 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@langchain/community": {
+ "version": "0.3.53",
+ "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.53.tgz",
+ "integrity": "sha512-TlQzXXuiqPkpALvvuClzt6K83EQ2oA+0B/UzWrrWQPCYpJtfy5kbT/Uwc4PPa8twdVUNpLcXgFaLtb3U1EXVAg==",
+ "license": "MIT",
+ "dependencies": {
+ "@langchain/openai": ">=0.2.0 <0.7.0",
+ "@langchain/weaviate": "^0.2.0",
+ "binary-extensions": "^2.2.0",
+ "expr-eval": "^2.0.2",
+ "flat": "^5.0.2",
+ "js-yaml": "^4.1.0",
+ "langchain": ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0",
+ "langsmith": "^0.3.46",
+ "uuid": "^10.0.0",
+ "zod": "^3.25.32"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@arcjet/redact": "^v1.0.0-alpha.23",
+ "@aws-crypto/sha256-js": "^5.0.0",
+ "@aws-sdk/client-bedrock-agent-runtime": "^3.749.0",
+ "@aws-sdk/client-bedrock-runtime": "^3.749.0",
+ "@aws-sdk/client-dynamodb": "^3.749.0",
+ "@aws-sdk/client-kendra": "^3.749.0",
+ "@aws-sdk/client-lambda": "^3.749.0",
+ "@aws-sdk/client-s3": "^3.749.0",
+ "@aws-sdk/client-sagemaker-runtime": "^3.749.0",
+ "@aws-sdk/client-sfn": "^3.749.0",
+ "@aws-sdk/credential-provider-node": "^3.388.0",
+ "@azure/search-documents": "^12.0.0",
+ "@azure/storage-blob": "^12.15.0",
+ "@browserbasehq/sdk": "*",
+ "@browserbasehq/stagehand": "^1.0.0",
+ "@clickhouse/client": "^0.2.5",
+ "@cloudflare/ai": "*",
+ "@datastax/astra-db-ts": "^1.0.0",
+ "@elastic/elasticsearch": "^8.4.0",
+ "@getmetal/metal-sdk": "*",
+ "@getzep/zep-cloud": "^1.0.6",
+ "@getzep/zep-js": "^0.9.0",
+ "@gomomento/sdk": "^1.51.1",
+ "@gomomento/sdk-core": "^1.51.1",
+ "@google-ai/generativelanguage": "*",
+ "@google-cloud/storage": "^6.10.1 || ^7.7.0",
+ "@gradientai/nodejs-sdk": "^1.2.0",
+ "@huggingface/inference": "^4.0.5",
+ "@huggingface/transformers": "^3.5.2",
+ "@ibm-cloud/watsonx-ai": "*",
+ "@lancedb/lancedb": "^0.12.0",
+ "@langchain/core": ">=0.3.58 <0.4.0",
+ "@layerup/layerup-security": "^1.5.12",
+ "@libsql/client": "^0.14.0",
+ "@mendable/firecrawl-js": "^1.4.3",
+ "@mlc-ai/web-llm": "*",
+ "@mozilla/readability": "*",
+ "@neondatabase/serverless": "*",
+ "@notionhq/client": "^2.2.10",
+ "@opensearch-project/opensearch": "*",
+ "@pinecone-database/pinecone": "*",
+ "@planetscale/database": "^1.8.0",
+ "@premai/prem-sdk": "^0.3.25",
+ "@qdrant/js-client-rest": "^1.15.0",
+ "@raycast/api": "^1.55.2",
+ "@rockset/client": "^0.9.1",
+ "@smithy/eventstream-codec": "^2.0.5",
+ "@smithy/protocol-http": "^3.0.6",
+ "@smithy/signature-v4": "^2.0.10",
+ "@smithy/util-utf8": "^2.0.0",
+ "@spider-cloud/spider-client": "^0.0.21",
+ "@supabase/supabase-js": "^2.45.0",
+ "@tensorflow-models/universal-sentence-encoder": "*",
+ "@tensorflow/tfjs-converter": "*",
+ "@tensorflow/tfjs-core": "*",
+ "@upstash/ratelimit": "^1.1.3 || ^2.0.3",
+ "@upstash/redis": "^1.20.6",
+ "@upstash/vector": "^1.1.1",
+ "@vercel/kv": "*",
+ "@vercel/postgres": "*",
+ "@writerai/writer-sdk": "^0.40.2",
+ "@xata.io/client": "^0.28.0",
+ "@zilliz/milvus2-sdk-node": ">=2.3.5",
+ "apify-client": "^2.7.1",
+ "assemblyai": "^4.6.0",
+ "azion": "^1.11.1",
+ "better-sqlite3": ">=9.4.0 <12.0.0",
+ "cassandra-driver": "^4.7.2",
+ "cborg": "^4.1.1",
+ "cheerio": "^1.0.0-rc.12",
+ "chromadb": "*",
+ "closevector-common": "0.1.3",
+ "closevector-node": "0.1.6",
+ "closevector-web": "0.1.6",
+ "cohere-ai": "*",
+ "convex": "^1.3.1",
+ "crypto-js": "^4.2.0",
+ "d3-dsv": "^2.0.0",
+ "discord.js": "^14.14.1",
+ "dria": "^0.0.3",
+ "duck-duck-scrape": "^2.2.5",
+ "epub2": "^3.0.1",
+ "fast-xml-parser": "*",
+ "firebase-admin": "^11.9.0 || ^12.0.0",
+ "google-auth-library": "*",
+ "googleapis": "*",
+ "hnswlib-node": "^3.0.0",
+ "html-to-text": "^9.0.5",
+ "ibm-cloud-sdk-core": "*",
+ "ignore": "^5.2.0",
+ "interface-datastore": "^8.2.11",
+ "ioredis": "^5.3.2",
+ "it-all": "^3.0.4",
+ "jsdom": "*",
+ "jsonwebtoken": "^9.0.2",
+ "llmonitor": "^0.5.9",
+ "lodash": "^4.17.21",
+ "lunary": "^0.7.10",
+ "mammoth": "^1.6.0",
+ "mariadb": "^3.4.0",
+ "mem0ai": "^2.1.8",
+ "mongodb": "^6.17.0",
+ "mysql2": "^3.9.8",
+ "neo4j-driver": "*",
+ "notion-to-md": "^3.1.0",
+ "officeparser": "^4.0.4",
+ "openai": "*",
+ "pdf-parse": "1.1.1",
+ "pg": "^8.11.0",
+ "pg-copy-streams": "^6.0.5",
+ "pickleparser": "^0.2.1",
+ "playwright": "^1.32.1",
+ "portkey-ai": "^0.1.11",
+ "puppeteer": "*",
+ "pyodide": ">=0.24.1 <0.27.0",
+ "redis": "*",
+ "replicate": "*",
+ "sonix-speech-recognition": "^2.1.1",
+ "srt-parser-2": "^1.2.3",
+ "typeorm": "^0.3.20",
+ "typesense": "^1.5.3",
+ "usearch": "^1.1.1",
+ "voy-search": "0.6.2",
+ "weaviate-client": "^3.5.2",
+ "web-auth-library": "^1.0.3",
+ "word-extractor": "*",
+ "ws": "^8.14.2",
+ "youtubei.js": "*"
+ },
+ "peerDependenciesMeta": {
+ "@arcjet/redact": {
+ "optional": true
+ },
+ "@aws-crypto/sha256-js": {
+ "optional": true
+ },
+ "@aws-sdk/client-bedrock-agent-runtime": {
+ "optional": true
+ },
+ "@aws-sdk/client-bedrock-runtime": {
+ "optional": true
+ },
+ "@aws-sdk/client-dynamodb": {
+ "optional": true
+ },
+ "@aws-sdk/client-kendra": {
+ "optional": true
+ },
+ "@aws-sdk/client-lambda": {
+ "optional": true
+ },
+ "@aws-sdk/client-s3": {
+ "optional": true
+ },
+ "@aws-sdk/client-sagemaker-runtime": {
+ "optional": true
+ },
+ "@aws-sdk/client-sfn": {
+ "optional": true
+ },
+ "@aws-sdk/credential-provider-node": {
+ "optional": true
+ },
+ "@aws-sdk/dsql-signer": {
+ "optional": true
+ },
+ "@azure/search-documents": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@browserbasehq/sdk": {
+ "optional": true
+ },
+ "@clickhouse/client": {
+ "optional": true
+ },
+ "@cloudflare/ai": {
+ "optional": true
+ },
+ "@datastax/astra-db-ts": {
+ "optional": true
+ },
+ "@elastic/elasticsearch": {
+ "optional": true
+ },
+ "@getmetal/metal-sdk": {
+ "optional": true
+ },
+ "@getzep/zep-cloud": {
+ "optional": true
+ },
+ "@getzep/zep-js": {
+ "optional": true
+ },
+ "@gomomento/sdk": {
+ "optional": true
+ },
+ "@gomomento/sdk-core": {
+ "optional": true
+ },
+ "@google-ai/generativelanguage": {
+ "optional": true
+ },
+ "@google-cloud/storage": {
+ "optional": true
+ },
+ "@gradientai/nodejs-sdk": {
+ "optional": true
+ },
+ "@huggingface/inference": {
+ "optional": true
+ },
+ "@huggingface/transformers": {
+ "optional": true
+ },
+ "@lancedb/lancedb": {
+ "optional": true
+ },
+ "@layerup/layerup-security": {
+ "optional": true
+ },
+ "@libsql/client": {
+ "optional": true
+ },
+ "@mendable/firecrawl-js": {
+ "optional": true
+ },
+ "@mlc-ai/web-llm": {
+ "optional": true
+ },
+ "@mozilla/readability": {
+ "optional": true
+ },
+ "@neondatabase/serverless": {
+ "optional": true
+ },
+ "@notionhq/client": {
+ "optional": true
+ },
+ "@opensearch-project/opensearch": {
+ "optional": true
+ },
+ "@pinecone-database/pinecone": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@premai/prem-sdk": {
+ "optional": true
+ },
+ "@qdrant/js-client-rest": {
+ "optional": true
+ },
+ "@raycast/api": {
+ "optional": true
+ },
+ "@rockset/client": {
+ "optional": true
+ },
+ "@smithy/eventstream-codec": {
+ "optional": true
+ },
+ "@smithy/protocol-http": {
+ "optional": true
+ },
+ "@smithy/signature-v4": {
+ "optional": true
+ },
+ "@smithy/util-utf8": {
+ "optional": true
+ },
+ "@spider-cloud/spider-client": {
+ "optional": true
+ },
+ "@supabase/supabase-js": {
+ "optional": true
+ },
+ "@tensorflow-models/universal-sentence-encoder": {
+ "optional": true
+ },
+ "@tensorflow/tfjs-converter": {
+ "optional": true
+ },
+ "@tensorflow/tfjs-core": {
+ "optional": true
+ },
+ "@upstash/ratelimit": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@upstash/vector": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "@vercel/postgres": {
+ "optional": true
+ },
+ "@writerai/writer-sdk": {
+ "optional": true
+ },
+ "@xata.io/client": {
+ "optional": true
+ },
+ "@zilliz/milvus2-sdk-node": {
+ "optional": true
+ },
+ "apify-client": {
+ "optional": true
+ },
+ "assemblyai": {
+ "optional": true
+ },
+ "azion": {
+ "optional": true
+ },
+ "better-sqlite3": {
+ "optional": true
+ },
+ "cassandra-driver": {
+ "optional": true
+ },
+ "cborg": {
+ "optional": true
+ },
+ "cheerio": {
+ "optional": true
+ },
+ "chromadb": {
+ "optional": true
+ },
+ "closevector-common": {
+ "optional": true
+ },
+ "closevector-node": {
+ "optional": true
+ },
+ "closevector-web": {
+ "optional": true
+ },
+ "cohere-ai": {
+ "optional": true
+ },
+ "convex": {
+ "optional": true
+ },
+ "crypto-js": {
+ "optional": true
+ },
+ "d3-dsv": {
+ "optional": true
+ },
+ "discord.js": {
+ "optional": true
+ },
+ "dria": {
+ "optional": true
+ },
+ "duck-duck-scrape": {
+ "optional": true
+ },
+ "epub2": {
+ "optional": true
+ },
+ "fast-xml-parser": {
+ "optional": true
+ },
+ "firebase-admin": {
+ "optional": true
+ },
+ "google-auth-library": {
+ "optional": true
+ },
+ "googleapis": {
+ "optional": true
+ },
+ "hnswlib-node": {
+ "optional": true
+ },
+ "html-to-text": {
+ "optional": true
+ },
+ "ignore": {
+ "optional": true
+ },
+ "interface-datastore": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "it-all": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ },
+ "jsonwebtoken": {
+ "optional": true
+ },
+ "llmonitor": {
+ "optional": true
+ },
+ "lodash": {
+ "optional": true
+ },
+ "lunary": {
+ "optional": true
+ },
+ "mammoth": {
+ "optional": true
+ },
+ "mariadb": {
+ "optional": true
+ },
+ "mem0ai": {
+ "optional": true
+ },
+ "mongodb": {
+ "optional": true
+ },
+ "mysql2": {
+ "optional": true
+ },
+ "neo4j-driver": {
+ "optional": true
+ },
+ "notion-to-md": {
+ "optional": true
+ },
+ "officeparser": {
+ "optional": true
+ },
+ "pdf-parse": {
+ "optional": true
+ },
+ "pg": {
+ "optional": true
+ },
+ "pg-copy-streams": {
+ "optional": true
+ },
+ "pickleparser": {
+ "optional": true
+ },
+ "playwright": {
+ "optional": true
+ },
+ "portkey-ai": {
+ "optional": true
+ },
+ "puppeteer": {
+ "optional": true
+ },
+ "pyodide": {
+ "optional": true
+ },
+ "redis": {
+ "optional": true
+ },
+ "replicate": {
+ "optional": true
+ },
+ "sonix-speech-recognition": {
+ "optional": true
+ },
+ "srt-parser-2": {
+ "optional": true
+ },
+ "typeorm": {
+ "optional": true
+ },
+ "typesense": {
+ "optional": true
+ },
+ "usearch": {
+ "optional": true
+ },
+ "voy-search": {
+ "optional": true
+ },
+ "weaviate-client": {
+ "optional": true
+ },
+ "web-auth-library": {
+ "optional": true
+ },
+ "word-extractor": {
+ "optional": true
+ },
+ "ws": {
+ "optional": true
+ },
+ "youtubei.js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@langchain/core": {
+ "version": "0.3.72",
+ "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.72.tgz",
+ "integrity": "sha512-WsGWVZYnlKffj2eEfDocPNiaTRoxyYiLSQdQ7oxZvxGZBqo/90vpjbC33UGK1uPNBM4kT+pkdaol/MnvKUh8TQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@cfworker/json-schema": "^4.0.2",
+ "ansi-styles": "^5.0.0",
+ "camelcase": "6",
+ "decamelize": "1.2.0",
+ "js-tiktoken": "^1.0.12",
+ "langsmith": "^0.3.46",
+ "mustache": "^4.2.0",
+ "p-queue": "^6.6.2",
+ "p-retry": "4",
+ "uuid": "^10.0.0",
+ "zod": "^3.25.32",
+ "zod-to-json-schema": "^3.22.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@langchain/core/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@langchain/core/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@langchain/openai": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.6.9.tgz",
+ "integrity": "sha512-Dl+YVBTFia7WE4/jFemQEVchPbsahy/dD97jo6A9gLnYfTkWa/jh8Q78UjHQ3lobif84j2ebjHPcDHG1L0NUWg==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tiktoken": "^1.0.12",
+ "openai": "5.12.2",
+ "zod": "^3.25.32"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@langchain/core": ">=0.3.68 <0.4.0"
+ }
+ },
+ "node_modules/@langchain/openai/node_modules/openai": {
+ "version": "5.12.2",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-5.12.2.tgz",
+ "integrity": "sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==",
+ "license": "Apache-2.0",
+ "bin": {
+ "openai": "bin/cli"
+ },
+ "peerDependencies": {
+ "ws": "^8.18.0",
+ "zod": "^3.23.8"
+ },
+ "peerDependenciesMeta": {
+ "ws": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@langchain/textsplitters": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@langchain/textsplitters/-/textsplitters-0.1.0.tgz",
+ "integrity": "sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tiktoken": "^1.0.12"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@langchain/core": ">=0.2.21 <0.4.0"
+ }
+ },
+ "node_modules/@langchain/weaviate": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@langchain/weaviate/-/weaviate-0.2.2.tgz",
+ "integrity": "sha512-nMkK4ZwfKjQR98kzpL/PPdFixdmD/KX89lZ9R5rhEShv3nfVyfGW8bVMpmC91kqIWxsjeqaqUZ1ZAdzpZRnE/w==",
+ "license": "MIT",
+ "dependencies": {
+ "uuid": "^10.0.0",
+ "weaviate-client": "^3.5.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@langchain/core": ">=0.2.21 <0.4.0"
+ }
+ },
"node_modules/@lukeed/csprng": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz",
@@ -2060,6 +2887,12 @@
"node": ">=8"
}
},
+ "node_modules/@microsoft/tsdoc": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz",
+ "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==",
+ "license": "MIT"
+ },
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
@@ -2376,6 +3209,26 @@
}
}
},
+ "node_modules/@nestjs/mapped-types": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.0.tgz",
+ "integrity": "sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
+ "class-transformer": "^0.4.0 || ^0.5.0",
+ "class-validator": "^0.13.0 || ^0.14.0",
+ "reflect-metadata": "^0.1.12 || ^0.2.0"
+ },
+ "peerDependenciesMeta": {
+ "class-transformer": {
+ "optional": true
+ },
+ "class-validator": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@nestjs/platform-express": {
"version": "11.1.6",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.6.tgz",
@@ -2414,6 +3267,39 @@
"typescript": ">=4.8.2"
}
},
+ "node_modules/@nestjs/swagger": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.2.0.tgz",
+ "integrity": "sha512-5wolt8GmpNcrQv34tIPUtPoV1EeFbCetm40Ij3+M0FNNnf2RJ3FyWfuQvI8SBlcJyfaounYVTKzKHreFXsUyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "@microsoft/tsdoc": "0.15.1",
+ "@nestjs/mapped-types": "2.1.0",
+ "js-yaml": "4.1.0",
+ "lodash": "4.17.21",
+ "path-to-regexp": "8.2.0",
+ "swagger-ui-dist": "5.21.0"
+ },
+ "peerDependencies": {
+ "@fastify/static": "^8.0.0",
+ "@nestjs/common": "^11.0.1",
+ "@nestjs/core": "^11.0.1",
+ "class-transformer": "*",
+ "class-validator": "*",
+ "reflect-metadata": "^0.1.12 || ^0.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@fastify/static": {
+ "optional": true
+ },
+ "class-transformer": {
+ "optional": true
+ },
+ "class-validator": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@nestjs/testing": {
"version": "11.1.6",
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.6.tgz",
@@ -2543,6 +3429,22 @@
"url": "https://opencollective.com/pkgr"
}
},
+ "node_modules/@playwright/test": {
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz",
+ "integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "playwright": "1.55.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@prisma/client": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.14.0.tgz",
@@ -2628,6 +3530,77 @@
"@prisma/debug": "6.14.0"
}
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@scarf/scarf": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
+ "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0"
+ },
"node_modules/@sinclair/typebox": {
"version": "0.34.40",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz",
@@ -2798,6 +3771,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/debug": {
+ "version": "4.1.12",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
@@ -2918,16 +3901,33 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@types/node": {
"version": "22.17.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz",
"integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==",
- "dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.13",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
+ "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.4"
+ }
+ },
"node_modules/@types/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
@@ -2942,6 +3942,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "license": "MIT"
+ },
"node_modules/@types/send": {
"version": "0.17.5",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
@@ -2996,6 +4002,25 @@
"@types/superagent": "^8.1.0"
}
},
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/uuid": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
+ "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/validator": {
+ "version": "13.15.2",
+ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz",
+ "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==",
+ "license": "MIT"
+ },
"node_modules/@types/xlsx": {
"version": "0.0.35",
"resolved": "https://registry.npmjs.org/@types/xlsx/-/xlsx-0.0.35.tgz",
@@ -3729,6 +4754,25 @@
"dev": true,
"license": "Apache-2.0"
},
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/abort-controller-x": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.4.3.tgz",
+ "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==",
+ "license": "MIT"
+ },
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -3800,6 +4844,19 @@
"node": ">=0.8"
}
},
+ "node_modules/agentkeepalive": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
+ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -3912,7 +4969,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -3978,7 +5034,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
"license": "Python-2.0"
},
"node_modules/array-timsort": {
@@ -3999,9 +5054,20 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/axios": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
+ "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-jest": {
"version": "30.0.5",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz",
@@ -4111,7 +5177,6 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -4128,6 +5193,18 @@
],
"license": "MIT"
},
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -4265,12 +5342,28 @@
"ieee754": "^1.1.13"
}
},
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause",
+ "peer": true
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"license": "MIT"
},
+ "node_modules/buffer-writer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
+ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
@@ -4407,7 +5500,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
@@ -4496,6 +5588,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/class-transformer": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
+ "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
+ "license": "MIT"
+ },
+ "node_modules/class-validator": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.2.tgz",
+ "integrity": "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/validator": "^13.11.8",
+ "libphonenumber-js": "^1.11.1",
+ "validator": "^13.9.0"
+ }
+ },
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -4552,7 +5661,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
@@ -4567,7 +5675,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -4577,7 +5684,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -4590,7 +5696,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -4645,7 +5750,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -4658,14 +5762,12 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
@@ -4749,6 +5851,15 @@
"node": "^14.18.0 || >=16.10.0"
}
},
+ "node_modules/console-table-printer": {
+ "version": "2.14.6",
+ "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.14.6.tgz",
+ "integrity": "sha512-MCBl5HNVaFuuHW6FGbL/4fB7N/ormCy+tQ+sxTrF6QtSbSNETvPuOVbkJBhzDgYhvjWGrTma4eYJa37ZuoQsPw==",
+ "license": "MIT",
+ "dependencies": {
+ "simple-wcswidth": "^1.0.1"
+ }
+ },
"node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
@@ -4868,6 +5979,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cross-fetch": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+ "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.7.0"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -4900,6 +6020,16 @@
}
}
},
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/dedent": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz",
@@ -4926,7 +6056,6 @@
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -4966,7 +6095,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.4.0"
@@ -5023,7 +6151,6 @@
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
- "devOptional": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -5053,6 +6180,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -5094,7 +6231,6 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
"license": "MIT"
},
"node_modules/empathic": {
@@ -5181,7 +6317,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -5197,7 +6332,6 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -5447,11 +6581,26 @@
"node": ">= 0.6"
}
},
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "license": "MIT"
+ },
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.x"
@@ -5516,6 +6665,12 @@
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
+ "node_modules/expr-eval": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expr-eval/-/expr-eval-2.0.2.tgz",
+ "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==",
+ "license": "MIT"
+ },
"node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
@@ -5565,6 +6720,13 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/fast-check": {
"version": "3.23.2",
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz",
@@ -5790,6 +6952,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "license": "BSD-3-Clause",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
"node_modules/flat-cache": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -5811,6 +6982,27 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -5860,7 +7052,6 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
- "dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
@@ -5873,11 +7064,17 @@
"node": ">= 6"
}
},
+ "node_modules/form-data-encoder": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
+ "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/form-data/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -5887,7 +7084,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -5896,6 +7092,20 @@
"node": ">= 0.6"
}
},
+ "node_modules/formdata-node": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
+ "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "node-domexception": "1.0.0",
+ "web-streams-polyfill": "4.0.0-beta.3"
+ },
+ "engines": {
+ "node": ">= 12.20"
+ }
+ },
"node_modules/formidable": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
@@ -6008,7 +7218,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
@@ -6191,11 +7400,33 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/graphql": {
+ "version": "16.11.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
+ "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
+ }
+ },
+ "node_modules/graphql-request": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz",
+ "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@graphql-typed-document-node/core": "^3.2.0",
+ "cross-fetch": "^3.1.5"
+ },
+ "peerDependencies": {
+ "graphql": "14 - 16"
+ }
+ },
"node_modules/handlebars": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5",
@@ -6217,7 +7448,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -6227,7 +7458,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6259,7 +7489,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@@ -6325,6 +7554,150 @@
"node": ">=10.17.0"
}
},
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core": {
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/ibm-cloud-sdk-core/-/ibm-cloud-sdk-core-5.4.2.tgz",
+ "integrity": "sha512-5VFkKYU/vSIWFJTVt392XEdPmiEwUJqhxjn1MRO3lfELyU2FB+yYi8brbmXUgq+D1acHR1fpS7tIJ6IlnrR9Cg==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.19.80",
+ "@types/tough-cookie": "^4.0.0",
+ "axios": "^1.11.0",
+ "camelcase": "^6.3.0",
+ "debug": "^4.3.4",
+ "dotenv": "^16.4.5",
+ "extend": "3.0.2",
+ "file-type": "16.5.4",
+ "form-data": "^4.0.4",
+ "isstream": "0.1.2",
+ "jsonwebtoken": "^9.0.2",
+ "mime-types": "2.1.35",
+ "retry-axios": "^2.6.0",
+ "tough-cookie": "^4.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/@types/node": {
+ "version": "18.19.123",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.123.tgz",
+ "integrity": "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/file-type": {
+ "version": "16.5.4",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz",
+ "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "readable-web-to-node-stream": "^3.0.0",
+ "strtok3": "^6.2.4",
+ "token-types": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/strtok3": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
+ "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "peek-readable": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/token-types": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
+ "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "ieee754": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/ibm-cloud-sdk-core/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -6361,7 +7734,7 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">= 4"
@@ -6462,7 +7835,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6550,6 +7922,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
@@ -7431,6 +8810,15 @@
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/js-tiktoken": {
+ "version": "1.0.21",
+ "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
+ "integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.5.1"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7442,7 +8830,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -7525,6 +8912,61 @@
"graceful-fs": "^4.1.6"
}
},
+ "node_modules/jsonpointer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
+ "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
+ "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -7535,6 +8977,136 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/langchain": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.31.tgz",
+ "integrity": "sha512-C7n7WGa44RytsuxEtGcArVcXidRqzjl6UWQxaG3NdIw4gIqErWoOlNC1qADAa04H5JAOARxuE6S99+WNXB/rzA==",
+ "license": "MIT",
+ "dependencies": {
+ "@langchain/openai": ">=0.1.0 <0.7.0",
+ "@langchain/textsplitters": ">=0.0.0 <0.2.0",
+ "js-tiktoken": "^1.0.12",
+ "js-yaml": "^4.1.0",
+ "jsonpointer": "^5.0.1",
+ "langsmith": "^0.3.46",
+ "openapi-types": "^12.1.3",
+ "p-retry": "4",
+ "uuid": "^10.0.0",
+ "yaml": "^2.2.1",
+ "zod": "^3.25.32"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@langchain/anthropic": "*",
+ "@langchain/aws": "*",
+ "@langchain/cerebras": "*",
+ "@langchain/cohere": "*",
+ "@langchain/core": ">=0.3.58 <0.4.0",
+ "@langchain/deepseek": "*",
+ "@langchain/google-genai": "*",
+ "@langchain/google-vertexai": "*",
+ "@langchain/google-vertexai-web": "*",
+ "@langchain/groq": "*",
+ "@langchain/mistralai": "*",
+ "@langchain/ollama": "*",
+ "@langchain/xai": "*",
+ "axios": "*",
+ "cheerio": "*",
+ "handlebars": "^4.7.8",
+ "peggy": "^3.0.2",
+ "typeorm": "*"
+ },
+ "peerDependenciesMeta": {
+ "@langchain/anthropic": {
+ "optional": true
+ },
+ "@langchain/aws": {
+ "optional": true
+ },
+ "@langchain/cerebras": {
+ "optional": true
+ },
+ "@langchain/cohere": {
+ "optional": true
+ },
+ "@langchain/deepseek": {
+ "optional": true
+ },
+ "@langchain/google-genai": {
+ "optional": true
+ },
+ "@langchain/google-vertexai": {
+ "optional": true
+ },
+ "@langchain/google-vertexai-web": {
+ "optional": true
+ },
+ "@langchain/groq": {
+ "optional": true
+ },
+ "@langchain/mistralai": {
+ "optional": true
+ },
+ "@langchain/ollama": {
+ "optional": true
+ },
+ "@langchain/xai": {
+ "optional": true
+ },
+ "axios": {
+ "optional": true
+ },
+ "cheerio": {
+ "optional": true
+ },
+ "handlebars": {
+ "optional": true
+ },
+ "peggy": {
+ "optional": true
+ },
+ "typeorm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/langsmith": {
+ "version": "0.3.63",
+ "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.63.tgz",
+ "integrity": "sha512-GrioB7LOUksKIYsdYbBUwyD3ezy+OAQ5eu5vebytMsX3wT0xfW4rbM+vHqCY7RgZwUYLR/RlpuC18pdO+NqugA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/uuid": "^10.0.0",
+ "chalk": "^4.1.2",
+ "console-table-printer": "^2.12.1",
+ "p-queue": "^6.6.2",
+ "p-retry": "4",
+ "semver": "^7.6.3",
+ "uuid": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "*",
+ "@opentelemetry/exporter-trace-otlp-proto": "*",
+ "@opentelemetry/sdk-trace-base": "*",
+ "openai": "*"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@opentelemetry/exporter-trace-otlp-proto": {
+ "optional": true
+ },
+ "@opentelemetry/sdk-trace-base": {
+ "optional": true
+ },
+ "openai": {
+ "optional": true
+ }
+ }
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -7559,6 +9131,12 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/libphonenumber-js": {
+ "version": "1.12.13",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.13.tgz",
+ "integrity": "sha512-QZXnR/OGiDcBjF4hGk0wwVrPcZvbSSyzlvkjXv5LFfktj7O2VZDrt4Xs8SgR/vOFco+qk1i8J43ikMXZoTrtPw==",
+ "license": "MIT"
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -7615,9 +9193,56 @@
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -7632,6 +9257,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -7649,6 +9281,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -7954,6 +9592,16 @@
"node": ">= 0.6"
}
},
+ "node_modules/mustache": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
+ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "mustache": "bin/mustache"
+ }
+ },
"node_modules/mute-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
@@ -8000,9 +9648,39 @@
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
+ "node_modules/nice-grpc": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/nice-grpc/-/nice-grpc-2.1.12.tgz",
+ "integrity": "sha512-J1n4Wg+D3IhRhGQb+iqh2OpiM0GzTve/kf2lnlW4S+xczmIEd0aHUDV1OsJ5a3q8GSTqJf+s4Rgg1M8uJltarw==",
+ "license": "MIT",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.13.1",
+ "abort-controller-x": "^0.4.0",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc-client-middleware-retry": {
+ "version": "3.1.11",
+ "resolved": "https://registry.npmjs.org/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-3.1.11.tgz",
+ "integrity": "sha512-xW/imz/kNG2g0DwTfH2eYEGrg1chSLrXtvGp9fg2qkhTgGFfAS/Pq3+t+9G8KThcC4hK/xlEyKvZWKk++33S6A==",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller-x": "^0.4.0",
+ "nice-grpc-common": "^2.0.2"
+ }
+ },
+ "node_modules/nice-grpc-common": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/nice-grpc-common/-/nice-grpc-common-2.0.2.tgz",
+ "integrity": "sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ts-error": "^1.0.6"
+ }
+ },
"node_modules/node-abort-controller": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
@@ -8010,6 +9688,27 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
"node_modules/node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@@ -8020,6 +9719,26 @@
"lodash": "^4.17.21"
}
},
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/node-fetch-native": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
@@ -8149,6 +9868,60 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/openai": {
+ "version": "4.104.0",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz",
+ "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "^18.11.18",
+ "@types/node-fetch": "^2.6.4",
+ "abort-controller": "^3.0.0",
+ "agentkeepalive": "^4.2.1",
+ "form-data-encoder": "1.7.2",
+ "formdata-node": "^4.3.2",
+ "node-fetch": "^2.6.7"
+ },
+ "bin": {
+ "openai": "bin/cli"
+ },
+ "peerDependencies": {
+ "ws": "^8.18.0",
+ "zod": "^3.23.8"
+ },
+ "peerDependenciesMeta": {
+ "ws": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/openai/node_modules/@types/node": {
+ "version": "18.19.123",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.123.tgz",
+ "integrity": "sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/openai/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/openapi-types": {
+ "version": "12.1.3",
+ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
+ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
+ "license": "MIT"
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -8214,6 +9987,15 @@
"node": ">=8"
}
},
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -8246,6 +10028,47 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-queue": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
+ "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^4.0.4",
+ "p-timeout": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
+ "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
+ "license": "MIT",
+ "dependencies": {
+ "p-finally": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
@@ -8263,6 +10086,12 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
+ "node_modules/packet-reader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
+ "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==",
+ "license": "MIT"
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -8387,6 +10216,20 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/peek-readable": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
+ "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
"node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
@@ -8394,6 +10237,97 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/pg": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz",
+ "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-writer": "2.0.0",
+ "packet-reader": "1.0.0",
+ "pg-connection-string": "^2.6.2",
+ "pg-pool": "^3.6.1",
+ "pg-protocol": "^1.6.0",
+ "pg-types": "^2.1.0",
+ "pgpass": "1.x"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.1.1"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz",
+ "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
+ "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
+ "license": "MIT"
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
+ "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
+ "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==",
+ "license": "MIT"
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -8505,6 +10439,53 @@
"pathe": "^2.0.3"
}
},
+ "node_modules/playwright": {
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz",
+ "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "playwright-core": "1.55.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz",
+ "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/pluralize": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
@@ -8515,6 +10496,45 @@
"node": ">=4"
}
},
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -8608,6 +10628,40 @@
}
}
},
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/protobufjs": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
+ "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -8621,11 +10675,30 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/psl": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
+ "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/lupomontero"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -8663,6 +10736,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -8750,6 +10830,65 @@
"node": ">= 6"
}
},
+ "node_modules/readable-web-to-node-stream": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz",
+ "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "readable-stream": "^4.7.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/readable-web-to-node-stream/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
+ "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
"node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@@ -8784,7 +10923,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -8800,6 +10938,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/resolve-cwd": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
@@ -8854,6 +10999,28 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/retry-axios": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-2.6.0.tgz",
+ "integrity": "sha512-pOLi+Gdll3JekwuFjXO3fTq+L9lzMQGcSq7M5gIjExcl3Gu1hd4XXuf5o3+LuSBsaULQH7DiNbsqPd1chVpQGQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "engines": {
+ "node": ">=10.7.0"
+ },
+ "peerDependencies": {
+ "axios": "*"
+ }
+ },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -8963,7 +11130,6 @@
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -9133,6 +11299,12 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/simple-wcswidth": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz",
+ "integrity": "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==",
+ "license": "MIT"
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -9174,6 +11346,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -9283,7 +11464,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@@ -9337,7 +11517,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -9347,7 +11526,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -9484,7 +11662,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -9493,6 +11670,30 @@
"node": ">=8"
}
},
+ "node_modules/swagger-ui-dist": {
+ "version": "5.21.0",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.21.0.tgz",
+ "integrity": "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@scarf/scarf": "=1.4.0"
+ }
+ },
+ "node_modules/swagger-ui-express": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
+ "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
+ "license": "MIT",
+ "dependencies": {
+ "swagger-ui-dist": ">=5.0.0"
+ },
+ "engines": {
+ "node": ">= v0.10.32"
+ },
+ "peerDependencies": {
+ "express": ">=4.0.0 || >=5.0.0-beta"
+ }
+ },
"node_modules/symbol-observable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
@@ -9787,6 +11988,38 @@
"url": "https://github.com/sponsors/Borewit"
}
},
+ "node_modules/tough-cookie": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+ "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
@@ -9810,6 +12043,12 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-error": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/ts-error/-/ts-error-1.0.6.tgz",
+ "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==",
+ "license": "MIT"
+ },
"node_modules/ts-jest": {
"version": "29.4.1",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz",
@@ -10124,7 +12363,6 @@
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/universalify": {
@@ -10222,12 +12460,36 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
+ "node_modules/uuid": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
+ "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@@ -10250,6 +12512,15 @@
"node": ">=10.12.0"
}
},
+ "node_modules/validator": {
+ "version": "13.15.15",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz",
+ "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -10293,6 +12564,54 @@
"defaults": "^1.0.3"
}
},
+ "node_modules/weaviate-client": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/weaviate-client/-/weaviate-client-3.8.1.tgz",
+ "integrity": "sha512-/bH5SO31gGGiI5RhvOEwQBs2DtORsssVjenWxdOQzGToAdmqRC4Oo9HZLIITX5BdFD0IqKDnY81nOZlJlHzn+g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "abort-controller-x": "^0.4.3",
+ "graphql": "^16.11.0",
+ "graphql-request": "^6.1.0",
+ "long": "^5.3.2",
+ "nice-grpc": "^2.1.12",
+ "nice-grpc-client-middleware-retry": "^3.1.11",
+ "nice-grpc-common": "^2.0.2",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/weaviate-client/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "4.0.0-beta.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
+ "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
"node_modules/webpack": {
"version": "5.101.3",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz",
@@ -10494,6 +12813,16 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -10542,7 +12871,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/wrap-ansi": {
@@ -10645,6 +12974,28 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
@@ -10679,7 +13030,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
@@ -10692,11 +13042,22 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/yaml": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
"license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
@@ -10715,7 +13076,6 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=12"
@@ -10756,6 +13116,25 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.24.6",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
+ "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
+ "license": "ISC",
+ "peer": true,
+ "peerDependencies": {
+ "zod": "^3.24.1"
+ }
}
}
}
diff --git a/package.json b/package.json
index 3d6b927..cc1871e 100644
--- a/package.json
+++ b/package.json
@@ -20,12 +20,20 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
+ "@langchain/community": "^0.3.53",
+ "@langchain/openai": "^0.6.9",
"@nestjs/common": "^11.0.1",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
+ "@nestjs/swagger": "^11.2.0",
"@prisma/client": "^6.14.0",
+ "class-transformer": "^0.5.1",
+ "class-validator": "^0.14.2",
+ "langchain": "^0.3.31",
+ "pg": "^8.11.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
+ "swagger-ui-express": "^5.0.1",
"xlsx": "^0.18.5"
},
"devDependencies": {
diff --git a/prisma/migrations/20250822104301_init/migration.sql b/prisma/migrations/20250822104301_init/migration.sql
new file mode 100644
index 0000000..d9a7623
--- /dev/null
+++ b/prisma/migrations/20250822104301_init/migration.sql
@@ -0,0 +1,26 @@
+-- Enable pgvector extension
+CREATE EXTENSION IF NOT EXISTS vector;
+
+-- CreateTable
+CREATE TABLE "icd_codes" (
+ "id" TEXT NOT NULL,
+ "code" TEXT NOT NULL,
+ "display" TEXT NOT NULL,
+ "version" TEXT NOT NULL,
+ "category" TEXT NOT NULL,
+ "embedding" vector(1536),
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL,
+
+ CONSTRAINT "icd_codes_pkey" PRIMARY KEY ("id")
+);
+
+-- Create unique index on code
+CREATE UNIQUE INDEX "icd_codes_code_key" ON "icd_codes"("code");
+
+-- Create ivfflat index for fast vector similarity search
+CREATE INDEX "icd_codes_embedding_idx" ON "icd_codes" USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
+
+-- Add comments for documentation
+COMMENT ON COLUMN "icd_codes"."embedding" IS 'Vector embedding for semantic search using pgvector (1536 dimensions)';
+COMMENT ON INDEX "icd_codes_embedding_idx" IS 'IVFFlat index for fast cosine similarity search with 100 lists';
diff --git a/prisma/migrations/20250822104302_add_pgvector/migration.sql b/prisma/migrations/20250822104302_add_pgvector/migration.sql
new file mode 100644
index 0000000..cc7de94
--- /dev/null
+++ b/prisma/migrations/20250822104302_add_pgvector/migration.sql
@@ -0,0 +1,27 @@
+-- Migration: Add pgvector support to icd_codes table
+
+-- Enable pgvector extension
+CREATE EXTENSION IF NOT EXISTS vector;
+
+-- Add embedding column with pgvector type
+ALTER TABLE "icd_codes" ADD COLUMN IF NOT EXISTS "embedding" vector(1536);
+
+-- Add metadata column for LangChain pgvector
+ALTER TABLE "icd_codes" ADD COLUMN IF NOT EXISTS "metadata" JSONB;
+
+-- Add content column for LangChain pgvector
+ALTER TABLE "icd_codes" ADD COLUMN IF NOT EXISTS "content" TEXT;
+
+-- Create ivfflat index for fast vector similarity search
+CREATE INDEX IF NOT EXISTS "icd_codes_embedding_idx" ON "icd_codes"
+USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
+
+-- Create index on metadata for fast JSON queries
+CREATE INDEX IF NOT EXISTS "icd_codes_metadata_idx" ON "icd_codes" USING GIN (metadata);
+
+-- Add comments for documentation
+COMMENT ON COLUMN "icd_codes"."embedding" IS 'Vector embedding for semantic search using pgvector (1536 dimensions)';
+COMMENT ON COLUMN "icd_codes"."metadata" IS 'JSON metadata for LangChain pgvector operations';
+COMMENT ON COLUMN "icd_codes"."content" IS 'Text content for LangChain pgvector operations';
+COMMENT ON INDEX "icd_codes_embedding_idx" IS 'IVFFlat index for fast cosine similarity search with 100 lists';
+COMMENT ON INDEX "icd_codes_metadata_idx" IS 'GIN index for fast JSON metadata queries';
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
new file mode 100644
index 0000000..044d57c
--- /dev/null
+++ b/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (e.g., Git)
+provider = "postgresql"
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 9b04afd..693693f 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -1,12 +1,5 @@
-// This is your Prisma schema file,
-// learn more about it in the docs: https://pris.ly/d/prisma-schema
-
-// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
-// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
-
generator client {
provider = "prisma-client-js"
- output = "../generated/prisma"
}
datasource db {
@@ -15,13 +8,18 @@ datasource db {
}
model IcdCode {
- id String @id @default(uuid())
- code String @unique
+ id String @id @default(uuid())
+ code String @unique
display String
version String
- category String // "ICD9" or "ICD10"
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
+ category String
+ embedding Unsupported("vector")?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ metadata Json?
+ content String?
+ @@index([embedding])
+ @@index([metadata], type: Gin)
@@map("icd_codes")
}
diff --git a/src/app.module.ts b/src/app.module.ts
index faca288..827aa67 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { IcdModule } from './icd/icd.module';
+import { HealthModule } from './health/health.module';
@Module({
- imports: [IcdModule],
+ imports: [IcdModule, HealthModule],
controllers: [AppController],
providers: [AppService],
})
diff --git a/src/health/health.controller.ts b/src/health/health.controller.ts
new file mode 100644
index 0000000..14152a7
--- /dev/null
+++ b/src/health/health.controller.ts
@@ -0,0 +1,83 @@
+import { Controller, Get } from '@nestjs/common';
+import {
+ ApiTags,
+ ApiOperation,
+ ApiResponse,
+ ApiProperty,
+} from '@nestjs/swagger';
+
+export class HealthCheckResponseDto {
+ @ApiProperty({ example: 'ok' })
+ status: string;
+
+ @ApiProperty({ example: '2024-01-01T00:00:00.000Z' })
+ timestamp: string;
+
+ @ApiProperty({ example: 3600 })
+ uptime: number;
+
+ @ApiProperty({ example: 'development' })
+ environment: string;
+
+ @ApiProperty({ example: '1.0.0' })
+ version: string;
+
+ @ApiProperty({ example: { status: 'connected' } })
+ database: {
+ status: string;
+ };
+}
+
+@ApiTags('Health')
+@Controller('health')
+export class HealthController {
+ @Get()
+ @ApiOperation({
+ summary: 'Health check endpoint',
+ description:
+ 'Check the health status of the application and its dependencies',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'Application is healthy',
+ type: HealthCheckResponseDto,
+ })
+ async getHealth(): Promise {
+ return {
+ status: 'ok',
+ timestamp: new Date().toISOString(),
+ uptime: process.uptime(),
+ environment: process.env.NODE_ENV || 'development',
+ version: '1.0.0',
+ database: {
+ status: 'connected', // In real implementation, check actual DB connection
+ },
+ };
+ }
+
+ @Get('ready')
+ @ApiOperation({
+ summary: 'Readiness check',
+ description: 'Check if the application is ready to serve requests',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'Application is ready',
+ })
+ async getReady() {
+ return { status: 'ready' };
+ }
+
+ @Get('live')
+ @ApiOperation({
+ summary: 'Liveness check',
+ description: 'Check if the application is alive',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'Application is alive',
+ })
+ async getLive() {
+ return { status: 'alive' };
+ }
+}
diff --git a/src/health/health.module.ts b/src/health/health.module.ts
new file mode 100644
index 0000000..7476abe
--- /dev/null
+++ b/src/health/health.module.ts
@@ -0,0 +1,7 @@
+import { Module } from '@nestjs/common';
+import { HealthController } from './health.controller';
+
+@Module({
+ controllers: [HealthController],
+})
+export class HealthModule {}
diff --git a/src/icd/dto/icd-response.dto.ts b/src/icd/dto/icd-response.dto.ts
new file mode 100644
index 0000000..3a39fbe
--- /dev/null
+++ b/src/icd/dto/icd-response.dto.ts
@@ -0,0 +1,192 @@
+import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
+
+export class IcdCodeDto {
+ @ApiProperty({
+ description: 'Unique identifier for the ICD code',
+ example: '550e8400-e29b-41d4-a716-446655440000',
+ })
+ id: string;
+
+ @ApiProperty({
+ description: 'ICD code',
+ example: 'E11.9',
+ })
+ code: string;
+
+ @ApiProperty({
+ description: 'Description of the ICD code',
+ example: 'Type 2 diabetes mellitus without complications',
+ })
+ display: string;
+
+ @ApiProperty({
+ description: 'Version of the ICD standard',
+ example: '2024',
+ })
+ version: string;
+
+ @ApiProperty({
+ description: 'ICD category',
+ example: 'ICD10',
+ enum: ['ICD9', 'ICD10'],
+ })
+ category: string;
+
+ @ApiProperty({
+ description: 'Creation timestamp',
+ example: '2024-01-01T00:00:00.000Z',
+ })
+ createdAt: Date;
+
+ @ApiProperty({
+ description: 'Last update timestamp',
+ example: '2024-01-01T00:00:00.000Z',
+ })
+ updatedAt: Date;
+}
+
+export class PaginationMetaDto {
+ @ApiProperty({
+ description: 'Current page number',
+ example: 1,
+ })
+ currentPage: number;
+
+ @ApiProperty({
+ description: 'Total number of pages',
+ example: 10,
+ })
+ totalPages: number;
+
+ @ApiProperty({
+ description: 'Total number of items',
+ example: 100,
+ })
+ totalItems: number;
+
+ @ApiProperty({
+ description: 'Number of items per page',
+ example: 10,
+ })
+ itemsPerPage: number;
+
+ @ApiProperty({
+ description: 'Whether there is a next page',
+ example: true,
+ })
+ hasNextPage: boolean;
+
+ @ApiProperty({
+ description: 'Whether there is a previous page',
+ example: false,
+ })
+ hasPreviousPage: boolean;
+}
+
+export class IcdSearchResponseDto {
+ @ApiProperty({
+ description: 'Request success status',
+ example: true,
+ })
+ success: boolean;
+
+ @ApiProperty({
+ description: 'Array of ICD codes',
+ type: [IcdCodeDto],
+ })
+ data: IcdCodeDto[];
+
+ @ApiProperty({
+ description: 'Pagination metadata',
+ type: PaginationMetaDto,
+ })
+ pagination: PaginationMetaDto;
+
+ @ApiPropertyOptional({
+ description: 'Response message',
+ example: 'ICD codes retrieved successfully',
+ })
+ message?: string;
+}
+
+export class IcdImportResponseDto {
+ @ApiProperty({
+ description: 'Request success status',
+ example: true,
+ })
+ success: boolean;
+
+ @ApiProperty({
+ description: 'Success message',
+ example: 'ICD data imported successfully',
+ })
+ message: string;
+
+ @ApiProperty({
+ description: 'Import statistics',
+ example: {
+ icd9Count: 150,
+ icd10Count: 250,
+ total: 400,
+ },
+ })
+ data: {
+ icd9Count: number;
+ icd10Count: number;
+ total: number;
+ };
+}
+
+export class IcdStatisticsDto {
+ @ApiProperty({
+ description: 'Total number of ICD9 codes',
+ example: 150,
+ })
+ icd9Count: number;
+
+ @ApiProperty({
+ description: 'Total number of ICD10 codes',
+ example: 250,
+ })
+ icd10Count: number;
+
+ @ApiProperty({
+ description: 'Total number of all ICD codes',
+ example: 400,
+ })
+ total: number;
+}
+
+export class IcdStatisticsResponseDto {
+ @ApiProperty({
+ description: 'Request success status',
+ example: true,
+ })
+ success: boolean;
+
+ @ApiProperty({
+ description: 'ICD statistics data',
+ type: IcdStatisticsDto,
+ })
+ data: IcdStatisticsDto;
+}
+
+export class ErrorResponseDto {
+ @ApiProperty({
+ description: 'Request success status',
+ example: false,
+ })
+ success: boolean;
+
+ @ApiProperty({
+ description: 'Error message',
+ example: 'Failed to process request',
+ })
+ message: string;
+
+ @ApiPropertyOptional({
+ description: 'Detailed error information',
+ example: 'Database connection failed',
+ })
+ error?: string;
+}
diff --git a/src/icd/dto/search-icd.dto.ts b/src/icd/dto/search-icd.dto.ts
index 8adf368..9a3e280 100644
--- a/src/icd/dto/search-icd.dto.ts
+++ b/src/icd/dto/search-icd.dto.ts
@@ -1,6 +1,62 @@
+import { ApiPropertyOptional } from '@nestjs/swagger';
+import {
+ IsOptional,
+ IsString,
+ IsNumber,
+ IsEnum,
+ Min,
+ Max,
+} from 'class-validator';
+import { Type } from 'class-transformer';
+
+export enum IcdCategory {
+ ICD9 = 'ICD9',
+ ICD10 = 'ICD10',
+}
+
export class SearchIcdDto {
- category?: 'ICD9' | 'ICD10';
+ @ApiPropertyOptional({
+ description: 'ICD category to filter by',
+ enum: IcdCategory,
+ example: 'ICD10',
+ })
+ @IsOptional()
+ @IsEnum(IcdCategory)
+ category?: IcdCategory;
+
+ @ApiPropertyOptional({
+ description: 'Search term for ICD code or description',
+ example: 'diabetes',
+ minLength: 1,
+ maxLength: 100,
+ })
+ @IsOptional()
+ @IsString()
search?: string;
+
+ @ApiPropertyOptional({
+ description: 'Page number for pagination',
+ example: 1,
+ minimum: 1,
+ default: 1,
+ })
+ @IsOptional()
+ @Type(() => Number)
+ @IsNumber()
+ @Min(1)
page?: number;
+
+ @ApiPropertyOptional({
+ description: 'Number of items per page',
+ example: 10,
+ minimum: 1,
+ maximum: 100,
+ default: 10,
+ })
+ @IsOptional()
+ @Type(() => Number)
+ @IsNumber()
+ @Min(1)
+ @Max(100)
limit?: number;
}
diff --git a/src/icd/icd.controller.ts b/src/icd/icd.controller.ts
index d97986c..24fada4 100644
--- a/src/icd/icd.controller.ts
+++ b/src/icd/icd.controller.ts
@@ -1,7 +1,22 @@
import { Controller, Get, Post, Query, Logger } from '@nestjs/common';
+import {
+ ApiTags,
+ ApiOperation,
+ ApiResponse,
+ ApiQuery,
+ ApiBadRequestResponse,
+ ApiInternalServerErrorResponse,
+} from '@nestjs/swagger';
import { IcdService } from './icd.service';
import { SearchIcdDto } from './dto/search-icd.dto';
+import {
+ IcdSearchResponseDto,
+ IcdImportResponseDto,
+ IcdStatisticsResponseDto,
+ ErrorResponseDto,
+} from './dto/icd-response.dto';
+@ApiTags('ICD')
@Controller('icd')
export class IcdController {
private readonly logger = new Logger(IcdController.name);
@@ -9,7 +24,25 @@ export class IcdController {
constructor(private readonly icdService: IcdService) {}
@Post('import')
- async importData() {
+ @ApiOperation({
+ summary: 'Import ICD data from Excel files',
+ description:
+ 'Import ICD-9 and ICD-10 codes from Excel files located in the test directory. This operation will process both ICD files and insert/update the database with the latest codes.',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'ICD data imported successfully',
+ type: IcdImportResponseDto,
+ })
+ @ApiBadRequestResponse({
+ description: 'Bad request - Invalid file format or missing files',
+ type: ErrorResponseDto,
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error during import process',
+ type: ErrorResponseDto,
+ })
+ async importData(): Promise {
try {
this.logger.log('Starting ICD data import...');
const result = await this.icdService.importIcdData();
@@ -20,21 +53,62 @@ export class IcdController {
};
} catch (error) {
this.logger.error('Error importing ICD data:', error);
- return {
- success: false,
- message: 'Failed to import ICD data',
- error: error.message,
- };
+ throw error;
}
}
@Get('search')
+ @ApiOperation({
+ summary: 'Search ICD codes with filters and pagination',
+ description:
+ 'Search for ICD codes using various filters like category, search term, with pagination support. Returns a paginated list of matching ICD codes.',
+ })
+ @ApiQuery({
+ name: 'category',
+ required: false,
+ description: 'Filter by ICD category',
+ enum: ['ICD9', 'ICD10'],
+ example: 'ICD10',
+ })
+ @ApiQuery({
+ name: 'search',
+ required: false,
+ description: 'Search term for ICD code or description',
+ example: 'diabetes',
+ })
+ @ApiQuery({
+ name: 'page',
+ required: false,
+ description: 'Page number for pagination',
+ example: 1,
+ type: 'number',
+ })
+ @ApiQuery({
+ name: 'limit',
+ required: false,
+ description: 'Number of items per page (max 100)',
+ example: 10,
+ type: 'number',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'ICD codes retrieved successfully',
+ type: IcdSearchResponseDto,
+ })
+ @ApiBadRequestResponse({
+ description: 'Bad request - Invalid query parameters',
+ type: ErrorResponseDto,
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error during search',
+ type: ErrorResponseDto,
+ })
async searchIcdCodes(
@Query('category') category?: string,
@Query('search') search?: string,
@Query('page') page?: string,
@Query('limit') limit?: string,
- ) {
+ ): Promise {
try {
const pageNum = page ? parseInt(page, 10) : 1;
const limitNum = limit ? parseInt(limit, 10) : 10;
@@ -48,20 +122,38 @@ export class IcdController {
return {
success: true,
- ...result,
+ data: result.data,
+ pagination: {
+ currentPage: result.page,
+ totalPages: result.totalPages,
+ totalItems: result.total,
+ itemsPerPage: result.limit,
+ hasNextPage: result.page < result.totalPages,
+ hasPreviousPage: result.page > 1,
+ },
};
} catch (error) {
this.logger.error('Error searching ICD codes:', error);
- return {
- success: false,
- message: 'Failed to search ICD codes',
- error: error.message,
- };
+ throw error;
}
}
@Get('statistics')
- async getStatistics() {
+ @ApiOperation({
+ summary: 'Get ICD database statistics',
+ description:
+ 'Retrieve statistics about the ICD database including total counts for ICD-9 and ICD-10 codes, and last import information.',
+ })
+ @ApiResponse({
+ status: 200,
+ description: 'Statistics retrieved successfully',
+ type: IcdStatisticsResponseDto,
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error while fetching statistics',
+ type: ErrorResponseDto,
+ })
+ async getStatistics(): Promise {
try {
const stats = await this.icdService.getStatistics();
return {
@@ -70,11 +162,7 @@ export class IcdController {
};
} catch (error) {
this.logger.error('Error getting statistics:', error);
- return {
- success: false,
- message: 'Failed to get statistics',
- error: error.message,
- };
+ throw error;
}
}
}
diff --git a/src/icd/icd.module.ts b/src/icd/icd.module.ts
index 7af14a2..5d15022 100644
--- a/src/icd/icd.module.ts
+++ b/src/icd/icd.module.ts
@@ -1,10 +1,12 @@
import { Module } from '@nestjs/common';
import { IcdController } from './icd.controller';
import { IcdService } from './icd.service';
+import { PgVectorModule } from './pgvector.module';
@Module({
controllers: [IcdController],
providers: [IcdService],
- exports: [IcdService],
+ imports: [PgVectorModule],
+ exports: [IcdService, PgVectorModule],
})
export class IcdModule {}
diff --git a/src/icd/icd.service.ts b/src/icd/icd.service.ts
index 7fdf3f6..23ed54a 100644
--- a/src/icd/icd.service.ts
+++ b/src/icd/icd.service.ts
@@ -181,6 +181,16 @@ export class IcdService {
skip,
take: limit,
orderBy: { code: 'asc' },
+ select: {
+ id: true,
+ code: true,
+ display: true,
+ version: true,
+ category: true,
+ createdAt: true,
+ updatedAt: true,
+ // Exclude embedding field to avoid deserialization error
+ },
}),
this.prisma.icdCode.count({ where }),
]);
diff --git a/src/icd/pgvector.controller.ts b/src/icd/pgvector.controller.ts
new file mode 100644
index 0000000..4eefd30
--- /dev/null
+++ b/src/icd/pgvector.controller.ts
@@ -0,0 +1,670 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Query,
+ Body,
+ HttpStatus,
+ ValidationPipe,
+ UsePipes,
+} from '@nestjs/common';
+import {
+ ApiTags,
+ ApiOperation,
+ ApiResponse,
+ ApiQuery,
+ ApiBody,
+ ApiProperty,
+ ApiConsumes,
+ ApiProduces,
+} from '@nestjs/swagger';
+import { PgVectorService, VectorSearchResult } from './pgvector.service';
+
+export class VectorSearchDto {
+ @ApiProperty({
+ description: 'Search query text for vector similarity search',
+ example: 'diabetes mellitus type 2',
+ minLength: 1,
+ maxLength: 500,
+ })
+ query: string;
+
+ @ApiProperty({
+ description: 'Maximum number of results to return',
+ example: 10,
+ required: false,
+ minimum: 1,
+ maximum: 100,
+ default: 10,
+ })
+ limit?: number;
+
+ @ApiProperty({
+ description: 'ICD category filter to narrow down search results',
+ example: 'ICD10',
+ required: false,
+ enum: ['ICD9', 'ICD10'],
+ default: undefined,
+ })
+ category?: string;
+
+ @ApiProperty({
+ description: 'Similarity threshold (0.0 - 1.0) for filtering results',
+ example: 0.7,
+ required: false,
+ minimum: 0.0,
+ maximum: 1.0,
+ default: 0.7,
+ })
+ threshold?: number;
+}
+
+export class EmbeddingRequestDto {
+ @ApiProperty({
+ description: 'Text to generate vector embedding for',
+ example: 'diabetes mellitus',
+ minLength: 1,
+ maxLength: 1000,
+ })
+ text: string;
+
+ @ApiProperty({
+ description: 'Embedding model to use for generation',
+ example: 'text-embedding-ada-002',
+ required: false,
+ default: 'text-embedding-ada-002',
+ })
+ model?: string;
+}
+
+export class VectorSearchResponseDto {
+ @ApiProperty({
+ description: 'Array of search results with similarity scores',
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ description: 'Unique identifier for the ICD code',
+ example: 'uuid-123',
+ },
+ code: {
+ type: 'string',
+ description: 'ICD code (e.g., E11.9)',
+ example: 'E11.9',
+ },
+ display: {
+ type: 'string',
+ description: 'Human readable description of the ICD code',
+ example: 'Type 2 diabetes mellitus without complications',
+ },
+ version: {
+ type: 'string',
+ description: 'ICD version (e.g., ICD-10-CM)',
+ example: 'ICD-10-CM',
+ },
+ category: {
+ type: 'string',
+ description: 'ICD category (ICD9 or ICD10)',
+ example: 'ICD10',
+ },
+ similarity: {
+ type: 'number',
+ description: 'Similarity score between 0 and 1',
+ example: 0.89,
+ },
+ },
+ },
+ })
+ data: VectorSearchResult[];
+
+ @ApiProperty({
+ description: 'Total number of results found',
+ example: 5,
+ minimum: 0,
+ })
+ total: number;
+
+ @ApiProperty({
+ description: 'Search query that was used',
+ example: 'diabetes mellitus type 2',
+ })
+ query: string;
+}
+
+export class EmbeddingStatsResponseDto {
+ @ApiProperty({
+ description: 'Total number of ICD codes in the system',
+ example: 1000,
+ minimum: 0,
+ })
+ total: number;
+
+ @ApiProperty({
+ description: 'Number of ICD codes with generated embeddings',
+ example: 500,
+ minimum: 0,
+ })
+ withEmbeddings: number;
+
+ @ApiProperty({
+ description: 'Number of ICD codes without embeddings',
+ example: 500,
+ minimum: 0,
+ })
+ withoutEmbeddings: number;
+
+ @ApiProperty({
+ description: 'Percentage of codes with embeddings',
+ example: 50.0,
+ minimum: 0,
+ maximum: 100,
+ })
+ percentage: number;
+
+ @ApiProperty({
+ description: 'Current status of the vector store',
+ example: 'Initialized',
+ enum: ['Initialized', 'Not Initialized', 'Error'],
+ })
+ vectorStoreStatus: string;
+}
+
+export class VectorStoreStatusDto {
+ @ApiProperty({
+ description: 'Whether the vector store is currently initialized',
+ example: true,
+ })
+ initialized: boolean;
+
+ @ApiProperty({
+ description: 'Number of documents currently in the vector store',
+ example: 1000,
+ minimum: 0,
+ })
+ documentCount: number;
+
+ @ApiProperty({
+ description: 'Embedding model currently being used',
+ example: 'OpenAI text-embedding-ada-002',
+ enum: ['OpenAI text-embedding-ada-002', 'Not Available'],
+ })
+ embeddingModel: string;
+
+ @ApiProperty({
+ description: 'Timestamp of last vector store update',
+ example: '2024-01-01T00:00:00.000Z',
+ })
+ lastUpdated: Date;
+}
+
+export class InitializeResponseDto {
+ @ApiProperty({
+ description: 'Success message',
+ example: 'Pgvector store initialized successfully',
+ })
+ message: string;
+
+ @ApiProperty({
+ description: 'Number of documents loaded into vector store',
+ example: 1000,
+ minimum: 0,
+ })
+ documentCount: number;
+}
+
+export class RefreshResponseDto {
+ @ApiProperty({
+ description: 'Success message',
+ example: 'Pgvector store refreshed successfully',
+ })
+ message: string;
+
+ @ApiProperty({
+ description: 'Number of documents in refreshed vector store',
+ example: 1000,
+ minimum: 0,
+ })
+ documentCount: number;
+}
+
+export class GenerateEmbeddingResponseDto {
+ @ApiProperty({
+ description: 'Generated vector embedding array',
+ type: 'array',
+ items: { type: 'number' },
+ example: [0.1, 0.2, 0.3, -0.1, 0.5],
+ })
+ embedding: number[];
+
+ @ApiProperty({
+ description: 'Number of dimensions in the embedding vector',
+ example: 1536,
+ minimum: 1,
+ })
+ dimensions: number;
+
+ @ApiProperty({
+ description: 'Model used to generate the embedding',
+ example: 'text-embedding-ada-002',
+ })
+ model: string;
+}
+
+export class GenerateAllEmbeddingsResponseDto {
+ @ApiProperty({
+ description: 'Number of embeddings successfully processed',
+ example: 500,
+ minimum: 0,
+ })
+ processed: number;
+
+ @ApiProperty({
+ description: 'Number of errors encountered during processing',
+ example: 0,
+ minimum: 0,
+ })
+ errors: number;
+
+ @ApiProperty({
+ description: 'Summary message of the operation',
+ example: 'Processed 500 embeddings with 0 errors',
+ })
+ message: string;
+}
+
+@ApiTags('PgVector Operations')
+@Controller('pgvector')
+@UsePipes(new ValidationPipe({ transform: true }))
+export class PgVectorController {
+ constructor(private readonly pgVectorService: PgVectorService) {}
+
+ @Post('search')
+ @ApiOperation({
+ summary: 'PgVector similarity search',
+ description:
+ 'Search ICD codes using pgvector similarity with the given query. Returns results ordered by similarity score.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiBody({
+ type: VectorSearchDto,
+ description: 'Search parameters for pgvector similarity search',
+ examples: {
+ diabetes: {
+ summary: 'Search for diabetes',
+ value: {
+ query: 'diabetes mellitus type 2',
+ limit: 10,
+ category: 'ICD10',
+ threshold: 0.7,
+ },
+ },
+ heart: {
+ summary: 'Search for heart conditions',
+ value: {
+ query: 'heart attack myocardial infarction',
+ limit: 5,
+ category: 'ICD10',
+ threshold: 0.8,
+ },
+ },
+ },
+ })
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Search results with similarity scores',
+ type: VectorSearchResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.BAD_REQUEST,
+ description: 'Invalid search parameters or query',
+ schema: {
+ type: 'object',
+ properties: {
+ statusCode: { type: 'number', example: 400 },
+ message: { type: 'string', example: 'Query is required' },
+ error: { type: 'string', example: 'Bad Request' },
+ },
+ },
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Internal server error during pgvector search',
+ schema: {
+ type: 'object',
+ properties: {
+ statusCode: { type: 'number', example: 500 },
+ message: { type: 'string', example: 'Internal server error' },
+ error: { type: 'string', example: 'Internal Server Error' },
+ },
+ },
+ })
+ async vectorSearch(
+ @Body() searchDto: VectorSearchDto,
+ ): Promise {
+ const results = await this.pgVectorService.vectorSearch(
+ searchDto.query,
+ searchDto.limit || 10,
+ searchDto.category,
+ searchDto.threshold || 0.7,
+ );
+
+ return {
+ data: results,
+ total: results.length,
+ query: searchDto.query,
+ };
+ }
+
+ @Get('search')
+ @ApiOperation({
+ summary: 'PgVector search via GET',
+ description:
+ 'Search ICD codes using pgvector similarity via query parameters. Alternative to POST method.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiQuery({
+ name: 'query',
+ description: 'Search query text for pgvector similarity search',
+ example: 'diabetes mellitus type 2',
+ required: true,
+ type: 'string',
+ })
+ @ApiQuery({
+ name: 'limit',
+ description: 'Maximum number of results to return',
+ example: 10,
+ required: false,
+ type: 'number',
+ minimum: 1,
+ maximum: 100,
+ })
+ @ApiQuery({
+ name: 'category',
+ description: 'ICD category filter to narrow down search results',
+ example: 'ICD10',
+ required: false,
+ type: 'string',
+ enum: ['ICD9', 'ICD10'],
+ })
+ @ApiQuery({
+ name: 'threshold',
+ description: 'Similarity threshold (0.0 - 1.0) for filtering results',
+ example: 0.7,
+ required: false,
+ type: 'number',
+ minimum: 0.0,
+ maximum: 1.0,
+ })
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Search results with similarity scores',
+ type: VectorSearchResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.BAD_REQUEST,
+ description: 'Invalid query parameters',
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Internal server error during pgvector search',
+ })
+ async vectorSearchGet(
+ @Query('query') query: string,
+ @Query('limit') limit?: string,
+ @Query('category') category?: string,
+ @Query('threshold') threshold?: string,
+ ): Promise {
+ const results = await this.pgVectorService.vectorSearch(
+ query,
+ limit ? parseInt(limit) : 10,
+ category,
+ threshold ? parseFloat(threshold) : 0.7,
+ );
+
+ return {
+ data: results,
+ total: results.length,
+ query,
+ };
+ }
+
+ @Post('hybrid-search')
+ @ApiOperation({
+ summary: 'Hybrid search (PgVector + Text)',
+ description:
+ 'Combine pgvector similarity with text search for better and more accurate results. Combines semantic understanding with traditional text matching.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiBody({
+ type: VectorSearchDto,
+ description: 'Search parameters for hybrid search',
+ examples: {
+ diabetes: {
+ summary: 'Hybrid search for diabetes',
+ value: {
+ query: 'diabetes mellitus type 2',
+ limit: 15,
+ category: 'ICD10',
+ },
+ },
+ },
+ })
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Hybrid search results combining pgvector and text search',
+ type: VectorSearchResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.BAD_REQUEST,
+ description: 'Invalid search parameters',
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Internal server error during hybrid search',
+ })
+ async hybridSearch(
+ @Body() searchDto: VectorSearchDto,
+ ): Promise {
+ const results = await this.pgVectorService.hybridSearch(
+ searchDto.query,
+ searchDto.limit || 10,
+ searchDto.category,
+ );
+
+ return {
+ data: results,
+ total: results.length,
+ query: searchDto.query,
+ };
+ }
+
+ @Post('generate-embedding')
+ @ApiOperation({
+ summary: 'Generate text embedding',
+ description:
+ 'Generate vector embedding for the given text using OpenAI. Returns 1536-dimensional vector.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiBody({
+ type: EmbeddingRequestDto,
+ description: 'Text to generate embedding for',
+ examples: {
+ diabetes: {
+ summary: 'Generate embedding for diabetes text',
+ value: {
+ text: 'diabetes mellitus',
+ model: 'text-embedding-ada-002',
+ },
+ },
+ heart: {
+ summary: 'Generate embedding for heart condition',
+ value: {
+ text: 'acute myocardial infarction',
+ model: 'text-embedding-ada-002',
+ },
+ },
+ },
+ })
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Generated embedding vector with metadata',
+ type: GenerateEmbeddingResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.BAD_REQUEST,
+ description: 'Invalid text input',
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error generating embedding',
+ })
+ async generateEmbedding(
+ @Body() requestDto: EmbeddingRequestDto,
+ ): Promise {
+ const embedding = await this.pgVectorService.generateEmbedding(
+ requestDto.text,
+ requestDto.model,
+ );
+
+ return {
+ embedding,
+ dimensions: embedding.length,
+ model: requestDto.model || 'text-embedding-ada-002',
+ };
+ }
+
+ @Post('generate-and-store-all-embeddings')
+ @ApiOperation({
+ summary: 'Generate and store embeddings for all ICD codes',
+ description:
+ 'Batch generate embeddings for all ICD codes and store them in the database with pgvector. This process may take some time depending on the number of codes.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Embedding generation and storage results summary',
+ type: GenerateAllEmbeddingsResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error during batch embedding generation and storage',
+ })
+ async generateAndStoreAllEmbeddings(): Promise {
+ const result = await this.pgVectorService.generateAndStoreAllEmbeddings();
+
+ return {
+ ...result,
+ message: `Processed ${result.processed} embeddings with ${result.errors} errors`,
+ };
+ }
+
+ @Get('stats')
+ @ApiOperation({
+ summary: 'Get embedding statistics',
+ description:
+ 'Get comprehensive statistics about ICD codes and their embedding status in the pgvector store.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiProduces('application/json')
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Embedding statistics and pgvector store status',
+ type: EmbeddingStatsResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error retrieving statistics',
+ })
+ async getEmbeddingStats(): Promise {
+ return await this.pgVectorService.getEmbeddingStats();
+ }
+
+ @Get('status')
+ @ApiOperation({
+ summary: 'Get pgvector store status',
+ description:
+ 'Get current operational status of the pgvector store including initialization state and document count.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiProduces('application/json')
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Current pgvector store status and configuration',
+ type: VectorStoreStatusDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error retrieving pgvector store status',
+ })
+ async getVectorStoreStatus(): Promise {
+ return await this.pgVectorService.getVectorStoreStatus();
+ }
+
+ @Post('initialize')
+ @ApiOperation({
+ summary: 'Initialize pgvector store',
+ description:
+ 'Initialize or reinitialize the pgvector store with all available ICD codes. This loads codes from the database into the pgvector store.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Pgvector store initialization results',
+ type: InitializeResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error during pgvector store initialization',
+ })
+ async initializeVectorStore(): Promise {
+ await this.pgVectorService.initializeVectorStore();
+ const status = await this.pgVectorService.getVectorStoreStatus();
+
+ return {
+ message: 'Pgvector store initialized successfully',
+ documentCount: status.documentCount,
+ };
+ }
+
+ @Post('refresh')
+ @ApiOperation({
+ summary: 'Refresh pgvector store',
+ description:
+ 'Refresh the pgvector store with the latest ICD codes data from the database. Useful after data updates.',
+ tags: ['PgVector Operations'],
+ })
+ @ApiConsumes('application/json')
+ @ApiProduces('application/json')
+ @ApiResponse({
+ status: HttpStatus.OK,
+ description: 'Pgvector store refresh results',
+ type: RefreshResponseDto,
+ })
+ @ApiResponse({
+ status: HttpStatus.INTERNAL_SERVER_ERROR,
+ description: 'Error during pgvector store refresh',
+ })
+ async refreshVectorStore(): Promise {
+ await this.pgVectorService.refreshVectorStore();
+ const status = await this.pgVectorService.getVectorStoreStatus();
+
+ return {
+ message: 'Pgvector store refreshed successfully',
+ documentCount: status.documentCount,
+ };
+ }
+}
diff --git a/src/icd/pgvector.module.ts b/src/icd/pgvector.module.ts
new file mode 100644
index 0000000..2cd7073
--- /dev/null
+++ b/src/icd/pgvector.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { PgVectorController } from './pgvector.controller';
+import { PgVectorService } from './pgvector.service';
+
+@Module({
+ controllers: [PgVectorController],
+ providers: [PgVectorService],
+ exports: [PgVectorService],
+})
+export class PgVectorModule {}
diff --git a/src/icd/pgvector.service.ts b/src/icd/pgvector.service.ts
new file mode 100644
index 0000000..0df4e8e
--- /dev/null
+++ b/src/icd/pgvector.service.ts
@@ -0,0 +1,611 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { PrismaClient } from '../../generated/prisma';
+import { OpenAIEmbeddings } from '@langchain/openai';
+import { PGVectorStore } from '@langchain/community/vectorstores/pgvector';
+import { Document } from 'langchain/document';
+import { Pool } from 'pg';
+
+export interface VectorSearchResult {
+ id: string;
+ code: string;
+ display: string;
+ version: string;
+ category: string;
+ similarity: number;
+}
+
+export interface EmbeddingRequest {
+ text: string;
+ model?: string;
+}
+
+@Injectable()
+export class PgVectorService {
+ private readonly logger = new Logger(PgVectorService.name);
+ private readonly prisma = new PrismaClient();
+ private readonly pool: Pool;
+ private vectorStore: PGVectorStore | null = null;
+ private embeddings: OpenAIEmbeddings | null = null;
+
+ constructor() {
+ // Initialize PostgreSQL connection pool
+ this.pool = new Pool({
+ connectionString: process.env.DATABASE_URL,
+ max: 20,
+ idleTimeoutMillis: 30000,
+ connectionTimeoutMillis: 2000,
+ });
+
+ this.initializeEmbeddings();
+ }
+
+ /**
+ * Initialize OpenAI embeddings
+ */
+ private async initializeEmbeddings() {
+ try {
+ const apiKey = process.env.OPENAI_API_KEY;
+ if (!apiKey) {
+ this.logger.error(
+ 'OPENAI_API_KEY not found. Vector operations require OpenAI API key.',
+ );
+ throw new Error('OPENAI_API_KEY is required for vector operations');
+ }
+
+ const apiModel = process.env.OPENAI_API_MODEL;
+ const modelName = apiModel || 'text-embedding-ada-002';
+
+ this.embeddings = new OpenAIEmbeddings({
+ openAIApiKey: apiKey,
+ modelName: modelName,
+ maxConcurrency: 5,
+ });
+
+ this.logger.log(
+ `OpenAI embeddings initialized successfully with model: ${modelName}`,
+ );
+ } catch (error) {
+ this.logger.error('Failed to initialize OpenAI embeddings:', error);
+ throw new Error(
+ `Failed to initialize OpenAI embeddings: ${error.message}`,
+ );
+ }
+ }
+
+ /**
+ * Initialize pgvector store dengan LangChain
+ */
+ async initializeVectorStore(): Promise {
+ try {
+ this.logger.log('Initializing pgvector store...');
+
+ if (!this.embeddings) {
+ throw new Error(
+ 'OpenAI embeddings not initialized. Cannot create vector store.',
+ );
+ }
+
+ // Get database connection string
+ const connectionString = process.env.DATABASE_URL;
+ if (!connectionString) {
+ throw new Error('DATABASE_URL not found');
+ }
+
+ // Initialize pgvector store without inserting data
+ this.vectorStore = await PGVectorStore.initialize(this.embeddings, {
+ postgresConnectionOptions: {
+ connectionString,
+ },
+ tableName: 'icd_codes',
+ columns: {
+ idColumnName: 'id',
+ vectorColumnName: 'embedding',
+ contentColumnName: 'content',
+ metadataColumnName: 'metadata',
+ },
+ });
+
+ this.logger.log('Pgvector store initialized successfully');
+ } catch (error) {
+ this.logger.error('Error initializing pgvector store:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Generate embedding untuk text menggunakan OpenAI
+ */
+ async generateEmbedding(
+ text: string,
+ model: string = 'text-embedding-ada-002',
+ ): Promise {
+ try {
+ this.logger.log(
+ `Generating embedding for text: ${text.substring(0, 100)}...`,
+ );
+
+ if (!this.embeddings) {
+ throw new Error(
+ 'OpenAI embeddings not initialized. Please check your API configuration.',
+ );
+ }
+
+ // Use OpenAI embeddings
+ const embedding = await this.embeddings.embedQuery(text);
+ this.logger.log(
+ `Generated OpenAI embedding with ${embedding.length} dimensions`,
+ );
+ return embedding;
+ } catch (error) {
+ this.logger.error('Error generating embedding:', error);
+ throw new Error(`Failed to generate embedding: ${error.message}`);
+ }
+ }
+
+ /**
+ * Generate dan simpan embeddings untuk sample ICD codes (default: 100)
+ */
+ async generateAndStoreAllEmbeddings(limit: number = 100): Promise<{
+ processed: number;
+ errors: number;
+ totalSample: number;
+ }> {
+ try {
+ this.logger.log(
+ `Starting batch embedding generation and storage for sample ${limit} ICD codes...`,
+ );
+
+ // Get sample ICD codes without embeddings using raw SQL
+ const codesWithoutEmbedding = await this.pool.query(
+ 'SELECT id, code, display, version, category FROM icd_codes WHERE embedding IS NULL LIMIT $1',
+ [limit],
+ );
+
+ if (codesWithoutEmbedding.rows.length === 0) {
+ this.logger.log('All ICD codes already have embeddings');
+ return { processed: 0, errors: 0, totalSample: 0 };
+ }
+
+ this.logger.log(
+ `Found ${codesWithoutEmbedding.rows.length} sample codes without embeddings (limited to ${limit})`,
+ );
+
+ let processed = 0;
+ let errors = 0;
+
+ // Process each code
+ for (let i = 0; i < codesWithoutEmbedding.rows.length; i++) {
+ const code = codesWithoutEmbedding.rows[i];
+ try {
+ // Create text representation for embedding
+ const text = `${code.code} - ${code.display}`;
+
+ // Generate embedding
+ const embedding = await this.generateEmbedding(text);
+
+ // Convert embedding array to proper vector format for pgvector
+ const vectorString = `[${embedding.join(',')}]`;
+
+ // Update database with embedding, metadata, and content using raw SQL
+ await this.pool.query(
+ `UPDATE icd_codes
+ SET embedding = $1::vector,
+ metadata = $2::jsonb,
+ content = $3
+ WHERE id = $4`,
+ [
+ vectorString,
+ JSON.stringify({
+ id: code.id,
+ code: code.code,
+ display: code.display,
+ version: code.version,
+ category: code.category,
+ }),
+ text,
+ code.id,
+ ],
+ );
+
+ processed++;
+
+ if (processed % 10 === 0) {
+ this.logger.log(
+ `Processed ${processed}/${codesWithoutEmbedding.rows.length} sample embeddings`,
+ );
+ }
+ } catch (error) {
+ this.logger.error(`Error processing code ${code.code}:`, error);
+ errors++;
+ }
+ }
+
+ this.logger.log(
+ `Sample embedding generation and storage completed. Processed: ${processed}, Errors: ${errors}, Total Sample: ${codesWithoutEmbedding.rows.length}`,
+ );
+ return {
+ processed,
+ errors,
+ totalSample: codesWithoutEmbedding.rows.length,
+ };
+ } catch (error) {
+ this.logger.error('Error in generateAndStoreAllEmbeddings:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Generate dan simpan embeddings untuk sample ICD codes dengan kategori tertentu
+ */
+ async generateAndStoreSampleEmbeddingsByCategory(
+ category: string,
+ limit: number = 100,
+ ): Promise<{
+ processed: number;
+ errors: number;
+ totalSample: number;
+ category: string;
+ }> {
+ try {
+ this.logger.log(
+ `Starting batch embedding generation for sample ${limit} ICD codes in category: ${category}`,
+ );
+
+ // Get sample ICD codes by category without embeddings using raw SQL
+ const codesWithoutEmbedding = await this.pool.query(
+ 'SELECT id, code, display, version, category FROM icd_codes WHERE embedding IS NULL AND category = $1 LIMIT $2',
+ [category, limit],
+ );
+
+ if (codesWithoutEmbedding.rows.length === 0) {
+ this.logger.log(
+ `No ICD codes found in category '${category}' without embeddings`,
+ );
+ return { processed: 0, errors: 0, totalSample: 0, category };
+ }
+
+ this.logger.log(
+ `Found ${codesWithoutEmbedding.rows.length} sample codes in category '${category}' without embeddings (limited to ${limit})`,
+ );
+
+ let processed = 0;
+ let errors = 0;
+
+ // Process each code
+ for (let i = 0; i < codesWithoutEmbedding.rows.length; i++) {
+ const code = codesWithoutEmbedding.rows[i];
+ try {
+ // Create text representation for embedding
+ const text = `${code.code} - ${code.display}`;
+
+ // Generate embedding
+ const embedding = await this.generateEmbedding(text);
+
+ // Convert embedding array to proper vector format for pgvector
+ const vectorString = `[${embedding.join(',')}]`;
+
+ // Update database with embedding, metadata, and content using raw SQL
+ await this.pool.query(
+ `UPDATE icd_codes
+ SET embedding = $1::vector,
+ metadata = $2::jsonb,
+ content = $3
+ WHERE id = $4`,
+ [
+ vectorString,
+ JSON.stringify({
+ id: code.id,
+ code: code.code,
+ display: code.display,
+ version: code.version,
+ category: code.category,
+ }),
+ text,
+ code.id,
+ ],
+ );
+
+ processed++;
+
+ if (processed % 10 === 0) {
+ this.logger.log(
+ `Processed ${processed}/${codesWithoutEmbedding.rows.length} sample embeddings in category '${category}'`,
+ );
+ }
+ } catch (error) {
+ this.logger.error(`Error processing code ${code.code}:`, error);
+ errors++;
+ }
+ }
+
+ this.logger.log(
+ `Sample embedding generation completed for category '${category}'. Processed: ${processed}, Errors: ${errors}, Total Sample: ${codesWithoutEmbedding.rows.length}`,
+ );
+ return {
+ processed,
+ errors,
+ totalSample: codesWithoutEmbedding.rows.length,
+ category,
+ };
+ } catch (error) {
+ this.logger.error(
+ `Error in generateAndStoreSampleEmbeddingsByCategory for category '${category}':`,
+ error,
+ );
+ throw error;
+ }
+ }
+
+ /**
+ * Vector similarity search menggunakan pgvector
+ */
+ async vectorSearch(
+ query: string,
+ limit: number = 10,
+ category?: string,
+ threshold: number = 0.7,
+ ): Promise {
+ try {
+ this.logger.log(`Performing pgvector search for: ${query}`);
+
+ if (!this.embeddings) {
+ throw new Error('OpenAI embeddings not initialized');
+ }
+
+ // Generate embedding for query
+ const queryEmbedding = await this.generateEmbedding(query);
+
+ // Convert embedding array to proper vector format for pgvector
+ const vectorString = `[${queryEmbedding.join(',')}]`;
+
+ // Build SQL query for vector similarity search
+ let sql = `
+ SELECT
+ id, code, display, version, category,
+ 1 - (embedding <=> $1::vector) as similarity
+ FROM icd_codes
+ WHERE embedding IS NOT NULL
+ `;
+
+ const params: any[] = [vectorString];
+ let paramIndex = 2;
+
+ if (category) {
+ sql += ` AND category = $${paramIndex}`;
+ params.push(category);
+ paramIndex++;
+ }
+
+ sql += ` ORDER BY embedding <=> $1::vector ASC LIMIT $${paramIndex}`;
+ params.push(limit);
+
+ // Execute raw SQL query
+ const result = await this.pool.query(sql, params);
+
+ // Transform and filter results
+ const filteredResults: VectorSearchResult[] = result.rows
+ .filter((row: any) => row.similarity >= threshold)
+ .map((row: any) => ({
+ id: row.id,
+ code: row.code,
+ display: row.display,
+ version: row.version,
+ category: row.category,
+ similarity: parseFloat(row.similarity),
+ }));
+
+ this.logger.log(
+ `Pgvector search returned ${filteredResults.length} results for query: "${query}"`,
+ );
+ return filteredResults;
+ } catch (error) {
+ this.logger.error('Error in pgvector search:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Hybrid search: combine vector similarity dengan text search
+ */
+ async hybridSearch(
+ query: string,
+ limit: number = 10,
+ category?: string,
+ vectorWeight: number = 0.7,
+ textWeight: number = 0.3,
+ ): Promise {
+ try {
+ this.logger.log(`Performing hybrid search for: ${query}`);
+
+ // Get vector search results
+ const vectorResults = await this.vectorSearch(
+ query,
+ limit * 2,
+ category,
+ 0.5,
+ );
+
+ // Get text search results
+ const textResults = await this.textSearch(query, limit * 2, category);
+
+ // Combine and score results
+ const combinedResults = new Map();
+
+ // Add vector results
+ for (const result of vectorResults) {
+ combinedResults.set(result.id, {
+ ...result,
+ similarity: result.similarity * vectorWeight,
+ });
+ }
+
+ // Add text results with text scoring
+ for (const result of textResults) {
+ const existing = combinedResults.get(result.id);
+ if (existing) {
+ // Combine scores
+ existing.similarity += (result.similarity || 0.5) * textWeight;
+ } else {
+ combinedResults.set(result.id, {
+ ...result,
+ similarity: (result.similarity || 0.5) * textWeight,
+ });
+ }
+ }
+
+ // Convert to array, sort by combined score, and limit
+ const results = Array.from(combinedResults.values());
+ results.sort((a, b) => b.similarity - a.similarity);
+
+ return results.slice(0, limit);
+ } catch (error) {
+ this.logger.error('Error in hybrid search:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Text-based search dengan scoring
+ */
+ private async textSearch(
+ query: string,
+ limit: number,
+ category?: string,
+ ): Promise {
+ try {
+ let sql = 'SELECT id, code, display, version, category FROM icd_codes';
+ const params: any[] = [];
+ let whereConditions: string[] = [];
+ let paramIndex = 1;
+
+ if (category) {
+ whereConditions.push(`category = $${paramIndex}`);
+ params.push(category);
+ paramIndex++;
+ }
+
+ if (query) {
+ whereConditions.push(
+ `(code ILIKE $${paramIndex} OR display ILIKE $${paramIndex})`,
+ );
+ params.push(`%${query}%`);
+ paramIndex++;
+ }
+
+ if (whereConditions.length > 0) {
+ sql += ' WHERE ' + whereConditions.join(' AND ');
+ }
+
+ sql += ' ORDER BY code ASC LIMIT $' + paramIndex;
+ params.push(limit);
+
+ const result = await this.pool.query(sql, params);
+
+ return result.rows.map((code) => ({
+ id: code.id,
+ code: code.code,
+ display: code.display,
+ version: code.version,
+ category: code.category,
+ similarity: 0.5, // Default text similarity score
+ }));
+ } catch (error) {
+ this.logger.error('Error in text search:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get embedding statistics
+ */
+ async getEmbeddingStats(): Promise<{
+ total: number;
+ withEmbeddings: number;
+ withoutEmbeddings: number;
+ percentage: number;
+ vectorStoreStatus: string;
+ }> {
+ try {
+ // Use raw SQL to get embedding statistics
+ const [totalResult, withEmbeddingsResult] = await Promise.all([
+ this.pool.query('SELECT COUNT(*) as count FROM icd_codes'),
+ this.pool.query(
+ 'SELECT COUNT(*) as count FROM icd_codes WHERE embedding IS NOT NULL',
+ ),
+ ]);
+
+ const total = parseInt(totalResult.rows[0].count);
+ const withEmbeddings = parseInt(withEmbeddingsResult.rows[0].count);
+ const withoutEmbeddings = total - withEmbeddings;
+ const percentage = total > 0 ? (withEmbeddings / total) * 100 : 0;
+ const vectorStoreStatus = this.vectorStore
+ ? 'Initialized'
+ : 'Not Initialized';
+
+ return {
+ total,
+ withEmbeddings,
+ withoutEmbeddings,
+ percentage: Math.round(percentage * 100) / 100,
+ vectorStoreStatus,
+ };
+ } catch (error) {
+ this.logger.error('Error getting embedding stats:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Refresh vector store dengan data terbaru
+ */
+ async refreshVectorStore(): Promise {
+ try {
+ this.logger.log('Refreshing pgvector store...');
+ await this.initializeVectorStore();
+ this.logger.log('Pgvector store refreshed successfully');
+ } catch (error) {
+ this.logger.error('Error refreshing pgvector store:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get vector store status
+ */
+ async getVectorStoreStatus(): Promise<{
+ initialized: boolean;
+ documentCount: number;
+ embeddingModel: string;
+ lastUpdated: Date;
+ }> {
+ try {
+ // Get document count from database using raw SQL
+ const result = await this.pool.query(
+ 'SELECT COUNT(*) as count FROM icd_codes WHERE embedding IS NOT NULL',
+ );
+ const documentCount = parseInt(result.rows[0].count);
+
+ const status = {
+ initialized: !!this.vectorStore,
+ documentCount,
+ embeddingModel: this.embeddings
+ ? `OpenAI ${process.env.OPENAI_API_MODEL || 'text-embedding-ada-002'}`
+ : 'Not Available',
+ lastUpdated: new Date(),
+ };
+
+ return status;
+ } catch (error) {
+ this.logger.error('Error getting vector store status:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Cleanup resources
+ */
+ async onModuleDestroy() {
+ await this.prisma.$disconnect();
+ await this.pool.end();
+ }
+}
diff --git a/src/main.ts b/src/main.ts
index f76bc8d..80aa6cf 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,8 +1,133 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
+import { Logger, ValidationPipe } from '@nestjs/common';
+import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
async function bootstrap() {
+ const logger = new Logger('Bootstrap');
+
const app = await NestFactory.create(AppModule);
- await app.listen(process.env.PORT ?? 3000);
+
+ // Environment configuration
+ const port = process.env.PORT ?? 3000;
+ const host = process.env.HOST ?? 'localhost';
+ const nodeEnv = process.env.NODE_ENV ?? 'development';
+
+ // CORS Configuration
+ const corsOrigins = process.env.CORS_ORIGINS?.split(',') ?? [
+ 'http://localhost:3000',
+ ];
+ const corsMethods = process.env.CORS_METHODS?.split(',') ?? [
+ 'GET',
+ 'HEAD',
+ 'PUT',
+ 'PATCH',
+ 'POST',
+ 'DELETE',
+ 'OPTIONS',
+ ];
+ const corsHeaders = process.env.CORS_HEADERS?.split(',') ?? [
+ 'Content-Type',
+ 'Accept',
+ 'Authorization',
+ 'X-Requested-With',
+ ];
+ const corsCredentials = process.env.CORS_CREDENTIALS === 'true';
+
+ // Enable CORS
+ app.enableCors({
+ origin: corsOrigins,
+ methods: corsMethods,
+ allowedHeaders: corsHeaders,
+ credentials: corsCredentials,
+ });
+
+ // Enable global validation pipe
+ app.useGlobalPipes(
+ new ValidationPipe({
+ whitelist: true,
+ forbidNonWhitelisted: true,
+ transform: true,
+ transformOptions: {
+ enableImplicitConversion: true,
+ },
+ }),
+ );
+
+ // Setup Swagger Documentation
+ if (process.env.ENABLE_DOCS === 'true') {
+ const config = new DocumentBuilder()
+ .setTitle('Claim Guard API')
+ .setDescription(
+ 'API documentation for Claim Guard Backend - ICD Code Management System',
+ )
+ .setVersion('1.0.0')
+ .setContact(
+ 'Development Team',
+ 'https://github.com/your-org/claim-guard-be',
+ 'dev@yourdomain.com',
+ )
+ .setLicense('MIT', 'https://opensource.org/licenses/MIT')
+ .addServer(
+ process.env.APP_URL || 'http://localhost:3000',
+ 'Development Server',
+ )
+ .addTag('ICD', 'ICD Code management operations')
+ .addTag('Health', 'Application health and monitoring')
+ .addBearerAuth(
+ {
+ type: 'http',
+ scheme: 'bearer',
+ bearerFormat: 'JWT',
+ name: 'JWT',
+ description: 'Enter JWT token',
+ in: 'header',
+ },
+ 'JWT-auth',
+ )
+ .build();
+
+ const document = SwaggerModule.createDocument(app, config);
+ SwaggerModule.setup('docs', app, document, {
+ swaggerOptions: {
+ persistAuthorization: true,
+ docExpansion: 'none',
+ filter: true,
+ showRequestDuration: true,
+ },
+ customSiteTitle: 'Claim Guard API Documentation',
+ customfavIcon: '/favicon.ico',
+ customCss: '.swagger-ui .topbar { display: none }',
+ });
+
+ logger.log(
+ `π Swagger Documentation enabled at: http://${host}:${port}/docs`,
+ );
+ }
+
+ // Global prefix for API endpoints (optional)
+ // app.setGlobalPrefix('api/v1');
+
+ // Request timeout
+ const requestTimeout = parseInt(process.env.REQUEST_TIMEOUT ?? '30000');
+
+ // Graceful shutdown
+ app.enableShutdownHooks();
+
+ await app.listen(port, host);
+
+ logger.log(`π Application is running on: http://${host}:${port}`);
+ logger.log(`π Environment: ${nodeEnv}`);
+ logger.log(`π CORS Origins: ${corsOrigins.join(', ')}`);
+
+ if (process.env.HEALTH_CHECK_ENABLED === 'true') {
+ logger.log(
+ `β€οΈ Health Check available at: http://${host}:${port}${process.env.HEALTH_CHECK_PATH || '/health'}`,
+ );
+ }
}
-bootstrap();
+
+bootstrap().catch((error) => {
+ console.error('β Error starting server:', error);
+ process.exit(1);
+});
diff --git a/verify_migration.sql b/verify_migration.sql
new file mode 100644
index 0000000..8a3af46
--- /dev/null
+++ b/verify_migration.sql
@@ -0,0 +1,112 @@
+-- =====================================================
+-- VERIFICATION: pgvector Migration Success
+-- =====================================================
+-- File: verify_migration.sql
+--
+-- Cara penggunaan:
+-- 1. Connect ke database: psql -d claim_guard -U username
+-- 2. Jalankan: \i verify_migration.sql
+-- =====================================================
+
+\echo 'π VERIFYING pgvector MIGRATION SUCCESS π'
+\echo '====================================================='
+
+-- Check pgvector extension
+SELECT
+ 'pgvector Extension' as component,
+ CASE
+ WHEN EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'vector')
+ THEN 'β
INSTALLED'
+ ELSE 'β NOT INSTALLED'
+ END as status;
+
+-- Check table structure
+SELECT
+ 'icd_codes Table' as component,
+ CASE
+ WHEN EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'icd_codes')
+ THEN 'β
EXISTS'
+ ELSE 'β MISSING'
+ END as status;
+
+-- Check all columns
+SELECT
+ column_name,
+ data_type,
+ is_nullable,
+ CASE
+ WHEN column_name IN ('embedding', 'metadata', 'content')
+ THEN 'β
pgvector column'
+ ELSE 'βΉοΈ Standard column'
+ END as status
+FROM information_schema.columns
+WHERE table_name = 'icd_codes'
+ORDER BY column_name;
+
+-- Check indexes
+SELECT
+ indexname,
+ indexdef,
+ CASE
+ WHEN indexname LIKE '%embedding%' OR indexname LIKE '%metadata%'
+ THEN 'β
Performance index'
+ ELSE 'βΉοΈ Standard index'
+ END as status
+FROM pg_indexes
+WHERE tablename = 'icd_codes'
+ORDER BY indexname;
+
+-- Test pgvector functionality
+\echo ''
+\echo 'π§ͺ TESTING pgvector FUNCTIONALITY π§ͺ'
+
+-- Test vector creation
+SELECT
+ '[1,2,3,4,5]'::vector(5) as test_vector_5d,
+ '[0.1,0.2,0.3]'::vector(3) as test_vector_3d;
+
+-- Test table data
+SELECT
+ COUNT(*) as total_rows,
+ COUNT(embedding) as rows_with_embeddings,
+ COUNT(metadata) as rows_with_metadata,
+ COUNT(content) as rows_with_content
+FROM icd_codes;
+
+-- Check sample data structure
+SELECT
+ id,
+ code,
+ display,
+ version,
+ category,
+ CASE
+ WHEN embedding IS NOT NULL THEN 'β
Has embedding'
+ ELSE 'β No embedding'
+ END as embedding_status,
+ CASE
+ WHEN metadata IS NOT NULL THEN 'β
Has metadata'
+ ELSE 'β No metadata'
+ END as metadata_status,
+ CASE
+ WHEN content IS NOT NULL THEN 'β
Has content'
+ ELSE 'β No content'
+ END as content_status
+FROM icd_codes
+LIMIT 5;
+
+\echo ''
+\echo 'π― MIGRATION VERIFICATION COMPLETE! π―'
+\echo '====================================================='
+\echo 'β
pgvector extension installed'
+\echo 'β
embedding column (vector type) added'
+\echo 'β
metadata column (JSONB) added'
+\echo 'β
content column (TEXT) added'
+\echo 'β
Performance indexes created'
+\echo ''
+\echo 'π NEXT STEPS:'
+\echo '1. Start application: npm run start:dev'
+\echo '2. Initialize vector store: POST /pgvector/initialize'
+\echo '3. Generate embeddings: POST /pgvector/generate-and-store-all-embeddings'
+\echo '4. Test vector search: POST /pgvector/search'
+\echo '====================================================='