expand.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. const { buildSchema, GraphQLObjectType, GraphQLString, GraphQLList, GraphQLSchema } = require('graphql');
  2. function mmExpandSchema(gqlSchema){
  3. const types = {}
  4. const _typeMap = gqlSchema.getTypeMap()
  5. const buildInTypes = ['Query', 'Mutation', 'ID', 'Float', "String", 'Int', 'Boolean',
  6. 'Query!', 'Mutation!', 'ID!', 'Float!', "String!", 'Int!', 'Boolean!' ]
  7. async function argToSavables(arg, outputTypeName, Savable){
  8. console.log('argToSavables', arg)
  9. const entity = arg._id ? await Savable.m[outputTypeName].findOne({_id: ObjectID(arg._id)}) :
  10. new Savable.classes[outputTypeName]({})
  11. const {_id, ...data} = arg;
  12. const type = _typeMap[outputTypeName + 'Input']
  13. const fields = type.getFields()
  14. for(let [fieldName, value] of Object.entries(data)){
  15. let typeName = fields[fieldName].type.toString()
  16. if (!buildInTypes.includes(typeName)){
  17. console.log('recursive', arg[fieldName], typeName)
  18. if (typeName[0] === '['){
  19. const nestedTypeName = typeName.slice(1,-6)
  20. console.log('array',nestedTypeName)
  21. entity[fieldName] = []
  22. for (let nestedArg of value){
  23. const nestedEntity = await argToSavables(nestedArg, nestedTypeName, Savable)
  24. entity[fieldName].push(nestedEntity)
  25. }
  26. }
  27. else {
  28. const nestedTypeName = typeName.slice(0,-5)
  29. console.log('one', nestedTypeName)
  30. entity[fieldName] = await argToSavables(value, nestedTypeName, Savable)
  31. }
  32. }
  33. else {
  34. entity[fieldName] = value
  35. }
  36. }
  37. return await entity.save()
  38. }
  39. let queryFields = _typeMap.Query ? _typeMap.Query.getFields() : {}
  40. let mutationFields = _typeMap.Mutation ? _typeMap.Mutation.getFields() : {}
  41. for (let [typeName, type] of Object.entries(_typeMap))
  42. if (!buildInTypes.includes(typeName) &&
  43. !typeName.startsWith('__')){
  44. if (typeName.endsWith('Input')){
  45. let outputTypeName = typeName.substr(0, typeName.length - 'Input'.length)
  46. if (outputTypeName in _typeMap){
  47. types[outputTypeName] = type
  48. const find = {
  49. type: GraphQLList(_typeMap[outputTypeName]),
  50. args: {query: {type: GraphQLString}},
  51. async resolve(root, args, context, info){
  52. //console.log(root, args, context, info)
  53. const Savable = context.models.SlicedSavable || context.models.Savable
  54. args = JSON.parse(args.query)
  55. let results = []
  56. for (let result of Savable.m[outputTypeName].find(...args)){
  57. try {result = await result} catch (e) { break }
  58. results.push(result)
  59. }
  60. return results;
  61. }
  62. }
  63. queryFields[`${outputTypeName}Find`] = find
  64. const findOne = {
  65. type: _typeMap[outputTypeName],
  66. args: {query: {type: GraphQLString}},
  67. async resolve(root, args, context, info){
  68. //console.log(root, args, context, info)
  69. const Savable = context.models.SlicedSavable || context.models.Savable
  70. args = JSON.parse(args.query)
  71. let [query] = args
  72. if (query._id && typeof query._id === 'string'){
  73. query._id = ObjectID(query._id)
  74. }
  75. let record = Savable.m[outputTypeName].findOne(query, ...args.slice(1))
  76. return record;
  77. }
  78. }
  79. queryFields[`${outputTypeName}FindOne`] = findOne
  80. const lowerCaseName = outputTypeName[0].toLowerCase() + outputTypeName.slice(1)
  81. const del = {
  82. type: _typeMap[outputTypeName],
  83. args: {[lowerCaseName]: {type: _typeMap[typeName]}},
  84. async resolve(root, args, context, info){
  85. //console.log(root, args, context, info)
  86. const Savable = context.models.SlicedSavable || context.models.Savable
  87. const arg = args[lowerCaseName]
  88. if (! ('_id' in arg)){
  89. return null;
  90. }
  91. let entity = await Savable.m[outputTypeName].findOne({_id: ObjectID(arg._id)})
  92. if (entity){
  93. let copy = {...record}
  94. await entity.delete()
  95. return copy;
  96. }
  97. return entity;
  98. }
  99. }
  100. mutationFields[`${outputTypeName}Delete`] = del
  101. const upsert = {
  102. type: _typeMap[outputTypeName],
  103. args: {[lowerCaseName]: {type: _typeMap[typeName]}},
  104. async resolve(root, args, context, info){
  105. //console.log(root, args, context, info)
  106. const Savable = context.models.SlicedSavable || context.models.Savable
  107. const arg = args[lowerCaseName]
  108. const entity = argToSavables(args[lowerCaseName], outputTypeName, Savable)
  109. return entity;
  110. }
  111. }
  112. mutationFields[`${outputTypeName}Upsert`] = upsert
  113. }
  114. }
  115. }
  116. let newQuery = new GraphQLObjectType({name: 'Query', fields: queryFields})
  117. let newMutation = new GraphQLObjectType({name: 'Mutation', fields: mutationFields})
  118. let newSchema = new GraphQLSchema({query: newQuery, mutation: newMutation})
  119. return newSchema;
  120. }
  121. module.exports = mmExpandSchema