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

@graphitation/apollo-react-relay-duct-tape

v1.3.9

Published

A compatibility wrapper that provides the react-relay API on top of Apollo Client.

Downloads

1,047

Readme

apollo-react-relay-duct-tape

A compatibility wrapper that provides the react-relay API on top of Apollo Client.

The name is a reference to the Apollo 13 mission.

Use this together with @graphitation/apollo-react-relay-duct-tape-compiler to have typings and compiled documents generated.

Setup

Installation

  • Install the packages from this repo:

    yarn add @graphitation/apollo-react-relay-duct-tape
    yarn add --dev @graphitation/apollo-react-relay-duct-tape-compiler
  • Patch your version of @apollo/client using the patch found in the patches directory. You can either do so manually or use a tool like patch-package.

  • For an expedient developer-experience, you will want to install the watchman tool.

    • On macOS (using homebrew): $ brew install watchman
    • On Windows (using chocolatey): $ choco install watchman

Configuration

TODO:

  • We cannot support the default apollo cache keys for fragments on Node [derived] interfaces. Seeing as Node semantics are so core to the ability to provide these APIs, it makes sense to remove the apollo default cache key support.

  • Copy apollo cache config required from the example app. This includes getting the list of possible types and the dataIdFromObject implementation.

  • Configure Apollo Client's cache to automatically add __typename field selections, which concrete types implement the Node interface, and the type-policies needed to read the watch query data from the store:

    import { InMemoryCache } from "@apollo/client";
    import { typePoliciesWithGlobalObjectIdStoreKeys as typePolicies } from "@graphitation/apollo-react-relay-duct-tape";
    
    const cache = new InMemoryCache({
      addTypename: true,
      // Be sure to specify types that implement the Node interface
      // See https://www.apollographql.com/docs/react/data/fragments/#using-fragments-with-unions-and-interfaces
      possibleTypes: {
        Node: ["Todo"],
      },
      // Either use the `typePoliciesWithGlobalObjectIdStoreKeys` object directly or otherwise extend appropriately. Alternatively you can also use typePoliciesWithDefaultApolloClientStoreKeys
      typePolicies: {
        Query: {
          fields: {
            __fragments: {
              read: typePolicies.Query.fields.__fragments.read,
            },
            node: {
              read: typePolicies.Query.fields.node.read,
            },
          },
        },
        Node: {
          fields: {
            __fragments: {
              read: typePolicies.Node.fields.__fragments.read,
            },
          },
        },
      },
      // Make sure to specify the dataIdFromObject implementation if you rely on typePoliciesWithGlobalObjectIdStoreKeys
      dataIdFromObject(responseObject, keyFieldsContext) {
        if (
          responseObject.id &&
          responseObject.__typename &&
          possibleTypes?.Node.includes(responseObject.__typename)
        ) {
          return responseObject.id as string;
        }
        // fallback to default way of doing it
        return defaultDataIdFromObject(responseObject, keyFieldsContext);
      },
    });

    In most cases as in the example app, you can just build the configuration using utilities exported from @graphitation/apollo-react-relay-duct-tape:

    import { InMemoryCache, defaultDataIdFromObject } from "@apollo/client";
    import { schema } from "fileWithYourSchema";
    import {
      typePoliciesWithGlobalObjectIdStoreKeys,
      getPossibleTypesAndDataIdFromNode,
    } from "@graphitation/apollo-react-relay-duct-tape";
    
    const { possibleTypes, dataIdFromObject } =
      getPossibleTypesAndDataIdFromNode(schema);
    
    const cache = new InMemoryCache({
      addTypename: true,
      possibleTypes, // already makes sure to contain all possible types for Node interface
      typePolicies: typePoliciesWithGlobalObjectIdStoreKeys,
      dataIdFromObject(responseObject, keyFieldsContext) {
        return (
          dataIdFromNode(responseObject, keyFieldsContext) ||
          defaultDataIdFromObject(responseObject, keyFieldsContext)
        );
      },
    });
  • Configure webpack to transform your code by replacing inline GraphQL documents with their compiled artefacts:

    const config: webpack.Configuration = {
      module: {
        rules: [
          {
            test: /.+?\.tsx?$/,
            loader: "@graphitation/embedded-document-artefact-loader/webpack",
            exclude: /node_modules/,
          },
        ],
      },
    };
  • TODO: Have a Node interface definition

  • TODO: Add node root field

  • Optionally, if you rely on Apollo Client's @client directive, be sure to explicitly add it to your local copy of your schema, otherwise the compiler will not accept its use.

    directive @client(always: Boolean) on FIELD

Usage

Build

In a shell, start the compiler and point it to your schema and source. Depending on the size of the code-base a first run may take a while, but subsequent builds should cached. For developer-expedience, it is advised to run the compiler using the watch mode -- provided you have installed the watchman tool.

$ yarn duct-tape-compiler          \
    --schema ./path/to/schema.graphql \
    --src ./path/to/source            \
    --watch

TODO:

  • Add Node interface to type that you want to start a new watch query for
  • Restart compiler

Runtime

TODO:

  • Add query hook
  • Add fragment hook
  • Import and use typings

Architecture

  • Fragment reference variables need to be propagated to child fragment hooks, so refetch hooks can re-use original request variables.
    • This cannot be done through React Context, because a refetch hook needs to be able to [partially] update original variables, which cannot be done with React Context.
    • Instead, we pass these as React props, which are populated through GraphQL as we can know exactly where [child] fragments are being referenced and the data needs to be encoded. The actual resolving of the data is done through the (./packages/apollo-react-relay-duct-tape/src/storeObservation/fragmentReferencesFieldPolicy.ts)[fragmentReferencesFieldPolicy] Apollo Cache field policy.
    • Because we can't just add a Apollo Cache field policy to any type, as we don't even know all types, we add it to the Node interface instead. The one other type we can assume to exist is the Query type.