-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
158 lines (148 loc) · 4.63 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"use-strict"
// Get the Kinvey Flex SDK.
const kinveyFlexSDK = require("kinvey-flex-sdk");
// GraphQL related dependencies.
const {
graphql,
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLNonNull,
} = require("graphql");
// The Kinvey Collection, that you will be dealing with.
const COLLECTION_NAME = "FriendsAges";
/**
* Since the Kinvey Flex SDK uses a callback pattern, we'll need to
* wrap those in promises.
*
* @param { Function } func
*/
function promisify(func) {
return (...args) => {
return new Promise((resolve, reject) => {
func(...args, (error, data) => {
if (error) {
return reject(error);
}
return resolve(data);
});
});
};
}
/**
* Fetch our Friend's data from the Kinvey Collection.
*
* @param { String } name
* @param { Object } context
*/
function fetchFriendData(name, context) {
const findPromisified = promisify(context.modules.dataStore().collection(COLLECTION_NAME).find);
return findPromisified(new context.modules.Query().equalTo("name", name))
.then(data => data[0]);
}
/**
* Logs any errors occured while processing the request.
*
* @param { Error } error
* @param { Object } context
*/
function logPromiseError(error, context) {
// Flex Logger is a custom module for logging.
// Please check the link given below.
// https://devcenter.kinvey.com/nodejs/guides/flex-services#LoggingMessages
context.flex.logger.error(error);
return Promise.reject(error);
}
/**
* Reveals to us what the age of a friend of ours is.
*
* @param { String } name
* @param { Object } context
*/
function getAge(name, context) {
return fetchFriendData(name, context)
.then((data) => {
if (!data || !data.age) {
return `Sorry. You still have not set age for your friend - ${name}. You can do that now.`;
}
return `Your friend - ${name}'s age is ${data.age}.`;
})
.catch(error => logPromiseError(error, context));
};
/**
* Sets the age of a friend of ours.
*
* @param { String } name
* @param { Number } age
* @param { Object } context
*/
function setAge(name, age, context) {
return fetchFriendData(name, context)
.then((data) => {
const savePromisified = promisify(context.modules.dataStore().collection(COLLECTION_NAME).save);
if (!data) {
return savePromisified({ name, age });
}
data.age = age;
return savePromisified(data);
})
.then(data => data.age)
.catch(error => logPromiseError(error, context));
};
// The query & mutation declarations to the schema.
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: "RootQueryType",
fields: {
getAge: {
args: { name: { name: "name", type: new GraphQLNonNull(GraphQLString) } },
type: GraphQLString,
resolve(parent, args, context) {
return getAge(args.name, context);
}
}
}
}),
mutation: new GraphQLObjectType({
name: "RootMutationType",
fields: {
setAge: {
args: {
name: { name: "name", type: new GraphQLNonNull(GraphQLString) },
age: { name: "age", type: new GraphQLNonNull(GraphQLInt) }
},
type: GraphQLString,
resolve(parent, args, context) {
return setAge(args.name, args.age, context);
}
}
}
})
});
// Initialize the Kinvey Flex Service.
kinveyFlexSDK.service((err, flex) => {
if (err) {
console.error("Error while initializing Flex!");
console.error(err);
return;
}
// Register the Kinvey Flex Function.
flex.functions.register("graphql", (context, complete, modules) => {
/**
* Since Flex functions get executed within different contexts (app environments),
* the information carried within the "context" and "modules" might
* differ. So, for each GraphQL request the respective function call's context needs
* to be prepared.
*/
const graphqlArguments = {
schema,
source: context.body.query,
contextValue: { flex, context, modules }
};
// FIRE!
graphql(graphqlArguments)
.then(data => complete().setBody(data).ok().next())
.catch(error => complete().setBody(error).runtimeError().done());
});
});