diff --git a/server/package.json b/server/package.json index 0661ea4..d705c3f 100644 --- a/server/package.json +++ b/server/package.json @@ -22,11 +22,14 @@ "dependencies": { "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", + "@nestjs/mapped-types": "*", "@nestjs/platform-express": "^10.0.0", + "@nestjs/swagger": "^7.1.10", "@prisma/client": "^5.1.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "jest-junit": "^16.0.0", + "meilisearch": "^0.34.1", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1" }, @@ -36,7 +39,7 @@ "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", "@types/jest": "^29.5.2", - "@types/node": "^20.3.1", + "@types/node": "^20.5.7", "@types/supertest": "^2.0.12", "@typescript-eslint/eslint-plugin": "^5.59.11", "@typescript-eslint/parser": "^5.59.11", @@ -52,7 +55,7 @@ "ts-loader": "^9.4.3", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", - "typescript": "^5.1.3" + "typescript": "^5.2.2" }, "jest": { "moduleFileExtensions": [ @@ -70,14 +73,26 @@ "**/*.{js,ts}" ], "coverageDirectory": "../test/coverage", - "coverageReporters": ["clover", "json", "lcov", "text"], + "coverageReporters": [ + "clover", + "json", + "lcov", + "text" + ], "testEnvironment": "node", "reporters": [ "default", - ["jest-junit", {"outputDirectory": "./test/result", "outputName": "report.xml"}] + [ + "jest-junit", + { + "outputDirectory": "./test/result", + "outputName": "report.xml" + } + ] ] }, "prisma": { - "schema": "./src/models/schema.prisma" + "schema": "./src/models/schema.prisma", + "seed": "ts-node src/models/seed.ts" } } diff --git a/server/src/api/jobs/job.dto.ts b/server/src/api/jobs/job.dto.ts new file mode 100644 index 0000000..fce5cea --- /dev/null +++ b/server/src/api/jobs/job.dto.ts @@ -0,0 +1,5 @@ +import { PartialType } from '@nestjs/mapped-types'; + +export class CreateJobDto {} + +export class UpdateJobDto extends PartialType(CreateJobDto) {} diff --git a/server/src/api/jobs/job.entity.ts b/server/src/api/jobs/job.entity.ts new file mode 100644 index 0000000..9195bb9 --- /dev/null +++ b/server/src/api/jobs/job.entity.ts @@ -0,0 +1,37 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Job, PaymentMethod, Schedule, Tag } from '@prisma/client'; + +export class JobEntity implements Job { + @ApiProperty() + id: number; + + @ApiProperty() + title: string; + + @ApiProperty() + type: string; + + @ApiProperty({ nullable: true }) + remarks: string; + + @ApiProperty() + personInChargeId: number; + + @ApiProperty() + customerId: number; + + @ApiProperty() + paymentMethod: PaymentMethod; + + @ApiProperty({ nullable: true }) + tags: Tag[] + + @ApiProperty({ nullable: true }) + schedules: Schedule[] + + @ApiProperty() + createdAt: Date; + + @ApiProperty() + updatedAt: Date; +} diff --git a/server/src/api/jobs/jobs.controller.spec.ts b/server/src/api/jobs/jobs.controller.spec.ts new file mode 100644 index 0000000..a196868 --- /dev/null +++ b/server/src/api/jobs/jobs.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { JobsController } from './jobs.controller'; +import { JobsService } from './jobs.service'; + +describe('JobsController', () => { + let controller: JobsController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [JobsController], + providers: [JobsService], + }).compile(); + + controller = module.get(JobsController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/server/src/api/jobs/jobs.controller.ts b/server/src/api/jobs/jobs.controller.ts new file mode 100644 index 0000000..a0da5cf --- /dev/null +++ b/server/src/api/jobs/jobs.controller.ts @@ -0,0 +1,20 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { ApiQuery, ApiTags } from '@nestjs/swagger'; +import { JobsService } from './jobs.service'; + +@ApiTags('jobs') +@Controller('jobs') +export class JobsController { + constructor(private readonly jobsService: JobsService) {} + + @ApiQuery({ + name: 'search', + required: false, + type: String, + description: "Optional search keyword" + }) + @Get() + async findAll(@Query('search') search: string) { + return await this.jobsService.findAll(search); + } +} diff --git a/server/src/api/jobs/jobs.module.ts b/server/src/api/jobs/jobs.module.ts new file mode 100644 index 0000000..11fc6c3 --- /dev/null +++ b/server/src/api/jobs/jobs.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { PrismaService } from 'src/database/connection.service'; +import { SearchService } from 'src/services/externalService/search.service'; +import { JobsController } from './jobs.controller'; +import { JobsService } from './jobs.service'; + +@Module({ + controllers: [JobsController], + providers: [JobsService, PrismaService, SearchService], +}) +export class JobsModule {} diff --git a/server/src/api/jobs/jobs.service.spec.ts b/server/src/api/jobs/jobs.service.spec.ts new file mode 100644 index 0000000..b0f3d2c --- /dev/null +++ b/server/src/api/jobs/jobs.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { JobsService } from './jobs.service'; + +describe('JobsService', () => { + let service: JobsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [JobsService], + }).compile(); + + service = module.get(JobsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/api/jobs/jobs.service.ts b/server/src/api/jobs/jobs.service.ts new file mode 100644 index 0000000..be7aa2b --- /dev/null +++ b/server/src/api/jobs/jobs.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@nestjs/common'; +import { Job } from '@prisma/client'; +import { PrismaService } from 'src/database/connection.service'; +import { SearchService } from 'src/services/externalService/search.service'; + +@Injectable() +export class JobsService { + constructor( + private prisma: PrismaService, + private searchService: SearchService + ){} + + async findAll(search?: string): Promise { + let jobs: Job[] = []; + + jobs = await this.prisma.job.findMany(); + + if (search) { + await this.searchService.addDocuments(jobs); + const results = await this.searchService.search(search); + + console.log(results); + + const jobIds = results.hits.map(hit => parseInt(hit.id)); + jobs = jobs.filter(job => jobIds.includes(job.id)); + } + + return jobs; + } +} diff --git a/server/src/api/sample/sample.entities.ts b/server/src/api/sample/sample.entities.ts index 43baf1a..e4be7bf 100644 --- a/server/src/api/sample/sample.entities.ts +++ b/server/src/api/sample/sample.entities.ts @@ -1,7 +1,7 @@ -import { SampleUser } from '@prisma/client'; +// import { SampleUser } from '@prisma/client'; -export class SampleUserEntity implements SampleUser { - id: number; - name: string; - email: string; -} +// export class SampleUserEntity implements SampleUser { +// id: number; +// name: string; +// email: string; +// } diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 001246b..8cd97ab 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,10 +1,13 @@ import { Module } from '@nestjs/common'; +import { JobsController } from './api/jobs/jobs.controller'; +import { JobsModule } from './api/jobs/jobs.module'; +import { JobsService } from './api/jobs/jobs.service'; import { DatabaseModule } from './database/database.module'; -import { SampleController } from './api/sample/sample.controller'; +import { SearchService } from './services/externalService/search.service'; @Module({ - imports: [DatabaseModule], - controllers: [SampleController], - providers: [], + imports: [DatabaseModule, JobsModule], + controllers: [JobsController], + providers: [JobsService, SearchService], }) export class AppModule {} diff --git a/server/src/main.ts b/server/src/main.ts index 8e348dc..8047b12 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,8 +1,19 @@ import { NestFactory } from '@nestjs/core'; +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); + + const config = new DocumentBuilder() + .setTitle('Sim-JMS') + .setDescription('This is the API documentation for sim-jms') + .setVersion('1.0') + .build(); + + const document = SwaggerModule.createDocument(app, config); + SwaggerModule.setup('api', app, document); + await app.listen(4000); } bootstrap(); diff --git a/server/src/models/data/customers.ts b/server/src/models/data/customers.ts new file mode 100644 index 0000000..ba81656 --- /dev/null +++ b/server/src/models/data/customers.ts @@ -0,0 +1,82 @@ +export const customers = [ + { + id: 1, + firstName: "John", + lastName: "Doe", + email: "johndoe@gmail.com", + contact: "+639876543210", + address: "8741 VonRueden Highway, West Virginia", + }, + { + id: 2, + firstName: "Jane", + lastName: "Smith", + email: "janesmith@gmail.com", + contact: "+630123546788", + address: "King Apt 906, Tennessee", + }, + { + id: 3, + firstName: "Michael", + lastName: "Smith", + email: "michaelsmith@gmail.com", + contact: "+63444543210", + address: "986 Senger Drive, Lake Aliza", + }, + { + id: 4, + firstName: "Ana", + lastName: "Rogers", + email: "anarogers@gmail.com", + contact: "+639277543210", + address: "580 Stroman Heights, Davismouth", + }, + { + id: 5, + firstName: "Kelly", + lastName: "Nier", + email: "kellynier@gmail.com", + contact: "+639123746890", + address: "55934 Veronica Knoll, South Dakota", + }, + { + id: 6, + firstName: "Curtis", + lastName: "Hegmann", + email: "curtishegmann@gmail.com", + contact: "+639277543321", + address: "123 Murray Village, Nebraska", + }, + { + id: 7, + firstName: "Hassan", + lastName: "Connel", + email: "hassanconnel@gmail.com", + contact: "+639274343321", + address: "389 Larkin Circle, Abbotport", + }, + { + id: 8, + firstName: "Ray", + lastName: "Summers", + email: "raysummers@gmail.com", + contact: "+639200343321", + address: "5327 Constance Harbors, West Marina", + }, + { + id: 9, + firstName: "Alice", + lastName: "Hills", + email: "alicehills@gmail.com", + contact: "+63231567891", + address: "544 Bertrand Row, Kansas", + }, + { + id: 10, + firstName: "Sheila", + lastName: "Comb", + email: "sheilacomb@gmail.com", + contact: "+63231567800", + address: "2029 Kuhlman Expressway, West Virginia", + }, +] diff --git a/server/src/models/data/jobs.ts b/server/src/models/data/jobs.ts new file mode 100644 index 0000000..670ce26 --- /dev/null +++ b/server/src/models/data/jobs.ts @@ -0,0 +1,84 @@ +import { PaymentMethod } from '@prisma/client'; + +export const jobs = [ + { + id: 1, + title: "Water Leak Repair", + type: "Type A", + personInChargeId: 1, + customerId: 1, + paymentMethod: PaymentMethod.CASH + }, + { + id: 2, + title: "New Air Conditioner Installation", + type: "Type B", + personInChargeId: 1, + customerId: 2, + paymentMethod: PaymentMethod.CASH + }, + { + id: 3, + title: "Drainage System Inspection", + type: "Type A", + personInChargeId: 1, + customerId: 3, + paymentMethod: PaymentMethod.CASH + }, + { + id: 4, + title: "New Heater Installation", + type: "Type A", + personInChargeId: 2, + customerId: 4, + paymentMethod: PaymentMethod.CASH + }, + { + id: 5, + title: "Air Duct Inspection", + type: "Type A", + personInChargeId: 2, + customerId: 5, + paymentMethod: PaymentMethod.CASH + }, + { + id: 6, + title: "Air Conditioner Cleaning", + type: "Type A", + personInChargeId: 2, + customerId: 6, + paymentMethod: PaymentMethod.CASH + }, + { + id: 7, + title: "Gutter Cleaning and Repair", + type: "Type A", + personInChargeId: 2, + customerId: 7, + paymentMethod: PaymentMethod.CASH + }, + { + id: 8, + title: "Plumbing Fixture Installation", + type: "Type A", + personInChargeId: 1, + customerId: 8, + paymentMethod: PaymentMethod.CASH + }, + { + id: 9, + title: "Interior Flooring Inspection", + type: "Type A", + personInChargeId: 1, + customerId: 9, + paymentMethod: PaymentMethod.CASH + }, + { + id: 10, + title: "Air Duct Cleaning", + type: "Type A", + personInChargeId: 2, + customerId: 10, + paymentMethod: PaymentMethod.CASH + }, +] diff --git a/server/src/models/data/users.ts b/server/src/models/data/users.ts new file mode 100644 index 0000000..3ce3dcd --- /dev/null +++ b/server/src/models/data/users.ts @@ -0,0 +1,14 @@ +export const users = [ + { + id: 1, + firstName: "Wiliam", + lastName: "Byers", + email: "williambyers@gmail.com", + }, + { + id: 2, + firstName: "Connie", + lastName: "Lee", + email: "connielee@gmail.com", + } +] diff --git a/server/src/models/migrations/20230830060051_init/migration.sql b/server/src/models/migrations/20230830060051_init/migration.sql new file mode 100644 index 0000000..393682a --- /dev/null +++ b/server/src/models/migrations/20230830060051_init/migration.sql @@ -0,0 +1,77 @@ +-- CreateEnum +CREATE TYPE "Role" AS ENUM ('USER', 'ADMIN'); + +-- CreateEnum +CREATE TYPE "Tag" AS ENUM ('TAG_A', 'TAG_B', 'TAG_C'); + +-- CreateEnum +CREATE TYPE "PaymentMethod" AS ENUM ('CASH', 'CARD', 'BANK_TRANSFER'); + +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "firstName" TEXT NOT NULL, + "lastName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "role" "Role" NOT NULL DEFAULT 'USER', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Job" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "type" TEXT NOT NULL, + "remarks" TEXT, + "personInChargeId" INTEGER NOT NULL, + "customerId" INTEGER NOT NULL, + "paymentMethod" "PaymentMethod" NOT NULL, + "tags" "Tag"[], + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Job_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Customer" ( + "id" SERIAL NOT NULL, + "firstName" TEXT NOT NULL, + "lastName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "contact" TEXT NOT NULL, + "address" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Customer_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Schedule" ( + "id" SERIAL NOT NULL, + "startDate" TIMESTAMP(3) NOT NULL, + "startTime" TIMESTAMP(3) NOT NULL, + "endDate" TIMESTAMP(3) NOT NULL, + "endTime" TIMESTAMP(3) NOT NULL, + "jobId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Schedule_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Job_customerId_key" ON "Job"("customerId"); + +-- AddForeignKey +ALTER TABLE "Job" ADD CONSTRAINT "Job_personInChargeId_fkey" FOREIGN KEY ("personInChargeId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Job" ADD CONSTRAINT "Job_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_jobId_fkey" FOREIGN KEY ("jobId") REFERENCES "Job"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/models/migrations/20230830081245_update_nullable_field/migration.sql b/server/src/models/migrations/20230830081245_update_nullable_field/migration.sql new file mode 100644 index 0000000..f65dd91 --- /dev/null +++ b/server/src/models/migrations/20230830081245_update_nullable_field/migration.sql @@ -0,0 +1,11 @@ +-- AlterTable +ALTER TABLE "Customer" ALTER COLUMN "updatedAt" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "Job" ALTER COLUMN "updatedAt" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "Schedule" ALTER COLUMN "updatedAt" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "updatedAt" DROP NOT NULL; diff --git a/server/src/models/migrations/20230830083652_update_default/migration.sql b/server/src/models/migrations/20230830083652_update_default/migration.sql new file mode 100644 index 0000000..6e4e05d --- /dev/null +++ b/server/src/models/migrations/20230830083652_update_default/migration.sql @@ -0,0 +1,24 @@ +/* + Warnings: + + - Made the column `updatedAt` on table `Customer` required. This step will fail if there are existing NULL values in that column. + - Made the column `updatedAt` on table `Job` required. This step will fail if there are existing NULL values in that column. + - Made the column `updatedAt` on table `Schedule` required. This step will fail if there are existing NULL values in that column. + - Made the column `updatedAt` on table `User` required. This step will fail if there are existing NULL values in that column. + +*/ +-- AlterTable +ALTER TABLE "Customer" ALTER COLUMN "updatedAt" SET NOT NULL, +ALTER COLUMN "updatedAt" SET DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "Job" ALTER COLUMN "updatedAt" SET NOT NULL, +ALTER COLUMN "updatedAt" SET DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "Schedule" ALTER COLUMN "updatedAt" SET NOT NULL, +ALTER COLUMN "updatedAt" SET DEFAULT CURRENT_TIMESTAMP; + +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "updatedAt" SET NOT NULL, +ALTER COLUMN "updatedAt" SET DEFAULT CURRENT_TIMESTAMP; diff --git a/server/src/models/migrations/migration_lock.toml b/server/src/models/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/server/src/models/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/server/src/models/schema.prisma b/server/src/models/schema.prisma index 108018e..f21de02 100644 --- a/server/src/models/schema.prisma +++ b/server/src/models/schema.prisma @@ -10,9 +10,70 @@ datasource db { url = env("DATABASE_URL") } -// Temporary model so that Prisma Client can initialize -model SampleUser { - id Int @id @default(autoincrement()) - name String - email String @unique +model User { + id Int @id @default(autoincrement()) + firstName String + lastName String + email String + role Role @default(USER) + jobs Job[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) +} + +model Job { + id Int @id @default(autoincrement()) + title String + type String + remarks String? + personInCharge User @relation(fields: [personInChargeId], references: [id]) + personInChargeId Int + customer Customer @relation(fields: [customerId], references: [id]) + customerId Int @unique + paymentMethod PaymentMethod + tags Tag[] + schedules Schedule[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) +} + +model Customer { + id Int @id @default(autoincrement()) + firstName String + lastName String + email String + contact String + address String + job Job? + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) +} + +model Schedule { + id Int @id @default(autoincrement()) + startDate DateTime + startTime DateTime + endDate DateTime + endTime DateTime + job Job @relation(fields: [jobId], references: [id]) + jobId Int + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) +} + +enum Role { + USER + ADMIN +} + +enum Tag { + TAG_A + TAG_B + TAG_C +} + +enum PaymentMethod { + CASH + CARD + BANK_TRANSFER } diff --git a/server/src/models/seed.ts b/server/src/models/seed.ts new file mode 100644 index 0000000..662b4d0 --- /dev/null +++ b/server/src/models/seed.ts @@ -0,0 +1,35 @@ +import { PrismaClient } from '@prisma/client'; +import { customers } from './data/customers'; +import { jobs } from './data/jobs'; +import { users } from './data/users'; + +const prisma = new PrismaClient(); + +const load = async () => { + try { + await prisma.$transaction([ + prisma.job.deleteMany(), + prisma.user.deleteMany(), + prisma.customer.deleteMany(), + + prisma.user.createMany({ + data: users + }), + + prisma.customer.createMany({ + data: customers + }), + + prisma.job.createMany({ + data: jobs + }), + ]); + } catch (error) { + console.log('Error seeding database'); + throw error; + } finally { + await prisma.$disconnect(); + } +} + +load(); diff --git a/server/src/services/externalService/search.service.ts b/server/src/services/externalService/search.service.ts new file mode 100644 index 0000000..aa5fe6d --- /dev/null +++ b/server/src/services/externalService/search.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@nestjs/common'; +import { Job } from '@prisma/client'; +import { EnqueuedTask, Index, MeiliSearch, SearchResponse } from 'meilisearch'; + +@Injectable() +export class SearchService { + private SearchClient: MeiliSearch; + + constructor() { + this.SearchClient = new MeiliSearch({ + host: 'http://host.docker.internal:7700', + }) + } + + private getIndex(): Index { + return this.SearchClient.index('jobs'); + } + + async addDocuments(docs: Job[]): Promise { + const index = this.getIndex(); + try { + return await index.addDocuments(docs); + } catch(e) { + console.log('Error adding documents'); + throw e; + } + } + + async search(query: string): Promise { + const index = this.getIndex(); + + return await index.searchGet( + query, + { + attributesToHighlight: ['title'], + attributesToSearchOn: ['title'], + attributesToRetrieve: ['*'], + } + ); + } +} \ No newline at end of file diff --git a/server/yarn.lock b/server/yarn.lock index d91c693..ae59d85 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -731,6 +731,11 @@ path-to-regexp "3.2.0" tslib "2.6.1" +"@nestjs/mapped-types@*", "@nestjs/mapped-types@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.2.tgz#c8a090a8d22145b85ed977414c158534210f2e4f" + integrity sha512-V0izw6tWs6fTp9+KiiPUbGHWALy563Frn8X6Bm87ANLRuE46iuBMD5acKBDP5lKL/75QFvrzSJT7HkCbB0jTpg== + "@nestjs/platform-express@^10.0.0": version "10.1.3" resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.1.3.tgz#d1f644e86f2bc45c7529b9eed7669613f4392e99" @@ -753,6 +758,17 @@ jsonc-parser "3.2.0" pluralize "8.0.0" +"@nestjs/swagger@^7.1.10": + version "7.1.10" + resolved "https://registry.yarnpkg.com/@nestjs/swagger/-/swagger-7.1.10.tgz#955deb9c428fae779d2988a0d24a55977a7be11d" + integrity sha512-qreCcxgHFyFX1mOfK36pxiziy4xoa/XcxC0h4Zr9yH54WuqMqO9aaNFhFyuQ1iyd/3YBVQB21Un4gQnh9iGm0w== + dependencies: + "@nestjs/mapped-types" "2.0.2" + js-yaml "4.1.0" + lodash "4.17.21" + path-to-regexp "3.2.0" + swagger-ui-dist "5.4.2" + "@nestjs/testing@^10.0.0": version "10.1.3" resolved "https://registry.yarnpkg.com/@nestjs/testing/-/testing-10.1.3.tgz#596a1dc580373b3b0b070ac73bf70e45f80197dd" @@ -791,16 +807,16 @@ node-fetch "^2.6.1" "@prisma/client@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.1.1.tgz#ea2b0c8599bdb3f86d92e8df46fba795a744db01" - integrity sha512-fxcCeK5pMQGcgCqCrWsi+I2rpIbk0rAhdrN+ke7f34tIrgPwA68ensrpin+9+fZvuV2OtzHmuipwduSY6HswdA== + version "5.2.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.2.0.tgz#cbfdd440614b38736563a7999f39922fcde0ed50" + integrity sha512-AiTjJwR4J5Rh6Z/9ZKrBBLel3/5DzUNntMohOy7yObVnVoTNVFi2kvpLZlFuKO50d7yDspOtW6XBpiAd0BVXbQ== dependencies: - "@prisma/engines-version" "5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e" + "@prisma/engines-version" "5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f" -"@prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e": - version "5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e.tgz#2e8a1f098ec09452dbe00923b24f582f95d1747c" - integrity sha512-owZqbY/wucbr65bXJ/ljrHPgQU5xXTSkmcE/JcbqE1kusuAXV/TLN3/exmz21SZ5rJ7WDkyk70J2G/n68iogbQ== +"@prisma/engines-version@5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f": + version "5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f.tgz#11366e7ff031c908debf4983248d40046016de37" + integrity sha512-jsnKT5JIDIE01lAeCj2ghY9IwxkedhKNvxQeoyLs6dr4ZXynetD0vTy7u6wMJt8vVPv8I5DPy/I4CFaoXAgbtg== "@prisma/engines@5.1.1": version "5.1.1" @@ -994,11 +1010,16 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== -"@types/node@*", "@types/node@^20.3.1": +"@types/node@*": version "20.4.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.9.tgz#c7164e0f8d3f12dfae336af0b1f7fdec8c6b204f" integrity sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ== +"@types/node@^20.5.7": + version "20.5.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" + integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -1922,6 +1943,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.6: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3290,6 +3318,13 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -3298,13 +3333,6 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3406,7 +3434,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.21: +lodash@4.17.21, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -3474,6 +3502,13 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +meilisearch@^0.34.1: + version "0.34.1" + resolved "https://registry.yarnpkg.com/meilisearch/-/meilisearch-0.34.1.tgz#9d003a81280a95394e52e2116e8244e3bca54555" + integrity sha512-7mrLp88JfrbvhAMhOjNPzHGd2iCLHgzNhkveMxppMOToMLQw4Ygof4ksQ9uFi7SKq3UwEhIoMoFT1rUHLD3vWQ== + dependencies: + cross-fetch "^3.1.6" + memfs@^3.4.1: version "3.6.0" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" @@ -3649,6 +3684,13 @@ node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4406,6 +4448,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swagger-ui-dist@5.4.2: + version "5.4.2" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz#ff7b936bdfc84673a1823a0f05f3a933ba7ccd4c" + integrity sha512-vT5QxP/NOr9m4gLZl+SpavWI3M9Fdh30+Sdw9rEtZbkqNmNNEPhjXas2xTD9rsJYYdLzAiMfwXvtooWH3xbLJA== + symbol-observable@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" @@ -4608,11 +4655,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typescript@5.1.6, typescript@^5.1.3: +typescript@5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + uid@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/uid/-/uid-2.0.2.tgz#4b5782abf0f2feeefc00fa88006b2b3b7af3e3b9"