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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@thor-commerce/graphql-client

v1.0.6

Published

Fetch-based GraphQL client for Thor Commerce APIs

Downloads

2,188

Readme

@thor-commerce/graphql-client

Thin but production-ready GraphQL client for Thor Commerce Admin and Storefront APIs.

It is intentionally transport-focused:

  • builds Thor API URLs
  • applies auth and default headers
  • handles retries for transient HTTP failures
  • returns structured GraphQL errors
  • supports @defer stream responses

If you want Apollo, urql, or another cache/client layer, use this package underneath or skip it entirely and bring your own client.

Installation

npm install @thor-commerce/graphql-client

Quick Start

import {createAdminGraphQLClient} from "@thor-commerce/graphql-client";

const admin = createAdminGraphQLClient({
  tenant: "demo",
  apiKey: process.env.THOR_ADMIN_API_KEY!,
});

const response = await admin.request<{
  stores: {nodes: Array<{id: string; name: string}>};
}>({
  query: `
    query Stores {
      stores {
        nodes {
          id
          name
        }
      }
    }
  `,
});

if (response.errors) {
  console.error(response.errors);
} else {
  console.log(response.data?.stores.nodes);
}

Client Constructors

Use the generic constructor when you want one shared API:

import {ApiType, createGraphQLClient} from "@thor-commerce/graphql-client";

const client = createGraphQLClient({
  apiType: ApiType.Storefront,
  tenant: "demo",
  apiKey: process.env.THOR_STOREFRONT_API_KEY!,
});

Use the convenience constructors for cleaner call sites:

import {
  createAdminGraphQLClient,
  createStorefrontGraphQLClient,
} from "@thor-commerce/graphql-client";

Request Modes

request() returns a structured result and does not throw for normal API failures:

const response = await admin.request<MyQuery, MyVariables>(query, {
  variables: {id: "gid://thor/Product/1"},
});

if (response.errors) {
  console.error(response.errors.networkStatusCode);
  console.error(response.errors.graphQLErrors);
}

requestOrThrow() is the ergonomic path when you want application-style exceptions:

const data = await admin.requestOrThrow<MyQuery>(query);

Typed Operations With @thor-commerce/graphql-codegen-preset

If you want generated result and variable types, pair this package with @thor-commerce/graphql-codegen-preset.

The cleanest setup today is to use client: ClientType.Apollo in codegen so you get operation result and variable types without coupling to another runtime client.

import {
  ApiType,
  ClientType,
  thorCommerceApiProject,
} from "@thor-commerce/graphql-codegen-preset";

export default {
  projects: {
    storefront: thorCommerceApiProject({
      apiType: ApiType.Storefront,
      client: ClientType.Apollo,
      outputDir: "./src/graphql",
      documents: ["./src/**/*.{ts,tsx}"],
    }),
  },
};

After running codegen, import the generated operation types and use them as generics on the Thor client:

import {createStorefrontGraphQLClient} from "@thor-commerce/graphql-client";
import type {
  GetProductQuery,
  GetProductQueryVariables,
} from "./graphql/storefront.generated";

const client = createStorefrontGraphQLClient({
  tenant: "demo",
  apiKey: process.env.THOR_STOREFRONT_API_KEY!,
});

const GET_PRODUCT_QUERY = `#graphql
  query GetProduct($handle: String!) {
    product(handle: $handle) {
      id
      name
    }
  }
`;

const data = await client.requestOrThrow<
  GetProductQuery,
  GetProductQueryVariables
>(GET_PRODUCT_QUERY, {
  variables: {
    handle: "classic-tee",
  },
});

That gives you:

  • typed variables at the call site
  • typed response data from request() or requestOrThrow()
  • the Thor runtime client for transport, retries, and error handling

requestStream() is for operations that declare @defer:

const stream = await admin.requestStream<ProductsQuery>(`
  query Products {
    products @defer {
      nodes {
        id
        name
      }
    }
  }
`);

for await (const chunk of stream) {
  if (chunk.errors) {
    console.error(chunk.errors);
    break;
  }

  console.log(chunk.data, chunk.hasNext);
}

Options

const client = createAdminGraphQLClient({
  tenant: "demo",
  apiKey: process.env.THOR_ADMIN_API_KEY!,
  headers: {
    "X-Trace-Id": "trace-123",
  },
  retries: 2,
  retriableStatusCodes: [429, 500, 502, 503, 504],
  defaultRetryWaitTime: 1_000,
  deprecationHeader: "X-Thor-Api-Deprecated-Reason",
  logger(event) {
    console.log(event.type, event.content);
  },
});

Supported options:

  • tenant
  • apiKey
  • apiType
  • baseUrl
  • headers
  • fetch
  • retries
  • retriableStatusCodes
  • defaultRetryWaitTime
  • deprecationHeader
  • logger

Notes

  • request() will tell you to use requestStream() if the operation contains @defer.
  • requestStream() will tell you to use request() if the operation is not streamable.
  • headers accepts a plain object, tuple array, or Headers instance.
  • The client sets Accept: application/json automatically, and upgrades it to multipart-compatible headers for deferred operations.