feat: add prisma stub and init schema

This commit is contained in:
Tianzhou Chen
2023-04-24 00:48:45 +08:00
parent f8f089238a
commit aabb9a0ce5
8 changed files with 322 additions and 13 deletions

View File

@ -2,3 +2,4 @@
OPENAI_API_KEY=YOUR_API_KEY
# Optional.
# OPENAI_API_ENDPOINT=YOUR_API_ENDPOINT
# TELEMETRY_DATABASE_URL=postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=sqlchat

View File

@ -35,6 +35,8 @@ SQL Chat is built by Next.js, it supports the following databases and will add m
- Only the database schema will be sent to the OpenAI API. No table data will be sent there.
- If you use [sqlchat.ai](https://sqlchat.ai), it will record the anonymised conversations.
## IP Whitelisting
If you use [sqlchat.ai](https://sqlchat.ai) to connect to your database, you need to add 0.0.0.0 (allow all connections)
@ -64,14 +66,44 @@ docker run --name sqlchat --platform linux/amd64 --env OPENAI_API_KEY=xxx --env
cp .env.example .env
```
2. Add your [API key](https://platform.openai.com/account/api-keys) and OpenAI API Endpoint(optional) to the newly created `.env` file;
1. Add your [API key](https://platform.openai.com/account/api-keys) and OpenAI API Endpoint(optional) to the newly created `.env` file;
3. Install dependencies and start the dev server;
1. Install dependencies and start the dev server;
```bash
pnpm i && pnpm dev
```
### Database Setup
1. Install prisma
```bash
pnpm install prisma --save-dev
```
1. Install prisma client
```bash
pnpm install @prisma/client
```
1. Generate prisma client from the model
```bash
pnpm prisma generate
```
1. Seed data
```bash
pnpm install typescript ts-node @types/node --save-dev
```
```bash
pnpm prisma db seed
```
## Common Questions
<details><summary>How to self host SQL Chat?</summary>

View File

@ -13,6 +13,7 @@
"@emotion/styled": "^11.10.6",
"@mui/material": "^5.11.14",
"@mui/styled-engine-sc": "^5.11.11",
"@prisma/client": "4.13.0",
"@radix-ui/react-dropdown-menu": "^2.0.4",
"@radix-ui/react-popover": "^1.0.5",
"@radix-ui/react-select": "^1.2.1",
@ -48,7 +49,7 @@
"@tailwindcss/typography": "^0.5.9",
"@types/lodash-es": "^4.17.7",
"@types/mssql": "^8.1.2",
"@types/node": "^18.11.18",
"@types/node": "^18.15.3",
"@types/pg": "^8.6.6",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.11",
@ -61,8 +62,13 @@
"mysql2": "^3.2.0",
"pg": "^8.10.0",
"postcss": "^8.4.20",
"prisma": "^4.13.0",
"react-syntax-highlighter": "^15.5.0",
"tailwindcss": "^3.2.4",
"typescript": "^4.9.4"
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
}
}

148
pnpm-lock.yaml generated
View File

@ -13,6 +13,9 @@ dependencies:
'@mui/styled-engine-sc':
specifier: ^5.11.11
version: 5.11.11(styled-components@5.3.9)
'@prisma/client':
specifier: 4.13.0
version: 4.13.0(prisma@4.13.0)
'@radix-ui/react-dropdown-menu':
specifier: ^2.0.4
version: 2.0.4(@types/react@18.0.28)(react-dom@18.2.0)(react@18.2.0)
@ -115,7 +118,7 @@ devDependencies:
specifier: ^8.1.2
version: 8.1.2
'@types/node':
specifier: ^18.11.18
specifier: ^18.15.3
version: 18.15.3
'@types/pg':
specifier: ^8.6.6
@ -153,14 +156,20 @@ devDependencies:
postcss:
specifier: ^8.4.20
version: 8.4.21
prisma:
specifier: ^4.13.0
version: 4.13.0
react-syntax-highlighter:
specifier: ^15.5.0
version: 15.5.0(react@18.2.0)
tailwindcss:
specifier: ^3.2.4
version: 3.2.7(postcss@8.4.21)
version: 3.2.7(postcss@8.4.21)(ts-node@10.9.1)
ts-node:
specifier: ^10.9.1
version: 10.9.1(@types/node@18.15.3)(typescript@4.9.5)
typescript:
specifier: ^4.9.4
specifier: ^4.9.5
version: 4.9.5
packages:
@ -458,6 +467,13 @@ packages:
to-fast-properties: 2.0.0
dev: false
/@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/trace-mapping': 0.3.9
dev: true
/@emotion/babel-plugin@11.10.6:
resolution: {integrity: sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==}
dependencies:
@ -650,7 +666,6 @@ packages:
/@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
dev: false
/@jridgewell/set-array@1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
@ -659,7 +674,6 @@ packages:
/@jridgewell/sourcemap-codec@1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
dev: false
/@jridgewell/trace-mapping@0.3.17:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
@ -668,6 +682,13 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14
dev: false
/@jridgewell/trace-mapping@0.3.9:
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@js-joda/core@5.5.3:
resolution: {integrity: sha512-7dqNYwG8gCt4hfg5PKgM7xLEcgSBcx/UgC92OMnhMmvAnq11QzDFPrxUkNR/u5kn17WWLZ8beZ4A3Qrz4pZcmQ==}
dev: true
@ -1001,6 +1022,28 @@ packages:
resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==}
dev: false
/@prisma/client@4.13.0(prisma@4.13.0):
resolution: {integrity: sha512-YaiiICcRB2hatxsbnfB66uWXjcRw3jsZdlAVxmx0cFcTc/Ad/sKdHCcWSnqyDX47vAewkjRFwiLwrOUjswVvmA==}
engines: {node: '>=14.17'}
requiresBuild: true
peerDependencies:
prisma: '*'
peerDependenciesMeta:
prisma:
optional: true
dependencies:
'@prisma/engines-version': 4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a
prisma: 4.13.0
dev: false
/@prisma/engines-version@4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a:
resolution: {integrity: sha512-fsQlbkhPJf08JOzKoyoD9atdUijuGBekwoOPZC3YOygXEml1MTtgXVpnUNchQlRSY82OQ6pSGQ9PxUe4arcSLQ==}
dev: false
/@prisma/engines@4.13.0:
resolution: {integrity: sha512-HrniowHRZXHuGT9XRgoXEaP2gJLXM5RMoItaY2PkjvuZ+iHc0Zjbm/302MB8YsPdWozAPHHn+jpFEcEn71OgPw==}
requiresBuild: true
/@radix-ui/number@1.0.0:
resolution: {integrity: sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA==}
dependencies:
@ -1448,7 +1491,7 @@ packages:
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: 3.2.7(postcss@8.4.21)
tailwindcss: 3.2.7(postcss@8.4.21)(ts-node@10.9.1)
dev: true
/@tediousjs/connection-string@0.4.2:
@ -1460,6 +1503,22 @@ packages:
engines: {node: '>= 10'}
dev: true
/@tsconfig/node10@1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
dev: true
/@tsconfig/node12@1.0.11:
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
dev: true
/@tsconfig/node14@1.0.3:
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
dev: true
/@tsconfig/node16@1.0.3:
resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
dev: true
/@types/debug@4.1.7:
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
dependencies:
@ -1668,6 +1727,11 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
/acorn-walk@8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
dev: true
/acorn@7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
@ -1725,6 +1789,10 @@ packages:
picomatch: 2.3.1
dev: true
/arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
/arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
dev: true
@ -2089,6 +2157,10 @@ packages:
yaml: 1.10.2
dev: false
/create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
dev: true
/cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
@ -2251,6 +2323,11 @@ packages:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
dev: true
/diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
dev: true
/diff@5.1.0:
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
engines: {node: '>=0.3.1'}
@ -3528,6 +3605,10 @@ packages:
engines: {node: '>=12'}
dev: true
/make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
dev: true
/markdown-table@3.0.3:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
dev: false
@ -4328,7 +4409,7 @@ packages:
postcss: 8.4.21
dev: true
/postcss-load-config@3.1.4(postcss@8.4.21):
/postcss-load-config@3.1.4(postcss@8.4.21)(ts-node@10.9.1):
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
engines: {node: '>= 10'}
peerDependencies:
@ -4342,6 +4423,7 @@ packages:
dependencies:
lilconfig: 2.1.0
postcss: 8.4.21
ts-node: 10.9.1(@types/node@18.15.3)(typescript@4.9.5)
yaml: 1.10.2
dev: true
@ -4419,6 +4501,14 @@ packages:
engines: {node: '>= 0.8.0'}
dev: true
/prisma@4.13.0:
resolution: {integrity: sha512-L9mqjnSmvWIRCYJ9mQkwCtj4+JDYYTdhoyo8hlsHNDXaZLh/b4hR0IoKIBbTKxZuyHQzLopb/+0Rvb69uGV7uA==}
engines: {node: '>=14.17'}
hasBin: true
requiresBuild: true
dependencies:
'@prisma/engines': 4.13.0
/prismjs@1.27.0:
resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==}
engines: {node: '>=6'}
@ -5137,7 +5227,7 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
/tailwindcss@3.2.7(postcss@8.4.21):
/tailwindcss@3.2.7(postcss@8.4.21)(ts-node@10.9.1):
resolution: {integrity: sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==}
engines: {node: '>=12.13.0'}
hasBin: true
@ -5161,7 +5251,7 @@ packages:
postcss: 8.4.21
postcss-import: 14.1.0(postcss@8.4.21)
postcss-js: 4.0.1(postcss@8.4.21)
postcss-load-config: 3.1.4(postcss@8.4.21)
postcss-load-config: 3.1.4(postcss@8.4.21)(ts-node@10.9.1)
postcss-nested: 6.0.0(postcss@8.4.21)
postcss-selector-parser: 6.0.11
postcss-value-parser: 4.2.0
@ -5233,6 +5323,37 @@ packages:
resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==}
dev: false
/ts-node@10.9.1(@types/node@18.15.3)(typescript@4.9.5):
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
'@types/node': 18.15.3
acorn: 8.8.2
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 4.9.5
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
/tsconfig-paths@3.14.2:
resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==}
dependencies:
@ -5459,6 +5580,10 @@ packages:
sade: 1.8.1
dev: false
/v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
dev: true
/v8-compile-cache@2.3.0:
resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==}
dev: true
@ -5545,6 +5670,11 @@ packages:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
/yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
dev: true
/zustand@4.3.6(react@18.2.0):
resolution: {integrity: sha512-6J5zDxjxLE+yukC2XZWf/IyWVKnXT9b9HUv09VJ/bwGCpKNcaTqp7Ws28Xr8jnbvnZcdRaidztAPsXFBIqufiw==}
engines: {node: '>=12.7.0'}

View File

@ -0,0 +1,33 @@
-- CreateTable
CREATE TABLE "Chat" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"ctx" JSONB NOT NULL,
CONSTRAINT "Chat_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Prompt" (
"id" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"q" TEXT NOT NULL,
"a" TEXT NOT NULL,
"upvote" BOOLEAN NOT NULL DEFAULT false,
"downvote" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "Prompt_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "Chat_createdAt_idx" ON "Chat"("createdAt");
-- CreateIndex
CREATE INDEX "Prompt_chatId_idx" ON "Prompt"("chatId");
-- CreateIndex
CREATE INDEX "Prompt_createdAt_idx" ON "Prompt"("createdAt");
-- AddForeignKey
ALTER TABLE "Prompt" ADD CONSTRAINT "Prompt_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"

34
prisma/schema.prisma Normal file
View File

@ -0,0 +1,34 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("TELEMETRY_DATABASE_URL")
}
model Chat {
id String @id @default(uuid())
createdAt DateTime @default(now())
ctx Json
prompts Prompt[]
@@index([createdAt])
}
model Prompt {
id String @id @default(uuid())
chat Chat @relation(fields: [chatId], references: [id])
chatId String
createdAt DateTime @default(now())
q String
a String
upvote Boolean @default(false)
downvote Boolean @default(false)
@@index([chatId])
@@index([createdAt])
}

70
prisma/seed.ts Normal file
View File

@ -0,0 +1,70 @@
import { PrismaClient, Prisma } from '@prisma/client'
import { v4 as uuidv4 } from "uuid";
const prisma = new PrismaClient()
const chatData: Prisma.ChatCreateInput[] = [
{
id: uuidv4(),
createdAt: new Date(),
ctx: {},
prompts: {
create: [
{
id: uuidv4(),
createdAt: new Date(),
q: "Hello",
a: "What can I help you with today?",
upvote: true,
downvote: false,
},
{
id: uuidv4(),
createdAt: new Date(),
q: "How are you?",
a: "Fine, thank you, and you?",
upvote: true,
downvote: false,
},
],
},
},
{
id: uuidv4(),
createdAt: new Date(),
ctx: {},
prompts: {
create: [
{
id: uuidv4(),
createdAt: new Date(),
q: "Tell me a joke",
a: "What do you call a fake noodle? An Impasta.",
upvote: true,
downvote: false,
},
],
},
},
]
async function main() {
console.log(`Start seeding ...`)
for (const c of chatData) {
const chat = await prisma.chat.create({
data: c,
})
console.log(`Created chat with id: ${chat.id}`)
}
console.log(`Seeding finished.`)
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})