Set up PostgreSQL database configuration and enhance application structure

- Added .env.example with database connection details and JWT configuration.
- Introduced docker-compose.yml for PostgreSQL service setup with health checks.
- Created drizzle.config.ts for database schema and migration management.
- Updated nest-cli.json to include Swagger plugin configuration for API documentation.
- Enhanced package.json with new database-related scripts and dependencies.
- Implemented initial database migrations for user and token management.
- Configured application bootstrap process to load environment variables and set up Swagger.
- Added shared application configuration in configure-app.ts for consistent setup.
- Included unit tests for application configuration and Swagger setup.
This commit is contained in:
shancheas
2026-08-21 15:00:19 +07:00
parent 7f37985d22
commit d01fd6e2ef
54 changed files with 4378 additions and 87 deletions
+71
View File
@@ -0,0 +1,71 @@
import { ConflictException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { DateTime } from '../../common/value-objects/date-time/date-time';
import type { User } from './user';
import { UsersRepository } from './users.repository';
import { UsersService } from './users.service';
describe('UsersService', () => {
let service: UsersService;
let repository: jest.Mocked<
Pick<UsersRepository, 'findById' | 'findByUsername' | 'create'>
>;
const now = DateTime.fromUnixMs(1_700_000_000_000);
const sampleUser: User = {
id: 'user-1',
username: 'alice',
passwordHash: 'hashed',
createdAt: now,
updatedAt: now,
};
beforeEach(async () => {
repository = {
findById: jest.fn(),
findByUsername: jest.fn(),
create: jest.fn(),
};
const moduleRef: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{ provide: UsersRepository, useValue: repository },
],
}).compile();
service = moduleRef.get(UsersService);
});
it('findById delegates to repository', async () => {
repository.findById.mockResolvedValue(sampleUser);
await expect(service.findById('user-1')).resolves.toEqual(sampleUser);
});
it('create stores lowercase username', async () => {
repository.findByUsername.mockResolvedValue(null);
repository.create.mockResolvedValue(sampleUser);
await service.create('Alice', 'hashed');
expect(repository.findByUsername).toHaveBeenCalledWith('alice');
expect(repository.create).toHaveBeenCalledWith({
username: 'alice',
passwordHash: 'hashed',
});
});
it('create throws ConflictException when username exists', async () => {
repository.findByUsername.mockResolvedValue(sampleUser);
await expect(service.create('alice', 'hashed')).rejects.toBeInstanceOf(
ConflictException,
);
expect(repository.create).not.toHaveBeenCalled();
});
it('findByUsername delegates to repository', async () => {
repository.findByUsername.mockResolvedValue(sampleUser);
await expect(service.findByUsername('Alice')).resolves.toEqual(sampleUser);
});
});