feat: add file storage service and update configurations

refactor: migrate to tsup for builds and update tsconfigs
fix: update error handling and validation in payment service
chore: update package scripts and dependencies
docs: update README and env examples
This commit is contained in:
Yuu Ottosoka
2025-07-12 16:01:57 +03:00
parent c0c04bbdba
commit f9ecac94f2
67 changed files with 3308 additions and 695 deletions

View File

@@ -0,0 +1,16 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ['@repo/eslint-config/library.js'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: true,
},
rules: {
'turbo/no-undeclared-env-vars': [
'error',
{
allowList: ['NODE_ENV'],
},
],
},
};

View File

@@ -87,6 +87,10 @@ export const PlanScalarFieldEnumSchema = z.enum(['id','code','name','description
export const SubscriptionScalarFieldEnumSchema = z.enum(['id','telegramUserId','planId','startedAt','expiresAt','canceledAt','createdAt','updatedAt']);
export const FileScalarFieldEnumSchema = z.enum(['id','filename','originalName','mimeType','size','path','createdAt','updatedAt']);
export const FileLinkScalarFieldEnumSchema = z.enum(['id','fileId','relationId','createdAt','updatedAt']);
export const SortOrderSchema = z.enum(['asc','desc']);
export const JsonNullValueInputSchema = z.enum(['JsonNull',]).transform((value) => (value === 'JsonNull' ? Prisma.JsonNull : value));
@@ -190,3 +194,34 @@ export const SubscriptionSchema = z.object({
})
export type Subscription = z.infer<typeof SubscriptionSchema>
/////////////////////////////////////////
// FILE SCHEMA
/////////////////////////////////////////
export const FileSchema = z.object({
id: z.string().uuid(),
filename: z.string(),
originalName: z.string(),
mimeType: z.string(),
size: z.number().int(),
path: z.string(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
})
export type File = z.infer<typeof FileSchema>
/////////////////////////////////////////
// FILE LINK SCHEMA
/////////////////////////////////////////
export const FileLinkSchema = z.object({
id: z.string().uuid(),
fileId: z.string(),
relationId: z.string(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
})
export type FileLink = z.infer<typeof FileLinkSchema>

View File

@@ -1,7 +1,30 @@
{
"name": "@repo/db",
"version": "0.0.0",
"version": "1.0.0",
"type": "module",
"private": true,
"files": [
"dist"
],
"main": "./dist/index.cjs",
"types": "./src/index.ts",
"exports": {
".": {
"import": {
"types": "./src/index.ts",
"default": "./dist/index.cjs"
},
"require": {
"types": "./src/index.ts",
"default": "./dist/index.cjs"
}
}
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"check-types": "tsc --noEmit",
"clean": "rm -rf dist",
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev --skip-generate",
"db:deploy": "prisma migrate deploy",
@@ -10,14 +33,14 @@
"dependencies": {
"@prisma/client": "^6.11.1",
"@repo/exceptions": "*",
"prisma-json-types-generator": "^3.5.1",
"zod-prisma-types": "^3.2.4"
"prisma-json-types-generator": "^3.5.1"
},
"devDependencies": {
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@types/node": "^24.0.10",
"prisma": "^6.11.1"
},
"exports": {
".": "./src/index.ts"
"prisma": "^6.11.1",
"tsup": "^8.3.5",
"typescript": "^5.8.3"
}
}

View File

@@ -48,7 +48,7 @@ model TelegramUser {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
payments Payment[]
payments Payment[]
subscription Subscription?
}
@@ -56,7 +56,7 @@ model Payment {
id String @id @default(cuid())
telegramUserId String
amount Decimal @db.Decimal(10, 2)
currency String
currency String
status PaymentStatus @default(PENDING)
provider String
providerId String?
@@ -78,10 +78,10 @@ model Plan {
code String @unique()
name String
description String?
durationDays Int
durationDays Int
dailyGenerations Int
price Int
currency String
currency String
subscriptions Subscription[]
@@ -89,20 +89,44 @@ model Plan {
}
model Subscription {
id String @id @default(uuid())
telegramUserId String @unique
planId String
id String @id @default(uuid())
telegramUserId String @unique
planId String
startedAt DateTime @default(now())
expiresAt DateTime
canceledAt DateTime?
startedAt DateTime @default(now())
expiresAt DateTime
canceledAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
plan Plan @relation(fields: [planId], references: [id], onDelete: Cascade)
plan Plan @relation(fields: [planId], references: [id], onDelete: Cascade)
telegramUser TelegramUser @relation(fields: [telegramUserId], references: [id], onDelete: Cascade)
@@index([telegramUserId])
@@index([planId])
}
model File {
id String @id @default(uuid())
filename String
originalName String
mimeType String
size Int
path String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
links FileLink[]
}
model FileLink {
id String @id @default(uuid())
fileId String
relationId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
file File @relation(fields: [fileId], references: [id], onDelete: Cascade)
}

View File

@@ -1,11 +1,11 @@
import { Prisma, PrismaClient as PrismaClientBase } from '../generated/prisma';
import { Prisma, PrismaClient as PrismaClientBase } from "../generated/prisma";
export const prisma = new PrismaClientBase().$extends({
model: {
$allModels: {
async exists<T>(
this: T,
where?: Prisma.Args<T, 'findFirst'>['where']
where?: Prisma.Args<T, "findFirst">["where"],
): Promise<boolean> {
const context = Prisma.getExtensionContext(this);
const result = await (context as any).findFirst({ where });
@@ -18,5 +18,5 @@ export const prisma = new PrismaClientBase().$extends({
export type PrismaClient = typeof prisma;
export type PrismaClientArg =
| Parameters<Parameters<PrismaClient['$transaction']>[0]>[0]
| Parameters<Parameters<PrismaClient["$transaction"]>[0]>[0]
| PrismaClient;

View File

@@ -1,7 +1,2 @@
export { prisma, type PrismaClientArg, type PrismaClient } from './client';
export * from '../generated/prisma';
export {
PaymentSchema,
TelegramUserSchema,
TelegramSessionSchema,
} from '../generated/zod';

View File

@@ -0,0 +1,16 @@
{
"extends": "@repo/typescript-config/library.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": ".",
"skipLibCheck": true,
"allowJs": false,
"noImplicitAny": false,
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"exactOptionalPropertyTypes": false
},
"include": ["src/**/*", "tsup.config.ts"],
"exclude": ["node_modules", "dist", "generated/**/*"]
}

View File

@@ -0,0 +1,16 @@
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs"],
dts: false,
splitting: false,
sourcemap: true,
clean: true,
external: ["@prisma/client"],
treeshake: false,
minify: false,
target: "node18",
platform: "node",
bundle: true,
});