Skip to content

Commit

Permalink
feat: move from mikro-orm to drizzle-orm (#335)
Browse files Browse the repository at this point in the history
- Replaces mikro-orm with drizzle-orm.
- Improves some pieces of code.
- Testing gaps filled.
  • Loading branch information
mvdicarlo authored Feb 11, 2025
1 parent 8664e29 commit 9108881
Show file tree
Hide file tree
Showing 234 changed files with 6,609 additions and 3,792 deletions.
17 changes: 10 additions & 7 deletions apps/client-server/src/app/account/account.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
ApiOkResponse,
ApiTags,
} from '@nestjs/swagger';
import { AccountId } from '@postybirb/types';
import { PostyBirbController } from '../common/controller/postybirb-controller';
import { Account } from '../database/entities/account.entity';
import { AccountService } from './account.service';
import { CreateAccountDto } from './dtos/create-account.dto';
import { SetWebsiteDataRequestDto } from './dtos/set-website-data-request.dto';
Expand All @@ -18,7 +18,7 @@ import { UpdateAccountDto } from './dtos/update-account.dto';
*/
@ApiTags('account')
@Controller('account')
export class AccountController extends PostyBirbController<Account> {
export class AccountController extends PostyBirbController<'AccountSchema'> {
constructor(readonly service: AccountService) {
super(service);
}
Expand All @@ -29,30 +29,33 @@ export class AccountController extends PostyBirbController<Account> {
create(@Body() createAccountDto: CreateAccountDto) {
return this.service
.create(createAccountDto)
.then((account) => this.service.getAccountDto(account));
.then((account) => account.toDTO());
}

@Post('/clear/:id')
@ApiOkResponse({ description: 'Account data cleared.' })
@ApiBadRequestResponse({ description: 'Bad request made.' })
async clear(@Param('id') id: string) {
async clear(@Param('id') id: AccountId) {
await this.service.clearAccountData(id);
return this.service.manuallyExecuteOnLogin(id);
}

@Get('/refresh/:id')
@ApiOkResponse({ description: 'Account login check queued.' })
async refresh(@Param('id') id: string) {
async refresh(@Param('id') id: AccountId) {
this.service.manuallyExecuteOnLogin(id);
}

@Patch(':id')
@ApiOkResponse({ description: 'Account updated.', type: Boolean })
@ApiNotFoundResponse({ description: 'Account Id not found.' })
update(@Body() updateAccountDto: UpdateAccountDto, @Param('id') id: string) {
update(
@Body() updateAccountDto: UpdateAccountDto,
@Param('id') id: AccountId,
) {
return this.service
.update(id, updateAccountDto)
.then((account) => this.service.getAccountDto(account));
.then((account) => account.toDTO());
}

@Post('/account-data')
Expand Down
5 changes: 2 additions & 3 deletions apps/client-server/src/app/account/account.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Module } from '@nestjs/common';
import { DatabaseModule } from '../database/database.module';
import { WebsitesModule } from '../websites/websites.module';
import { AccountController } from './account.controller';
import { AccountService } from './account.service';
import { WebsitesModule } from '../websites/websites.module';

@Module({
imports: [DatabaseModule, WebsitesModule],
imports: [WebsitesModule],
providers: [AccountService],
controllers: [AccountController],
exports: [AccountService],
Expand Down
83 changes: 69 additions & 14 deletions apps/client-server/src/app/account/account.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { MikroORM } from '@mikro-orm/core';
import { Test, TestingModule } from '@nestjs/testing';
import { DatabaseModule } from '../database/database.module';
import { clearDatabase } from '@postybirb/database';
import { NULL_ACCOUNT_ID } from '@postybirb/types';
import { waitUntil } from '../utils/wait.util';
import { WebsiteImplProvider } from '../websites/implementations/provider';
import { UnknownWebsite } from '../websites/website';
import { WebsiteRegistryService } from '../websites/website-registry.service';
import { AccountService } from './account.service';
import { CreateAccountDto } from './dtos/create-account.dto';
Expand All @@ -10,37 +12,89 @@ describe('AccountsService', () => {
let service: AccountService;
let registryService: WebsiteRegistryService;
let module: TestingModule;
let orm: MikroORM;

beforeEach(async () => {
clearDatabase();
module = await Test.createTestingModule({
imports: [DatabaseModule],
providers: [AccountService, WebsiteRegistryService, WebsiteImplProvider],
}).compile();

service = module.get<AccountService>(AccountService);
registryService = module.get<WebsiteRegistryService>(
WebsiteRegistryService,
);
orm = module.get(MikroORM);
try {
await orm.getSchemaGenerator().refreshDatabase();
} catch {
// none
}

await service.onModuleInit();
});

afterAll(async () => {
await orm.close(true);
await module.close();
});

it('should be defined', () => {
expect(service).toBeDefined();
});

it('should manually execute onLogin', async () => {
const mockWebsiteRegistry = jest.spyOn(registryService, 'findInstance');
const mockEmitter = jest.spyOn(service, 'emit');
mockEmitter.mockReturnValue(undefined);
const getLoginState = jest
.fn()
.mockReturnValueOnce({
isLoggedIn: false,
pending: true,
})
.mockReturnValueOnce({
isLoggedIn: true,
pending: false,
})
.mockReturnValueOnce({
isLoggedIn: true,
pending: false,
});

const onLogin = jest.fn();

mockWebsiteRegistry.mockReturnValue({
onLogin,
getLoginState,
onBeforeLogin: jest.fn(),
onAfterLogin: jest.fn(),
} as unknown as UnknownWebsite);

await service.manuallyExecuteOnLogin(NULL_ACCOUNT_ID);
expect(mockWebsiteRegistry).toHaveBeenCalledTimes(1);
expect(getLoginState).toHaveBeenCalledTimes(3);
expect(onLogin).toHaveBeenCalledTimes(1);
});

it('should set and clear account data', async () => {
const dto = new CreateAccountDto();
dto.groups = ['test'];
dto.name = 'test';
dto.website = 'test';

const record = await service.create(dto);
expect(registryService.findInstance(record)).toBeDefined();

await waitUntil(() => !record.websiteInstance?.getLoginState().pending, 50);
expect(record.websiteInstance?.getWebsiteData()).toEqual({
test: 'test-mode',
});

await service.setAccountData({
id: record.id,
data: { test: 'test-mode-2' },
});
expect(record.websiteInstance?.getWebsiteData()).toEqual({
test: 'test-mode-2',
});

await service.clearAccountData(record.id);
expect(record.websiteInstance?.getWebsiteData()).toEqual({});
});

it('should create entities', async () => {
const dto = new CreateAccountDto();
dto.groups = ['test'];
Expand All @@ -51,17 +105,18 @@ describe('AccountsService', () => {
expect(registryService.findInstance(record)).toBeDefined();

const groups = await service.findAll();
await waitUntil(() => !record.websiteInstance?.getLoginState().pending, 50);
expect(groups).toHaveLength(1);
expect(groups[0].name).toEqual(dto.name);
expect(groups[0].website).toEqual(dto.website);
expect(groups[0].groups).toEqual(dto.groups);
expect(service.getAccountDto(record)).toEqual({
expect(record.toDTO()).toEqual({
groups: dto.groups,
name: dto.name,
website: dto.website,
id: record.id,
createdAt: record.createdAt.toISOString(),
updatedAt: record.updatedAt.toISOString(),
createdAt: record.createdAt,
updatedAt: record.updatedAt,
state: {
isLoggedIn: true,
pending: false,
Expand Down
Loading

0 comments on commit 9108881

Please sign in to comment.