หัดใช้ GraphQL ตอนที่ 1.5 จัดระเบียบการสร้าง Schema ซักหน่อย (ฉบับโค้ดๆไปเหอะ)

Part นี้ จะมาจัดระเบียบการวาง File, Folder ใหม่ซะหน่อย จะให้เขียนโค้ด โดยใช้ File เดียวก็น่าหงุดหงิดไปใช่เล่น ซึ่งการจะแยก Module นั้นเราจะใช้ เจ้า module.exports นี้แหละ ทั้ง part ก็มีแค่เรื่องเดียวการใช้ module.export และ import มาใช้แบบ ES5 ไปก่อนนะครับ ไม่อยากใช้ ES6 เดี๋ยวจะมีอะไรมาเยอะเกิน

ตามรูปที่เพิ่มก็มี Folder และ File เปล่าๆอยู่

part1.5
- graphql // folder
- products // folder
- inputtype.js // file
- mutationfields.js // file
- queryfields.js // file
- schema.js // file

ต่อไปจะแยก module กัน

เริ่มจากไปเปิดไฟล์ server.js แล้ว copy โค้ดมาให้หมดเลย แล้วไปวางที่ไฟล์ schema.js

schema.js

ทีนี้เราจะเอาโค้ดส่วนที่จะใช้อย่างเดียวอยู่ไว้ อะไรไม่ใช้เอาออก

ตัดโค้ดออกครั้งแรก ที่ไฟล์ schema.js จะได้

// schema.js
var graphql = require('graphql');
var GraphQLSchema = graphql.GraphQLSchema;
var GraphQLObjectType = graphql.GraphQLObjectType;
var GraphQLString = graphql.GraphQLString;
var GraphQLList = graphql.GraphQLList;
var GraphQLInt = graphql.GraphQLInt;
var voteType = new GraphQLObjectType({
name: "vote",
description: "vote of The product",
fields: () => ({
star: {
type: GraphQLInt,
description: "one_star of the vote",
},
men: {
type: GraphQLInt,
description: "men of vote",
},
women: {
type: GraphQLInt,
description: "women of vote",
}
})
});
var productType = new GraphQLObjectType({
name: "products",
description: "Detail of The product",
fields: () => ({
name: {
type: GraphQLString,
description: "Name of the product",
},
price: {
type: GraphQLInt,
description: "price of product",
},
category: {
type: new GraphQLList(GraphQLString),
description: "category of product",
},
vote: {
type: new GraphQLList(voteType),
description: "vote of product",
}
})
});
var queryType = new GraphQLObjectType({
name: "queryProduct",
description: "query of product",
fields: () => ({
hey: {
type: GraphQLString,
resolve: function(_, args){
return products[0].name
}
},
getProducts: {
type: new GraphQLList(productType),
resolve: function(_, args){
return products
}
},
getProductByPrice: {
type: new GraphQLList(productType),
args: {
price: {
type: GraphQLInt
}
},
resolve: function(_, args){
var filterProduct = products.filter(function(product){
return product.price <= args.price
})
return filterProduct
}
}
})
});
var mutationType = new GraphQLObjectType({
name: "mutationProduct",
description: "mutation of product",
fields: () => ({
addProduct: {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
},
price: {
type: GraphQLInt
},
category: {
type: new GraphQLList(GraphQLString)
}
},
resolve: function(_, args){
var product = {
name: args.name,
price: args.price,
category: args.category
}
products.push(product)
return products
}
},
deleteProduct: {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
}
},
resolve: function(_, args){
return products.filter(function(product){
return product.name != args.name // bad
})
}
}
})
});
var MyGraphQLSchema = new GraphQLSchema({
query: queryType,
mutation: mutationType
});

ต่อไปที่ไฟล์ inputtype.js เอาเก็บรูปแบบข้อมูลต่างๆว่า Api นี้จะ return อะไรกลับไปให้บ้าง copy โค้ดที่ไฟล์ schema.js มาให้หมดแล้ววาง

inpputtype.js

ตัดโค้ดให้เหลือที่ใช้แค่นี้ inpputype.js

// inputtype.js
var graphql = require('graphql');
var GraphQLObjectType = graphql.GraphQLObjectType;
var GraphQLString = graphql.GraphQLString;
var GraphQLList = graphql.GraphQLList;
var GraphQLInt = graphql.GraphQLInt;
var voteType = new GraphQLObjectType({
name: "vote",
description: "vote of The product",
fields: () => ({
star: {
type: GraphQLInt,
description: "one_star of the vote",
},
men: {
type: GraphQLInt,
description: "men of vote",
},
women: {
type: GraphQLInt,
description: "women of vote",
}
})
});
var productType = new GraphQLObjectType({
name: "products",
description: "Detail of The product",
fields: () => ({
name: {
type: GraphQLString,
description: "Name of the product",
},
price: {
type: GraphQLInt,
description: "price of product",
},
category: {
type: new GraphQLList(GraphQLString),
description: "category of product",
},
vote: {
type: new GraphQLList(voteType),
description: "vote of product",
}
})
});
module.exports = {
productType: productType
}

ต่อไปที่ไฟล์ queryfields.js ทำเหมือนเดิม copy โค้ดที่ไฟล์ schema.js มาให้หมดแล้ววาง

queryfields.js

แล้วตัดโค้ดที่ไม่ใช้ออก เพิ่มโค้ดใหม่ โค้ดจะเป็นแบบนี้

// queryfields.js
var graphql = require('graphql');
var GraphQLObjectType = graphql.GraphQLObjectType;
var GraphQLString = graphql.GraphQLString;
var GraphQLList = graphql.GraphQLList;
var GraphQLInt = graphql.GraphQLInt;
var { productType } = require('./inputtype')
var products = require('../../data');
var getHey = {
type: GraphQLString,
resolve: function(_, args){
return products[0].name
}
}
var getProducts = {
type: new GraphQLList(productType),
resolve: function(_, args){
return products
}
}
var getProductByPrice = {
type: new GraphQLList(productType),
args: {
price: {
type: GraphQLInt
}
},
resolve: function(_, args){
var filterProduct = products.filter(function(product){
return product.price <= args.price
})
return filterProduct
}
}
module.exports = {
getHey: getHey, // ไม่จำเป็นที่ชื่อต้องซ้ำกัน
getProducts: getProducts,
getProductByPrice: getProductByPrice,
}

อธิบายตรง module.exports ซักนิด รูปแบบมันจะเป็น key : value

key จะเป็นชื่อเอาไว้ใช้ตอน import ที่ไฟล์อื่น

value คือ การทำงานของตัวแปรที่รับเข้ามาอาจจะเป็นfunctionหรือค่าอะไรก็ตาม ที่ไฟล์ปัจจุบัน

กลับไปที่ ไฟล์ schema.js

เปลี่ยนแปลงโค้ดครั้งที่สอง เป็น

// schema.js
var graphql = require('graphql');
var GraphQLSchema = graphql.GraphQLSchema;
var GraphQLObjectType = graphql.GraphQLObjectType;
var GraphQLString = graphql.GraphQLString;
var GraphQLList = graphql.GraphQLList;
var GraphQLInt = graphql.GraphQLInt;
var { getHey, getProducts, getProductByPrice } = require('./products/queryfields');
var queryType = new GraphQLObjectType({
name: "queryProduct",
description: "query of product",
fields: {
hey: getHey,
getProducts: getProducts,
getProductByPrice: getProductByPrice
}
});
var mutationType = new GraphQLObjectType({
name: "mutationProduct",
description: "mutation of product",
fields: () => ({
addProduct: {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
},
price: {
type: GraphQLInt
},
category: {
type: new GraphQLList(GraphQLString)
}
},
resolve: function(_, args){
var product = {
name: args.name,
price: args.price,
category: args.category
}
products.push(product)
return products
}
},
deleteProduct: {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
}
},
resolve: function(_, args){
return products.filter(function(product){
return product.name != args.name // bad
})
}
}
})
});
var MyGraphQLSchema = new GraphQLSchema({
query: queryType,
mutation: mutationType
});
var { getHey, getProducts, getProductByPrice } = require(‘./queryfields’); คือวิธีการ import ไฟล์ queryfields.js มาใช้

ต่อไปที่ไฟล์ mutationfields.js เหมือนเดิม copy โค้ดที่ schema.js ไปวาง

จากนั้นเปลี่ยนเพิ่มโค้ดให้เป็นแบบนี้

// mutationfields.js
var graphql = require('graphql');
var GraphQLObjectType = graphql.GraphQLObjectType;
var GraphQLString = graphql.GraphQLString;
var GraphQLList = graphql.GraphQLList;
var GraphQLInt = graphql.GraphQLInt;
var { productType } = require('./inputtype')
var products = require('../../data');
var addProduct = {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
},
price: {
type: GraphQLInt
},
category: {
type: new GraphQLList(GraphQLString)
}
},
resolve: function(_, args){
var product = {
name: args.name,
price: args.price,
category: args.category
}
products.push(product)
return products
}
}
var deleteProduct = {
type: new GraphQLList(productType),
args: {
name: {
type: GraphQLString
}
},
resolve: function(_, args){
return products.filter(function(product){
return product.name != args.name // bad
})
}
}
module.exports = {
addProduct: addProduct,
deleteProduct: deleteProduct
}

จากนั้นไปเปลี่ยนแปลงที่ไฟล์ schema.js ครั้งที่สาม

// schema.js
var graphql = require('graphql');
var GraphQLSchema = graphql.GraphQLSchema;
var GraphQLObjectType = graphql.GraphQLObjectType;
var { getHey, getProducts, getProductByPrice } = require('./products/queryfields');
var { addProduct, deleteProduct } = require('./products/mutationfields');
var queryType = new GraphQLObjectType({
name: "queryProduct",
description: "query of product",
fields: {
hey: getHey,
getProducts: getProducts,
getProductByPrice: getProductByPrice
}
});
var mutationType = new GraphQLObjectType({
name: "mutationProduct",
description: "mutation of product",
fields: {
addProduct: addProduct,
deleteProduct: deleteProduct
}
});
var MyGraphQLSchema = new GraphQLSchema({
query: queryType,
mutation: mutationType
});
module.exports = MyGraphQLSchema

จบสำหรับการแยก module ให้ไฟล์ schema แล้ว

ต่อไปก็ไปที่ไฟล์ server.js เปลี่ยนเป็นแบบนี้

var express = require('express');
var graphqlHTTP = require('express-graphql');
var app = express();
var PORT = process.env.port || 3000
var MyGraphQLSchema = require('./graphql/schema');
app.use('/graphql', graphqlHTTP({
schema: MyGraphQLSchema,
graphiql: true
}));
app.listen(PORT);
console.log("Server running on localhost:", PORT);

เสร็จเรียบร้อยแล้วครับ รู้สึกได้เลยว่าโค้ดเป็นระเบียบขึ้นเยอะ แล้วลองกลับไปใช้งานที่ GraphiQL ดูว่ายังใช้ได้เหมือนเดิมเปล่า

สุดท้ายการแยก Module นั้น ขึ้นอยู่การ Design ของแต่ละคนเลยนะครับ

โค้ด https://github.com/kenshero/learn-graphql

ตอนต่อไป เชื่อมต่อกับ MongoDB