Skip to main content

Dependency Injection

Frourio use frouriojs/velona for Dependency Injection.

server/api/tasks/index.ts
import { Task } from '$/types';

export type Methods = {
get: {
query?: {
limit?: number;
message?: string;
};

resBody: Task[];
};
};
server/service/tasks.ts
import { PrismaClient } from '@prisma/client';
import { depend } from 'velona'; // dependency of frourio
import { Task } from '$/types';

const prisma = new PrismaClient();

export const getTasks = depend(
{ prisma: prisma as { task: { findMany(): Promise<Task[]> } } }, // inject prisma
async (
{ prisma },
limit?: number // prisma is injected object
) => (await prisma.task.findMany()).slice(0, limit)
);
server/api/tasks/controller.ts
import { defineController } from './$relay';
import { getTasks } from '$/service/tasks';

const print = (text: string) => console.log(text);

export default defineController(
{ getTasks, print }, // inject functions
({ getTasks, print }) => ({
// getTasks and print are injected function
get: async ({ query }) => {
if (query?.message) print(query.message);

return { status: 200, body: await getTasks(query?.limit) };
},
})
);
server/test/server.test.ts
import controller from '$/api/tasks/controller';

test('dependency injection into controller', async () => {
let printedMessage = '';

const injectedController = controller.inject((deps) => ({
getTasks: deps.getTasks.inject({
prisma: {
task: {
findMany: () =>
Promise.resolve([
{ id: 0, label: 'task1', done: false },
{ id: 1, label: 'task2', done: false },
{ id: 2, label: 'task3', done: true },
{ id: 3, label: 'task4', done: true },
{ id: 4, label: 'task5', done: false },
]),
},
},
}),
print: (text: string) => {
printedMessage = text;
},
}))();

const limit = 3;
const message = 'test message';
const res = await injectedController.get({
query: { limit, message },
});

expect(res.body).toHaveLength(limit);
expect(printedMessage).toBe(message);
});

Results

$ npm test

PASS server/test/server.test.ts
✓ dependency injection into controller (4 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.67 s, estimated 8 s
Ran all test suites.