Skip to content

Commit

Permalink
Merge pull request #8 from mathiasberggren/feature/openapi-and-valida…
Browse files Browse the repository at this point in the history
…tion

Add support for OpenAPI, Zod validation and Console
  • Loading branch information
mathiasberggren authored Apr 9, 2024
2 parents 7a87102 + 70bc2f3 commit fdc4387
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 33 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
vite.config.ts
10 changes: 9 additions & 1 deletion apps/api/nest-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
"compilerOptions": {
"deleteOutDir": true,
"builder": "swc",
"typeCheck": true
"typeCheck": true,
"plugins": [
{
"name": "@nestjs/swagger",
"options": {
"introspectComments": true
}
}
]
}
}
16 changes: 13 additions & 3 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,24 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json",
"db:migrate": "npx prisma migrate dev",
"db:deploy": "npx prisma migrate deploy",
"console": "npm run start -- --watch --entryFile repl"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.2",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.3.1",
"@prisma/client": "^5.11.0",
"nest-winston": "^1.9.4",
"nestjs-zod": "^3.0.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"winston": "^3.13.0"
"winston": "^3.13.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@automock/adapters.nestjs": "^2.1.0",
Expand Down Expand Up @@ -66,7 +72,11 @@
"includedScripts": [
"build",
"test",
"lint"
"lint",
"start:dev"
]
},
"prisma": {
"schema": "src/database/schema.prisma"
}
}
14 changes: 12 additions & 2 deletions apps/api/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Logger, Module } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'
import { APP_PIPE } from '@nestjs/core'
import { ZodValidationPipe } from 'nestjs-zod'

import { AppController } from './app.controller'
import { AppService } from './app.service'
import { DatabaseModule } from '../database/database.module'

@Module({
imports: [ConfigModule.forRoot()],
imports: [ConfigModule.forRoot(), DatabaseModule],
controllers: [AppController],
providers: [Logger, AppService]
providers: [
Logger,
AppService,
{
provide: APP_PIPE,
useClass: ZodValidationPipe
}
]
})
export class AppModule {}
9 changes: 9 additions & 0 deletions apps/api/src/database/database.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Global, Module } from '@nestjs/common'
import { PrismaService } from './prisma.service'

@Global()
@Module({
providers: [PrismaService],
exports: [PrismaService]
})
export class DatabaseModule {}
File renamed without changes.
File renamed without changes.
85 changes: 61 additions & 24 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,85 @@
* This is only a minimal backend to get started.
*/

import { Logger } from '@nestjs/common'
import {
Logger, INestApplication,
NestApplicationOptions
} from '@nestjs/common'
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'
import { NestFactory } from '@nestjs/core'

import {
utilities as nestWinstonModuleUtilities,
WinstonModule
} from 'nest-winston'
import * as winston from 'winston'
import { patchNestJsSwagger } from 'nestjs-zod'

import { AppModule } from './app/app.module'

async function bootstrap () {
const API_PREFIX = 'api'
const OPENAPI_PREFIX = 'docs'

export let viteNodeApp: Promise<INestApplication>

function bootstrapOpenAPI (app: INestApplication) {
patchNestJsSwagger()
const config = new DocumentBuilder()
.setTitle('Streaming Subscription API')
.setDescription('The API for managing subscriptions from streaming services')
.setVersion('0.2')
.addTag('subscriptions', 'Operations related to streaming subscriptions')
.build()
const document = SwaggerModule.createDocument(app, config)
SwaggerModule.setup(OPENAPI_PREFIX, app, document)
}

function bootstrapLogger () {
const instance = WinstonModule.createLogger({
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
nestWinstonModuleUtilities.format.nestLike('Streaming Subs', {
colors: true,
prettyPrint: true
})
)
})
// other transports...
]
}
)

return instance
}

export async function createApp (
options?: NestApplicationOptions
): Promise<INestApplication> {
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
nestWinstonModuleUtilities.format.nestLike('Streaming Subs', {
colors: true,
prettyPrint: true
})
)
})
// other transports...
]
})
logger: bootstrapLogger()
})

const globalPrefix = 'api'
app.setGlobalPrefix(globalPrefix)
app.setGlobalPrefix(API_PREFIX)
bootstrapOpenAPI(app)

return app
}

async function main () {
const port = process.env.PORT ?? 3000

const app = await createApp()
await app.listen(port)
Logger.log(
`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`
`🚀 Application is running on: http://localhost:${port}/${API_PREFIX}`
)
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
if (process.env.NODE_ENV === 'production') {
void bootstrap()
void main()
} else {
viteNodeApp = createApp()
}
console.log('process.env.NODE_ENV', process.env.NODE_ENV)
export const viteNodeApp = NestFactory.create(AppModule)
5 changes: 5 additions & 0 deletions apps/api/src/metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-disable */
export default async () => {
const t = {};
return { "@nestjs/swagger": { "models": [], "controllers": [] } };
};
12 changes: 12 additions & 0 deletions apps/api/src/repl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { repl } from '@nestjs/core'
import { AppModule } from './app/app.module'

async function bootstrap () {
const replServer = await repl(AppModule)
replServer.setupHistory('.nestjs_repl_history', (err) => {
if (err != null) {
console.error(err)
}
})
}
void bootstrap()
1 change: 1 addition & 0 deletions apps/api/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig(({ command, mode }: ConfigEnv) => {
return {
base: '/api',
server: {
// vite server configs, for details see \[vite doc\](https://vitejs.dev/config/#server-host)
port: 3000
Expand Down
Loading

0 comments on commit fdc4387

Please sign in to comment.