Merge branch 'devel' of https://github.com/VulcanJS/Vulcan into devel

This commit is contained in:
SachaG 2018-09-12 10:07:23 +09:00
commit 493380889b
7 changed files with 42 additions and 22 deletions

View file

@ -61,7 +61,7 @@ export default function withMulti(options) {
const { fragmentName, fragment } = extractFragmentInfo(options, collectionName); const { fragmentName, fragment } = extractFragmentInfo(options, collectionName);
const typeName = collection.options.typeName; const typeName = collection.options.typeName;
const resolverName = Utils.camelCaseify(Utils.pluralize(typeName)); const resolverName = collection.options.multiResolverName;
// build graphql query from options // build graphql query from options
const query = gql` const query = gql`
@ -189,7 +189,7 @@ export default function withMulti(options) {
: providedTerms; : providedTerms;
return props.data.fetchMore({ return props.data.fetchMore({
variables: { terms: newTerms }, // ??? not sure about 'terms: newTerms' variables: { input: { terms: newTerms } }, // ??? not sure about 'terms: newTerms'
updateQuery(previousResults, { fetchMoreResult }) { updateQuery(previousResults, { fetchMoreResult }) {
// no more post to fetch // no more post to fetch
if (!fetchMoreResult.data) { if (!fetchMoreResult.data) {

View file

@ -94,7 +94,7 @@ export function getDefaultResolvers(options) {
description: `A single ${typeName} document fetched by ID or slug`, description: `A single ${typeName} document fetched by ID or slug`,
async resolver(root, { input = {} }, context, { cacheControl }) { async resolver(root, { input = {} }, context, { cacheControl }) {
const { selector = {}, enableCache = false } = input; const { selector = {}, enableCache = false, allowNull = false } = input;
debug(''); debug('');
debugGroup(`--------------- start \x1b[35m${typeName} Single Resolver\x1b[0m ---------------`); debugGroup(`--------------- start \x1b[35m${typeName} Single Resolver\x1b[0m ---------------`);
@ -116,8 +116,12 @@ export function getDefaultResolvers(options) {
: await Connectors.get(collection, selector); : await Connectors.get(collection, selector);
if (!doc) { if (!doc) {
const MissingDocumentError = createError('app.missing_document', { message: 'app.missing_document' }); if (allowNull) {
throw new MissingDocumentError({ data: { documentId, slug } }); return { result: null };
} else {
const MissingDocumentError = createError('app.missing_document', { message: 'app.missing_document' });
throw new MissingDocumentError({ data: { documentId, slug } });
}
} }
// if collection has a checkAccess function defined, use it to perform a check on the current document // if collection has a checkAccess function defined, use it to perform a check on the current document
@ -137,4 +141,4 @@ export function getDefaultResolvers(options) {
}, },
}, },
}; };
} }

View file

@ -37,7 +37,7 @@ Mongo.Collection.prototype.attachSchema = function (schemaOrFields) {
} else { } else {
this.simpleSchema().extend(schemaOrFields) this.simpleSchema().extend(schemaOrFields)
} }
} };
/** /**
* @summary Add an additional field (or an array of fields) to a schema. * @summary Add an additional field (or an array of fields) to a schema.
@ -134,6 +134,8 @@ export const createCollection = options => {
// add typeName if missing // add typeName if missing
collection.typeName = typeName; collection.typeName = typeName;
collection.options.typeName = typeName; collection.options.typeName = typeName;
collection.options.singleResolverName = Utils.camelCaseify(typeName);
collection.options.multiResolverName = Utils.camelCaseify(Utils.pluralize(typeName));
// add collectionName if missing // add collectionName if missing
collection.collectionName = collectionName; collection.collectionName = collectionName;
@ -158,13 +160,13 @@ export const createCollection = options => {
hidden: true, hidden: true,
type: Array, type: Array,
isIntlData: true, isIntlData: true,
} };
delete schema[`${fieldName}_intl`].intl; delete schema[`${fieldName}_intl`].intl;
schema[`${fieldName}_intl.$`] = { schema[`${fieldName}_intl.$`] = {
type: getIntlString(), type: getIntlString(),
} };
// if original field is required, enable custom validation function instead of `optional` property // if original field is required, enable custom validation function instead of `optional` property
if (!schema[fieldName].optional) { if (!schema[fieldName].optional) {
@ -287,9 +289,9 @@ export const createCollection = options => {
// console.log(parameters); // console.log(parameters);
return parameters; return parameters;
} };
Collections.push(collection); Collections.push(collection);
return collection; return collection;
} };

View file

@ -50,6 +50,7 @@ SimpleSchema.extendOptions([
'options', // form options 'options', // form options
'query', // field-specific data loading query 'query', // field-specific data loading query
'selectable', // field can be used as part of a selector when querying for data 'selectable', // field can be used as part of a selector when querying for data
'unique', // field can be used as part of a selectorUnique when querying for data
'orderable', // field can be used to order results when querying for data 'orderable', // field can be used to order results when querying for data
'intl', // set to `true` to make a field international 'intl', // set to `true` to make a field international

View file

@ -125,7 +125,7 @@ export const GraphQLSchema = {
this.directives = deepmerge(this.directives, directive); this.directives = deepmerge(this.directives, directive);
}, },
// for a given schema, return main type fields, selector fields, // for a given schema, return main type fields, selector fields,
// unique selector fields, orderBy fields, creatable fields, and updatable fields // unique selector fields, orderBy fields, creatable fields, and updatable fields
getFields(schema, typeName) { getFields(schema, typeName) {
const fields = { const fields = {
@ -227,7 +227,17 @@ export const GraphQLSchema = {
} }
if (field.selectable) { if (field.selectable) {
// TODO fields.selector.push({
name: fieldName,
type: inputFieldType,
});
}
if (field.selectable && field.unique) {
fields.selectorUnique.push({
name: fieldName,
type: inputFieldType,
});
} }
if (field.orderable) { if (field.orderable) {
@ -289,13 +299,13 @@ export const GraphQLSchema = {
const queryResolvers = {}; const queryResolvers = {};
// single // single
if (resolvers.single) { if (resolvers.single) {
addGraphQLQuery(singleQueryTemplate({ typeName }), resolvers.single.description); addGraphQLQuery(singleQueryTemplate({ typeName }), resolvers.single.description);
queryResolvers[Utils.camelCaseify(typeName)] = resolvers.single.resolver.bind(resolvers.single); queryResolvers[Utils.camelCaseify(typeName)] = resolvers.single.resolver.bind(resolvers.single);
} }
// multi // multi
if (resolvers.multi) { if (resolvers.multi) {
addGraphQLQuery(multiQueryTemplate({ typeName }), resolvers.multi.description); addGraphQLQuery(multiQueryTemplate({ typeName }), resolvers.multi.description);
queryResolvers[Utils.camelCaseify(Utils.pluralize(typeName))] = resolvers.multi.resolver.bind(resolvers.multi); queryResolvers[Utils.camelCaseify(Utils.pluralize(typeName))] = resolvers.multi.resolver.bind(resolvers.multi);
} }

View file

@ -2,7 +2,7 @@ import { Utils } from './utils';
export const convertToGraphQL = (fields, indentation) => { export const convertToGraphQL = (fields, indentation) => {
return fields.length > 0 ? fields.map(f => fieldTemplate(f, indentation)).join(`\n`) : ''; return fields.length > 0 ? fields.map(f => fieldTemplate(f, indentation)).join(`\n`) : '';
} };
export const arrayToGraphQL = fields => fields.map(f => `${f.name}: ${f.type}`).join(', '); export const arrayToGraphQL = fields => fields.map(f => `${f.name}: ${f.type}`).join(', ');
@ -19,7 +19,7 @@ export const getArguments = args => {
} else { } else {
return ''; return '';
} }
} };
/* ------------------------------------- Generic Field Template ------------------------------------- */ /* ------------------------------------- Generic Field Template ------------------------------------- */
@ -158,6 +158,8 @@ export const singleInputTemplate = ({ typeName }) =>
selector: ${typeName}SelectorUniqueInput selector: ${typeName}SelectorUniqueInput
# Whether to enable caching for this query # Whether to enable caching for this query
enableCache: Boolean enableCache: Boolean
# Return null instead of throwing MissingDocumentError
allowNull: Boolean
}`; }`;
/* /*
@ -175,11 +177,11 @@ type MultiMovieInput {
export const multiInputTemplate = ({ typeName }) => export const multiInputTemplate = ({ typeName }) =>
`input Multi${typeName}Input { `input Multi${typeName}Input {
# A JSON object that contains the query terms used to fetch data # A JSON object that contains the query terms used to fetch data
terms: JSON, terms: JSON,
# How much to offset the results by # How much to offset the results by
offset: Int, offset: Int,
# A limit for the query # A limit for the query
limit: Int, limit: Int,
# Whether to enable caching for this query # Whether to enable caching for this query
enableCache: Boolean enableCache: Boolean
# Whether to calculate totalCount for this query # Whether to calculate totalCount for this query
@ -348,7 +350,7 @@ export const createInputTemplate = ({ typeName }) =>
/* /*
Type for update mutation input argument Type for update mutation input argument
type UpdateMovieInput { type UpdateMovieInput {
selector: MovieSelectorUniqueInput! selector: MovieSelectorUniqueInput!
@ -540,4 +542,4 @@ export const deleteClientTemplate = ({ typeName, fragmentName }) =>
...${fragmentName} ...${fragmentName}
} }
} }
}`; }`;

View file

@ -205,6 +205,7 @@ Users.isAdminById = Users.isAdmin;
Users.getViewableFields = function (user, collection, document) { Users.getViewableFields = function (user, collection, document) {
return Utils.arrayToFields(_.compact(_.map(collection.simpleSchema()._schema, return Utils.arrayToFields(_.compact(_.map(collection.simpleSchema()._schema,
(field, fieldName) => { (field, fieldName) => {
if (fieldName.indexOf('.$') > -1) return null;
return Users.canReadField(user, field, document) ? fieldName : null; return Users.canReadField(user, field, document) ? fieldName : null;
} }
))); )));