prisma2.0和nexus搭建graphql后端(2)—nexus

前言

nexus是一个令人愉快的GraphQL应用程序框架,是Node.js代码优先的GraphQL框架。文档:https://www.nexusjs.org (这个文档还在建设中,其中有些错误的地方)。
Nexus有一个官方的Prisma插件,可帮助您将GraphQL API连接到数据库。具体prisma的知识见这篇文章:prisma2.0和nexus搭建graphql后端(1)—prisma2.0

nexus安装

Nexus开箱即用,带有CLI。安装命令如下:

yarn global add nexus

这只是您现在需要了解的3个CLI命令:
nexus dev:此命令以监视模式启动开发服务器。每次更改文件时,您的应用都会重新启动。
nexus build:此命令将构建一个“生产就绪”服务器,准备进行部署。
nexus create: 它将为您搭建一个新的Nexus项目。这就是通常应启动Nexus项目的方式。

nexus启动

  1. 初始化 package.json 安装nexus
mkdir nexus-tutorial && cd nexus-tutorial
yarn init
yarn add nexus
  1. 修改package.json的命令
"scripts": {
  "dev": "nexus dev",
  "build": "nexus build"
}
  1. 新建app.ts mkdir api && touch api/app.ts 在app.ts里面写代码
  2. 运行 yarn dev
  3. 编译 yarn build

还可以用 nexus create 命令一键帮你把框架搭建好,它会提示你选择yarn还是npm ,同时会提示你是否要使用prisma,然后选择数据种类。按照提示走,会帮你搭建好最初的框架。同时里面还有些示例代码。
过程如下:
在这里插入图片描述
prisma2.0和nexus搭建graphql后端(2)—nexus_第1张图片
生成的目录结构如下:
prisma2.0和nexus搭建graphql后端(2)—nexus_第2张图片
然后yarn dev 最后访问 http://localhost:4000

nexus 反射

Nexus有一个非常规的概念,叫做“反射”。它指的是这样一个事实,即当nexus dev或nexus build运行时,不仅会运行您的应用程序代码,而且还在收集信息并且在派生工件。反射用途包括:

  • 弄清楚您正在使用哪些插件,以及通过的设置
  • 生成TypeScript类型以为您的解析器提供完全的类型安全性
  • 生成SDL文件
    注意:即使您不打算运行服务,也请您nexus dev.如果您忘记运行nexus dev,那么您将不会获得解析器所期望的静态打字体验。(typescript的代码提示)

nexus定义Object Types

object Types对象类型:在许多情况下,您不想从API返回数字或字符串。您要返回一个具有其自身复杂行为的对象。 就是这里的 object Types。

mkdir api/graphql && touch api/graphql/Post.ts

Post.ts 的内容如下

import { schema } from 'nexus'

schema.objectType({
  name: 'Post',            // <- Name of your type
  definition(t) {
    t.int('id')            // <- Field named `id` of type `Int`
    t.string('title')      // <- Field named `title` of type `String`
    t.string('body')          // <- Field named `body` of type `String`
    t.boolean('published') // <- Field named `published` of type `Boolean`
  },
})

GraphQL context

GraphQL上下文是在所有解析器之间共享的普通JavaScript对象。

// touch api/db.ts
// api/db.ts

export const db = {
  posts: [{ id: 1, title: 'Nexus', body: '...', published: false }],
}

// api/app.ts

import { schema } from 'nexus'
import { db } from './db'

schema.addToContext(() => {
  return {
    db,
  }
})

nexus Query

// api/graphql/Post.ts     
// ...

schema.extendType({
  type: 'Query',            
  definition(t) {
    t.field('drafts', {      // 第一个参数指定字段的名称3
      type: 'Post',         // 指定字段的类型应该是
      list: true,           // 返回数组
       resolve(_root, _args, ctx) {                             // 上下文是第三个参数,通常标识为ctx
	      return ctx.db.posts.filter(p => p.published === false)  
      },
    })
  },
})

nexus Mutation

// api/graphql/Post.ts
schema.extendType({
  type: 'Mutation',
  definition(t) {
    t.field('createDraft', {
      type: 'Post',
     args: {                                        // 将args属性添加到字段定义以定义其args。键是arg名称,值是类型规范。
       title: schema.stringArg({ required: true }), // 使用Nexus辅助函数定义arg类型。例如schema.intArg和schema.booleanArg。
       body: schema.stringArg({ required: true }),  // 如果要引用类似某些InputObject的类型,请使用schema.arg({type:“ ...”})。
     },
      resolve(_root, args, ctx) {
       const draft = {
         id: ctx.db.posts.length + 1,
         title: args.title,                         // 在我们的解析器中,访问我们在上面指定的args并将它们传递给我们的自定义逻辑。
         body: args.body,
         published: false,
       }
       ctx.db.posts.push(draft)
       return draft
       ctx.db.posts.push(/*...*/)
       return // ...
      },
    })
  },
})

nexus 加入prisma

  1. yarn add prisma nexus-plugin-prisma
// api/app.ts

import { use } from 'nexus'
import { prisma } from 'nexus-plugin-prisma'

use(prisma())
mkdir prisma
touch prisma/schema.prisma
touch prisma/.env
// prisma/schema.prisma

datasource postgres {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

# prisma/.env
DATABASE_URL=""  // 这里是数据库地址
  1. 连接数据库有两种方式 具体见上prisma篇 这里不再重复
    第一种是 先定义好 schema的data model 再利用prisma migrate命令生成数据库
    第二种是 先建好数据库表 再利用prisma instrospect生产schema的data model
  2. app.ts
import { use } from 'nexus'
import { prisma } from 'nexus-plugin-prisma'
use(prisma())

prisma generate 生成prisma client

  1. object type
import {schema} from "nexus"

schema.objectType({
    name: "Post",
    definition(t) {
        t.id("id")
        t.string("title")
        t.string("body")
        t.boolean("publish")
    }
})
  1. query
    (1) 不分页
import { schema } from 'nexus';

import { PostWhereInput } from '.prisma/client';

schema.extendType({
  type: 'Query',
  definition(t) {
    t.list.field('posts', {
      args: {
        isPublished: schema.booleanArg({ required: false }),
        title: schema.stringArg({ required: false, default: '' }),
        body: schema.stringArg({ required: false, description: '' })
      },
      type: 'Post',
      resolve(_root, args, ctx) {
        let { isPublished, title, body } = args;
        let whereObj: PostWhereInput = {
          title: {
            contains: title
          },
          body: {
            contains: body
          }
        };
        if (isPublished !== undefined) {
          whereObj.published = isPublished;
        }
        return ctx.db.post.findMany({
          where: whereObj
        });
      }
    });
  }
});

(2) 分页

import { schema } from 'nexus';
import { PostWhereInput } from '.prisma/client';

schema.extendType({
  type: 'Query',
  definition(t) {
    t.field('postsWithPageInfo', {
      type: 'PostWithPageInfo',
      args: {
        pn: schema.intArg({ required: true }),
        ps: schema.intArg({ required: true }),
        isPublished: schema.booleanArg({ required: false }),
        title: schema.stringArg({ required: false, default: '' }),
        body: schema.stringArg({ required: false, description: '' })
      },
      resolve: async (_root, args, ctx) => {
        let { isPublished, title, body, pn, ps } = args;
        let whereObj: PostWhereInput = {
          title: {
            contains: title
          },
          body: {
            contains: body
          }
        };
        if (isPublished !== undefined) {
          whereObj.published = isPublished;
        }
        const data = await ctx.db.post.findMany({
          where: whereObj,
          skip: ps * (pn - 1),
          first: ps
        });

        const total = await ctx.db.post.count({ where: whereObj });
        return {
          data,
          pageInfo: { pn, ps, total }
        };
      }
    });
  }
});
  1. mutation
    (1)create
import { schema } from 'nexus';

schema.extendType({
  type: 'Mutation',
  definition(t) {
    t.field('createPost', {
      type: 'Post',
      args: {
        isPublished: schema.booleanArg({ required: false, default: false }),
        title: schema.stringArg({ required: true }),
        body: schema.stringArg({ required: true })
      },
      resolve(_root, args, ctx) {
        let { isPublished, title, body } = args;
        return ctx.db.post.create({ data: { published: isPublished as boolean, title, body } });
      }
    });
  }
});

(2) delete

import { schema } from 'nexus';

schema.extendType({
  type: 'Mutation',
  definition(t) {
    t.field('deletePosts', {
      type: 'BatchPayload',
      args: {
        ids: schema.intArg({ required: true, list: true })
      },
      resolve: async (_root, args, ctx) => {
        const { ids } = args;
        return ctx.db.post.deleteMany({ where: { id: { in: ids } } });
      }
    });
  }
});

(3) update

import { schema } from 'nexus';

import { PostUpdateInput } from '.prisma/client';

schema.extendType({
  type: 'Mutation',
  definition(t) {
    t.field('updatePost', {
      type: 'Post',
      args: {
        id: schema.intArg({ required: true }),
        title: schema.stringArg({ required: false }),
        body: schema.stringArg({ required: false }),
        published: schema.booleanArg({ required: false })
      },
      resolve: async (_root, args, ctx) => {
        const { id, title, body, published } = args;

        const post = await ctx.db.post.findOne({ where: { id } });
        if (!post) {
          throw new Error(`id为${id}的文章不存在`);
        }

        const data: PostUpdateInput = {};
        if (title !== undefined) {
          data.title = title;
        }
        if (body !== undefined) {
          data.body = body;
        }
        if (published !== undefined) {
          data.published = published;
        }
        return ctx.db.post.update({ data, where: { id } });
      }
    });
  }
});

你可能感兴趣的:(prisma)