prisma

Prisma API:核心概念

2018-05-07  本文已影响15人  guog

本文属使用Prisma构建GraphQL服务系列。

数据模型和Prisma database schema

Prisma服务的Prisma API完全以其数据模型为中心。

该API是基于与您的Prisma服务关联的数据模型自动生成的。

Prisma API中暴露的每个操作都与您的数据模型中的模型或关系相关联:

定义Prisma API中可用的GraphQL操作的实际GraphQL schema也称为Prisma database schema。

高级API概念

节点选择

Prisma API中的许多操作仅影响数据库中现有节点的一个子集,通常甚至仅影响单个节点。

在这种情况下,您需要一种方法来请求API中的特定节点 - 通常用where参数。

节点可以通过@unique指令标记的任何字段进行选择。

type Post {
  id: ID! @unique
  title: String!
  published: Boolean @default(value: "false")
}

以下是需要节点选择的一些场景。

通过email检索单个节点:

query {
  post(where: {
    email: "hello@graph.cool"
  }) {
    id
  }
}

更新单个节点的title

mutation {
  updatePost(
    where: {
      id: "ohco0iewee6eizidohwigheif"
    }
    data: {
      title: "GraphQL is awesome"
    }
  ) {
    id
  }
}

一次更新多个节点的published

mutation {
  updatePost(
    where: {
      id_in: ["ohco0iewee6eizidohwigheif", "phah4ooqueengij0kan4sahlo", "chae8keizohmiothuewuvahpa"]
    }
    data: {
      published: true
    }
  ) {
    count
  }
}

批量操作

节点选择概念的一个应用是批量操作,批量更新或删除已针对大量节点进行了优化。因此,这些突变仅返回有多少节点受到影响,而不是特定节点上的完整信息。
例如,突变updateManyPostsdeleteManyPosts提供了一个where参数来选择特定节点,并返回一个包含受影响节点数的计数字段(请参见上面的示例)。

请注意,批量突变不会触发订阅事件!

连接

与直接返回节点列表的简单对象查询相比,连接查询基于中继连接(Relay Connection)模型。除了分页信息之外,连接还提供了聚合等高级功能。

例如,尽管posts查询允许您选择特定的Post节点,但可以通过某些字段对结果进行排序并对结果进行分页,postsConnection查询还允许您计算所有未发布的帖子。

query {
  postsConnection {
    # `aggregate` allows to perform common aggregation operations
    aggregate {
      count
    }
    edges {
      # each `node` refers to a single `Post` element
      node {
        title
      }
    }
  }
}

事务性突变

Prisma API中非批处理操作的单个突变总是以事务方式执行,即使它们包含可能跨越关系的许多操作。这对于在多种类型上执行多个数据库写入的嵌套变异特别有用。

一个例子是创建一个User节点和两个将要连接的Post节点,同时也将User节点连接到另外两个已存在的Post节点,所有这些都在一个突变中。如果任何提交的操作失败(例如由于违反@unique字段约束),整个突变将回滚!

突变是事务性的,意味着它们是原子( atomic)的和孤立(isolated)的。这意味着在同一嵌套突变的两个独立行为之间,没有其他突变可以改变数据。在完成突变处理之前,单一行为的结果也不能被观察到。

级连删除

Prisma支持数据模型中关系的不同删除行为。有两种主要的删除行为:

如上所述,您可以为相关节点指定专门的删除行为。这就是@relation指令的onDelete参数所要做的。

type User {
  id: ID! @unique
  comments: [Comment!]! @relation(name: "CommentAuthor", onDelete: CASCADE)
  blog: Blog @relation(name: "BlogOwner", onDelete: CASCADE)
}

type Blog {
  id: ID! @unique
  comments: [Comment!]! @relation(name: "Comments", onDelete: CASCADE)
  owner: User! @relation(name: "BlogOwner", onDelete: SET_NULL)
}

type Comment {
  id: ID! @unique
  blog: Blog! @relation(name: "Comments", onDelete: SET_NULL)
  author: User @relation(name: "CommentAuthor", onDelete: SET_NULL)
}

认证(Authentication)

API 密钥(API secret)

Prisma服务的GraphQL API通常受到您在prisma.yml中指定为secret属性的API密钥的保护。

这是一个指定secretprisma.yml的例子:

endpoint: http://localhost:4466/myapi/dev
datamodel: datamodel.graphql

secret: mysecret123 # your API secret

API令牌(API token)

API令牌(token)用于对您的Prisma API进行身份验证。 API secret用于签署一个JWT,它需要在针对您的Prisma API进行的HTTP请求的Authorization标头中使用:

Authorization: Bearer __YOUR_API_TOKEN__

使用Prisma CLI获取API令牌

获取API令牌的最简单方法是使用Prisma CLI中的prisma token命令:

prisma token

prisma.yml可用的目录中运行prisma token时,CLI将从prisma.yml读取secret属性并生成相应的JWT。

在GraphQL Playground中进行身份验证

获得Prisma API的API令牌后,您可以使用它来验证您的API请求。例如,通过GraphQL Playground使用API​​。

一旦您为您的Prisma API打开了Playground,请打开Playground左下角的HTTP HEADERS字段。然后将您的API token粘贴为Authorization字段的值:

{
  "Authorization": "Bearer __YOUR_API_TOKEN__"
}

实际有了真正的令牌时,像如下这样:

{
  "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InNlcnZpY2UiOiJibG9nckBkZXYiLCJyb2xlcyI6WyJhZG1pbiJdfSwiaWF0IjoxNTE4NzE2NjA4LCJleHAiOjE1MTkzMjE0MDh9.zqBh_Oo4RmV4j3UQeVDYqJDxV-YHQiOR-XIlhjbWejw"
}
Authorization

声明

JWT必须包含不同的声明:

将来可能会通过引入诸如["write:Log", "read:*"]等角色的概念来支持更细粒度的访问控制。
这里是一个JTW的Payload示例。

{
  "exp": 1300819380,
  "service": "my-service@prod"
}

使用JavaScript生成服务token

考虑下面的prisma.yml

service: my-service

stage: ${env:PRISMA_STAGE}
cluster: ${env:PRISMA_CLUSTER}

datamodel: database/datamodel.graphql

secret: ${env:PRISMA_SECRET}

注意,次数为使用了环境变量的prisma.yml

一个服务节点创建了JWT标记,基于jsonwebtoken,对于服务my-service的stage PRISMA_STAGE是这样的:

var jwt = require('jsonwebtoken')

jwt.sign(
  {
    data: {
      service: 'my-service@' + process.env.PRISMA_STAGE,
    },
  },
  process.env.PRISMA_SECRET,
  {
    expiresIn: '1h',
  }
)

JWT验证

对于针对Prisma服务提出的请求,JWT的以下属性将得到验证:

错误处理

当您的某个查询或突变发生错误时,响应包含错误属性,其中包含有关错误代码,错误消息等的更多信息。

有两种API错误:

注意:error字段依据的GraphQL错误处理规范进行。

应用错误

API返回的错误通常表明某些内容对于请求的查询或突变不正确。您可能无意中在您的查询中输入了错字或忘记了必需的参数。尝试调查您的输入以找出与错误消息相关的可能错误。

错误解决

以下是您可能遇到的常见错误列表:

  1. Authentication

1.1 Insufficient permissions / Invalid token

{
  "errors": [
    {
      "code": 3015,
      "requestId": "api:api:cjc3kda1l000h0179mvzirggl",
      "message":
        "Your token is invalid. It might have expired or you might be using a token from a different project."
    }
  ]
}

检查您提供的令牌是否尚未过期,并使用prisma.yml中列出的secret进行签名。

内部服务错误

请查阅服务日志以获取有关该错误的更多信息。对于本地群集,可以使用prisma logs命令完成此操作。

上一篇 下一篇

猜你喜欢

热点阅读