Skip to content

Commit

Permalink
refactor: core design final (#38)
Browse files Browse the repository at this point in the history
* separate controller class unrelated to the app

* group routes into plugins

* inject database and controller into state

* Add prefix to all endpoints

* refactor: core design final pass

* Add vscode tabsize to settings

* Remove extra comments and refactor

---------

Co-authored-by: yamyam263 <yamyam263@gmail.com>
  • Loading branch information
Hajbo and yamcodes committed Sep 27, 2023
1 parent 2bf8fb0 commit 1bb1c77
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 86 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.tabSize": 2
}
24 changes: 10 additions & 14 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
// see: https://docs.nestjs.com/modules

import { Elysia } from "elysia";
import UsersService from "./users/users.service";
import UsersController from "./users/users.controller";
import { db } from "@/database.providers";

// the word 'setup' (instead of e.g. 'bootstrap') is in correspondence with the official elysiajs docs
// see: https://elysiajs.com/patterns/dependency-injection.html#dependency-injection

export const setup = () => {
const usersService = UsersService(db);
const usersController = UsersController(usersService);

return new Elysia()
.use(usersController)
}
import { usersPlugin } from "./users/users.plugin";

/**
* Add all plugins to the app
*/
export const setupApp = () => {
return new Elysia()
.use(usersPlugin)
.post("/", ({ store }) => store.usersService.findAll());
};
6 changes: 3 additions & 3 deletions src/database.providers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { drizzle, PostgresJsDatabase } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { dbCredentialsString } from '@db/config';
import { drizzle, PostgresJsDatabase } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { dbCredentialsString } from "@db/config";

// for migrations
export const migrationClient = postgres(dbCredentialsString, { max: 1 });
Expand Down
6 changes: 2 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Elysia } from "elysia";
import { setup } from "@/app.module";
import { setupApp } from "@/app.module";

const app = new Elysia()
.use(setup)
.listen(3000);
const app = new Elysia({ prefix: "/api" }).use(setupApp).listen(3000);

console.log(
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
Expand Down
38 changes: 0 additions & 38 deletions src/users/users.controller.ts

This file was deleted.

10 changes: 10 additions & 0 deletions src/users/users.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Elysia } from "elysia";
import { UsersService } from "@/users/users.service";
import { UsersRepository } from "@/users/users.repository";
import { db } from "@/database.providers";

export const setupUsers = () => {
const usersRepository = new UsersRepository(db);
const usersService = new UsersService(usersRepository);
return new Elysia().state(() => ({ usersService }));
};
7 changes: 7 additions & 0 deletions src/users/users.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Elysia } from "elysia";
import { setupUsers } from "@/users/users.module";

export const usersPlugin = new Elysia({ prefix: "/users" })
.use(setupUsers)
.post("/", ({ store }) => store.usersService.findAll())
.post("/login", ({ store }) => store.usersService.findAll());
14 changes: 14 additions & 0 deletions src/users/users.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// users.repository.ts
// in charge of database interactions

import { users } from "./users.schema";
import { PostgresJsDatabase } from "drizzle-orm/postgres-js";

export class UsersRepository {
// the type here is
constructor(private readonly db: PostgresJsDatabase) {}

async findAll() {
return this.db.select().from(users);
}
}
30 changes: 17 additions & 13 deletions src/users/users.schema.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { sql } from "drizzle-orm";
import { pgTable, text, date, serial} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from 'drizzle-typebox';
import { Type } from '@sinclair/typebox';
import { pgTable, text, date, serial } from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-typebox";
import { Type } from "@sinclair/typebox";

export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').notNull(),
bio: text('bio').notNull(),
image: text('image').notNull(),
password: text('password').notNull(),
username: text('username').notNull(),
created_at: date('created_at').default(sql`CURRENT_DATE`),
updated_at: date('updated_at').default(sql`CURRENT_DATE`),
export const users = pgTable("users", {
id: serial("id").primaryKey(),
email: text("email").notNull(),
bio: text("bio").notNull(),
image: text("image").notNull(),
password: text("password").notNull(),
username: text("username").notNull(),
created_at: date("created_at").default(sql`CURRENT_DATE`),
updated_at: date("updated_at").default(sql`CURRENT_DATE`),
});

// Schema for inserting a user - can be used to validate API requests
const insertUserSchemaRaw = createInsertSchema(users);
export const insertUserSchema = Type.Omit(insertUserSchemaRaw, ['id', 'created_at', 'updated_at']);
export const insertUserSchema = Type.Omit(insertUserSchemaRaw, [
"id",
"created_at",
"updated_at",
]);

// Schema for selecting a user - can be used to validate API responses
export const selectUserSchema = createSelectSchema(users);
21 changes: 7 additions & 14 deletions src/users/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import {users} from "./users.schema";
import {PostgresJsDatabase} from "drizzle-orm/postgres-js";
// users.service.ts
// in charge of business logic - generate slug, fetch data from other services, cache something, etc.

// note that we should specifically NOT import the db and use it here
// so we can mock it in tests and switch it out as needed
// also, this would hurt the single responsibility principle.
import { UsersRepository } from "@/users/users.repository";

export class UsersService {
constructor(private readonly repository: UsersRepository) {}

// the type here is
constructor(private readonly db: PostgresJsDatabase) {}

async findAll() {
return this.db.select().from(users);
}
async findAll() {
return this.repository.findAll();
}
}

// export a factory for consistency with other providers (like the controller)
export default (db: PostgresJsDatabase) => new UsersService(db);

0 comments on commit 1bb1c77

Please sign in to comment.