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

graphablejson

v0.20.0

Published

Use GraphQL and REST together

Downloads

12

Readme

Graphable JSON JS

This is a JavaScript implementation of Graphable JSON.

Install

Run the following to install the library:

npm install graphablejson

There is an example API found https://graphablejsonapi.glitch.me/orders/1000. You can also view the GraphQL example directory to see how this library can be used.

Usage

gqlQuery

The gqlQuery function is takes a URL and query and retrieves the requested data. Support is limited at this point. It takes a URL and a GraphQL AST and returns an object with async generators. This allows the client to lazily load the data from the API instead of requested all of the URLs at once.

It requires you to have graphql-js and something like graphql-tag to be able to pass in an AST.

// Expecting the following result for the URL:
// https://graphablejsonapi.glitch.me/examples/example2
//
// {
//   customer_number: "8000",
//   order: [
//     {
//       url: "https://graphablejsonapi.glitch.me/orders/1000",
//       order_number: "1000",
//       total: 150,
//       unit: "USD"
//      }
//   ]
// };

const gql = require('graphql-tag');
const { gqlQuery, utils } = require('graphablejson');

const result = await gqlQuery('https://graphablejsonapi.glitch.me/examples/example2', gql`{
  order {
    order_number
    total
  }
}`);

// expandObject will follow links until the object is full expanded
console.log(await utils.expandObject(await result));

This makes use of all the functionality listed below. It will follow links and paginated collections.

Technical Details

This section gives a look into how the library handles responses.

Web Aware with RESTful JSON

The library will follow links represented in RESTful JSON if it finds one in place of a property. This allows for API responses to evolve without breaking queries.

Let's say the current document we have is an order and looks like:

{
  "order_number": "1234",
  "customer_url": "/customers/4"
}

And the customer found at /customers/4 is:

{
  "first_name": "John",
  "last_name": "Doe",
}

The query below will request the data and resolve the link. If the data were included in the first response, it would return it, but since it's linked, it will follow the link to get the data.

const { gqlQuery } = require('graphablejson');
const gql = require('graphql-tag');

const result = gqlQuery('https://example.com', gql`
  order_number
  customer {
    first_name
    last_name
  }
`);

Collections

Additionally, APIs may need to return a partial set of items and let the client request more if necessary by way of pagination. A collection object is used to make this possible. It wraps values with an $item property so the JSON can move from values, to arrays, to paginated arrays.

// We'll say the following response is found at http://example.com
// {
//   url: 'https://example.com/customer/4538',
//   order: [
//     {
//       url: 'https://example.com/order/1234',
//       order_number: '1234',
//       total_amount: '$100.00'
//     },
//     {
//       url: 'https://example.com/order/1235',
//       order_number: '1235',
//       total_amount: '$120.00'
//     }
//   ]
// };

// Returns all of the order objects found directly in the object
const result = gqlQuery('https://example.com', gql`
  order {
    order_number
    total_amount
  }
`);

Below shows the same values changing to use a collection.

A collection is denoted by the $item property. Remember that values can be arrays or single values, so $item can be either an array of items or a single item.

Here is the customer again, this time with a linked collection of orders.

{
  "url": 'https://example.com/customer/4538',
  "order_url": "http://example.com/orders"
}

Here is the first page for the orders.

{
  "url": 'https://example.com/orders?page=1',
  "$item": [
    {
      "url": 'https://example.com/order/1234',
      "order_number": '1234',
      "total_amount": '$100.00'
    },
    {
      "url": 'https://example.com/order/1235',
      "order_number": '1235',
      "total_amount": '$120.00'
    }
  ],
  "next_url": 'https://example.com/orders?page=2'
}

And the second page of orders.

{
  url: 'https://example.com/orders?page=2',
  $item: [
    {
      url: 'https://example.com/order/1236',
      order_number: '1236',
      total_amount: '$100.00'
    }
  ],
  prev_url: 'https://example.com/orders?page=1'
}

The same query listed above will work for this. It will follow next_url links and return each item found in $item.

This however is not always the best method as including the items in the collection means we cannot cache individual items. To help, we can use links to each item and let the Graphable JSON client resolve the links. This makes use of the same pattern of linking to values by appending a _url to the $item property and making each item a separate link.

{
  "order": {
    "url": 'https://example.com/orders?page=1',
    "$item_url": [
      'https://example.com/orders/1234',
      'https://example.com/orders/1235'
    ],
    "next_url": 'https://example.com/orders?page=2'
  }
}