diff --git a/src/db/repo/action.repo.ts b/src/db/repo/action.repo.ts new file mode 100644 index 0000000000000000000000000000000000000000..75f8e16e64ccfdf94c24c192350284d1c2227672 --- /dev/null +++ b/src/db/repo/action.repo.ts @@ -0,0 +1,56 @@ +import { Service } from "typedi"; +import type { ActionInput, ActionModel, ActionUpdate } from "../schema/action.schema"; +import db from ".."; +import actionTable, { actionSchemas } from "../schema/action.schema"; +import { eq } from "drizzle-orm"; +import { z } from "zod"; + +@Service() +export class ActionRepo { + async findMany():Promise<ActionModel[]>{ + + return z.array(actionSchemas.model).parse(await db.query.actionTable.findMany()) + } + async findById(id: ActionModel['id']): Promise<ActionModel | null>{ + const action = await db.query.actionTable.findFirst({ + where: eq(actionTable.id, id) + }) + + if(!action) return null + return actionSchemas.model.parse(action) + } + async findByName(name: ActionModel['name']): Promise<ActionModel | null>{ + const action = await db.query.actionTable.findFirst({ + where: eq(actionTable.name, name) + }) + + if(!action) return null + return actionSchemas.model.parse(action) + } + async create(action: ActionInput, tx?: db): Promise<ActionModel>{ + const repo = tx ?? db + const [ret] = await repo + .insert(actionTable) + .values(action) + .returning() + + return actionSchemas.model.parse(ret) + } + async update(action: ActionUpdate): Promise<ActionModel>{ + const [ret] = await db + .update(actionTable) + .set(action) + .where(eq(actionTable.id, action.id)) + .returning() + + return actionSchemas.model.parse(ret) + } + async delete(id: ActionModel['id']): Promise<ActionModel>{ + const [ret] = await db + .delete(actionTable) + .where(eq(actionTable.id, id)) + .returning() + + return actionSchemas.model.parse(ret) + } +} \ No newline at end of file diff --git a/src/db/schema/action.schema.ts b/src/db/schema/action.schema.ts new file mode 100644 index 0000000000000000000000000000000000000000..59f7d1280fd54591e8bbb2935d7eafd48bb2b909 --- /dev/null +++ b/src/db/schema/action.schema.ts @@ -0,0 +1,41 @@ +import { sql } from "drizzle-orm" +import { pgTable, serial, text, timestamp, varchar } from "drizzle-orm/pg-core" +import { createInsertSchema, createSelectSchema } from "drizzle-zod" +import type { z } from "zod" + +const actionTable = pgTable('action', { + id: serial('id').primaryKey() + .unique() + .notNull(), + name: varchar('name', {length: 255}) + .unique() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string' }) + .notNull() + .defaultNow(), + updatedAt: timestamp('updated_at', { mode: 'string' }) + .notNull() + .defaultNow() + .$onUpdate(() => sql`current_timestamp`), +}) + +const actionModelSchema = createSelectSchema(actionTable) +const actionDtoSchema = actionModelSchema +const actionInputSchema = createInsertSchema(actionTable) +const actionUpdateSchema = actionInputSchema + .partial() + .required({ id: true }) + +export type ActionModel = z.infer<typeof actionModelSchema> +export type ActionDto = z.infer<typeof actionDtoSchema> +export type ActionInput = z.infer<typeof actionInputSchema> +export type ActionUpdate = z.infer<typeof actionUpdateSchema> + +export const actionSchemas = { + model: actionModelSchema, + dto: actionDtoSchema, + input: actionInputSchema, + update: actionUpdateSchema +} + +export default actionTable \ No newline at end of file diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index da1a4fd6b21e587bddc11512d32f72e737c5bacb..3c8b2a3abf87271d6661271bca941a38c210acc9 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -29,6 +29,7 @@ import resourceLikesTable from '../relations/resource-likes.relation' import resourceEducationalStagesTable from './resource-educational-stages.schema' import itemsTable from './items.schema' import userAchievementsTable from '../relations/user-achievements.relation' +import actionTable from './action.schema' export { userTable, @@ -60,6 +61,7 @@ export { achievementTable, itemsTable, userAchievementsTable, + actionTable, } export const tables = [ @@ -88,4 +90,5 @@ export const tables = [ achievementTable, itemsTable, userAchievementsTable, + actionTable, ] diff --git a/src/db/seed.ts b/src/db/seed.ts index cd5371300a44ebac0970562f34919eb6a31d13f9..40fb50e8435effea6558ae31b61a65d70ee8efde 100644 --- a/src/db/seed.ts +++ b/src/db/seed.ts @@ -47,5 +47,6 @@ await seeds.resourceEducationalStagesSeed(db) await seeds.achievementSeed(db) await seeds.itemsSeed(db) await seeds.userAchievementsSeed(db) +await seeds.actionSeed(db) await connection.end() diff --git a/src/db/seeds/action.seed.ts b/src/db/seeds/action.seed.ts new file mode 100644 index 0000000000000000000000000000000000000000..1ff06318cedf7b51177d9e5d0ce589aa0f7f77b3 --- /dev/null +++ b/src/db/seeds/action.seed.ts @@ -0,0 +1,145 @@ +import type db from "@/db"; +import actionTable, { type ActionInput } from "../schema/action.schema"; + +export default async function seed(db: db) { + await db.insert(actionTable).values(actionsData) +} + +const actionsData: ActionInput[] = [ + { + name: "Publicar" + }, + { + name: "Favoritar" + }, + { + name: "Avaliar " + }, + { + name: "Comentar" + }, + { + name: "Seguir Usuário" + }, + { + name: "Ser Seguido" + }, + { + name: "Fazer Download de um Recurso" + }, + { + name: "Fazer Login" + }, + { + name: "Meses de Conta" + }, + { + name: "Visualizar um Recurso" + }, + { + name: "Visualizar uma Coleção" + }, + { + name: "Criar Coleção" + }, + { + name: "Adicionar Recurso a Coleção" + }, + { + name: "Adicionar Foto de Perfil" + }, + { + name: "Adicionar Capa de Perfil" + }, + { + name: "Adicionar Descrição do Usuário" + }, + { + name: "Autenticação de Professor" + }, + { + name: "Assistir Apresentação" + }, + { + name: "Visualizar um Material" + }, + { + name: "Compartilhar" + }, + { + name: "Visualizar um Recurso de Língua Espanhola" + }, + { + name: "Visualizar um Recurso de Língua Inglesa" + }, + { + name: "Visualizar um Recurso de Arte" + }, + { + name: "Visualizar um Recurso de Língua Portuguesa" + }, + { + name: "Visualizar um Recurso de Biologia" + }, + { + name: "Visualizar um Recurso de Ciências da Natureza" + }, + { + name: "Visualizar um Recurso de Educação Física" + }, + { + name: "Visualizar um Recurso de Filosofia" + }, + { + name: "Visualizar um Recurso de Física" + }, + { + name: "Visualizar um Recurso de Geografia" + }, + { + name: "Visualizar um Recurso de História" + }, + { + name: "Visualizar um Recurso de Matemática" + }, + { + name: "Visualizar um Recurso de Química" + }, + { + name: "Visualizar um Recurso de Sociologia" + }, + { + name: "Visualizar um Recurso de Outras Línguas" + }, + { + name: "Visualizar um Recurso de Ensino Religioso" + }, + { + name: "Visualizar um Recurso de Outros" + }, + { + name: "Visualizar um Recurso de Informática" + }, + { + name: "Visualizar um Recurso de Direitos Humanos" + }, + { + name: "Visualizar um Recurso de Educação Ambiental" + }, + { + name: "Visualizar um Recurso de Educação do Campo" + }, + { + name: "Visualizar um Recurso de Educação Especial" + }, + { + name: "Visualizar um Recurso de Educação Indígena" + }, + { + name: "Visualizar um Recurso de Educação Quilombola" + }, + { + name: "Visualizar um Recurso de Educação Sexual" + }, + +] \ No newline at end of file diff --git a/src/db/seeds/index.ts b/src/db/seeds/index.ts index 19c5bcfa5bdc830c9764ca03cc1abfa5f95cef34..0e6a1758f8d01904909189b713b5c5495b052bc2 100644 --- a/src/db/seeds/index.ts +++ b/src/db/seeds/index.ts @@ -24,3 +24,4 @@ export { default as resourceEducationalStagesSeed } from './resource-educational export { default as achievementSeed } from './achievement.seed' export { default as itemsSeed } from './items.seed' export { default as userAchievementsSeed } from './user-achievements.seed' +export { default as actionSeed } from './action.seed' diff --git a/src/index.ts b/src/index.ts index 5612fc6c5d94dd07eb6cf12dc895d10f1f39d7ce..6c4fd6e83a8f990480f034b04129c08da8f0c26b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,7 @@ import { publicResourceEducationalStagesRouter, resourceEducationalStagesRouter import { achievementRouter, publicAchievementRouter } from './routes/achievement.route' import { itemsRouter, publicItemsRouter } from './routes/items.route' import { publicUserAchievementsRoute, userAchievementsRouter } from './routes/user-achievements.route' +import { actionRouter } from './routes/action.route' const app = new Hono() @@ -121,6 +122,7 @@ app .route('/user-institutions', userInstitutionRouter) .route('/resourceEducationalStages', resourceEducationalStagesRouter) .route('/items', itemsRouter) + .route('/actions', actionRouter) .route('/achievements', achievementRouter) .route('/resourceLikes', resourceLikesRoutes) .route('/userAchievements', userAchievementsRouter) diff --git a/src/routes/action.route.ts b/src/routes/action.route.ts new file mode 100644 index 0000000000000000000000000000000000000000..bc8582f149f0da429855a950e28ff5e423eb6bd6 --- /dev/null +++ b/src/routes/action.route.ts @@ -0,0 +1,101 @@ +import { ActionService } from "@/services/action.service" +import Container from "typedi" +import { honoWithJwt } from ".." +import { zValidator } from "@hono/zod-validator" +import { actionSchemas } from "@/db/schema/action.schema" +import { createApexError, HttpStatus } from "@/services/error.service" +import { z } from "zod" + +const service = Container.get(ActionService) + +export const actionRouter = honoWithJwt() +.post('/create', zValidator('json', actionSchemas.input), + async (c) => { + try{ + const input = await c.req.valid('json') + + const action = actionSchemas.dto.parse( + await service.create(input) + ) + + return c.json(action) + } catch (e){ + return c.json( + createApexError({ + status: 'error', + message: 'could not create action', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } +}) +.get('/actions', + async (c) => { + try { + const actions = z.array(actionSchemas.dto).parse(await service.findMany()) + + return c.json({actions}) + } catch (e) { + return c.notFound() + } +}) +.get('/:name', + async (c) => { + try { + const name = c.req.param('name') + + const action = actionSchemas.dto.parse(await service.findByName(name)) + + return c.json({ action }) + } catch (e) { + return c.notFound() + } +}) +.post('/update', + zValidator('json', actionSchemas.update), + async (c) => { + try { + const input = await c.req.valid('json') + const action = actionSchemas.dto.parse(await service.update(input)) + + return c.json({ action }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not update action', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } +) +.delete('/delete/:id', + async (c) =>{ + try{ + const id: number = +c.req.param('id') + + const action = actionSchemas.dto.parse( + await service.delete(id) + ) + + return c.json(action) + } catch (e){ + return c.json( + createApexError({ + status: 'error', + message: 'could delete action', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } +}) \ No newline at end of file diff --git a/src/services/action.service.ts b/src/services/action.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..abb012c403bb7e6d6b04abba8a3e225a54d42884 --- /dev/null +++ b/src/services/action.service.ts @@ -0,0 +1,35 @@ +import type db from "@/db" +import { ActionRepo } from "@/db/repo/action.repo" +import type { ActionModel, ActionInput, ActionUpdate } from "@/db/schema/action.schema" +import { Inject, Service } from "typedi" + +@Service() +export class ActionService{ + @Inject() + private readonly repo: ActionRepo + + async findMany():Promise<ActionModel[]>{ + + return this.repo.findMany() + } + async findById(id: ActionModel['id']): Promise<ActionModel | null>{ + + return this.repo.findById(id) + } + async findByName(name: ActionModel['name']): Promise<ActionModel | null>{ + + return this.repo.findByName(name) + } + async create(action: ActionInput, tx?: db): Promise<ActionModel>{ + + return this.repo.create(action, tx) + } + async update(action: ActionUpdate): Promise<ActionModel>{ + + return this.repo.update(action) + } + async delete(id: ActionModel['id']): Promise<ActionModel>{ + + return this.repo.delete(id) + } +} \ No newline at end of file