Enhance NestJS application with SWC builder configuration, add @nestjs/devtools-integration for development support, and refactor various components for improved readability. Update package dependencies and streamline import statements across multiple files.
This commit is contained in:
@@ -6,6 +6,14 @@
|
||||
"compilerOptions": {
|
||||
"watchAssets": true,
|
||||
"deleteOutDir": true,
|
||||
"builder": {
|
||||
"type": "swc",
|
||||
"options": {
|
||||
"copyFiles": true,
|
||||
"includeDotfiles": true
|
||||
}
|
||||
},
|
||||
"typeCheck": true,
|
||||
"assets": [
|
||||
{
|
||||
"include": "**/*.pug",
|
||||
|
||||
1561
package-lock.json
generated
1561
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -44,6 +44,7 @@
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/config": "^3.2.3",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/devtools-integration": "^0.1.6",
|
||||
"@nestjs/event-emitter": "^2.1.1",
|
||||
"@nestjs/graphql": "^12.2.0",
|
||||
"@nestjs/jwt": "^10.2.0",
|
||||
@@ -141,19 +142,13 @@
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"collectCoverageFrom": ["**/*.(t|j)s"],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
},
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Param,
|
||||
Body,
|
||||
Headers,
|
||||
} from '@nestjs/common'
|
||||
import { Controller, Get, Post, Put, Delete, Param, Body, Headers } from '@nestjs/common'
|
||||
import { ClerkService } from './clerk.service'
|
||||
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'
|
||||
@ApiTags('Clerk')
|
||||
@@ -18,7 +9,7 @@ export class ClerkController {
|
||||
@Post('webhook')
|
||||
@ApiOperation({ summary: 'Clerk Webhook' })
|
||||
@ApiResponse({ status: 200, description: 'Webhook created successfully' })
|
||||
webhook(@Headers() headers: Headers, @Body() body: any) {
|
||||
webhook(@Body() body: any) {
|
||||
return this.clerkService.webhook(body)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
export enum DocumentEvent {
|
||||
CREATED = 'document_created',
|
||||
CHANGED = 'document_changed',
|
||||
DELETED = 'document_deleted',
|
||||
SAVED = 'document_saved',
|
||||
PAGE_CREATED = 'document_page_created',
|
||||
PAGE_DELETED = 'document_page_deleted',
|
||||
DOCUMENT_CREATED = 'document_created',
|
||||
ACTIVE_DOCUMENT_ID_CHANGED = 'document_active_document_id_changed',
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common'
|
||||
import {
|
||||
Pothos,
|
||||
PothosRef,
|
||||
PothosSchema,
|
||||
SchemaBuilderToken,
|
||||
} from '@smatch-corp/nestjs-pothos'
|
||||
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||
import { Builder, SchemaContext } from '../Graphql/graphql.builder'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { DocumentEvent } from './document.event'
|
||||
@@ -99,10 +94,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
...query,
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
where: {
|
||||
OR: [
|
||||
{ ownerId: ctx.http.me.id },
|
||||
{ collaborators: { some: { userId: ctx.http.me.id } } },
|
||||
],
|
||||
OR: [{ ownerId: ctx.http.me.id }, { collaborators: { some: { userId: ctx.http.me.id } } }],
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -138,11 +130,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (ctx.isSubscription) throw new Error('Not allowed')
|
||||
const userId = ctx.http?.me?.id
|
||||
if (!userId) throw new Error('User not found')
|
||||
const fileUrl = await this.minio.getFileUrl(
|
||||
'document',
|
||||
'document',
|
||||
'document',
|
||||
)
|
||||
const fileUrl = await this.minio.getFileUrl('document', 'document', 'document')
|
||||
if (!fileUrl) throw new Error('File not found')
|
||||
const document = await this.prisma.document.create({
|
||||
...query,
|
||||
@@ -211,10 +199,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
delta,
|
||||
senderId: ctx.http?.me?.id,
|
||||
}
|
||||
ctx.http.pubSub.publish(
|
||||
`${DocumentEvent.CHANGED}.${args.documentId}`,
|
||||
documentDelta,
|
||||
)
|
||||
ctx.http.pubSub.publish(`${DocumentEvent.CHANGED}.${args.documentId}`, documentDelta)
|
||||
return documentDelta
|
||||
},
|
||||
}),
|
||||
@@ -275,9 +260,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (
|
||||
document.ownerId !== ctx.http?.me?.id &&
|
||||
!document.isPublic &&
|
||||
!document.collaborators.some(
|
||||
(c) => c.userId === ctx.http?.me?.id && c.writable,
|
||||
)
|
||||
!document.collaborators.some((c) => c.userId === ctx.http?.me?.id && c.writable)
|
||||
)
|
||||
throw new Error('User is not owner or collaborator of document')
|
||||
return await this.prisma.document.update({
|
||||
@@ -302,8 +285,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
where: { id: args.documentId },
|
||||
})
|
||||
if (!document) throw new Error('Document not found')
|
||||
if (document.ownerId !== ctx.http?.me?.id)
|
||||
throw new Error('User is not owner of document')
|
||||
if (document.ownerId !== ctx.http?.me?.id) throw new Error('User is not owner of document')
|
||||
return await this.prisma.documentCollaborator.create({
|
||||
data: {
|
||||
documentId: args.documentId,
|
||||
@@ -342,17 +324,16 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (!document.isPublic) {
|
||||
if (
|
||||
document.ownerId !== ctx.websocket?.me?.id &&
|
||||
!document.collaborators.some(
|
||||
(c) => c.userId === ctx.websocket?.me?.id && c.writable,
|
||||
)
|
||||
!document.collaborators.some((c) => c.userId === ctx.websocket?.me?.id && c.writable)
|
||||
)
|
||||
throw new Error('User is not owner or collaborator of document')
|
||||
}
|
||||
return pubSub.asyncIterator([
|
||||
`${DocumentEvent.CHANGED}.${documentId}`,
|
||||
`${DocumentEvent.CREATED}.${documentId}`,
|
||||
`${DocumentEvent.DELETED}.${documentId}`,
|
||||
`${DocumentEvent.SAVED}.${documentId}`,
|
||||
`${DocumentEvent.PAGE_CREATED}.${documentId}`,
|
||||
`${DocumentEvent.PAGE_DELETED}.${documentId}`,
|
||||
`${DocumentEvent.ACTIVE_DOCUMENT_ID_CHANGED}.${documentId}`,
|
||||
]) as unknown as AsyncIterable<DocumentDelta>
|
||||
},
|
||||
|
||||
@@ -3,64 +3,12 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'
|
||||
import Delta, { Op } from 'quill-delta'
|
||||
import { MinioService } from '../Minio/minio.service'
|
||||
import { DocumentDelta } from './document.type'
|
||||
import { JSDOM } from 'jsdom'
|
||||
import { Logger } from '@nestjs/common'
|
||||
import { PrismaService } from 'src/Prisma/prisma.service'
|
||||
@Injectable()
|
||||
export class DocumentService {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
private quill: any
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly minio: MinioService,
|
||||
public document: JSDOM,
|
||||
) {
|
||||
;(async () => {
|
||||
await this.loadQuill()
|
||||
})()
|
||||
}
|
||||
|
||||
private async loadQuill() {
|
||||
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
||||
const { window } = new JSDOM('<!doctype html><html><body></body></html>')
|
||||
const { navigator } = window
|
||||
const { Node } = window
|
||||
global.window = window
|
||||
global.document = window.document
|
||||
global.navigator = navigator
|
||||
global.Node = Node
|
||||
}
|
||||
|
||||
const { default: Quill } = await import('quill')
|
||||
this.quill = Quill
|
||||
}
|
||||
// TODO: maybe never do :)
|
||||
async handleOnChange(documentId: string, delta: DocumentDelta) {}
|
||||
|
||||
async handleOnSave(documentId: string) {}
|
||||
|
||||
async handleOnSync(documentId: string) {}
|
||||
|
||||
async requestSync(documentId: string, page?: number) {
|
||||
// using pubsub to broadcast to all clients
|
||||
// this.pubSub.publish(`document:sync:${documentId}`, {
|
||||
// documentId,
|
||||
// page,
|
||||
// })
|
||||
}
|
||||
|
||||
async clientRequestSave(documentId: string) {
|
||||
// using pubsub to broadcast to all clients
|
||||
// this.pubSub.publish(`document:save:${documentId}`, {
|
||||
// documentId,
|
||||
// })
|
||||
}
|
||||
|
||||
async serverRequestSave(documentId: string) {}
|
||||
|
||||
async generatePreviewImage(documentId: string) {}
|
||||
|
||||
async allPageToDelta(documentId: string) {}
|
||||
|
||||
async toDocx(documentId: string) {}
|
||||
) {}
|
||||
}
|
||||
|
||||
// epess/documents/<id>/<page>
|
||||
|
||||
@@ -36,10 +36,7 @@ export class MinioService {
|
||||
}
|
||||
let url = null
|
||||
// check if presignUrl is provided and not expired else get new presignUrl
|
||||
if (
|
||||
presignUrl &&
|
||||
!DateTimeUtils.isExpired(presignUrl.split('&X-Amz-Date=')[1])
|
||||
) {
|
||||
if (presignUrl && !DateTimeUtils.isExpired(presignUrl.split('&X-Amz-Date=')[1])) {
|
||||
url = presignUrl
|
||||
} else {
|
||||
try {
|
||||
@@ -81,14 +78,30 @@ export class MinioService {
|
||||
}
|
||||
|
||||
async deleteFile(id: string, category: string) {
|
||||
return await this.minioClient.removeObject(
|
||||
this.configService.get('BUCKET_NAME') ?? 'epess',
|
||||
`${category}/${id}`,
|
||||
)
|
||||
return await this.minioClient.removeObject(this.configService.get('BUCKET_NAME') ?? 'epess', `${category}/${id}`)
|
||||
}
|
||||
// create a folder for a document pattern epess/documents/<id>/<page>
|
||||
async createDocumentFolder(id: string) {
|
||||
return await this.minioClient.putObject(this.configService.get('BUCKET_NAME') ?? 'epess', `documents/${id}`, '')
|
||||
}
|
||||
|
||||
async streamFile(id: string, category: string) {}
|
||||
|
||||
async upsertDocumentFolder(id: string, page: string) {
|
||||
return await this.minioClient.putObject(
|
||||
this.configService.get('BUCKET_NAME') ?? 'epess',
|
||||
`documents/${id}/${page}`,
|
||||
'',
|
||||
)
|
||||
}
|
||||
// export document to docx format by get all pages and convert to docx
|
||||
async exportDocument(id: string) {
|
||||
// get all pages
|
||||
const pages = await this.minioClient.listObjects(
|
||||
this.configService.get('BUCKET_NAME') ?? 'epess',
|
||||
`documents/${id}`,
|
||||
)
|
||||
// convert to docx
|
||||
// const docx = await this.convertToDocx(pages)
|
||||
}
|
||||
fileName() {
|
||||
// generate a unique file name using uuid
|
||||
return uuidv4()
|
||||
|
||||
@@ -4,15 +4,10 @@ import { Injectable, Logger } from '@nestjs/common'
|
||||
import { PrismaService } from 'src/Prisma/prisma.service'
|
||||
|
||||
import { AppConfigService } from 'src/AppConfig/appconfig.service'
|
||||
import {
|
||||
PreviewScheduleType,
|
||||
ScheduleConfigType,
|
||||
ScheduleConfigTypeForCenter,
|
||||
ScheduleSlotType,
|
||||
} from './schedule.d'
|
||||
import { PreviewScheduleType, ScheduleConfigType, ScheduleConfigTypeForCenter, ScheduleSlotType } from './schedule.d'
|
||||
import { Config, Schedule, ScheduleDate } from '@prisma/client'
|
||||
import { DateTime, Settings, Zone } from 'luxon'
|
||||
import * as _ from 'lodash'
|
||||
import _ from 'lodash'
|
||||
import { ScheduleDateInput } from './schedule'
|
||||
|
||||
@Injectable()
|
||||
@@ -22,9 +17,7 @@ export class ScheduleService {
|
||||
private readonly appConfigService: AppConfigService,
|
||||
) {}
|
||||
|
||||
async createSchedulePreviewForSingleDay(
|
||||
scheduleConfig: ScheduleConfigType,
|
||||
): Promise<PreviewScheduleType> {
|
||||
async createSchedulePreviewForSingleDay(scheduleConfig: ScheduleConfigType): Promise<PreviewScheduleType> {
|
||||
// generate Slot By config
|
||||
const slots = this.generateSlots(scheduleConfig)
|
||||
|
||||
@@ -35,12 +28,8 @@ export class ScheduleService {
|
||||
}
|
||||
|
||||
// create preview for center require scheduleConfigInput: { startDate: "2024-11-02T00:00:00.000Z", endDate: "2024-11-22T00:00:00.000Z", slots: [1, 3], days: [2, 5] }
|
||||
async createSchedulePreviewForCenter(
|
||||
scheduleConfig: ScheduleConfigTypeForCenter,
|
||||
): Promise<PreviewScheduleType> {
|
||||
const config: ScheduleConfigType = (
|
||||
await this.appConfigService.getVisibleConfigs()
|
||||
).reduce((acc, curr) => {
|
||||
async createSchedulePreviewForCenter(scheduleConfig: ScheduleConfigTypeForCenter): Promise<PreviewScheduleType> {
|
||||
const config: ScheduleConfigType = (await this.appConfigService.getVisibleConfigs()).reduce((acc, curr) => {
|
||||
// @ts-ignore
|
||||
acc[curr.key] = curr.value
|
||||
return acc
|
||||
@@ -54,9 +43,7 @@ export class ScheduleService {
|
||||
|
||||
async generateScheduleDates(schedule: Schedule): Promise<ScheduleDate[]> {
|
||||
// generate schedule dates based on data and config
|
||||
const config: ScheduleConfigType = (
|
||||
await this.appConfigService.getVisibleConfigs()
|
||||
).reduce((acc, curr) => {
|
||||
const config: ScheduleConfigType = (await this.appConfigService.getVisibleConfigs()).reduce((acc, curr) => {
|
||||
// @ts-ignore
|
||||
acc[curr.key] = curr.value
|
||||
return acc
|
||||
@@ -72,11 +59,7 @@ export class ScheduleService {
|
||||
const scheduleDates: ScheduleDateInput[] = []
|
||||
|
||||
// loop each day from scheduleStart to scheduleEnd
|
||||
for (
|
||||
let date = scheduleStart;
|
||||
date <= scheduleEnd;
|
||||
date = date.plus({ days: 1 })
|
||||
) {
|
||||
for (let date = scheduleStart; date <= scheduleEnd; date = date.plus({ days: 1 })) {
|
||||
// Check if the current date matches one of the specified days of the week
|
||||
if (daysOfWeeks.includes(date.weekday)) {
|
||||
// loop through slots
|
||||
@@ -85,10 +68,7 @@ export class ScheduleService {
|
||||
slot,
|
||||
slotDuration.toString(),
|
||||
slotBreakDuration.toString(),
|
||||
DateTimeUtils.getATimeWithDateB(
|
||||
DateTime.fromISO(config.dayStartTime),
|
||||
date,
|
||||
).toISO() ?? '',
|
||||
DateTimeUtils.getATimeWithDateB(DateTime.fromISO(config.dayStartTime), date).toISO() ?? '',
|
||||
)
|
||||
scheduleDates.push({
|
||||
scheduleId: schedule.id,
|
||||
@@ -103,10 +83,9 @@ export class ScheduleService {
|
||||
}
|
||||
}
|
||||
}
|
||||
const scheduleDatesCreated =
|
||||
await this.prisma.scheduleDate.createManyAndReturn({
|
||||
data: scheduleDates,
|
||||
})
|
||||
const scheduleDatesCreated = await this.prisma.scheduleDate.createManyAndReturn({
|
||||
data: scheduleDates,
|
||||
})
|
||||
|
||||
return scheduleDatesCreated
|
||||
}
|
||||
@@ -137,11 +116,7 @@ query CenterPreviewSchedule {
|
||||
const scheduleStart = DateTime.fromISO(_scheduleConfig.startDate)
|
||||
const scheduleEnd = DateTime.fromISO(_scheduleConfig.endDate)
|
||||
// loop each day from scheduleStart to scheduleEnd
|
||||
for (
|
||||
let date = scheduleStart;
|
||||
date <= scheduleEnd;
|
||||
date = date.plus({ days: 1 })
|
||||
) {
|
||||
for (let date = scheduleStart; date <= scheduleEnd; date = date.plus({ days: 1 })) {
|
||||
// Check if the current date matches one of the specified days of the week
|
||||
if (daysOfWeeks.includes(date.weekday)) {
|
||||
// loop through slots
|
||||
@@ -151,10 +126,7 @@ query CenterPreviewSchedule {
|
||||
slot,
|
||||
_config.slotDuration,
|
||||
_config.slotBreakDuration,
|
||||
DateTimeUtils.getATimeWithDateB(
|
||||
DateTime.fromISO(_config.dayStartTime),
|
||||
date,
|
||||
).toISO() ?? '',
|
||||
DateTimeUtils.getATimeWithDateB(DateTime.fromISO(_config.dayStartTime), date).toISO() ?? '',
|
||||
)
|
||||
// if the slot is not overlapping with mid day break time, add it to the slots
|
||||
if (
|
||||
@@ -213,24 +185,11 @@ query CenterPreviewSchedule {
|
||||
return slots
|
||||
}
|
||||
|
||||
isOverLapping(
|
||||
startTime1: DateTime,
|
||||
endTime1: DateTime,
|
||||
startTime2: DateTime,
|
||||
endTime2: DateTime,
|
||||
) {
|
||||
return (
|
||||
Math.max(startTime1.toMillis(), startTime2.toMillis()) <
|
||||
Math.min(endTime1.toMillis(), endTime2.toMillis())
|
||||
)
|
||||
isOverLapping(startTime1: DateTime, endTime1: DateTime, startTime2: DateTime, endTime2: DateTime) {
|
||||
return Math.max(startTime1.toMillis(), startTime2.toMillis()) < Math.min(endTime1.toMillis(), endTime2.toMillis())
|
||||
}
|
||||
|
||||
calculateNumberOfSlots(
|
||||
startTime: string,
|
||||
endTime: string,
|
||||
slotDuration: string,
|
||||
slotBreakDuration: string,
|
||||
) {
|
||||
calculateNumberOfSlots(startTime: string, endTime: string, slotDuration: string, slotBreakDuration: string) {
|
||||
const _startTime = DateTimeUtils.toTime(startTime)
|
||||
const _endTime = DateTimeUtils.toTime(endTime)
|
||||
const _slotDuration = parseInt(slotDuration) // minutes
|
||||
@@ -247,20 +206,12 @@ query CenterPreviewSchedule {
|
||||
second: _endTime.second,
|
||||
})
|
||||
|
||||
const totalMinutes =
|
||||
(endDate.toMillis() - startDate.toMillis()) / (60 * 1000)
|
||||
const numberOfSlots = Math.floor(
|
||||
totalMinutes / (_slotDuration + _slotBreakDuration),
|
||||
)
|
||||
const totalMinutes = (endDate.toMillis() - startDate.toMillis()) / (60 * 1000)
|
||||
const numberOfSlots = Math.floor(totalMinutes / (_slotDuration + _slotBreakDuration))
|
||||
return numberOfSlots
|
||||
}
|
||||
|
||||
getSlotStartAndEndTime(
|
||||
slotNumber: number,
|
||||
slotDuration: string,
|
||||
slotBreakDuration: string,
|
||||
dayStartTime: string,
|
||||
) {
|
||||
getSlotStartAndEndTime(slotNumber: number, slotDuration: string, slotBreakDuration: string, dayStartTime: string) {
|
||||
const durationInMinutes = parseInt(slotDuration)
|
||||
const breakDurationInMinutes = parseInt(slotBreakDuration)
|
||||
const initialStartTime = DateTime.fromISO(dayStartTime)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DevtoolsModule } from '@nestjs/devtools-integration'
|
||||
import { ClerkModule } from './Clerk/clerk.module'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
import { GraphqlModule } from './Graphql/graphql.module'
|
||||
@@ -9,6 +10,10 @@ import { CronModule } from './Cron/cron.module'
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
DevtoolsModule.register({
|
||||
http: process.env.NODE_ENV !== 'production',
|
||||
port: 8000,
|
||||
}),
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import * as _ from 'lodash'
|
||||
import {
|
||||
DateTime,
|
||||
Settings,
|
||||
HourNumbers,
|
||||
MinuteNumbers,
|
||||
SecondNumbers,
|
||||
DayNumbers,
|
||||
WeekdayNumbers,
|
||||
} from 'luxon'
|
||||
import _ from 'lodash'
|
||||
import { DateTime, Settings, HourNumbers, MinuteNumbers, SecondNumbers, DayNumbers, WeekdayNumbers } from 'luxon'
|
||||
|
||||
Settings.defaultLocale = 'en-US'
|
||||
Settings.defaultZone = 'utc'
|
||||
@@ -52,22 +44,11 @@ export class DateTimeUtils {
|
||||
return DateTime.fromISO(expires) < DateTime.now()
|
||||
}
|
||||
|
||||
static isOverlap(
|
||||
startA: DateTime,
|
||||
endA: DateTime,
|
||||
startB: DateTime,
|
||||
endB: DateTime,
|
||||
): boolean {
|
||||
return (
|
||||
this.getOverlapRange(startA, endA, startB, endB).start <
|
||||
this.getOverlapRange(startA, endA, startB, endB).end
|
||||
)
|
||||
static isOverlap(startA: DateTime, endA: DateTime, startB: DateTime, endB: DateTime): boolean {
|
||||
return this.getOverlapRange(startA, endA, startB, endB).start < this.getOverlapRange(startA, endA, startB, endB).end
|
||||
}
|
||||
|
||||
static isOverlaps(
|
||||
listA: { start: DateTime; end: DateTime }[],
|
||||
listB: { start: DateTime; end: DateTime }[],
|
||||
): boolean {
|
||||
static isOverlaps(listA: { start: DateTime; end: DateTime }[], listB: { start: DateTime; end: DateTime }[]): boolean {
|
||||
for (const a of listA) {
|
||||
for (const b of listB) {
|
||||
if (this.isOverlap(a.start, a.end, b.start, b.end)) {
|
||||
|
||||
37
src/main.ts
37
src/main.ts
@@ -10,39 +10,22 @@ import { readFileSync } from 'node:fs'
|
||||
import { json } from 'express'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule)
|
||||
const app = await NestFactory.create(AppModule, {})
|
||||
// load private key and public key
|
||||
const privateKey = readFileSync(
|
||||
path.join(__dirname, 'KeyStore', 'private_key.pem'),
|
||||
'utf8',
|
||||
)
|
||||
const publicKey = readFileSync(
|
||||
path.join(__dirname, 'KeyStore', 'public_key.pem'),
|
||||
'utf8',
|
||||
)
|
||||
const privateKey = readFileSync(path.join(__dirname, 'KeyStore', 'private_key.pem'), 'utf8')
|
||||
const publicKey = readFileSync(path.join(__dirname, 'KeyStore', 'public_key.pem'), 'utf8')
|
||||
// set private key and public key to env
|
||||
process.env.JWT_RS256_PRIVATE_KEY = privateKey
|
||||
process.env.JWT_RS256_PUBLIC_KEY = publicKey
|
||||
|
||||
Logger.log(
|
||||
`Private key: ${privateKey.slice(0, 10).replace(/\n/g, '')}...`,
|
||||
'Bootstrap',
|
||||
)
|
||||
Logger.log(
|
||||
`Public key: ${publicKey.slice(0, 10).replace(/\n/g, '')}...`,
|
||||
'Bootstrap',
|
||||
)
|
||||
Logger.log(`Private key: ${privateKey.slice(0, 10).replace(/\n/g, '')}...`, 'Bootstrap')
|
||||
Logger.log(`Public key: ${publicKey.slice(0, 10).replace(/\n/g, '')}...`, 'Bootstrap')
|
||||
|
||||
const corsOrigin = (process.env.CORS_ORIGIN ?? '').split(',') // split by comma to array
|
||||
app.enableCors({
|
||||
origin: corsOrigin,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
||||
allowedHeaders: [
|
||||
'Content-Type',
|
||||
'*',
|
||||
'x-apollo-operation-name',
|
||||
'x-session-id',
|
||||
],
|
||||
allowedHeaders: ['Content-Type', '*', 'x-apollo-operation-name', 'x-session-id'],
|
||||
credentials: true,
|
||||
})
|
||||
|
||||
@@ -63,8 +46,7 @@ async function bootstrap() {
|
||||
get: {
|
||||
tags: ['GraphQL'],
|
||||
summary: 'GraphQL Playground',
|
||||
description:
|
||||
'Access the GraphQL Playground to interact with the GraphQL API.',
|
||||
description: 'Access the GraphQL Playground to interact with the GraphQL API.',
|
||||
responses: {
|
||||
'200': {
|
||||
description: 'GraphQL Playground',
|
||||
@@ -90,10 +72,7 @@ async function bootstrap() {
|
||||
)
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
} catch (error: any) {
|
||||
Logger.error(
|
||||
`Error in file upload middleware: ${error.message}`,
|
||||
'Bootstrap',
|
||||
)
|
||||
Logger.error(`Error in file upload middleware: ${error.message}`, 'Bootstrap')
|
||||
// Optionally, you can handle the error further or rethrow it
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user