在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):nicolasdao/graphql-s2s开源软件地址(OpenSource Url):https://github.com/nicolasdao/graphql-s2s开源编程语言(OpenSource Language):JavaScript 99.7%开源软件介绍(OpenSource Introduction):
GraghQL Schema-2-Schema Transpiler ·Table Of ContentsWhat It DoesGraphQL S2S enriches the standard GraphQL Schema string used by both graphql.js and the Apollo Server. The enriched schema supports:
Installnodenpm install graphql-s2s --save browser<script src="https://unpkg.com/[email protected]/lib/graphqls2s.min.js"></script>
It is also possible to embed it after installing the graphql-s2s npm package: <script src="./node_modules/graphql-s2s/lib/graphqls2s.min.js"></script> Getting StartedBasicconst { transpileSchema } = require('graphql-s2s').graphqls2s
const { makeExecutableSchema } = require('graphql-tools')
const schema = `
type Node {
id: ID!
}
type Person inherits Node {
firstname: String
lastname: String
}
type Student inherits Person {
nickname: String
}
type Query {
students: [Student]
}
`
const resolver = {
Query: {
students(root, args, context) {
// replace this dummy code with your own logic to extract students.
return [{ id: 1, firstname: "Carry", lastname: "Connor", nickname: "Cannie" }]
}
}
};
const executableSchema = makeExecutableSchema({
typeDefs: [transpileSchema(schema)],
resolvers: resolver
}) Type InheritanceSingle Inheritanceconst schema = `
type Node {
id: ID!
}
# Inheriting from the 'Node' type
type Person inherits Node {
firstname: String
lastname: String
}
# Inheriting from the 'Person' type
type Student inherits Person {
nickname: String
}
` Multiple Inheritanceconst schema = `
type Node {
id: ID!
}
type Address {
streetAddress: String
city: String
state: String
}
# Inheriting from the 'Node' & 'Adress' type
type Person inherits Node, Address {
id: ID!
streetAddress: String
city: String
state: String
firstname: String
lastname: String
}
` More details in the code below. Generic Typesconst schema = `
# Defining a generic type
type Paged<T> {
data: [T]
cursor: ID
}
type Question {
name: String!
text: String!
}
# Using the generic type
type Student {
name: String
questions: Paged<Question>
}
# Using the generic type
type Teacher {
name: String
students: Paged<Student>
}
` More details in the code below. Metadata Decorationconst schema = `
# Defining a custom 'node' metadata attribute
@node
type Node {
id: ID!
}
type Student inherits Node {
name: String
# Defining another custom 'edge' metadata, and supporting a generic type
@edge(some other metadata using whatever syntax I want)
questions: [String]
}
` The enriched schema provides a richer and more compact notation. The transpiler converts the enriched schema into the standard expected by graphql.js (using the buildSchema method) as well as the Apollo Server. For more details on how to extract those extra information from the string schema, use the method getSchemaAST (example in section Metadata Decoration). Metadata can be added to decorate the schema types and properties. Add whatever you want as long as it starts with @ and start hacking your schema. The original intent of that feature was to decorate the schema with metadata @node and @edge so we could add metadata about the nature of the relations between types. Metadata can also be used to customize generic types names as shown in section How to use a custom name on generic types?. Deconstructing - Transforming - Rebuilding QueriesThis feature allows your GraphQl server to deconstruct any GraphQl query as an AST that can then be filtered and modified based on your requirements. That AST can then be rebuilt as a valid GraphQL query. A great example of that feature in action is the graphql-authorize middleware for graphql-serverless which filters query's properties based on the user's rights. For a concrete example, refer to the code below. How ToHow to use a custom name on generic types?Use the special keyword const schema = `
type Post {
code: String
}
type Brand {
id: ID!
name: String
posts: Page<Post>
}
@alias((T) => T + 's')
type Page<T> {
data: [T]
}
` After transpilation, the resulting schema is: const output = transpileSchema(schema)
// output:
// =======
// type Post {
// code: String
// }
//
// type Brand {
// id: ID!
// name: String
// posts: Posts
// }
//
// type Posts {
// data: [Post]
// } ExamplesWARNING: the following examples will be based on 'graphql-tools' from the Apollo team, but the string schema could also be used with the 'buildSchema' method from graphql.js Type InheritanceNOTE: The examples below only use 'type', but it would also work on 'input' and 'interface' Before graphql-s2s const schema = `
type Teacher {
id: ID!
creationDate: String
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
title: String!
}
type Student {
id: ID!
creationDate: String
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
nickname: String!
}` After graphql-s2s const schema = `
type Node {
id: ID!
creationDate: String
}
type Person inherits Node {
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
}
type Teacher inherits Person {
title: String!
}
type Student inherits Person {
nickname: String!
}` Full code example const { transpileSchema } = require('graphql-s2s').graphqls2s
const { makeExecutableSchema } = require('graphql-tools')
const { students, teachers } = require('./dummydata.json')
const schema = `
type Node {
id: ID!
creationDate: String
}
type Person inherits Node {
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
}
type Teacher inherits Person {
title: String!
}
type Student inherits Person {
nickname: String!
questions: [Question]
}
type Question inherits Node {
name: String!
text: String!
}
type Query {
# ### GET all users
#
students: [Student]
# ### GET all teachers
#
teachers: [Teacher]
}
`
const resolver = {
Query: {
students(root, args, context) {
return Promise.resolve(students)
},
teachers(root, args, context) {
return Promise.resolve(teachers)
}
}
}
const executableSchema = makeExecutableSchema({
typeDefs: [transpileSchema(schema)],
resolvers: resolver
}) Generic TypesNOTE: The examples below only use 'type', but it would also work on 'input' Before graphql-s2s const schema = `
type Teacher {
id: ID!
creationDate: String
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
title: String!
}
type Student {
id: ID!
creationDate: String
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
nickname: String!
questions: Questions
}
type Question {
id: ID!
creationDate: String
name: String!
text: String!
}
type Teachers {
data: [Teacher]
cursor: ID
}
type Students {
data: [Student]
cursor: ID
}
type Questions {
data: [Question]
cursor: ID
}
type Query {
# ### GET all users
#
students: Students
# ### GET all teachers
#
teachers: Teachers
}
` After graphql-s2s const schema = `
type Paged<T> {
data: [T]
cursor: ID
}
type Node {
id: ID!
creationDate: String
}
type Person inherits Node {
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
}
type Teacher inherits Person {
title: String!
}
type Student inherits Person {
nickname: String!
questions: Paged<Question>
}
type Question inherits Node {
name: String!
text: String!
}
input Filter<FilterFields> {
field: FilterFields!,
value: String!
}
enum TeachersFilterFields {
firstName
lastName
}
type Query {
# ### GET all users
#
students: Paged<Student>
# ### GET all teachers
# You can use generic types on parameters, too.
#
teachers(filter: Filter<TeachersFilterFields>): Paged<Teacher>
}
` This is very similar to C# or Java generic classes. What the transpiler will do is to simply recreate 3 types (one for Paged<Question>, Paged<Student> and Paged<Teacher>), and one input (Filter<TeachersFilterFields>). If we take the Paged<Question> example, the transpiled type will be: type PagedQuestion {
data: [Question]
cursor: ID
} Full code example const { transpileSchema } = require('graphql-s2s').graphqls2s
const { makeExecutableSchema } = require('graphql-tools')
const { students, teachers } = require('./dummydata.json')
const schema = `
type Paged<T> {
data: [T]
cursor: ID
}
type Node {
id: ID!
creationDate: String
}
type Person inherits Node {
firstname: String!
middlename: String
lastname: String!
age: Int!
gender: String
}
type Teacher inherits Person {
title: String!
}
type Student inherits Person {
nickname: String!
questions: Paged<Question>
}
type Question inherits Node {
name: String!
text: String!
}
type Query {
# ### GET all users
#
students: Paged<Student>
# ### GET all teachers
#
teachers: Paged<Teacher>
}
`
const resolver = {
Query: {
students(root, args, context) {
return Promise.resolve({ data: students.map(s => ({ __proto__:s, questions: { data: s.questions, cursor: null }})), cursor: null })
},
teachers(root, args, context) {
return Promise.resolve({ data: teachers, cursor: null });
}
}
}
const executableSchema = makeExecutableSchema({
typeDefs: [transpileSchema(schema)],
resolvers: resolver
}) Metadata DecorationDefine your own custom metadata and decorate your GraphQL schema with new types of data. Let's imagine we want to explicitely add metadata about the type of relations between nodes, we could write something like this: const { getSchemaAST } = require('graphql-s2s').graphqls2s
const schema = `
@node
type User {
@edge('<-[CREATEDBY]-')
posts: [Post]
}
`
const schemaObjects = getSchemaAST(schema);
// -> schemaObjects
// {
// "type": "TYPE",
// "name": "User",
// "metadata": {
// "name": "node",
// "body": "",
// "schemaType": "TYPE",
// "schemaName": "User", "parent": null
// },
// "genericType": null,
// "blockProps": [{
// "comments": "",
// "details": {
// "name": "posts",
// "metadata": {
// "name": "edge",
// "body": "(\'<-[CREATEDBY]-\')",
// "schemaType": "PROPERTY",
// "schemaName": "posts: [Post]",
// "parent": {
// "type": "TYPE",
// "name": "User",
// "metadata": {
// "type": "TYPE",
// "name": "node"
// }
// }
// },
// "params": null,
// "result": {
// "originName": "[Post]",
// "isGen": false,
// "name": "[Post]"
// }
// },
// "value": "posts: [Post]"
// }],
// "inherits": null,
// "implements": null
// } Deconstructing - Transforming - Rebuilding QueriesThis feature allows your GraphQl server to deconstruct any GraphQl query as an AST that can then be filtered and modified based on your requirements. That AST can then be rebuilt as a valid GraphQL query. A great example of that feature in action is the graphql-authorize middleware for graphql-serverless which filters query's properties based on the user's rights. const { getQueryAST, buildQuery, getSchemaAST } = require('graphql-s2s').graphqls2s
const schema = `
type Property {
name: String
@auth
address: String
}
input InputWhere {
name: String
locations: [LocationInput]
}
input LocationInput {
type: String
value: String
}
type Query {
properties(where: InputWhere): [Property]
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论