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

@dotdev/shopify-client

v0.1.18

Published

Typed API client for the Shopify Admin and Storefront GraphQL APIs

Downloads

713

Readme

Shopify Client

This package combines graphql-codegen and graphql-request to provide a fully typed Shopify client for the Shopify GraphQL Admin API and the Shopify Storefront API (coming soon).

  • Built in Shopify authentication headers
  • Fully typed using your own queries, mutations and fragments
  • Rate limit error handling with backoff and retry (coming soon)
  • Round robin credential cycling for spreading rate limits across multiple keys

Motivation

Shopify offers two GrahpQL APIs: the Storefront API and the GraphQL Admin API. These APIs can be accessed using any GraphQL compatible client or even plain old fetch. However, despite GraphQL being inherently strongly typed, none of these tools give us typescript types without extensive configuration.

For example, if you wanted to use the productCreate mutation, you need to first reference the documentation page or a GraphQL introspection tool to find out what the input and output looks like. Then you would probably use graphql-tag to define your mutation which you then pass into your GraphQL client along with your mutation arguments.

The problem with this is at no stage has your mutation or arguments been type checked against the actual Shopify API. This includes when you're executing the mutation in your app logic. The only time you find out something isn't right, is when you run the query during testing and Shopify returns an error.

This problem is exacerbated when you need to migrate to a newer API version which might include changes to available fields and required mutation arguments. The only way to test these would be to run them, which is usually left to production.

Introducing type safety

By applying types to our queries and mutations and most importantly validating these types against the real Shopify API, we can be sure that the execution will work in production.

This was previously attempted with the @dotdev/shopify package. The idea was that rather than calling GraphQL directly, we would instead define a class with methods like createProduct which had the input and response already typed out. The problem with this was that the queries themselves were locked into the package, making it inflexible if you wanted to update something. We were constantly adding new methods and udpating types to match the latest API.

Ultimately, because it was so annoying to use, everyone stopped using it and went back to direct GraphQL queries.

Type generation

Building on the above, we still want our queries and mutations to be typed, but we want our queries and mutations to remain flexible, such that we can update them specifically for our app. We also want them to automatically update when we update the Shopify API version (and fail if they no longer match) without making arduous updates to this package.

To tackle this, this package interacts with a special auto-generated type file, generated using graphql-codegen. To generate this file, you define all the queries, mutations and fragments you want to use within your app, using .graphql files. Once defined, you run a generation command which reads in your files, connects to the actual Shopify API to fetch the current types, and generates a special typescript file which is consumed by this package.

With this methodology, this package actually contains no types at all and has no dependency on a specific API version. However, you can still call shopifyAdmin.client.createProduct as expected with full type safety.

Installation

npm i @dotdev/shopify-client --save

Usage

When you have completed the setup section below to generate your GraphQL types, you will instantiate the ShopifyAdmin class using your generated type file.

import { ShopifyAdmin } from "@dotdev/shopify-client";

// see setup section for how to generate this
import { getSdk } from "./generated/graphql";

const shopify = new ShopifyAdmin({
  getSdk,
  // or use an array to use key cycling
  credentials: {
    password: "supersecret",
  },
});

// product will have the appropriate type as defined
// by your mutation query attributes
const product = await shopify.client.createProduct({
  input: {
    // this will throw a type error, as Shopify
    // expects title to be a string
    title: true,
  },
});

Setup

This library does not contain any Shopify types. To populate .client with the queries and mutations utilised by your app, you need to provide a special getSdk parameter in the constructor. This parameter is fetched from an auto-generated typescript file which contains the GraphQL queries, mutations and fragments used by your app alongside the types returned and expected to be received by your target Shopify API version.

Installaing @graphql-codegen

Within your project, run the following to install the necessary development dependencies to generate your types.

npm i @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-generic-sdk @graphql-codegen/typescript-operations --save-dev

Defining your queries, mutations and fragments

Choose a directory in your project where you will define the GraphQL queries, mutations and fragments to be used by your application. You might choose ./graphql but it can be anywhere you like.

Within this directory, create a separate .graphql file each query, mutation and fragment you want to use. For example, if wanted to use the productCreate mutation, you might create a file called productCreate.graphql with the following contents.

mutation productCreate($input: ProductInput!) {
  productCreate(input: $input) {
    product {
      ...productFragment
    }
    userErrors {
      field
      message
    }
  }
}

Notice that in the above mutation, we are referencing a fragment called productFragment. You would define this fragment in it's own file called productFragment.graphql.

fragment productFragment on Product {
  id
  handle
  title
  ...other properties
}

Each of your mutations and queries must be named as this is what names the method applied to the Shopify client. For example, the mutation above is called productCreate which means it will be available at shopify.client.productCreate(). This means we can use multiple versions of the same Shopify mutation or query, but for different purposes.

Create a codegen.json file

In the root of your project, create a new file called codegen.json with the following contents. This file is what configures graphql-codegen and points it at your GraphQL files.

The shop and password included in the file below is a restricted API key within a DotDev sandbox store. You are free to use the token below and commit it to your project. This is where the GraphQL schema will be downloaded from and Shopify requires an access token for all requests, even just to fetch the schema.

Note the API version within the Shopify URL. If you wish to target a different API version, simply update it in the URL and schema will be pulled from there instead.

{
  "overwrite": true,
  "schema": {
    "https://dotdev-plus-sandbox.myshopify.com/admin/api/2021-01/graphql.json": {
      "headers": {
        "X-Shopify-Access-Token": "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"
      }
    }
  },
  "documents": "graphql/**/*.graphql",
  "generates": {
    "generated/graphql.ts": {
      "plugins": [
        "typescript",
        "typescript-operations",
        "typescript-generic-sdk"
      ]
    }
  }
}

Add the generate command to your package scripts

Each time you make changes to your GraphQL files or upgrade the API version, you will need to regenerate your types to get the methods added to the SDK. Since this is something you might do regularly, you will want to add the command as a package.json script.

"scripts": {
  "generate-shopify-types": "graphql-codegen --config codegen.json"
}

Generate your types file

To generate your types file, run the command below. This will scan your GraphQL directory for the queries and mutations you're using in your app, connect to the Shopify API to get the schema for the current version, and finally generate a typescript file into generated/graphql.ts.

npm run generate-shopify-types

Begin using the client

Now that you have completed setup, follow the usage section to begin using your new fully typed Shopify client.