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 🙏

© 2024 – Pkg Stats / Ryan Hefner

graphql-define-resolvers

v1.0.0

Published

Collect typed GraphQL resolvers across multiple modules.

Downloads

5

Readme

graphql-define-resolvers

Collect typed GraphQL query/mutation resolvers across multiple modules.

Assumes a GraphQL server project with resolver types generated with @graphql-codegen/typescript-resolvers.

Install

npm install graphql-define-resolvers

Use

Create resolvers/index.ts:

import { defineSimpleResolvers } from "graphql-define-resolvers"

// Resolver types generated with @graphql-codegen/typescript-resolvers
import type { Resolvers } from "../types"

export const { defineQuery, defineMutation } = defineResolvers<Resolvers>()

Define individual resolvers under resolvers/<module>/<resolver>.ts:

import { defineQuery } from ".."
import { db } from "../../db"

export default defineQuery("whoami", async (parent, args, context, info) => {
  const { userId } = context
  return userId ? await db.user.find(userId) : null
})

Merge and consume resolvers:

import { mergeResolvers } from "@graphql-tools/merge"

import whoami from "./resolvers/auth/whoami"
// import ... from "./resolvers/.../..."

const resolvers = mergeResolvers([
  whoami,
  // ...
])

const server = new ApolloServer<ResolverContext>({ typeDefs, resolvers })

Using import.meta.glob

This option is available only when using Vite or similar modern bundler.

Instead of manually importing all modules, use import.meta.glob to import them at once:

import { mergeResolvers } from "@graphql-tools/merge"

const resolvers = mergeResolvers(
  Object.values<Resolvers>(import.meta.glob("./glob/*/*.ts", { import: "default", eager: true })),
)

Beware that eager glob import could easily cause circular import errors (for instance, that will happen if you put this code in the same module which exports defineQuery).

For such cases, use non-eager glob import:

const resolvers = mergeResolvers(
  await Promise.all(
    Object.values(import.meta.glob("./resolvers/*/*.ts", { import: "default" }))
      .map(m => m() as Promise<Resolvers>),
  ),
)

Define multiple resolvers

In resolvers/index.ts, export createResolvers alongside defineQuery:

export const { defineQuery, defineMutation, createResolvers } = defineResolvers<Resolvers>()

In resolver modules where you want to define multiple resolvers, use createResolvers:

import { createResolvers } from ".."
import { db } from "../../db"

const resolvers = createResolvers()

// Same API as in standalone defineQuery
resolvers.defineQuery("whoami", async (parent, args, context, info) => {
  const { userId } = context
  return userId ? await db.user.find(userId) : null
})

resolvers.defineMutation("login", async (parent, args, context, info) => {
  // implementation omitted for brevity
})

export default resolvers

Single resolvers collector

Another approach is using a single resolvers collector object for all resolvers.

In resolvers/index.ts:

import { defineSimpleResolvers } from "graphql-define-resolvers"

// Resolver types generated with @graphql-codegen/typescript-resolvers
import type { Resolvers } from "../types"

const { createResolvers } = defineResolvers<Resolvers>()

export const resolvers = createResolvers()

Define individual resolvers under resolvers/<module>/<resolver>.ts:

import { resolvers } from ".."
import { db } from "../../db"

resolvers.defineQuery("whoami", async (parent, args, context, info) => {
  const { userId } = context
  return userId ? await db.user.find(userId) : null
})

Then import all resolver modules, either manually or with import.meta.glob (eager or non-eager depending on how you organize modules).

For example, you can add this to the end of resolvers/index.ts:

await Promise.all(Object.values(import.meta.glob("./*/*.ts")).map(m => m()))

The resolvers object created with createResolvers implements Resolvers and is ready to be directly consumed by a GraphQL server:

import { resolvers } from "./resolvers"

const server = new ApolloServer<ResolverContext>({ typeDefs, resolvers })

Simple resolvers

This module provides an alternative way to define resolvers, where they accept not 4 arguments parent, args, context, info, but a single object argument with the same keys: { parent, args, context, info }.

To opt in, use defineSimpleResolvers instead of defineResolvers:

export const { defineQuery, defineMutation, createResolvers } = defineSimpleResolvers<Resolvers>()

and then use simplified callbacks:

export default defineQuery("whoami", ({ context }) => {
  const { userId } = context
  return userId ? await db.user.find(userId) : null
})