diff --git a/.gitignore b/.gitignore index 761ad693..013f07e3 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,7 @@ Thumbs.db # typescript *.tsbuildinfo -next-env.d.ts \ No newline at end of file +next-env.d.ts + +# recnet-api specific +apps/**/pnpm-lock.yaml diff --git a/Procfile b/Procfile index f2b57968..b35fc393 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: pnpm nx deploy recnet-api +web: cd dist/apps/recnet-api && node main.js diff --git a/apps/recnet-api/buildspec.yml b/apps/recnet-api/buildspec.yml new file mode 100644 index 00000000..acb0ba1a --- /dev/null +++ b/apps/recnet-api/buildspec.yml @@ -0,0 +1,29 @@ +version: 0.2 + +phases: + install: + runtime-versions: + nodejs: 18 + commands: + - npm i -g pnpm + - pnpm i --frozen-lockfile + pre_build: + commands: + - pnpm nx clean recnet-api + - pnpm nx prisma:generate recnet-api + build: + commands: + - pnpm nx build recnet-api + post_build: + commands: + - rm -rf node_modules + - cp -R apps/recnet-api/prisma/ dist/apps/recnet-api/prisma + - cd dist/apps/recnet-api + - pnpm install --prod --frozen-lockfile + - pnpx prisma generate --schema=prisma/schema.prisma + +artifacts: + files: + - "dist/apps/recnet-api/**/*" + - "Procfile" + enable-symlinks: yes diff --git a/apps/recnet-api/prisma/migrations/20240306064817_init/migration.sql b/apps/recnet-api/prisma/migrations/20240306064817_init/migration.sql new file mode 100644 index 00000000..9d69e0b8 --- /dev/null +++ b/apps/recnet-api/prisma/migrations/20240306064817_init/migration.sql @@ -0,0 +1,102 @@ +-- CreateEnum +CREATE TYPE "Provider" AS ENUM ('FACEBOOK', 'GOOGLE'); + +-- CreateEnum +CREATE TYPE "Role" AS ENUM ('ADMIN', 'USER'); + +-- CreateTable +CREATE TABLE "User" ( + "id" VARCHAR(64) NOT NULL, + "provider" "Provider" NOT NULL, + "providerId" VARCHAR(128) NOT NULL, + "email" VARCHAR(128) NOT NULL, + "handle" VARCHAR(32) NOT NULL, + "displayName" VARCHAR(32) NOT NULL, + "inviteCode" VARCHAR(64), + "photoUrl" VARCHAR(256) NOT NULL, + "affiliation" VARCHAR(32), + "bio" TEXT, + "lastLoginAt" TIMESTAMP(3) NOT NULL, + "role" "Role" NOT NULL DEFAULT 'USER', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "FollowingRecord" ( + "userId" VARCHAR(64) NOT NULL, + "followerId" VARCHAR(64) NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "FollowingRecord_pkey" PRIMARY KEY ("userId","followerId") +); + +-- CreateTable +CREATE TABLE "Recommendation" ( + "id" VARCHAR(64) NOT NULL, + "userId" VARCHAR(64) NOT NULL, + "articleId" VARCHAR(64) NOT NULL, + "description" TEXT NOT NULL, + "cutoff" TIMESTAMP(3) NOT NULL, + "createAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Recommendation_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Article" ( + "id" VARCHAR(64) NOT NULL, + "doi" VARCHAR(32), + "title" VARCHAR(256) NOT NULL, + "author" VARCHAR(256) NOT NULL, + "link" VARCHAR(256) NOT NULL, + "year" SMALLINT NOT NULL, + "month" SMALLINT, + "isVerified" BOOLEAN NOT NULL DEFAULT false, + "createAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Article_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "InviteCode" ( + "id" SERIAL NOT NULL, + "code" VARCHAR(64) NOT NULL, + "ownerId" VARCHAR(64) NOT NULL, + "issuedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "usedById" VARCHAR(64), + "usedAt" TIMESTAMP(3), + + CONSTRAINT "InviteCode_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_handle_key" ON "User"("handle"); + +-- CreateIndex +CREATE UNIQUE INDEX "InviteCode_usedById_key" ON "InviteCode"("usedById"); + +-- AddForeignKey +ALTER TABLE "FollowingRecord" ADD CONSTRAINT "FollowingRecord_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "FollowingRecord" ADD CONSTRAINT "FollowingRecord_followerId_fkey" FOREIGN KEY ("followerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Recommendation" ADD CONSTRAINT "Recommendation_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Recommendation" ADD CONSTRAINT "Recommendation_articleId_fkey" FOREIGN KEY ("articleId") REFERENCES "Article"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "InviteCode" ADD CONSTRAINT "InviteCode_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "InviteCode" ADD CONSTRAINT "InviteCode_usedById_fkey" FOREIGN KEY ("usedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/recnet-api/prisma/migrations/migration_lock.toml b/apps/recnet-api/prisma/migrations/migration_lock.toml new file mode 100644 index 00000000..fbffa92c --- /dev/null +++ b/apps/recnet-api/prisma/migrations/migration_lock.toml @@ -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" \ No newline at end of file diff --git a/apps/recnet-api/prisma/schema.prisma b/apps/recnet-api/prisma/schema.prisma new file mode 100644 index 00000000..acb76369 --- /dev/null +++ b/apps/recnet-api/prisma/schema.prisma @@ -0,0 +1,99 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("PRISMA_DATABASE_URL") +} + +// Define enum types +enum Provider { + FACEBOOK + GOOGLE + // Add other providers here as needed +} + +enum Role { + ADMIN + USER +} + +model User { + id String @id @db.VarChar(64) @default(uuid()) // Primary key, UUID type + provider Provider // Enum type + providerId String @db.VarChar(128) + email String @db.VarChar(128) @unique + handle String @db.VarChar(32) @unique + displayName String @db.VarChar(32) + inviteCode String? @db.VarChar(64) + photoUrl String @db.VarChar(256) + affiliation String? @db.VarChar(32) + bio String? + lastLoginAt DateTime + role Role @default(USER) // Enum type + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + following FollowingRecord[] @relation("Following") + followers FollowingRecord[] @relation("Follower") + recommendations Recommendation[] + inviteCodeOwner InviteCode[] @relation("InviteCodeOwner") + inviteCodeUsed InviteCode? @relation("InviteCodeUsedBy") +} + +model FollowingRecord { + userId String @db.VarChar(64) + followerId String @db.VarChar(64) + createdAt DateTime + + @@id([userId, followerId]) + user User @relation("Following", fields: [userId], references: [id]) + follower User @relation("Follower", fields: [followerId], references: [id]) +} + +model Recommendation { + id String @id @db.VarChar(64) @default(uuid()) + userId String @db.VarChar(64) + articleId String @db.VarChar(64) + description String + cutoff DateTime + createAt DateTime @default(now()) + updateAt DateTime @default(now()) @updatedAt + + user User @relation(fields: [userId], references: [id]) // User who made the recommendation + article Article @relation(fields: [articleId], references: [id]) // Article being recommended +} + +model Article { + id String @id @db.VarChar(64) @default(uuid()) + doi String? @db.VarChar(32) + title String @db.VarChar(256) + author String @db.VarChar(256) + link String @db.VarChar(256) + year Int @db.SmallInt + month Int? @db.SmallInt + isVerified Boolean @default(false) + createAt DateTime @default(now()) + updateAt DateTime @default(now()) @updatedAt + + recommendations Recommendation[] +} + +model InviteCode { + id Int @id @default(autoincrement()) + code String @db.VarChar(64) + ownerId String @db.VarChar(64) + issuedAt DateTime @default(now()) + usedById String? @db.VarChar(64) @unique + usedAt DateTime? + + owner User @relation("InviteCodeOwner", fields: [ownerId], references: [id]) + usedBy User? @relation("InviteCodeUsedBy", fields: [usedById], references: [id]) +} diff --git a/apps/recnet-api/project.json b/apps/recnet-api/project.json index c66a40bc..ef045d2f 100644 --- a/apps/recnet-api/project.json +++ b/apps/recnet-api/project.json @@ -27,7 +27,7 @@ } } }, - "prebuild": { + "clean": { "executor": "nx:run-commands", "options": { "commands": ["rm -rf dist"], @@ -35,6 +35,16 @@ "forwardAllArgs": false } }, + "prisma:generate": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpx prisma generate --schema=apps/recnet-api/prisma/schema.prisma" + ], + "cwd": ".", + "forwardAllArgs": false + } + }, "deploy": { "executor": "nx:run-commands", "options": { @@ -42,6 +52,17 @@ "cwd": ".", "forwardAllArgs": false } + }, + "sync-package-lock": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "# TODO: delete this target once https://github.com/nrwl/nx/issues/21651 is fixed", + "cp pnpm-lock.yaml apps/recnet-api/" + ], + "cwd": ".", + "forwardAllArgs": false + } } }, "tags": [] diff --git a/apps/recnet-api/src/app.module.ts b/apps/recnet-api/src/app.module.ts index d348bb8a..c3cc1a89 100644 --- a/apps/recnet-api/src/app.module.ts +++ b/apps/recnet-api/src/app.module.ts @@ -1,9 +1,10 @@ import { Module } from "@nestjs/common"; import { HealthModule } from "./modules/health/health.module"; +import { UserModule } from "./modules/user/user.module"; @Module({ - imports: [HealthModule], + imports: [HealthModule, UserModule], controllers: [], providers: [], }) diff --git a/apps/recnet-api/src/database/prisma/prisma.connection.provider.ts b/apps/recnet-api/src/database/prisma/prisma.connection.provider.ts new file mode 100644 index 00000000..95fc05e1 --- /dev/null +++ b/apps/recnet-api/src/database/prisma/prisma.connection.provider.ts @@ -0,0 +1,53 @@ +import { execSync } from "child_process"; + +import { Injectable, OnModuleInit } from "@nestjs/common"; +import { PrismaClient } from "@prisma/client"; + +const postgresConfig = { + host: process.env.RDS_HOSTNAME, + port: parseInt(process.env.RDS_PORT, 10), + database: process.env.RDS_DB_NAME, + username: process.env.RDS_USERNAME, + password: process.env.RDS_PASSWORD, +}; + +@Injectable() +export class PrismaConnectionProvider + extends PrismaClient + implements OnModuleInit +{ + private prismaUrl: string; + + constructor() { + const connectionUrl = `postgresql://${postgresConfig.username}:${encodeURIComponent( + postgresConfig.password + )}@${postgresConfig.host}:${postgresConfig.port}/${ + postgresConfig.database + }?schema=recnet`; + + super({ + datasources: { + db: { + url: `${connectionUrl}&pool_timeout=60`, + }, + }, + }); + + this.prismaUrl = connectionUrl; + } + + async onModuleInit() { + await this.$connect(); + + const prismaSchema = process.env.PRISMA_SCHEMA || "prisma/schema.prisma"; + + if (process.env.DB_MIGRATE === "true") { + execSync( + `export PRISMA_DATABASE_URL=${this.prismaUrl} && pnpx prisma migrate deploy --schema=${prismaSchema}`, + { stdio: "inherit" } + ); + } + } +} + +export default PrismaConnectionProvider; diff --git a/apps/recnet-api/src/database/prisma/prisma.module.ts b/apps/recnet-api/src/database/prisma/prisma.module.ts new file mode 100644 index 00000000..3c5f1455 --- /dev/null +++ b/apps/recnet-api/src/database/prisma/prisma.module.ts @@ -0,0 +1,9 @@ +import { Module } from "@nestjs/common"; + +import PrismaConnectionProvider from "./prisma.connection.provider"; + +@Module({ + providers: [PrismaConnectionProvider], + exports: [PrismaConnectionProvider], +}) +export class PrismaModule {} diff --git a/apps/recnet-api/src/database/repository/db.repository.module.ts b/apps/recnet-api/src/database/repository/db.repository.module.ts new file mode 100644 index 00000000..c8e0db45 --- /dev/null +++ b/apps/recnet-api/src/database/repository/db.repository.module.ts @@ -0,0 +1,11 @@ +import { Module } from "@nestjs/common"; + +import UserRepository from "./user.repository"; +import { PrismaModule } from "../prisma/prisma.module"; + +@Module({ + imports: [PrismaModule], + providers: [UserRepository], + exports: [UserRepository], +}) +export class DbRepositoryModule {} diff --git a/apps/recnet-api/src/database/repository/user.repository.ts b/apps/recnet-api/src/database/repository/user.repository.ts new file mode 100644 index 00000000..57dedf79 --- /dev/null +++ b/apps/recnet-api/src/database/repository/user.repository.ts @@ -0,0 +1,15 @@ +import { Injectable } from "@nestjs/common"; +import { User } from "@prisma/client"; + +import PrismaConnectionProvider from "src/database/prisma/prisma.connection.provider"; + +@Injectable() +export default class UserRepository { + constructor(private readonly prisma: PrismaConnectionProvider) {} + + public async findByHandle(handle: string): Promise { + return this.prisma.user.findFirst({ + where: { handle }, + }); + } +} diff --git a/apps/recnet-api/src/modules/health/health.service.spec.ts b/apps/recnet-api/src/modules/health/health.service.spec.ts index 2b676210..8406e0f3 100644 --- a/apps/recnet-api/src/modules/health/health.service.spec.ts +++ b/apps/recnet-api/src/modules/health/health.service.spec.ts @@ -9,6 +9,6 @@ describe("HealthService", () => { it("should return status ok", async () => { const result = await healthService.getHealth(); - expect(result).toEqual({ status: "OK" }); + expect(result).toEqual({ status: "OK!" }); }); }); diff --git a/apps/recnet-api/src/modules/health/health.service.ts b/apps/recnet-api/src/modules/health/health.service.ts index 5c578ea1..d55b1062 100644 --- a/apps/recnet-api/src/modules/health/health.service.ts +++ b/apps/recnet-api/src/modules/health/health.service.ts @@ -3,6 +3,6 @@ import { Injectable } from "@nestjs/common"; @Injectable() export class HealthService { getHealth(): { status: string } { - return { status: "OK" }; + return { status: "OK!" }; } } diff --git a/apps/recnet-api/src/modules/user/user.controller.ts b/apps/recnet-api/src/modules/user/user.controller.ts new file mode 100644 index 00000000..c29bc02c --- /dev/null +++ b/apps/recnet-api/src/modules/user/user.controller.ts @@ -0,0 +1,16 @@ +import { Controller, Get, Param } from "@nestjs/common"; +import { User as UserModel } from "@prisma/client"; +import UserRepository from "src/database/repository/user.repository"; + +@Controller("user") +export class UserController { + constructor(private readonly userRepository: UserRepository) {} + + /* For development */ + @Get(":handle") + public async getUserByHandle( + @Param("handle") handle: string + ): Promise> { + return this.userRepository.findByHandle(handle); + } +} diff --git a/apps/recnet-api/src/modules/user/user.module.ts b/apps/recnet-api/src/modules/user/user.module.ts new file mode 100644 index 00000000..e35a4790 --- /dev/null +++ b/apps/recnet-api/src/modules/user/user.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; + +import { UserController } from "./user.controller"; +import { DbRepositoryModule } from "src/database/repository/db.repository.module"; + +@Module({ + controllers: [UserController], + imports: [DbRepositoryModule], +}) +export class UserModule {} diff --git a/apps/recnet-api/webpack.config.js b/apps/recnet-api/webpack.config.js index 37061d64..ecf70f0a 100644 --- a/apps/recnet-api/webpack.config.js +++ b/apps/recnet-api/webpack.config.js @@ -14,6 +14,7 @@ module.exports = { assets: ["./src/assets"], optimization: false, outputHashing: "none", + generatePackageJson: true, }), ], }; diff --git a/package.json b/package.json index bcdaad10..87a1824e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,9 @@ "name": "@recnet/source", "version": "0.0.0", "license": "MIT", - "scripts": {}, + "scripts": { + "postinstall": "npx nx run-many --target sync-package-lock --all" + }, "private": true, "dependencies": { "@hookform/resolvers": "^3.3.4", @@ -11,6 +13,7 @@ "@nestjs/platform-express": "^10.0.2", "@nestjs/swagger": "^7.3.0", "@next/third-parties": "^14.1.0", + "@prisma/client": "5.10.2", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "@radix-ui/themes": "^2.0.3", @@ -33,6 +36,7 @@ "react-email": "2.0.0", "react-hook-form": "^7.50.0", "react-loader-spinner": "^6.1.6", + "recnet-api": "link:dist/apps/recnet-api", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.0", "server-only": "^0.0.1", @@ -88,6 +92,7 @@ "nx": "18.0.4", "postcss": "8.4.21", "prettier": "^3.2.4", + "prisma": "^5.10.2", "tailwindcss": "^3.3.0", "ts-jest": "^29.1.0", "ts-node": "10.9.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d73406d3..c24dbf51 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - dependencies: '@hookform/resolvers': specifier: ^3.3.4 @@ -23,6 +19,9 @@ dependencies: '@next/third-parties': specifier: ^14.1.0 version: 14.1.0(next@14.1.0)(react@18.2.0) + '@prisma/client': + specifier: 5.10.2 + version: 5.10.2(prisma@5.10.2) '@radix-ui/react-icons': specifier: ^1.3.0 version: 1.3.0(react@18.2.0) @@ -89,6 +88,9 @@ dependencies: react-loader-spinner: specifier: ^6.1.6 version: 6.1.6(react-dom@18.2.0)(react@18.2.0) + recnet-api: + specifier: link:dist/apps/recnet-api + version: link:dist/apps/recnet-api reflect-metadata: specifier: ^0.1.13 version: 0.1.14 @@ -250,6 +252,9 @@ devDependencies: prettier: specifier: ^3.2.4 version: 3.2.5 + prisma: + specifier: ^5.10.2 + version: 5.10.2 tailwindcss: specifier: ^3.3.0 version: 3.4.1(ts-node@10.9.1) @@ -1885,7 +1890,6 @@ packages: cpu: [ppc64] os: [aix] requiresBuild: true - dev: false optional: true /@esbuild/android-arm64@0.19.11: @@ -1894,7 +1898,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-arm@0.19.11: @@ -1903,7 +1906,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-x64@0.19.11: @@ -1912,7 +1914,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/darwin-arm64@0.19.11: @@ -1921,7 +1922,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/darwin-x64@0.19.11: @@ -1930,7 +1930,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-arm64@0.19.11: @@ -1939,7 +1938,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-x64@0.19.11: @@ -1948,7 +1946,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm64@0.19.11: @@ -1957,7 +1954,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm@0.19.11: @@ -1966,7 +1962,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ia32@0.19.11: @@ -1975,7 +1970,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-loong64@0.19.11: @@ -1984,7 +1978,6 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-mips64el@0.19.11: @@ -1993,7 +1986,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ppc64@0.19.11: @@ -2002,7 +1994,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-riscv64@0.19.11: @@ -2011,7 +2002,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-s390x@0.19.11: @@ -2020,7 +2010,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-x64@0.19.11: @@ -2029,7 +2018,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/netbsd-x64@0.19.11: @@ -2038,7 +2026,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: false optional: true /@esbuild/openbsd-x64@0.19.11: @@ -2047,7 +2034,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: false optional: true /@esbuild/sunos-x64@0.19.11: @@ -2056,7 +2042,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: false optional: true /@esbuild/win32-arm64@0.19.11: @@ -2065,7 +2050,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-ia32@0.19.11: @@ -2074,7 +2058,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-x64@0.19.11: @@ -2083,7 +2066,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): @@ -4144,11 +4126,11 @@ packages: style-loader: 3.3.4(webpack@5.90.3) stylus: 0.59.0 stylus-loader: 7.1.3(stylus@0.59.0)(webpack@5.90.3) - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107)(webpack@5.90.3) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.101)(esbuild@0.19.11)(webpack@5.90.3) ts-loader: 9.5.1(typescript@5.3.3)(webpack@5.90.3) tsconfig-paths-webpack-plugin: 4.0.0 tslib: 2.6.2 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.90.3) webpack-node-externals: 3.0.0 webpack-subresource-integrity: 5.1.0(webpack@5.90.3) @@ -4221,6 +4203,46 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dev: true + /@prisma/client@5.10.2(prisma@5.10.2): + resolution: {integrity: sha512-ef49hzB2yJZCvM5gFHMxSFL9KYrIP9udpT5rYo0CsHD4P9IKj473MbhU1gjKKftiwWBTIyrt9jukprzZXazyag==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + prisma: 5.10.2 + dev: false + + /@prisma/debug@5.10.2: + resolution: {integrity: sha512-bkBOmH9dpEBbMKFJj8V+Zp8IZHIBjy3fSyhLhxj4FmKGb/UBSt9doyfA6k1UeUREsMJft7xgPYBbHSOYBr8XCA==} + + /@prisma/engines-version@5.10.0-34.5a9203d0590c951969e85a7d07215503f4672eb9: + resolution: {integrity: sha512-uCy/++3Jx/O3ufM+qv2H1L4tOemTNqcP/gyEVOlZqTpBvYJUe0tWtW0y3o2Ueq04mll4aM5X3f6ugQftOSLdFQ==} + + /@prisma/engines@5.10.2: + resolution: {integrity: sha512-HkSJvix6PW8YqEEt3zHfCYYJY69CXsNdhU+wna+4Y7EZ+AwzeupMnUThmvaDA7uqswiHkgm5/SZ6/4CStjaGmw==} + requiresBuild: true + dependencies: + '@prisma/debug': 5.10.2 + '@prisma/engines-version': 5.10.0-34.5a9203d0590c951969e85a7d07215503f4672eb9 + '@prisma/fetch-engine': 5.10.2 + '@prisma/get-platform': 5.10.2 + + /@prisma/fetch-engine@5.10.2: + resolution: {integrity: sha512-dSmXcqSt6DpTmMaLQ9K8ZKzVAMH3qwGCmYEZr/uVnzVhxRJ1EbT/w2MMwIdBNq1zT69Rvh0h75WMIi0mrIw7Hg==} + dependencies: + '@prisma/debug': 5.10.2 + '@prisma/engines-version': 5.10.0-34.5a9203d0590c951969e85a7d07215503f4672eb9 + '@prisma/get-platform': 5.10.2 + + /@prisma/get-platform@5.10.2: + resolution: {integrity: sha512-nqXP6vHiY2PIsebBAuDeWiUYg8h8mfjBckHh6Jezuwej0QJNnjDiOq30uesmg+JXxGk99nqyG3B7wpcOODzXvg==} + dependencies: + '@prisma/debug': 5.10.2 + /@protobufjs/aspromise@1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} requiresBuild: true @@ -6053,7 +6075,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@swc/core-darwin-arm64@1.3.107: @@ -6070,7 +6091,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@swc/core-darwin-x64@1.3.107: @@ -6087,7 +6107,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm-gnueabihf@1.3.107: @@ -6104,7 +6123,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm64-gnu@1.3.107: @@ -6121,7 +6139,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm64-musl@1.3.107: @@ -6138,7 +6155,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-x64-gnu@1.3.107: @@ -6155,7 +6171,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-x64-musl@1.3.107: @@ -6172,7 +6187,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-arm64-msvc@1.3.107: @@ -6189,7 +6203,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-ia32-msvc@1.3.107: @@ -6206,7 +6219,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-x64-msvc@1.3.107: @@ -6241,7 +6253,6 @@ packages: '@swc/core-win32-arm64-msvc': 1.3.101 '@swc/core-win32-ia32-msvc': 1.3.101 '@swc/core-win32-x64-msvc': 1.3.101 - dev: false /@swc/core@1.3.107(@swc/helpers@0.5.6): resolution: {integrity: sha512-zKhqDyFcTsyLIYK1iEmavljZnf4CCor5pF52UzLAz4B6Nu/4GLU+2LQVAf+oRHjusG39PTPjd2AlRT3f3QWfsQ==} @@ -6862,7 +6873,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.90.3) /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.90.3): @@ -6872,7 +6883,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.90.3) /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.90.3): @@ -6886,7 +6897,7 @@ packages: webpack-dev-server: optional: true dependencies: - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.90.3) /@xtuc/ieee754@1.2.0: @@ -7368,7 +7379,7 @@ packages: '@babel/core': 7.23.9 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /babel-plugin-const-enum@1.2.0(@babel/core@7.23.9): @@ -8073,7 +8084,7 @@ packages: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /core-js-compat@3.36.0: @@ -8207,7 +8218,7 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.35) postcss-value-parser: 4.2.0 semver: 7.6.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /css-minimizer-webpack-plugin@5.0.1(webpack@5.90.3): @@ -8241,7 +8252,7 @@ packages: postcss: 8.4.35 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /css-select@5.1.0: @@ -8965,7 +8976,6 @@ packages: '@esbuild/win32-arm64': 0.19.11 '@esbuild/win32-ia32': 0.19.11 '@esbuild/win32-x64': 0.19.11 - dev: false /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} @@ -9782,7 +9792,7 @@ packages: semver: 7.6.0 tapable: 2.2.1 typescript: 5.3.3 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /form-data@2.5.1: @@ -11615,7 +11625,7 @@ packages: dependencies: klona: 2.0.6 less: 4.1.3 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /less@4.1.3: @@ -11658,7 +11668,7 @@ packages: webpack-sources: optional: true dependencies: - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-sources: 3.2.3 dev: true @@ -12068,7 +12078,7 @@ packages: webpack: ^5.0.0 dependencies: schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /minimalistic-assert@1.0.1: @@ -13005,7 +13015,7 @@ packages: klona: 2.0.6 postcss: 8.4.21 semver: 7.6.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /postcss-merge-longhand@6.0.2(postcss@8.4.35): @@ -13377,6 +13387,14 @@ packages: react: 18.2.0 dev: false + /prisma@5.10.2: + resolution: {integrity: sha512-hqb/JMz9/kymRE25pMWCxkdyhbnIWrq+h7S6WysJpdnCvhstbJSNP/S6mScEcqiB8Qv2F+0R3yG+osRaWqZacQ==} + engines: {node: '>=16.13'} + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 5.10.2 + /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} @@ -13998,7 +14016,7 @@ packages: klona: 2.0.6 neo-async: 2.6.2 sass: 1.71.1 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /sass@1.71.1: @@ -14378,7 +14396,7 @@ packages: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.0.2 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /source-map-support@0.5.13: @@ -14676,7 +14694,7 @@ packages: peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /styled-components@6.1.8(react-dom@18.2.0)(react@18.2.0): @@ -14741,7 +14759,7 @@ packages: fast-glob: 3.3.2 normalize-path: 3.0.0 stylus: 0.59.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /stylus@0.59.0: @@ -14975,31 +14993,6 @@ packages: serialize-javascript: 6.0.2 terser: 5.28.1 webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) - dev: false - - /terser-webpack-plugin@5.3.10(@swc/core@1.3.107)(webpack@5.90.3): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.22 - '@swc/core': 1.3.107(@swc/helpers@0.5.6) - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.28.1 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) /terser@5.28.1: resolution: {integrity: sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==} @@ -15180,7 +15173,7 @@ packages: semver: 7.6.0 source-map: 0.7.4 typescript: 5.3.3 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /ts-node@10.9.1(@swc/core@1.3.107)(@types/node@20.11.20)(typescript@5.3.3): @@ -15477,7 +15470,7 @@ packages: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /url-parse@1.5.10: @@ -15640,7 +15633,7 @@ packages: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-merge: 5.10.0 /webpack-dev-middleware@5.3.3(webpack@5.90.3): @@ -15654,7 +15647,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.90.3): @@ -15698,7 +15691,7 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.90.3) webpack-dev-middleware: 5.3.3(webpack@5.90.3) ws: 8.16.0 @@ -15737,7 +15730,7 @@ packages: optional: true dependencies: typed-assert: 1.0.9 - webpack: 5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4) + webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /webpack@5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4): @@ -15779,47 +15772,6 @@ packages: - '@swc/core' - esbuild - uglify-js - dev: false - - /webpack@5.90.3(@swc/core@1.3.107)(webpack-cli@5.1.4): - resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.11.6 - '@webassemblyjs/wasm-edit': 1.11.6 - '@webassemblyjs/wasm-parser': 1.11.6 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.15.0 - es-module-lexer: 1.4.1 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107)(webpack@5.90.3) - watchpack: 2.4.0 - webpack-cli: 5.1.4(webpack@5.90.3) - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js /websocket-driver@0.7.4: resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} @@ -16112,3 +16064,7 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/tsconfig.base.json b/tsconfig.base.json index 2b91b0de..6042a7d9 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -7,7 +7,7 @@ "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, - "importHelpers": true, + "importHelpers": false, "target": "es2015", "module": "esnext", "lib": ["es2020", "dom"],