Vulcan/packages/nova-lib/lib/graphql.js

147 lines
3.7 KiB
JavaScript
Raw Normal View History

2016-11-03 21:39:09 +09:00
import deepmerge from 'deepmerge';
const jsTypeToGraphQLType = typeName => {
switch (typeName) {
case "Date":
return "String";
case "Number":
return "Float";
// assume all arrays contains strings for now
case "Array":
return "[String]";
case "Object":
return "???";
default:
return typeName;
}
}
Telescope.graphQL = {
// collections used to auto-generate schemas
collections: [],
2016-11-08 15:12:23 +09:00
addCollection(collection) {
this.collections.push(collection);
},
getCollectionsSchemas() {
const collectionsSchemas = this.collections.map(collection => {
2016-11-08 15:12:23 +09:00
return this.generateSchema(collection);
}).join('\n');
return collectionsSchemas;
},
// additional schemas
schemas: [],
addSchema(schema) {
this.schemas.push(schema);
},
getAdditionalSchemas() {
const additionalSchemas = this.schemas.join('\n');
return additionalSchemas;
},
// queries
queries: [],
addQuery(query) {
this.queries.push(query);
},
// mutations
mutations: [],
addMutation(mutation) {
this.mutations.push(mutation);
},
// add resolvers
2016-11-03 21:39:09 +09:00
resolvers: {},
addResolvers(resolvers) {
this.resolvers = deepmerge(this.resolvers, resolvers);
},
// add objects to context
2016-11-03 21:39:09 +09:00
context: {},
addToContext(object) {
this.context = deepmerge(this.context, object);
2016-11-07 17:45:17 +09:00
},
2016-11-08 15:12:23 +09:00
generateSchema(collection) {
const collectionName = collection._name;
2016-11-08 15:12:23 +09:00
const mainTypeName = collection.typeName ? collection.typeName : Telescope.utils.camelToSpaces(_.initial(collectionName).join('')); // default to posts -> Post
let schema = collection.simpleSchema()._schema;
// backward-compatibility code: we do not want user.telescope fields in the graphql schema
if (collectionName === "users") {
// grab the users schema keys
const schemaKeys = Object.keys(schema);
// remove any field beginning by telescope: .telescope, .telescope.upvotedPosts.$, ...
const filteredSchemaKeys = schemaKeys.filter(key => key.slice(0,9) !== 'telescope');
// replace the previous schema by an object based on this filteredSchemaKeys
schema = filteredSchemaKeys.reduce((sch, key) => ({...sch, [key]: schema[key]}), {});
}
let mainSchema = [], inputSchema = [], unsetSchema = [];
_.forEach(schema, (field, key) => {
// console.log(field, key)
const fieldType = jsTypeToGraphQLType(field.type.name);
if (key.indexOf('$') === -1 && fieldType !== "???") { // skip fields with "$" and unknown fields
// 1. main schema
2016-11-08 15:16:58 +09:00
mainSchema.push(`${key}: ${fieldType}`);
// if field has a resolver, also push it to schema
if (field.resolveAs) {
mainSchema.push(field.resolveAs);
}
if (field.insertableIf || field.editableIf) {
const isRequired = field.optional ? '' : '!';
// 2. input schema
inputSchema.push(`${key}: ${fieldType}${isRequired}`);
// 3. unset schema
unsetSchema.push(`${key}: Boolean`);
}
}
});
const graphQLSchema = `
type ${mainTypeName} {
${mainSchema.join('\n ')}
}
input ${collectionName}Input {
${inputSchema.join('\n ')}
}
input ${collectionName}Unset {
${unsetSchema.join('\n ')}
}
`;
// const graphQLSchema = _.compact(_.map(schema, (field, key) => {
// // console.log(field, key)
// if (key.indexOf('$') !== -1) {
// // skip fields with "$"
// return
// } else {
// // if field has a resolver, use it, else use a name: type pattern
// return !!field.resolveAs ? field.resolveAs : `${key}: ${jsTypeToGraphQLType(field.type.name)}`
// }
// })).join('\n');
return graphQLSchema;
}
};