Modularizing Prisma-client application


#1

I wanted a more modular resolver structure for my application that uses prisma-client. Put simply, I wanted to group my files together by what area of the application they were dealing with, ie. auth/users/vehicles, etc.

Within each of these directories I wanted to be able to further discern that a given file contained mutation, type, or query resolvers.

I have a directory structure such as this:

src/
  resolvers/
    user/
      user.type.ts
      user.mutation.ts
      user.query.ts
  index.ts

The user resolver looks as it would in any prisma-client example:

export const User = {
  id: parent => parent.id,
  company: parent => prisma.user({ id: parent.id }).company(),
  email: parent => prisma.user({ id: parent.id }).login().email(),
  displayName: parent => parent.displayName,
  photoUrl: parent => parent.photoUrl,
  phoneNumber: parent => parent.phoneNumber,
  notifications: parent => prisma.user({ id: parent.id }).notifications()
};

.query and .mutation files all declare their methods at the top of the file and export them in module.exports

async function login() {
  throw new Error('Not implemented');
}

module.exports = {
  login
}

Then in resolvers/index.ts, the file imported by the main index.ts, we export an object with all of the Mutation, Query, Type resolvers on it

import { sync } from 'glob';
import { startCase } from 'lodash';

// Use glob to read all the files matching the given pattern
const resolverFiles = sync(`./**/*.*.ts`, { cwd: __dirname, ignore: './node_modules/**' });

// Build the resolvers object that is exported by this file
export const resolvers = resolverFiles.reduce((accum, file) => {
  const pathArray: string[] = file.slice(0, -3).split('/');
  const [name, type] = pathArray[pathArray.length - 1].split('.')
    .map(string => startCase(string).replace(/\s+/g, ''));
  const imported = require(file);
  if (accum.hasOwnProperty(type)) {
    accum[type] = { ...accum[type], ...imported };
  } else {
    accum[name] = imported[name];
  }
  return accum;
}, {
   Query: {}, Mutation: {}
});

I’m sure it still has plenty of room for improvement, but let me know what you guys think! Hope it’s helpful to someone.