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

lightning-graphql

v3.1.0

Published

Lite Cache-less GraphQL client with excellent type-support for Node and Browsers.

Downloads

5

Readme

Lightning GraphQL

Lightning GraphQL logo

Lite Cache-less GraphQL client with excellent type-support for Node and Browsers. This library's default datafetcher only works with queries and mutations and not subscriptions, so if you want that still use the fetcher option and provide your own datafetcher (providing your own datafetcher can also fix other things e.g. the queries being cache-less)

Why?: I couldn't find a simple way to go from writing graphql queries on my server that wouldn't be cached between requests, and I also wanted a library that didn't compromise on type-safety and great developer experience (DX).

Table Of Contents

External Code Demos:

Stackblitz Collection of Demos

Client Examples

Given a queries.graphql like so that has been generated to a file called ./__generated__/client-types.ts:

query Books {
  books {
    title
    author
  }
}

query Authors {
  authors
}

query BookByTitle($title: String!) {
  findBookByTitle(title: $title) {
    title
    author
  }
}

mutation Noop {
  noop
}

We can write our client like so:

client.ts

import {GraphQLClient} from "lightning-graphql"
// Generated from graphql-codegen with TypedDocumentNodes.
import * as source from "./__generated__/client-types";

const client = GraphQLClient({
  source,
  endpoint: serverURL,
});

// All these methods are camelcased named versions of queries and mutations written in the above queries file.
// The methods below also come with great type-hints and safety.
const book = await client.bookByTitle({
  title: "The Great Gatsby",
}); // get Book by title
const books = await client.books({}); // get all Books 
const truthy = await client.noop({}); // runs the Noop mutation
const authors = await client.authors({}); // get all Authors 

If you notice above our client is generated and populated with all information from the Query file. This is possible because of GraphQL Codegen's TypedDocumentNodes.

Minimal Example with Server and Full Type Support

Server Setup

First we get our ./src/schema.graphql file:

type Book {
  title: String
  author: String
}

type Query {
  books: [Book]
  authors: [String]
  findBookByTitle(title: String!): Book
}

type Mutation {
  noop: Boolean!
}

Then we write a somewhat large ./src/server.js file:

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { readFileSync } from "node:fs";
import { ListenOptions } from "node:net";
import { join } from "node:path";

const books = [
  {
    title: "The Great Gatsby",
    author: "F. Scott Fitzgerald",
  },
  {
    title: "Where the Sidewalk Ends",
    author: "Shel Silverstein",
  },
];

const typeDefs = readFileSync(join(__dirname, "schema.graphql"), {
  encoding: "utf-8",
});

export const resolvers = {
  Query: {
    books: () => books,
    authors: () => books.map((x) => x.author),
    findBookByTitle(_root: any, { title }: { title: string }) {
      return books.find((x) => x.title === title);
    },
  },
  Mutation: {
    noop: () => true,
  },
};

const server = (listen: ListenOptions) => {
  const server = new ApolloServer({
    typeDefs,
    resolvers,
  });
  return {
    async listen() {
      return startStandaloneServer(server, {
        listen,
      });
    },
    async unlisten() {
      await server.stop();
    },
  };
};

const port = 3322;
server({
  port: 3322
}).listen();

Client Setup

With the server finished we then write our query in ./src/queries.graphql

query Books {
  books {
    title
    author
  }
}

query Authors {
  authors
}

query BookByTitle($title: String!) {
  findBookByTitle(title: $title) {
    title
    author
  }
}

mutation Noop {
  noop
}

Then we generate types for the Schema and Query:

By first installing packages for codegen:

Choose an npm or yarn install:

npm

npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node

yarn:

yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node

Then setting up the following ./codegen.yml:

# You provide a schema and documents
schema: "./src/schema.graphql"
documents: "./src/queries.graphql"
generates:
  # These line can change to where you want the types to go.
  ./src/__generated__/client-types.ts:
    # All three of these are required 
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typed-document-node"

The following package.json script called generate:

{
  // ...
  "scripts": {
    // ...
    "generate": "graphql-codegen --config codegen.yml"
  }
  // ...
}

Then generate the client types with:

npm run generate

Then we can finally write our Queries in a ./src/client.ts file where we get all the type-safe goodness!

import {GraphQLClient} from "lightning-graphql";

const serverURL = "http://localhost:3322/graphql";
const client = GraphQLClient({
  source: await import("./__generated__/client-types"),
  endpoint: serverURL,
});

// All these methods are camelcased named versions of queries and mutations written in the above queries file.
const book = await client.bookByTitle({
  title: "The Great Gatsby",
}); // get Book by title
const books = await client.books({}); // get all Books 
const truthy = await client.noop({}); // runs the Noop mutation
const authors = await client.authors({}); // get all Authors 

Supplying your own custom fetcher instead of using the default fetch.

import {GraphQLClient} from "lightning-graphql"
const client = GraphQLClient({
  source: await import("./__generated__/client-types"),
  endpoint: serverURL,
  fetcher ({endpoint, query, type}) {
    return async (variables, options) => {
      // Go Fetch Your Data!
    }
  }
});

Supplying fetchOptions.

There are two ways to supply fetchOptions:

import {GraphQLClient} from "lightning-graphql"



// First way is to send it into the GraphQLClient
const client = GraphQLClient({
  source: await import("./__generated__/client-types"),
  endpoint: serverURL,
  options: {
    // Send in a context if you have a custom fetcher.
    context: {},
    fetchOptions: {
      // extra fetch options any options given to fetch's second parameter work here.
    }
  }
});

// First way is to send it into the GraphQLClient
const books = await client.books({}, {
  // Send in a context.
  context: {},
  fetchOptions: {
    // Extra fetch options.
  }
})