20 changed files with 383 additions and 10 deletions
-
7.env
-
9package.json
-
13prisma/migrations/20230414015851_init/migration.sql
-
3prisma/migrations/migration_lock.toml
-
21prisma/schema.prisma
-
43prisma/seed.ts
-
4src/app.module.ts
-
20src/articles/articles.controller.spec.ts
-
48src/articles/articles.controller.ts
-
11src/articles/articles.module.ts
-
18src/articles/articles.service.spec.ts
-
36src/articles/articles.service.ts
-
15src/articles/dto/create-article.dto.ts
-
4src/articles/dto/update-article.dto.ts
-
25src/articles/entities/article.entity.ts
-
11src/main.ts
-
8src/prisma/prisma.module.ts
-
18src/prisma/prisma.service.spec.ts
-
11src/prisma/prisma.service.ts
-
68yarn.lock
@ -0,0 +1,7 @@ |
|||
# Environment variables declared in this file are automatically made available to Prisma. |
|||
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema |
|||
|
|||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. |
|||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings |
|||
|
|||
DATABASE_URL="mysql://root:root@localhost:3306/median" |
|||
@ -0,0 +1,13 @@ |
|||
-- CreateTable |
|||
CREATE TABLE `Article` ( |
|||
`id` INTEGER NOT NULL AUTO_INCREMENT, |
|||
`title` VARCHAR(191) NOT NULL, |
|||
`description` VARCHAR(191) NULL, |
|||
`body` VARCHAR(191) NOT NULL, |
|||
`published` BOOLEAN NOT NULL DEFAULT false, |
|||
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), |
|||
`updatedAt` DATETIME(3) NOT NULL, |
|||
|
|||
UNIQUE INDEX `Article_title_key`(`title`), |
|||
PRIMARY KEY (`id`) |
|||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; |
|||
@ -0,0 +1,3 @@ |
|||
# Please do not edit this file manually |
|||
# It should be added in your version-control system (i.e. Git) |
|||
provider = "mysql" |
|||
@ -0,0 +1,21 @@ |
|||
// This is your Prisma schema file, |
|||
// learn more about it in the docs: https://pris.ly/d/prisma-schema |
|||
|
|||
generator client { |
|||
provider = "prisma-client-js" |
|||
} |
|||
|
|||
datasource db { |
|||
provider = "mysql" |
|||
url = env("DATABASE_URL") |
|||
} |
|||
|
|||
model Article { |
|||
id Int @id @default(autoincrement()) |
|||
title String @unique |
|||
description String? |
|||
body String |
|||
published Boolean @default(false) |
|||
createdAt DateTime @default(now()) |
|||
updatedAt DateTime @updatedAt |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// prisma/seed.ts
|
|||
|
|||
import { PrismaClient } from "@prisma/client"; |
|||
|
|||
// initialize Prisma Client
|
|||
const prisma = new PrismaClient(); |
|||
|
|||
async function main() { |
|||
// create two dummy articles
|
|||
const post1 = await prisma.article.upsert({ |
|||
where: { title: 'Prisma Adds Support for MongoDB' }, |
|||
update: {}, |
|||
create: { |
|||
title: 'Prisma Adds Support for MongoDB', |
|||
body: 'Support for MongoDB has been one of the most requested features since the initial release of...', |
|||
description: "We are excited to share that today's Prisma ORM release adds stable support for MongoDB!", |
|||
published: false, |
|||
} |
|||
}) |
|||
|
|||
const post2 = await prisma.article.upsert({ |
|||
where: { title: "What's new in Prisma? (Q1/22)" }, |
|||
update: {}, |
|||
create: { |
|||
title: "What's new in Prisma? (Q1/22)", |
|||
body: 'Our engineers have been working hard, issuing new releases with many improvements...', |
|||
description: |
|||
'Learn about everything in the Prisma ecosystem and community from January to March 2022.', |
|||
published: true, |
|||
}, |
|||
}); |
|||
|
|||
console.log({ post1, post2 }); |
|||
} |
|||
|
|||
// execute the main function
|
|||
main().catch((e)=>{ |
|||
console.error(e) |
|||
process.exit(1) |
|||
}).finally(async () => { |
|||
// close Prisma Client at the end
|
|||
await prisma.$disconnect() |
|||
}) |
|||
@ -1,9 +1,11 @@ |
|||
import { Module } from '@nestjs/common'; |
|||
import { AppController } from './app.controller'; |
|||
import { AppService } from './app.service'; |
|||
import { PrismaModule } from './prisma/prisma.module'; |
|||
import { ArticlesModule } from './articles/articles.module'; |
|||
|
|||
@Module({ |
|||
imports: [], |
|||
imports: [PrismaModule, ArticlesModule], |
|||
controllers: [AppController], |
|||
providers: [AppService], |
|||
}) |
|||
|
|||
@ -0,0 +1,20 @@ |
|||
import { Test, TestingModule } from '@nestjs/testing'; |
|||
import { ArticlesController } from './articles.controller'; |
|||
import { ArticlesService } from './articles.service'; |
|||
|
|||
describe('ArticlesController', () => { |
|||
let controller: ArticlesController; |
|||
|
|||
beforeEach(async () => { |
|||
const module: TestingModule = await Test.createTestingModule({ |
|||
controllers: [ArticlesController], |
|||
providers: [ArticlesService], |
|||
}).compile(); |
|||
|
|||
controller = module.get<ArticlesController>(ArticlesController); |
|||
}); |
|||
|
|||
it('should be defined', () => { |
|||
expect(controller).toBeDefined(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,48 @@ |
|||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; |
|||
import { ArticlesService } from './articles.service'; |
|||
import { CreateArticleDto } from './dto/create-article.dto'; |
|||
import { UpdateArticleDto } from './dto/update-article.dto'; |
|||
import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger'; |
|||
import { ArticleEntity } from './entities/article.entity'; |
|||
|
|||
@Controller('articles') |
|||
@ApiTags('articles') |
|||
export class ArticlesController { |
|||
constructor(private readonly articlesService: ArticlesService) { } |
|||
|
|||
@Post() |
|||
@ApiCreatedResponse({ type: ArticleEntity }) |
|||
create(@Body() createArticleDto: CreateArticleDto) { |
|||
return this.articlesService.create(createArticleDto); |
|||
} |
|||
|
|||
@Get('drafts') |
|||
@ApiOkResponse({ type: ArticleEntity, isArray: true }) |
|||
findDrafts() { |
|||
return this.articlesService.findDrafts(); |
|||
} |
|||
|
|||
@Get() |
|||
@ApiOkResponse({ type: ArticleEntity, isArray: true }) |
|||
findAll() { |
|||
return this.articlesService.findAll(); |
|||
} |
|||
|
|||
@Get(':id') |
|||
@ApiOkResponse({ type: ArticleEntity }) |
|||
findOne(@Param('id') id: string) { |
|||
return this.articlesService.findOne(+id); |
|||
} |
|||
|
|||
@Patch(':id') |
|||
@ApiOkResponse({ type: ArticleEntity }) |
|||
update(@Param('id') id: string, @Body() updateArticleDto: UpdateArticleDto) { |
|||
return this.articlesService.update(+id, updateArticleDto); |
|||
} |
|||
|
|||
@Delete(':id') |
|||
@ApiOkResponse({ type: ArticleEntity }) |
|||
remove(@Param('id') id: string) { |
|||
return this.articlesService.remove(+id); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
import { Module } from '@nestjs/common'; |
|||
import { ArticlesService } from './articles.service'; |
|||
import { ArticlesController } from './articles.controller'; |
|||
import { PrismaModule } from 'src/prisma/prisma.module'; |
|||
|
|||
@Module({ |
|||
controllers: [ArticlesController], |
|||
providers: [ArticlesService], |
|||
imports: [PrismaModule] |
|||
}) |
|||
export class ArticlesModule {} |
|||
@ -0,0 +1,18 @@ |
|||
import { Test, TestingModule } from '@nestjs/testing'; |
|||
import { ArticlesService } from './articles.service'; |
|||
|
|||
describe('ArticlesService', () => { |
|||
let service: ArticlesService; |
|||
|
|||
beforeEach(async () => { |
|||
const module: TestingModule = await Test.createTestingModule({ |
|||
providers: [ArticlesService], |
|||
}).compile(); |
|||
|
|||
service = module.get<ArticlesService>(ArticlesService); |
|||
}); |
|||
|
|||
it('should be defined', () => { |
|||
expect(service).toBeDefined(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,36 @@ |
|||
import { Injectable } from '@nestjs/common'; |
|||
import { CreateArticleDto } from './dto/create-article.dto'; |
|||
import { UpdateArticleDto } from './dto/update-article.dto'; |
|||
import { PrismaService } from 'src/prisma/prisma.service'; |
|||
|
|||
@Injectable() |
|||
export class ArticlesService { |
|||
constructor(private prisma: PrismaService) { } |
|||
|
|||
create(createArticleDto: CreateArticleDto) { |
|||
return this.prisma.article.create({ data: createArticleDto }) |
|||
} |
|||
|
|||
findDrafts() { |
|||
return this.prisma.article.findMany({ where: { published: false } }) |
|||
} |
|||
|
|||
findAll() { |
|||
return this.prisma.article.findMany({ where: { published: true } }) |
|||
} |
|||
|
|||
findOne(id: number) { |
|||
return this.prisma.article.findUnique({ where: { id } }) |
|||
} |
|||
|
|||
update(id: number, updateArticleDto: UpdateArticleDto) { |
|||
return this.prisma.article.update({ |
|||
where: { id }, |
|||
data: updateArticleDto |
|||
}) |
|||
} |
|||
|
|||
remove(id: number) { |
|||
return this.prisma.article.delete({ where: { id } }) |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
import { ApiProperty } from '@nestjs/swagger' |
|||
|
|||
export class CreateArticleDto { |
|||
@ApiProperty() |
|||
title: string |
|||
|
|||
@ApiProperty({ required: false }) |
|||
description?: string |
|||
|
|||
@ApiProperty() |
|||
body: string |
|||
|
|||
@ApiProperty({ required: false, default: false }) |
|||
published?: boolean = false |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
import { PartialType } from '@nestjs/swagger'; |
|||
import { CreateArticleDto } from './create-article.dto'; |
|||
|
|||
export class UpdateArticleDto extends PartialType(CreateArticleDto) {} |
|||
@ -0,0 +1,25 @@ |
|||
import { Article } from '@prisma/client' |
|||
import { ApiProperty } from '@nestjs/swagger' |
|||
|
|||
export class ArticleEntity implements Article { |
|||
@ApiProperty() |
|||
id: number |
|||
|
|||
@ApiProperty() |
|||
title: string |
|||
|
|||
@ApiProperty({ required: false, nullable: true }) |
|||
description: string | null |
|||
|
|||
@ApiProperty() |
|||
body: string |
|||
|
|||
@ApiProperty() |
|||
published: boolean |
|||
|
|||
@ApiProperty() |
|||
createdAt: Date |
|||
|
|||
@ApiProperty() |
|||
updatedAt: Date |
|||
} |
|||
@ -1,8 +1,19 @@ |
|||
import { NestFactory } from '@nestjs/core'; |
|||
import { AppModule } from './app.module'; |
|||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; |
|||
|
|||
async function bootstrap() { |
|||
const app = await NestFactory.create(AppModule); |
|||
|
|||
const config = new DocumentBuilder() |
|||
.setTitle('Median') |
|||
.setDescription('The Median API description') |
|||
.setVersion('0.1') |
|||
.build() |
|||
|
|||
const document = SwaggerModule.createDocument(app, config) |
|||
SwaggerModule.setup('api', app, document) |
|||
|
|||
await app.listen(3000); |
|||
} |
|||
bootstrap(); |
|||
@ -0,0 +1,8 @@ |
|||
import { Module } from '@nestjs/common'; |
|||
import { PrismaService } from './prisma.service'; |
|||
|
|||
@Module({ |
|||
providers: [PrismaService], |
|||
exports: [PrismaService] |
|||
}) |
|||
export class PrismaModule {} |
|||
@ -0,0 +1,18 @@ |
|||
import { Test, TestingModule } from '@nestjs/testing'; |
|||
import { PrismaService } from './prisma.service'; |
|||
|
|||
describe('PrismaService', () => { |
|||
let service: PrismaService; |
|||
|
|||
beforeEach(async () => { |
|||
const module: TestingModule = await Test.createTestingModule({ |
|||
providers: [PrismaService], |
|||
}).compile(); |
|||
|
|||
service = module.get<PrismaService>(PrismaService); |
|||
}); |
|||
|
|||
it('should be defined', () => { |
|||
expect(service).toBeDefined(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,11 @@ |
|||
import { INestApplication, Injectable } from '@nestjs/common'; |
|||
import { PrismaClient } from '@prisma/client' |
|||
|
|||
@Injectable() |
|||
export class PrismaService extends PrismaClient { |
|||
async enableShutdownHooks(app: INestApplication) { |
|||
this.$on('beforeExit', async () => { |
|||
await app.close() |
|||
}) |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue