From d340a4cad19bae0b3fd03403b96863123526bc41 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Sat, 27 Dec 2025 05:25:20 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Prisma=20=EB=B0=8F=20Redis=20=ED=81=B4?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EC=96=B8=ED=8A=B8=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B5=AC=EC=84=B1=20=EB=B0=8F?= =?UTF-8?q?=20=EC=BB=A4=EB=84=A5=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/package.json | 7 +++++ packages/common/prisma/schema.prisma | 10 +++++++ packages/common/src/index.ts | 3 +- packages/common/src/infra/postgres.ts | 42 ++++++++++++++++++++++++++ packages/common/src/infra/redis.ts | 43 +++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 packages/common/prisma/schema.prisma create mode 100644 packages/common/src/infra/postgres.ts create mode 100644 packages/common/src/infra/redis.ts diff --git a/packages/common/package.json b/packages/common/package.json index 5924ef6..08da5df 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -9,5 +9,12 @@ "dev": "node -e \"console.log('dev not configured')\"", "lint": "node -e \"console.log('lint not configured')\"", "test": "node -e \"console.log('test not configured')\"" + }, + "dependencies": { + "@prisma/client": "^5.18.0", + "redis": "^4.7.0" + }, + "devDependencies": { + "prisma": "^5.18.0" } } diff --git a/packages/common/prisma/schema.prisma b/packages/common/prisma/schema.prisma new file mode 100644 index 0000000..c3975a1 --- /dev/null +++ b/packages/common/prisma/schema.prisma @@ -0,0 +1,10 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +// TODO: Translate docs/architecture/postgres-schema.md into Prisma models. diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index cb0ff5c..03ece44 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1 +1,2 @@ -export {}; +export * from './infra/postgres'; +export * from './infra/redis'; diff --git a/packages/common/src/infra/postgres.ts b/packages/common/src/infra/postgres.ts new file mode 100644 index 0000000..461c325 --- /dev/null +++ b/packages/common/src/infra/postgres.ts @@ -0,0 +1,42 @@ +import { PrismaClient, type PrismaClientOptions } from '@prisma/client'; + +export interface PostgresConfig { + url: string; + log?: PrismaClientOptions['log']; +} + +export interface PostgresConnector { + readonly prisma: PrismaClient; + connect(): Promise; + disconnect(): Promise; +} + +export const resolvePostgresConfigFromEnv = ( + env: NodeJS.ProcessEnv = process.env +): PostgresConfig => { + const url = env.DATABASE_URL ?? ''; + if (!url) { + throw new Error('DATABASE_URL is required to create a Postgres client.'); + } + + return { url }; +}; + +export const createPostgresConnector = ( + config: PostgresConfig +): PostgresConnector => { + const prisma = new PrismaClient({ + datasources: { + db: { + url: config.url, + }, + }, + log: config.log, + }); + + return { + prisma, + connect: () => prisma.$connect(), + disconnect: () => prisma.$disconnect(), + }; +}; diff --git a/packages/common/src/infra/redis.ts b/packages/common/src/infra/redis.ts new file mode 100644 index 0000000..e5b6d6c --- /dev/null +++ b/packages/common/src/infra/redis.ts @@ -0,0 +1,43 @@ +import { createClient, type RedisClientOptions, type RedisClientType } from 'redis'; + +export interface RedisConfig { + url: string; + database?: number; + options?: Omit; +} + +export interface RedisConnector { + readonly client: RedisClientType; + connect(): Promise; + disconnect(): Promise; +} + +export const resolveRedisConfigFromEnv = ( + env: NodeJS.ProcessEnv = process.env +): RedisConfig => { + const url = env.REDIS_URL ?? ''; + if (!url) { + throw new Error('REDIS_URL is required to create a Redis client.'); + } + + const database = env.REDIS_DB !== undefined ? Number(env.REDIS_DB) : undefined; + if (database !== undefined && Number.isNaN(database)) { + throw new Error('REDIS_DB must be a number when provided.'); + } + + return { url, database }; +}; + +export const createRedisConnector = (config: RedisConfig): RedisConnector => { + const client = createClient({ + url: config.url, + database: config.database, + ...config.options, + }); + + return { + client, + connect: () => client.connect(), + disconnect: () => client.quit(), + }; +};