Backend Technical Details¶
Architecture Overview¶
The BidScript backend is built using NestJS, a progressive Node.js framework that employs modern design patterns and best practices. It follows a modular architecture with dependency injection for maintainable and testable code.
Design Patterns¶
- Dependency Injection: Core pattern for managing dependencies
- Repository Pattern: Abstracts data access layer
- Module Pattern: Organises code into cohesive modules
- Service Layer: Encapsulates business logic
- Controller-Service-Repository: Layered architecture
- Event-Driven Architecture: Using event emitters for loose coupling
- Middleware Pipeline: For request processing
- Gateway Pattern: For WebSocket communication
Directory Structure¶
bidssappserver-nestjs/
├── src/
│ ├── main.ts # Application entry point
│ ├── app.module.ts # Root application module
│ ├── app.controller.ts # Root controller
│ ├── app.service.ts # Root service
│ ├── auth/ # Authentication module
│ │ ├── auth.module.ts
│ │ ├── auth.service.ts
│ │ ├── auth.controller.ts
│ │ ├── strategies/ # Passport strategies
│ │ └── guards/ # Auth guards
│ ├── azure/ # Azure services integration
│ │ ├── azure.module.ts
│ │ ├── azure.service.ts # Core Azure service
│ │ ├── blob.service.ts # Azure Storage management
│ │ ├── document-parse.service.ts # Document parsing
│ │ └── azure-sql.service.ts # Azure SQL database
│ ├── chat/ # Chat functionality
│ │ ├── chat.module.ts
│ │ ├── chat.controller.ts
│ │ ├── chat.service.ts
│ │ ├── chat-context.service.ts # Chat context management
│ │ └── chat.dto.ts # Data transfer objects
│ ├── rag/ # Retrieval Augmented Generation
│ │ ├── rag.module.ts
│ │ ├── rag.service.ts # RAG implementation
│ │ └── dto/ # RAG DTOs
│ ├── editor/ # Document editor module
│ │ ├── editor.module.ts
│ │ ├── editor.controller.ts
│ │ ├── editor.service.ts
│ │ ├── editor.gateway.ts # WebSocket gateway
│ │ └── dto/ # Editor DTOs
│ ├── llama/ # Llama integration
│ │ ├── llama.module.ts
│ │ └── llama.service.ts # Llama document parsing
│ ├── langchain/ # LangChain module
│ │ ├── langchain.module.ts
│ │ ├── langchain.service.ts
│ │ └── chains/ # Custom LangChain chains
│ ├── vectorstore/ # Vector database
│ │ ├── vectorstore.module.ts
│ │ └── vectorstore.service.ts # Vector DB operations
│ ├── redis/ # Redis module
│ │ ├── redis.module.ts
│ │ └── redis.service.ts # Redis operations
│ ├── conversation/ # Conversation history
│ │ ├── conversation.module.ts
│ │ └── conversation.service.ts # Conversation management
│ ├── theme/ # Theming functionality
│ │ ├── theme.module.ts
│ │ └── theme.service.ts # Theme management
│ ├── grafana/ # Monitoring
│ │ ├── grafana.module.ts
│ │ └── grafana.service.ts # Metrics collection
│ └── types/ # TypeScript type definitions
│ ├── dto/ # Common DTOs
│ └── interfaces/ # TypeScript interfaces
├── test/ # Tests
│ ├── app.e2e-spec.ts # E2E tests
│ └── jest-e2e.json # Jest E2E config
├── dist/ # Compiled output
├── node_modules/ # Dependencies
├── .env # Environment variables
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── nest-cli.json # NestJS CLI configuration
├── docker-compose.yml # Docker Compose config
└── Dockerfile # Docker config
Module Architecture¶
NestJS Module System¶
Each feature in the application is organised into a NestJS module that exports services and controllers:
@Module({
imports: [
// Imported modules
DependentModule,
],
controllers: [FeatureController],
providers: [FeatureService],
exports: [FeatureService],
})
export class FeatureModule {}
Application Bootstrap¶
The application bootstrap process is defined in main.ts:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Configure body parser, CORS, validation pipe, etc.
await app.listen(process.env.PORT || 3000);
}
bootstrap();
Authentication System¶
JWT Authentication¶
The backend uses JWT (JSON Web Tokens) for stateless authentication:
-
Authentication Flow:
-
User submits credentials
- Server validates and issues JWT token
- Token is included in subsequent requests
-
JWT Guard validates token on protected routes
-
JWT Configuration:
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: process.env.JWT_EXPIRATION || "8h" },
});
- Global Guard:
AI Integration Architecture¶
RAG (Retrieval Augmented Generation)¶
The RAG system enhances AI responses with relevant information from indexed documents:
-
Document Processing Pipeline:
-
Document upload and storage
- Text extraction
- Chunking and preprocessing
- Embedding generation
-
Vector database indexing
-
Query Pipeline:
- Query embedding generation
- Semantic search in vector database
- Context retrieval
- Context augmentation
- LLM generation with augmented context
Azure OpenAI Integration¶
The application integrates with Azure OpenAI services:
const openAIClient = new OpenAIClient(
process.env.AZURE_OPENAI_ENDPOINT,
new AzureKeyCredential(process.env.AZURE_OPENAI_API_KEY)
);
WebSocket Implementation¶
Socket.IO Integration¶
Real-time communication is implemented using Socket.IO with NestJS WebSocket gateways:
@WebSocketGateway({
cors: {
origin: true,
credentials: true,
},
namespace: "chat",
})
export class ChatGateway implements OnGatewayInit, OnGatewayConnection {
// WebSocket event handlers
}
YJS for Collaborative Editing¶
The editor uses YJS for conflict-free collaborative editing:
@WebSocketGateway({
namespace: "editor/yjs",
})
export class EditorGateway {
// YJS document handling
}
Database and Storage¶
Azure Blob Storage¶
Document storage is managed through Azure Blob Storage:
const containerClient = blobServiceClient.getContainerClient(
process.env.AZURE_STORAGE_CONTAINER
);
Vector Database (Pinecone)¶
Embeddings are stored in Pinecone vector database:
const pinecone = new Pinecone({
apiKey: process.env.PINECONE_API_KEY,
environment: process.env.PINECONE_ENVIRONMENT,
});
const index = pinecone.Index(process.env.PINECONE_INDEX);
Redis¶
Redis is used for caching and job queues:
// Redis module registration
RedisModule.forRootAsync({
useFactory: () => ({
config: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT, 10),
password: process.env.REDIS_PASSWORD,
},
}),
});
Background Processing¶
Bull Queue¶
Background jobs are processed using Bull queue with Redis:
@Process('parse-document')
async processDocument(job: Job<DocumentProcessingData>) {
// Process document in background
}
Error Handling¶
Global Exception Filter¶
The application uses a global exception filter for consistent error responses:
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: any, host: ArgumentsHost) {
// Format and return error response
}
}
Validation and Security¶
Request Validation¶
Data validation is implemented using class-validator and pipes:
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
})
);
DTO Example¶
export class CreateChatSessionDto {
@IsString()
@IsNotEmpty()
title: string;
@IsArray()
@IsOptional()
documentIds?: string[];
@IsString()
@IsOptional()
contextType?: string;
}
API Documentation¶
API documentation is generated using Swagger/OpenAPI:
const config = new DocumentBuilder()
.setTitle("BidScript API")
.setDescription("BidScript Backend API")
.setVersion("1.0")
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api-docs", app, document);
Testing Strategy¶
Unit Testing¶
Services and controllers are unit tested with Jest:
describe("ChatService", () => {
let service: ChatService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ChatService,
// Mock dependencies
],
}).compile();
service = module.get<ChatService>(ChatService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
});
E2E Testing¶
End-to-end tests use SuperTest with NestJS testing utilities:
describe("AppController (e2e)", () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it("/health (GET)", () => {
return request(app.getHttpServer()).get("/health").expect(200);
});
});
CI/CD Pipeline¶
GitHub Actions¶
Continuous integration and deployment are managed through GitHub Actions:
name: CI/CD Pipeline
on:
push:
branches: [main, staging]
pull_request:
branches: [main]
jobs:
build-and-test:
# CI steps for building and testing
deploy:
# CD steps for deployment
Monitoring and Logging¶
Logging¶
The application uses NestJS Logger for structured logging:
const logger = new Logger("ModuleName");
logger.log("Info message");
logger.error("Error message", trace);
Metrics¶
Prometheus metrics are exposed for monitoring: