GraphQL === ## Scalar Types - `Int`: A signed 32-bit integer. - `Float`: A signed double-precision floating point value. - `String`: A UTF-8 character sequece. - `Boolean`: `true` or `false`. - `ID`: The ID scalar type represents unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an `ID` signifies that it is not intended to be human-readable. ## Design Patterns of GraphQL ### Node ID Interface Pattern: Node ID Interface 一方面增加了結構的可讀性,讓人可以一眼了解這個物件的重要性與意義,另一方面前端也能針對物件的 id 做 caching 或其他管理,以增加效能與效率。 ``` type Node { id: ID! } type User Implement Node { id: ID! ... } type Post Implement Node { id: ID! ... } ``` 另外還可以開這麼一個 query field 來增加 Schema 的彈性。 ``` type Query { node(id: ID!): Node } ``` **Recommend: All important business objects implement Node Interface.** ### Connection Pattern: When data are much amount of array, it will cause the issue of performance of the query. Connection pattern can be used be pagination strategy. ``` type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String } type UserEdge { cursor: String! node: User } type UserConnection { edges: [UserEdge!]! pageInfo: PageInfo! total: Int } ``` ### Viewer Pattern: 使用 Viewer 模式可以很切合地配合前端的需求,只要使用 `query.viewer` 就可以滿足一個使用者幾乎所有的資料需求。 此外 Viewer 模式讓你的權限管理更加方便,不必要一隻一隻 query 的檢查,只需要配合進來的 viewer 身份給予符合權限的資料即可以,因此非常適合有很多種使用者身份的系統。 ``` type Viewer { self: User products: [Product] orders: [Order] cart: Cart recommendedProducts: [Product] } ``` ### Relay Mutation Pattern: Relay uses a common pattern for mutations, where there are root fields on the mutation type with a single argument, `input`, and where the input and output both contain a client mutation identifier used to reconcile requests and responses. By convention, mutations are named as verbs, their inputs are the name with "Input" appended at the end, and they return an object that is the name with "Payload" appended. ``` input IntroduceShipmentInput { factionId: ID! shipName: String! clientMutationId: String! } type IntroduceShipmentPayload { faction: Faction ship: Ship clientMutationId: String! } type Mutation { introduceShip(input: IntroduceShipmentInput!): IntroduceShipmentPayload } ```