-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.js
122 lines (98 loc) · 2.7 KB
/
graph.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
import * as path from 'path'
import camelCase from 'lodash/camelCase'
import map from 'lodash/map'
import mapValues from 'lodash/mapValues'
import { fileLoader, mergeTypes } from 'merge-graphql-schemas'
const TYPES = ['Int', 'Float', 'String', 'Boolean', 'ID']
// SCHEMA
const generateSchema = (models) => {
const typeDefs = mergeTypes(map(models, generateModelTypes))
const resolvers = generateModelResolvers(models)
return {
typeDefs,
resolvers,
}
}
// TYPEDEFS
const generateType = (model, attributes) => {
const withID = { _id: 'ID!', ...attributes }
const mapped = map(withID, (type, key) => `${key}: ${type}`)
return `
type ${model} {
${mapped.join('\n ')}
}
`
}
const generateInput = (model, attributes) => {
const replaced = mapValues(attributes, (type, key) =>
TYPES.includes(type.replace(/!/g, ''))
? type
: `ID`
)
const mapped = map(replaced, (type, key) =>
`${key}: ${type.replace(/!/g, '')}`
)
return `
input ${model}Input {
${mapped.join('\n ')}
}
`
}
const generateModelTypes = (attributes, name) => {
const type = generateType(name, attributes)
const input = generateInput(name, attributes)
return `
type Query {
${camelCase(name)}s: [${name}]
${camelCase(name)}(_id: ID!): ${name}
}
type Mutation {
create${name}(input: ${name}Input): ${name}
update${name}(_id: ID!, input: ${name}Input): ${name}
delete${name}(_id: ID!): ${name}
}
${type}
${input}
`
}
// RESOLVERS
const generateModelResolvers = (schema) =>
map(schema, generateResolvers)
const generateResolvers = (attributes, model) => ({
Query: {
[`${camelCase(model)}s`]: generateResolver(
model,
(Model, args) => Model.find(args)
),
[camelCase(model)]: generateResolver(
model,
(Model, args) => Model.findOne(args)
),
},
Mutation: {
[`create${model}`]: generateResolver(
model,
(Model, { input }) => Model.create(input),
),
[`update${model}`]: generateResolver(
model,
(Model, { _id, input }) =>
Model.findOneAndUpdate({ _id }, input, { new: true }),
),
[`delete${model}`]: generateResolver(
model,
(Model, { _id }) => Model.deleteOne({ _id }),
),
},
[model]: generateAttributeResolvers(model, attributes)
})
const generateResolver = (model, run) =>
(parent, args, context) =>
run(context[model], args)
const generateAttributeResolvers = (model, attributes) =>
mapValues(attributes, generateAttributeResolver(model))
const generateAttributeResolver = (model) => (type, name) =>
TYPES.includes(type.replace(/!/g, ''))
? (parent) => parent[name]
: (parent, args, context) => context[type].findOne({ _id: parent[name] })
export default generateSchema