curl https://www.gitignore.io/api/osx,node,intellij+iml,visualstudiocode -o .gitignore
// tsconfig.json
$ cat << EOF > tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"lib": ["esnext"],
"esModuleInterop": true,
"strict": true
},
"include": ["src/**/*"]
}
EOF
$ yarn init -y
$ yarn add typescript ts-node ts-node-dev @types/node --dev
$ yarn add @prisma/client nexus-prisma @nexus/schema apollo-server graphql
$ yarn add @prisma/cli --dev
$ yarn run prisma init
// prisma/schema.prisma
$ cat << EOF > prisma/schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
EOF
// prisma/.env
$ cat << EOF > prisma/.env
DATABASE_URL="mysql://root@localhost:3306/my_prisma"
EOF
$ yarn run prisma introspect
$ yarn run prisma generate
$ mkdir src
// src/context.ts
$ cat << EOF > src/context.ts
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
export interface Context {
prisma: PrismaClient
}
export function createContext(): Context {
return { prisma }
}
EOF
// src/schema.ts
$ cat << EOF > src/schema.ts
import { nexusPrismaPlugin } from 'nexus-prisma'
import { intArg, makeSchema, objectType, stringArg } from '@nexus/schema'
const User = objectType({
name: 'User',
definition(t) {
t.model.id()
t.model.name()
t.model.email()
t.model.posts({
pagination: false,
})
},
})
const Post = objectType({
name: 'Post',
definition(t) {
t.model.id()
t.model.title()
t.model.content()
t.model.published()
t.model.author()
t.model.authorId()
},
})
const Query = objectType({
name: 'Query',
definition(t) {
t.crud.post()
t.list.field('feed', {
type: 'Post',
resolve: (_, args, ctx) => {
return ctx.prisma.post.findMany({
where: { published: true },
})
},
})
t.list.field('filterPosts', {
type: 'Post',
args: {
searchString: stringArg({ nullable: true }),
},
resolve: (_, { searchString }, ctx) => {
return ctx.prisma.post.findMany({
where: {
OR: [
{ title: { contains: searchString } },
{ content: { contains: searchString } },
],
},
})
},
})
},
})
const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.crud.createOneUser({ alias: 'signupUser' })
t.crud.deleteOnePost()
t.field('createDraft', {
type: 'Post',
args: {
title: stringArg({ nullable: false }),
content: stringArg(),
authorEmail: stringArg(),
},
resolve: (_, { title, content, authorEmail }, ctx) => {
return ctx.prisma.post.create({
data: {
title,
content,
published: false,
author: {
connect: { email: authorEmail },
},
},
})
},
})
t.field('publish', {
type: 'Post',
nullable: true,
args: {
id: intArg(),
},
resolve: (_, { id }, ctx) => {
return ctx.prisma.post.update({
where: { id: Number(id) },
data: { published: true },
})
},
})
},
})
export const schema = makeSchema({
types: [Query, Mutation, Post, User],
plugins: [nexusPrismaPlugin()],
outputs: {
schema: __dirname + '/../schema.graphql',
typegen: __dirname + '/generated/nexus.ts',
},
typegenAutoConfig: {
contextType: 'Context.Context',
sources: [
{
source: '@prisma/client',
alias: 'prisma',
},
{
source: require.resolve('./context'),
alias: 'Context',
},
],
},
})
EOF
// src/server.ts
$ cat << \EOF > src/server.ts
import { ApolloServer } from 'apollo-server'
import { schema } from './schema'
import { createContext } from './context'
new ApolloServer({ schema, context: createContext }).listen(
{ port: 4000 },
() =>
console.log(
`🚀 Server ready at: http://localhost:4000\n⭐️ See sample queries: http://pris.ly/e/ts/graphql-apollo-server#using-the-graphql-api`,
),
)
EOF
$ yarn ts-node-dev --no-notify --respawn --transpileOnly src/server
DBから yarn run prisma introspect
する場合、 schemaのPostとなっているリレーション名をpostsなどに修正するのは手動
exampleにあるpackage.jsonのscriptsは以下
"scripts": {
"start": "node dist/server",
"clean": "rm -rf dist",
"build": "npm -s run clean && npm -s run generate && tsc",
"generate": "npm -s run generate:prisma && npm -s run generate:nexus",
"generate:prisma": "prisma generate",
"generate:nexus": "ts-node --transpile-only src/schema",
"postinstall": "npm -s run generate",
"dev": "ts-node-dev --no-notify --respawn --transpileOnly src/server"
}