Skip to content

Instantly share code, notes, and snippets.

@sibelius
Created February 26, 2020 18:53
Show Gist options
  • Save sibelius/bb129795f44a0f114cffbfdc5d754815 to your computer and use it in GitHub Desktop.
Save sibelius/bb129795f44a0f114cffbfdc5d754815 to your computer and use it in GitHub Desktop.
createLoader used on react europe relay workshop
// eslint-disable-next-line
import { mongooseLoader } from '@entria/graphql-mongoose-loader';
import DataLoader from 'dataloader';
import { ConnectionArguments } from 'graphql-relay';
import { Model, Types } from 'mongoose';
import { buildMongoConditionsFromFilters } from '@entria/graphql-mongo-helpers';
import { validateContextUser } from './validateContextUser';
import { withConnectionCursor } from './withConnectionCursor';
const defaultViewerCanSee = (context, data) => data;
type DataLoaderKey = string | Types.ObjectId;
type CreateLoaderArgs<Context> = {
model: Model<any>;
viewerCanSee?: (context: Context, any) => Promise<object>;
loaderName: string;
filterMapping?: object;
};
export const createLoader = <Context extends object>({
model,
viewerCanSee = defaultViewerCanSee,
loaderName,
filterMapping = {},
}: CreateLoaderArgs<Context>) => {
class Loader {
constructor(data: any) {
// TODO - improve this - get only model paths
// eslint-disable-next-line
Object.keys(data).map(key => {
this[key] = data[key];
});
this.id = data.id || data._id;
}
}
const nameIt = (name, cls) => ({ [name]: class extends cls {} }[name]);
const Wrapper = nameIt(model.collection.collectionName, Loader);
const getLoader = () => new DataLoader(ids => mongooseLoader(model, ids));
const load = async (context: Context, id: DataLoaderKey) => {
if (!id) {
return null;
}
try {
const data = await context.dataloaders[loaderName].load(id.toString());
if (!data) {
return null;
}
const filteredData = await viewerCanSee(context, data);
return filteredData ? new Wrapper(filteredData) : null;
} catch (err) {
return null;
}
};
const clearCache = ({ dataloaders }: Context, id: string) => dataloaders[loaderName].clear(id.toString());
const loadAll = validateContextUser(
withConnectionCursor(model, load, (context: Context, args: ConnectionArguments) => {
const builtMongoConditions = buildMongoConditionsFromFilters(context, args.filters, filterMapping);
const conditions = {
...builtMongoConditions.conditions,
};
const sort = {
createdAt: -1,
};
return {
conditions,
sort,
};
}),
);
return {
Wrapper,
getLoader,
clearCache,
load,
loadAll,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment