npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

apollo-modules

v1.0.7

Published

Modular system for building apollo schemas

Downloads

42

Readme

Apollo Modules

This set of helpers facilitates the use of GraphQL and Apollo, it allows you to define schemas splits based on domain elements (queries, mutations, resolvers)

npm Circle CI Coverage Status MIT License

Server

This package allows for modular definition of GraphQL schema. Modular definition can reflect the strucutre of your Domain Elements. The advantage of this approach is that you can keep your queries and mutations close to your domain element. A graphQL module contains following properties:

declare interface ApolloModule {
  // definition of types 
  schema: string;
  // definition of queries
  queryText?: string;
  // implementation of queries
  queries?: Object;
  // implementation of type resolvers
  resolvers?: Object;
  // definition of mutations
  mutationText?: string;
  // implmentation of mutations
  mutations?: Object;
  // allows you to modify apollo Options (e.g. context) based on current request
  modifyOptions?: (req: any, apolloOptions: ApolloOptions) => void 
}

Please see the section Examples examples on how to use the domain element schema and also how to use server helpers:

To use modules in your code you need to do following:

import { addModules } from 'apollo-modules';
import { makeExecutableSchema } from 'graphql-tools';
import myModule from './my_module'; 

// import all your modules
const modules = addModules([
  myModule,
  ...
];

// build your schema
const schema = makeExecutableSchema({ typeDefs: modules.schema, resolvers: modules.resolvers, allowUndefinedInResolve: true });

// init your apollo server as usual
...

Following are the available methods from this package.

  1. addModules(definition: IApolloQueryDefinition[]): void: compiles schema of several domain elements (Example: Generating schemas)
  2. createServer(apolloOptions?: ApolloOptions, executableSchema?: any): (req: any) => IApolloOptions provides easy initialisation of the Apollo server.
  3. ioSchema: generates your defined schema type as both input and ouput type. This is used, when you want to be sending whole documents to GraphQL server and probably is not the best practice. When defining the IO type all you need to do is to append the $Input after the type name. (Example: Advanced Schema)

Examples

List of examples of common uses of our helpers

Creating apollo server

In this example we load several modules and initialise a new server instance

import dateModule from 'apollo-modules-date';
import myModule from './myApolloModule';
import { createServer, addModules } from 'apollo-modules';

const modules = addModules([ dateModule, myModule ]);
const schema = makeExecutableSchema({ typeDefs: modules.schema, resolvers: modules.resolvers });

const graphqlOptions = {
  context,
  modules, // this needs to be there if you use options
  schema
};

// init express
const app = ....
app.use('/graphql', apollo.apolloExpress(createServer(graphqlOptions)));

Simple schema

In this example we initialise a simple schema that modifies the context upon each request.

import { Mongo } from 'meteor/mongo';
import { Exercises } from './exercise_schema';

export const Practicals = new Mongo.Collection<Cs.Collections.IPracticalDAO>('practicals');

const schema = `
  type Practical {
    _id: String
    name: String
    description: String
    exercises: [Exercise]
  }
`;

const queryText = `
  practical(id: String, userId: String): Practical
`;

const modifyOptions = (req: any, apolloOptions: ApolloOptions) {
  // modify context
  apolloOptions.context.myValue = "NewValue";
}

const queries = {
  practical(root: any, { id }: any, { userId }: Apollo.IApolloContext): Cs.Collections.IPracticalDAO {
    if (!userId) {
      return;
    }
    return Practicals.findOne({ _id: id });
  }
};

const resolvers = {
  Practical: {
    exercises(practical: Cs.Collections.IPracticalDAO) {
      return Exercises.find({ _id: { $in: practical.exercises } }).fetch();
    }
  }
};

const definition: IApolloDefinition = {
  schema,
  resolvers,
  queries,
  queryText,
  modifyOptions
};

export default definition;

Schema with input/output elements

import { Mongo } from 'meteor/mongo';
import { Random } from 'meteor/random';
import { ioSchema } from 'apollo-mantra/server';

declare global {
  
export const Exercises = new Mongo.Collection<Cs.Collections.IExerciseDAO>('exercises');
export const Questions = new Mongo.Collection<Cs.Collections.IQuestionDAO>('questions');
export const Possibilities = new Mongo.Collection<Cs.Collections.IQuestionPossibilitiesDAO>('possibilities');
export const Solutions = new Mongo.Collection<Cs.Collections.ISolutionDAO>('solutions');

const schema = `
  ${ioSchema(`Exercise$Input {
    _id: String
    name: String
    instructions: String
    group: String
    questions: [Question$Input]
  }`)}

  ${ioSchema(`Question$Input {
    _id: String
    description: String
    question: String
    expectedAnswer: String
    validation: String
    control: String
    possibilities: [Possibility$Input]
    points: Float
  }`)}

  ${ioSchema(`Possibility$Input {
    question: String
    answer: String
  }`)}

  type Solution {
    _id: String
    userId: String
    user: String
    semesterId: String
    practicalId: String
    exerciseId: String
    questionId: String
    userQuestion: String
    expectedAnswer: String
    userAnswer: String
    mark: Float
    created: Date
    modified: Date
    finished: Boolean
    tutorComment: String
  }
`;

const queryText = `
  exercise(id: String, userId: String): Exercise
  practicalSolutions(semesterId: String, practicalId: String, userId: String): [Solution]
  markingSolutions(semesterId: String, practicalId: String, lastModification: Date, userId: String): [Solution]
`;

const queries = {
  exercise(root: any, { id }: any, { user, userId }: Apollo.IApolloContext): Cs.Collections.IExerciseDAO {
    if (!user) {
      return null;
    }
    return Exercises.findOne({ _id: id });
  },
  markingSolutions(root: any, { semesterId, practicalId, lastModification }: any, { user }: Apollo.IApolloContext): Cs.Collections.ISolutionDAO[] {
    if (!user || user.roles.indexOf('tutor') === -1) {
      return [];
    }
    console.log(lastModification);
    return Solutions.find({ semesterId, practicalId, modified: { $gt: lastModification } }).fetch();
  },
  practicalSolutions(root: any, { semesterId, practicalId }: any, { userId, user }: Apollo.IApolloContext): Cs.Collections.ISolutionDAO[] {
    const options = { fields: { expectedAnswer: 0 } };
    return Solutions.find({ userId, semesterId, practicalId }, options).fetch();
  }
};

const mutationText = `
  mark(solutionIds: [String]!, comments: [String]!, marks: [Float]!): Boolean
  save(exercise: ExerciseInput): Boolean
`;

interface IActionAnswer {
  solutionIds: string[];
  userAnswers: string[];
  finished: boolean;
}

interface IActionMark {
  solutionIds: string[];
  comments: string[];
  marks: number[];
}

interface IActionSave {
  exercise: Cs.Entities.IExercise;
}

const mutations = {
  mark(root: any, { solutionIds, comments, marks }: IActionMark, { user, userId }: Apollo.IApolloContext) {
    // check for tutor
    if (!user.roles.find((r) => r === 'tutor')) {
      return;
    }

    let total = 0;
    for (let i = 0; i < solutionIds.length; i++) {
      let cm = marks[i] ? marks[i] : 0;
      Solutions.update({ _id: solutionIds[i] }, {
        $set: {
          mark: cm,
          tutorComment: comments[i]
        }
      });
    }
  },
  save(root: any, { exercise }: IActionSave, { user }: Apollo.IApolloContext) {
    if (!user.roles.find((r) => r === 'tutor')) {
      return;
    }

    // first update the exercise 
    Exercises.update({ _id: exercise._id }, {
      $set: {
        name: exercise.name,
        instructions: exercise.instructions,
        group: exercise.group,
        questions: exercise.questions.map((e) => e._id)
      }
    });

    // then update all questions
    for (let question of exercise.questions) {
      Questions.upsert({ _id: question._id }, { $set: question });
    }
  }
};

const resolvers = {
  Exercise: {
    questions(exercise: Cs.Collections.IExerciseDAO, params: any, { user }: Apollo.IApolloContext): Cs.Collections.IQuestionDAO[] {
      let options = {};
      if (!user.roles || user.roles.indexOf('tutor') === -1) {
        options = { fields: { expectedAnswer: 0, validation: 0, possibilities: 0 } };
      }
      return Questions.find({ _id: { $in: exercise.questions } }, options).fetch();
    }
  },
  Question: {
    possibilities(question: Cs.Collections.IQuestionDAO): Cs.Collections.IQuestionPossibilityDAO[] {
      if (question.possibilitiesGroupId) {
        return Possibilities.findOne({ _id: question.possibilitiesGroupId }).possibilities;
      } else {
        return null;
      }
    }
  }
};

const definition: IApolloDefinition = {
  schema,
  resolvers,
  queries,
  queryText,
  mutationText,
  mutations
};

export default definition;