Skip to content

Commit

Permalink
chore: init
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesschobel committed Jan 26, 2021
0 parents commit 3f8f789
Show file tree
Hide file tree
Showing 16 changed files with 416 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}
84 changes: 84 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# REST API Example

This example shows how to implement a **REST API** using [NestJS](https://docs.nestjs.com/) and [Prisma Client](https://www.prisma.io/docs/concepts/components/prisma-client). It uses a SQLite database file with some initial dummy data which you can find at [`./prisma/dev.db`](./prisma/dev.db). The example was bootstrapped using the NestJS CLI command `nest new rest-nestjs`.

## How to use

### 1. Download example & install dependencies

Download this example:

```
curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/typescript/rest-nestjs
```

Install npm dependencies:
```
cd rest-nestjs
npm install
```

Note that this also generates Prisma Client JS into `node_modules/@prisma/client` via a `postinstall` hook of the `@prisma/client` package from your `package.json`.

<Details><Summary><strong>Alternative:</strong> Clone the entire repo</Summary>

Clone this repository:

```
git clone [email protected]:prisma/prisma-examples.git --depth=1
```

Install npm dependencies:

```
cd prisma-examples/typescript/rest-nestjs
npm install
```

</Details>

### 2. Start the REST API server

```
npm run dev
```

The server is now running on `http://localhost:3000`. You can now the API requests, e.g. [`http://localhost:3000/feed`](http://localhost:3000/feed).

## Using the REST API

You can access the REST API of the server using the following endpoints:

### `GET`

- `/post/:id`: Fetch a single post by its `id`
- `/feed`: Fetch all _published_ posts
- `/filterPosts?searchString={searchString}`: Filter posts by `title` or `content`

### `POST`

- `/post`: Create a new post
- Body:
- `title: String` (required): The title of the post
- `content: String` (optional): The content of the post
- `authorEmail: String` (required): The email of the user that creates the post
- `/user`: Create a new user
- Body:
- `email: String` (required): The email address of the user
- `name: String` (optional): The name of the user

### `PUT`

- `/publish/:id`: Publish a post by its `id`

### `DELETE`

- `/post/:id`: Delete a post by its `id`


## Next steps

- Check out the [Prisma docs](https://www.prisma.io/docs)
- Share your feedback in the [`prisma2`](https://prisma.slack.com/messages/CKQTGR6T0/) channel on the [Prisma Slack](https://slack.prisma.io/)
- Create issues and ask questions on [GitHub](https://github.com/prisma/prisma/)

4 changes: 4 additions & 0 deletions nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
72 changes: 72 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"name": "rest-nestjs",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"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"
},
"dependencies": {
"@nestjs/common": "7.6.6",
"@nestjs/core": "7.6.6",
"@nestjs/platform-express": "7.6.6",
"@prisma/client": "2.15.0",
"reflect-metadata": "0.1.13",
"rimraf": "3.0.2",
"rxjs": "6.6.3"
},
"devDependencies": {
"@nestjs/cli": "7.5.4",
"@nestjs/schematics": "7.2.7",
"@nestjs/testing": "7.6.6",
"@prisma/cli": "2.15.0",
"@types/express": "4.17.11",
"@types/jest": "26.0.20",
"@types/node": "14.14.22",
"@types/supertest": "2.0.10",
"@typescript-eslint/eslint-plugin": "4.14.1",
"@typescript-eslint/parser": "4.14.1",
"eslint": "7.18.0",
"eslint-config-prettier": "7.0.0",
"eslint-plugin-prettier": "3.3.1",
"jest": "26.6.3",
"prettier": "2.2.1",
"supertest": "6.1.3",
"ts-jest": "26.4.4",
"ts-loader": "8.0.14",
"ts-node": "9.1.1",
"tsconfig-paths": "3.9.0",
"typescript": "4.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
Binary file added prisma/dev.db
Binary file not shown.
24 changes: 24 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "sqlite"
url = "file:./dev.db"
}

model User {
email String @unique
id Int @id @default(autoincrement())
name String?
posts Post[]
}

model Post {
authorId Int?
content String?
id Int @id @default(autoincrement())
published Boolean @default(false)
title String
author User? @relation(fields: [authorId], references: [id])
}
85 changes: 85 additions & 0 deletions src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
Controller,
Get,
Param,
Post,
Body,
Put,
Delete,
Query,
} from '@nestjs/common'
import { PrismaService } from './prisma.service'
import { User as UserModel, Post as PostModel } from '@prisma/client'

@Controller()
export class AppController {
constructor(private readonly prismaService: PrismaService) {}

@Get('post/:id')
async getPostById(@Param('id') id: string): Promise<PostModel> {
return this.prismaService.post.findUnique({ where: { id: Number(id) } })
}

@Get('feed')
async getPublishedPosts(): Promise<PostModel[]> {
return this.prismaService.post.findMany({
where: { published: true },
})
}

@Get('filterPosts')
async getFilteredPosts(
@Query('searchString') searchString: string,
): Promise<PostModel[]> {
return this.prismaService.post.findMany({
where: {
OR: [
{
title: { contains: searchString },
},
{
content: { contains: searchString },
},
],
},
})
}

@Post('post')
async createDraft(
@Body() postData: { title: string; content?: string; authorEmail: string },
): Promise<PostModel> {
const { title, content, authorEmail } = postData
return this.prismaService.post.create({
data: {
title,
content,
author: {
connect: { email: authorEmail },
},
},
})
}

@Post('user')
async signupUser(
@Body() userData: { name?: string; email: string },
): Promise<UserModel> {
return this.prismaService.user.create({
data: userData,
})
}

@Put('publish/:id')
async publishPost(@Param('id') id: string): Promise<PostModel> {
return this.prismaService.post.update({
where: { id: Number(id) },
data: { published: true },
})
}

@Delete('post/:id')
async deletePost(@Param('id') id: string): Promise<PostModel> {
return this.prismaService.post.delete({ where: { id: Number(id) } })
}
}
10 changes: 10 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { PrismaService } from './prisma.service'

@Module({
imports: [],
controllers: [AppController],
providers: [PrismaService],
})
export class AppModule {}
8 changes: 8 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'

async function bootstrap() {
const app = await NestFactory.create(AppModule)
await app.listen(3000)
}
bootstrap()
15 changes: 15 additions & 0 deletions src/prisma.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'
import { PrismaClient } from '@prisma/client'

@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy {
async onModuleInit() {
await this.$connect()
}

async onModuleDestroy() {
await this.$disconnect()
}
}
Loading

0 comments on commit 3f8f789

Please sign in to comment.