diff --git a/bun.lockb b/bun.lockb index 44aaed9..38606e0 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/migrations/20240703103050_accounts.up.sql b/migrations/20240703103050_accounts.up.sql new file mode 100644 index 0000000..66ca2c2 --- /dev/null +++ b/migrations/20240703103050_accounts.up.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS public.accounts +( + id integer NOT NULL GENERATED ALWAYS AS IDENTITY, + username text NOT NULL, + password text NOT NULL, + role_id smallint NOT NULL DEFAULT '1'::smallint, + created_at timestamp without time zone NOT NULL DEFAULT now(), + updated_at timestamp without time zone NOT NULL DEFAULT now(), + CONSTRAINT accounts_pkey PRIMARY KEY (id), + CONSTRAINT accounts_username_key UNIQUE (username) +); \ No newline at end of file diff --git a/migrations/20240703103105_movies.up.sql b/migrations/20240703103105_movies.up.sql new file mode 100644 index 0000000..47faa7d --- /dev/null +++ b/migrations/20240703103105_movies.up.sql @@ -0,0 +1,15 @@ +-- Add migration script here + +CREATE TABLE IF NOT EXISTS public.movies +( + id integer NOT NULL GENERATED ALWAYS AS IDENTITY, + title text NOT NULL, + overview text NOT NULL, + poster_path text NOT NULL, + backdrop_path text, + release_date date NOT NULL, + tmdb_id integer NOT NULL, + created_at timestamp without time zone NOT NULL DEFAULT now(), + updated_at timestamp without time zone NOT NULL DEFAULT now(), + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/package.json b/package.json index 544af2d..2371f8d 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,10 @@ "typescript": "^5.6.2" }, "dependencies": { + "fastify": "^5.2.0", "hono": "^4.6.15", - "pg": "^8.13.1" + "inversify": "^6.2.1", + "pg": "^8.13.1", + "reflect-metadata": "^0.2.2" } } diff --git a/src/accounts/AccountsController.ts b/src/accounts/AccountsController.ts new file mode 100644 index 0000000..020f900 --- /dev/null +++ b/src/accounts/AccountsController.ts @@ -0,0 +1,4 @@ +import { injectable } from "inversify"; + +@injectable() +export default class AccountsController {} diff --git a/src/accounts/AccountsRouter.ts b/src/accounts/AccountsRouter.ts new file mode 100644 index 0000000..62b1486 --- /dev/null +++ b/src/accounts/AccountsRouter.ts @@ -0,0 +1,7 @@ +import type { FastifyInstance, FastifyPluginCallback } from "fastify"; + +const accountsRouter: FastifyPluginCallback = (fastify, opts, done) => { + done(); +}; + +export default accountsRouter; diff --git a/src/accounts/repository/AccountsRepository.ts b/src/accounts/repository/AccountsRepository.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/accounts/repository/IAccountsRepository.ts b/src/accounts/repository/IAccountsRepository.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/accounts/service/AccountsService.ts b/src/accounts/service/AccountsService.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/accounts/service/IAccountsService.ts b/src/accounts/service/IAccountsService.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/app.ts b/src/app.ts index e69de29..e61df32 100644 --- a/src/app.ts +++ b/src/app.ts @@ -0,0 +1,17 @@ +import Fastify from "fastify"; +import APIError from "./core/errors/APIError"; + +import accountsRouter from "./accounts/AccountsRouter"; + +const app = Fastify(); + +app.register(accountsRouter, { prefix: "/accounts" }); + +app.setErrorHandler((err, request, reply) => { + const apiError = + err instanceof APIError + ? err + : new APIError("Internal Server Error", 500, err); + + reply.status(apiError.statusCode).send(apiError.toStruct()); +}); diff --git a/src/core/databases/PgDatabase.ts b/src/core/databases/PgDatabase.ts index b349339..4db0d3f 100644 --- a/src/core/databases/PgDatabase.ts +++ b/src/core/databases/PgDatabase.ts @@ -1,4 +1,5 @@ -import { Client, Pool, type PoolClient, type QueryResult } from "pg"; +import { injectable } from "inversify"; +import { Pool, type PoolClient, type QueryResult } from "pg"; import type { SqlParams } from "./IDatabase"; import type IDatabase from "./IDatabase"; @@ -10,6 +11,7 @@ export interface PgConnectionOptions { password: string; } +@injectable() export default class PgDatabase implements IDatabase { private pool: Pool; diff --git a/src/core/errors/APIError.ts b/src/core/errors/APIError.ts index e808f3f..63bf86e 100644 --- a/src/core/errors/APIError.ts +++ b/src/core/errors/APIError.ts @@ -1,21 +1,31 @@ export interface APIErrorStruct { msg: string; statusCode: number; + cause?: string; } export default class APIError extends Error { public statusCode: number; - constructor(msg?: string, statusCode?: number, options?: ErrorOptions) { + public cause?: Error; + + constructor( + msg?: string, + statusCode?: number, + cause?: Error, + options?: ErrorOptions, + ) { super(msg, options); this.statusCode = statusCode || 500; + this.cause = cause; } toStruct(): APIErrorStruct { return { msg: this.message, statusCode: this.statusCode, + cause: this.cause?.message, }; } } diff --git a/tsconfig.json b/tsconfig.json index ffc08ab..ef809f3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,9 @@ // Some stricter flags (disabled by default) "noUnusedLocals": false, "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false + "noPropertyAccessFromIndexSignature": false, + + "experimentalDecorators": true, + "emitDecoratorMetadata": true } }