Support alternative data stores with SQLite implementation#73
Conversation
This implements a repository pattern to abstract database-specific operations and adds SQLite as an alternative to PostgreSQL for lower-cost deployments. Key changes: - Add PasswordService with bcrypt for application-layer password hashing - Create repository interfaces for Account, Token, Auth, and Comment - Implement PostgreSQL repositories wrapping existing pgtyped queries - Implement SQLite repositories using better-sqlite3 - Add DatabaseModule with factory pattern for selecting database provider - Add in-memory queue for SQLite mode (pg-boss requires PostgreSQL) - Update services to use repository interfaces instead of direct DB access - Support automatic migration of legacy SHA256 passwords to bcrypt on login - Add session store factory supporting both PostgreSQL and SQLite Configuration: - DB_PROVIDER=sqlite|postgres (default: postgres) - SQLITE_PATH=./data/jcomments.db (default path) - QUEUE_PROVIDER=pgboss|memory (auto-detected from DB_PROVIDER) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a repository pattern to abstract database operations and adds SQLite as an alternative to PostgreSQL for lower-cost deployments. The key architectural change is moving from direct database access to repository interfaces, enabling support for multiple database backends.
Changes:
- Introduces bcrypt-based password hashing to replace legacy SHA256, with automatic migration on user login
- Implements repository pattern with interfaces for Account, Token, Auth, and Comment operations
- Adds SQLite support with better-sqlite3 and in-memory queue for single-process deployments
- Provides database and queue provider factories with environment-based selection
- Updates all services to use repository interfaces instead of direct database queries
Reviewed changes
Copilot reviewed 56 out of 57 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Adds bcrypt, better-sqlite3, and better-sqlite3-session-store dependencies |
| src/shared/crypto/password.service.ts | New service for bcrypt password hashing with legacy SHA256 verification support |
| src/shared/crypto/password.service.spec.ts | Comprehensive test coverage for password service |
| src/shared/repositories/*.ts | Repository interface definitions for Account, Token, Auth, and Comment |
| src/shared/repositories/postgres/*.ts | PostgreSQL repository implementations wrapping pgtyped queries |
| src/shared/repositories/sqlite/*.ts | SQLite repository implementations using better-sqlite3 |
| src/shared/database/database.module.ts | Factory module for selecting and configuring database providers |
| src/shared/database/session-store.factory.ts | Factory for creating session stores based on database provider |
| src/shared/queue/queue.module.ts | Factory module for selecting queue providers (pgboss or memory) |
| src/shared/queue/memory/*.ts | In-memory queue implementation for SQLite mode |
| src/shared/accounts/account.service.ts | Updated to use repository interfaces with password migration logic |
| src/shared/auth/auth.service.ts | Updated to use repository interfaces and PasswordService |
| src/shared/comments/comment.service.ts | Updated to use CommentRepository interface |
| src/console/console.service.ts | Added SQLite migration support and bootstrap command |
| scripts/migrate-pg-to-sqlite.ts | Migration script to export PostgreSQL data to SQLite |
| sql/sqlite/schema.sql | SQLite schema definition equivalent to PostgreSQL migrations |
| docker-compose.yml | Updated environment variable names for PostgreSQL |
| Dockerfile | Updated to Node.js 22 (from 20-alpine) |
| .env.example | Added configuration options for database and queue providers |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async send(queueName: string, data: unknown): Promise<string | null> { | ||
| const handler = this.handlers.get(queueName) | ||
| if (handler) { | ||
| // Process immediately | ||
| await handler({ data }) | ||
| } |
There was a problem hiding this comment.
Missing error handling: If the handler throws an error during execution, it will propagate to the caller. This differs from pg-boss behavior which would typically handle errors within the job queue system. Consider wrapping the handler call in a try-catch block and logging errors appropriately.
|
|
||
| @Module({ | ||
| imports: [forwardRef(() => CommentsModule), AccountsModuleCore, PgBossQueueModule], | ||
| imports: [forwardRef(() => CommentsModule), AccountsModuleCore, QueueModule.forRoot()], |
There was a problem hiding this comment.
Redundant QueueModule.forRoot() import: The QueueModule is already imported globally at the root WebModule level (line 23 in web.module.ts). This redundant import in the AccountsModule could lead to multiple instances of the queue being created. Since QueueModule is marked as @global(), it should be automatically available to all modules without re-importing.
| # Stage 1: Build the application | ||
| # Use a Node.js image | ||
| FROM node:20-alpine as builder | ||
| FROM node:22 as builder |
There was a problem hiding this comment.
Breaking change in Node.js version: The Dockerfile changes from node:20-alpine to node:22, which is a major version upgrade. This could introduce compatibility issues with existing deployments and dependencies. Consider documenting this change in the PR description and ensuring all dependencies are compatible with Node.js 22.
This implements a repository pattern to abstract database-specific operations and adds SQLite as an alternative to PostgreSQL for lower-cost deployments.
Key changes:
Configuration: