Skip to content

Instantly share code, notes, and snippets.

@rafaelcorreiapoli
Last active March 28, 2020 20:52
Show Gist options
  • Save rafaelcorreiapoli/8f13c097c2f8f1557b4ae8dd08098c09 to your computer and use it in GitHub Desktop.
Save rafaelcorreiapoli/8f13c097c2f8f1557b4ae8dd08098c09 to your computer and use it in GitHub Desktop.
interface IArgDescription {
name: string;
type: () => any;
}
interface IResolverDescription {
name: string;
resolver: Function;
decorator: MethodDecorator;
methodArgs: IArgDescription[];
}
export const GraphQLCrud = <T>({
name,
classType,
updateInputClassType,
}: {
name: string;
classType: Type<T>;
updateInputClassType: Type<any>;
}): ClassDecorator => target => {
Resolver(classType)(target);
const instanceName = 'instance';
const getOneMethodName = `single${name}`;
const getManyMethodName = `all${name}s`;
const deleteMethodName = `delete${name}`;
const updateMethodName = `update${name}`;
const findOneResolver = (id: number) => {
// TODO: How can I access the Service here?
};
const findManyResolver = () => {
// TODO: How can I access the Service here?
};
const deleteOneResolver = (id: number) => {
// TODO: How can I access the Service here?
};
const updateResolver = (id: number, payload: typeof updateInputClassType) => {
// TODO: How can I access the Service here?
};
@ObjectType(`Update${name}Payload`, {
isAbstract: true,
})
class UpdatePayload {
@Field(() => classType, { name: name.toLowerCase() })
[instanceName]: typeof classType;
}
const resolvers: IResolverDescription[] = [
{
decorator: Query(() => classType),
name: getOneMethodName,
resolver: findOneResolver,
methodArgs: [
{
name: 'id',
type: () => Int,
},
],
},
{
decorator: Query(() => [classType]),
name: getManyMethodName,
resolver: findManyResolver,
methodArgs: [],
},
{
decorator: Mutation(() => DeletePayload),
name: deleteMethodName,
resolver: deleteOneResolver,
methodArgs: [
{
name: 'id',
type: () => Int,
},
],
},
{
decorator: Mutation(() => UpdatePayload),
name: updateMethodName,
resolver: updateResolver,
methodArgs: [
{
name: 'id',
type: () => Int,
},
{
name: 'payload',
type: () => updateInputClassType,
},
],
},
];
const getDescriptorForMethod = (method: string) =>
Object.getOwnPropertyDescriptor(target.prototype, method);
const registerMethodOnPrototype = (key: string, fn: Function) => {
Object.defineProperty(target.prototype, key, {
value: fn,
configurable: true,
enumerable: true,
writable: true,
});
};
const registerMethodArgs = (resolverDescription: IResolverDescription) => {
for (const [
i,
{ name, type },
] of resolverDescription.methodArgs.entries()) {
Args({
name,
type,
})(target.prototype, resolverDescription.name, i);
}
};
const registerResolver = (resolverDescription: IResolverDescription) => {
registerMethodOnPrototype(
resolverDescription.name,
resolverDescription.resolver,
);
resolverDescription.decorator(
target.prototype,
resolverDescription.name,
getDescriptorForMethod(resolverDescription.name),
);
registerMethodArgs(resolverDescription);
};
for (const resolver of resolvers) {
registerResolver(resolver);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment