Skip to content

Instantly share code, notes, and snippets.

@thebigredgeek
Created December 5, 2016 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save thebigredgeek/1b061644fd3e4f475574e71838bfd178 to your computer and use it in GitHub Desktop.
Save thebigredgeek/1b061644fd3e4f475574e71838bfd178 to your computer and use it in GitHub Desktop.
Breed-able Resolvers
import { AlreadyAuthenticatedError, NotAuthenticatedError, NotAuthorizedError } from '../errors/functional';
import createResolver from '../lib/createResolver';
export const baseResolver = createResolver();
export const isAuthenticatedResolver = baseResolver.createResolver(
(root, args, context) => {
if (!context.user || !context.user.id) throw new NotAuthenticatedError();
}
);
export const isNotAuthenticatedResolver = baseResolver.createResolver(
(roor, args, context) => {
if (context.user && context.user.id) throw new AlreadyAuthenticatedError();
}
)
export const isExpertResolver = isAuthenticatedResolver.createResolver(
async (root, args, context) => {
const expert = await context.user.getExpert();
if (!expert) throw new NotAuthorizedError();
context.user.Expert = expert;
}
)
export const isCustomerResolver = isAuthenticatedResolver.createResolver(
async (root, args, context) => {
const customer = await context.user.getCustomer();
if (!customer) throw new NotAuthorizedError();
context.user.Customer = customer;
}
);
import _ from 'underscore';
import objectPath from 'object-path';
import { createError } from 'apollo-errors';
const pathExists = (key = '', obj = {}) => {
if (key.indexOf('&&') !== -1) return key.split(/\s*\&\&\s*/).reduce((bool, key) => bool && pathExists(key.trim(), obj), true);
if (key.indexOf('||') !== -1) return key.split(/\s*\|\|\s*/).reduce((bool, key) => bool || pathExists(key.trim(), obj), false);
key = key.replace(/\[(\w+)\]/g, '.$1') // convert indexes to properties
return !!objectPath.get(obj, key);
};
export const createRequiredFieldsValidator = (argKey = '', fields = {}) => {
const Errors = Object.keys(fields)
.reduce((hash, key) => ({
...hash,
[key]: createError(`FieldsRequiredError`, {
message: fields[key],
data: {
path: key
}
})
}), {});
return (root, args, context) => {
Object.keys(fields).forEach(key => {
if (!pathExists(args, key)) throw new Errors[key]();
});
};
};
const createResolver = (resFn, errFn) => {
const baseResolver = async (root, args = {}, context = {}) => {
try {
if (!_.isFunction(resFn)) return null;
return await resFn(root, args, context);
} catch (err) {
if (!_.isFunction(errFn)) throw err;
const parsedError = await errFn(root, args, context, err)
throw parsedError || err;
}
};
baseResolver.createResolver = (cResFn, cErrFn) => createResolver(
async (root, args, context) => {
const r = _.isFunction(resFn) ? await resFn(root, args, context) : null;
if (r) return r;
return _.isFunction(cResFn) ? await cResFn(root, args, context) : null;
},
async (root, args, context, err) => {
const r = _.isFunction(errFn) ? await errFn(root, args, context, err) : null;
if (r) throw r;
const cR = _.isFunction(cErrFn) ? await cErrFn(root, args, context, err) : null;
throw cR || err;
}
);
baseResolver.requireArgs = (argKey = '', fields = {}) => {
const validator = createRequiredFieldsValidator(argKey, fields)
return createResolver(
async (root, args, context) => {
await validator(root, args, context);
return _.isFunction(resFn) ? await resFn(root, args, context) : null;
}
)
};
return baseResolver;
};
export default createResolver;
import { isNotAuthenticatedResolver } from './_base';
import { LoginFailedError } from '../errors/functional';
export const loginUser = isNotAuthenticatedResolver.createResolver(
async (root, { user: { email, password } }, context) => {
const { models: { User } } = context;
const { user, token } = await User.login({ email, password });
if (!user) throw new LoginFailedError();
context.user = user; //attach user to context for subsequent requests
return {
...user.toJSON(),
token
}
}
);
export default {
User: {
CurrentLocation: user => user.getCurrentLocation(),
HomeLocation: user => user.getHomeLocation(),
Resume: user => user.getResume(),
Avatar: user => user.getAvatar(),
Customer: user => user.getCustomer(),
Expert: (user, args, context) => context.models.User.rebuild(user).getExpert(),
PastPositions: d => d,
CurrentPosition: user => user.getCurrentPosition(),
Skills: user => user.getSkills(),
//Emails: d => d
},
Mutation: {
loginUser
},
Query: {
getMyUser: (r, a, { user }) => user
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment