0.30.0 • Published 8 months ago

@greenwood/plugin-graphql v0.30.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

@greenwood/plugin-graphql

Overview

A plugin for Greenwood to support using GraphQL to query Greenwood's content graph with our optional pre-made queries. It runs apollo-server on the backend at build time and provides a "read-only" @apollo/client "like" interface for the frontend that you can use.

This package assumes you already have @greenwood/cli installed.

Caveats

As of now, this plugin requires some form of prerendering either through: 1. Enabling custom imports or 1. Installing the Puppeteer renderer plugin.

Installation

You can use your favorite JavaScript package manager to install this package.

# npm
npm install @greenwood/plugin-graphql --save-dev

# yarn
yarn add @greenwood/plugin-graphql --dev

Usage

Add this plugin to your greenwood.config.js and configure with either prerender: true or by adding the greenwoodPluginRendererPuppeteer plugin.

import { greenwoodPluginGraphQL } from '@greenwood/plugin-graphql';
import { greenwoodPluginRendererPuppeteer } from '@greenwood/plugin-renderer-puppeteer'; // if using puppeteer

export default {
  // ...
  prerender: true, // if using custom imports
  plugins: [
    greenwoodPluginGraphQL(),
    greenwoodPluginRendererPuppeteer()
  ]
}

Example

This will then allow you to use GraphQL to query your content from your client side. At build time, it will generate JSON files so that the data is still accessible through hydration techniques.

import client from '@greenwood/plugin-graphql/src/core/client.js';
import CollectionQuery from '@greenwood/plugin-graphql/src/queries/collection.gql';

const template = document.createElement('template');

class HeaderComponent extends HTMLElement {
  async connectedCallback() {
    super.connectedCallback();

    if (!this.shadowRoot) {
      const response = await client.query({
        query: CollectionQuery,
        variables: {
          name: 'nav'
        }
      });
      const navigation = response.data.collection;
      
      template.innerHTML = `
        <nav>
          <ul>
            ${navigation.map((item) => {
              const { route, label } = item;

              return html`
                <li>
                  <a href="${route}" title="Click to visit the ${label} page">${label}</a>
                </li>
              `;
            })}
          </ul>
        </nav>
      `;

      this.attachShadow({ mode: 'open' });
      this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
  }
}

customElements.define('app-header', HeaderComponent);

For more general purpose information on content with data in Greenwood, please see our docs.

Schema

The basic page schema follow the structure of the page data structure. Currently, the main "API" is just a list of all pages in your pages/ directory, represented as a Page type definition. This is called Greenwood's graph.

This is what the schema looks like:

graph {
  id,
  label,
  title,
  route,
  layout
}

All queries return subsets and / or derivatives of the graph.

Queries

Greenwood provides a couple of queries out of the box that you can use to get access to the graph and start using it in your components, which we'll get to next.

Graph

The Graph query returns an array of all pages.

import client from '@greenwood/plugin-graphql/src/core/client.js';
import GraphQuery from '@greenwood/plugin-graphql/src/queries/graph.gql';

.
.
.

async connectedCallback() {
  super.connectedCallback();
  const response = await client.query({
    query: GraphQuery
  });

  this.posts = response.data.graph;
}

Collections

Based on our Collections feature for querying based on collections.

import client from '@greenwood/plugin-graphql/src/core/client.js';
import CollectionQuery from '@greenwood/plugin-graphql/src/queries/collection.gql';

.
.
.

async connectedCallback() {
  super.connectedCallback();
  const response = await client.query({
    query: CollectionQuery,
    variables: {
      name: 'nav'
    }
  });

  this.items = response.data.collection;
}

Children

This will return a set of pages under a specific route and is akin to using getContentByRoute.

import client from '@greenwood/plugin-graphql/src/core/client.js';
import ChildrenQuery from '@greenwood/plugin-graphql/src/queries/children.gql';

.
.
.

async connectedCallback() {
  super.connectedCallback();
  const response = await client.query({
    query: ChildrenQuery,
    variables: {
      parent: '/blog'
    }
  });

  this.posts = response.data.children;
}

Custom

You can of course come up with your own as needed! Greenwood provides the gql-tag module and will also resolve .gql or .graphql file extensions!

/* src/data/my-query.gql */
query {
  graph {
    /* whatever you are looking for */
  }
}

Or within your component

import gql from 'graphql-tag';  // comes with Greenwood

const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`

Sorting

The position of items within a query can be sorted by simply adding the order variable to our query.

const response = await client.query({
  query: CollectionQuery,
  variables: {
    name: 'navigation',
    order: 'order_asc'
  }
});

The following sorts are available.

SortDescription
no order declared, sorts by alphabetical file name
order_ascSort by index, ascending order
order_descSort by index, descending order
title_ascSort by title, ascending order
title_descSort by title, descending order

Filtering

If you only want specific items to show within a specific subdirectory. You can also include the route variable to narrow down a set of pages. This would be useful for a sub navigation menu, for example if you only want pages under /blog/, you can set the route variable accordingly.

const response = await client.query({
  query: CollectionQuery,
  variables: {
    name: 'shelf',
    order: 'order_asc',
    route: '/blog/'
  }
});

Custom Schemas

This plugin also supports you providing your own custom schemas in your project so you can make GraphQL pull in whatever data or content you need!

Just create a data/schema directory and then Greenwood will look for any files inside it that you can use to export typeDefs and resolvers. Each schema file must specifically export a customTypeDefs and customResolvers.

Example

For example, you could create a "gallery" schema that could be used to group and organize photos for your frontend using variable.

import gql from 'graphql-tag';

const getGallery = async (root, query) => {
  if (query.name === 'logos') {
    // you could of course use fs here and look up files on the filesystem, or remotely!
    return [{
      name: 'logos',
      title: 'Home Page Logos',
      images: [{
        path: '/assets/logo1.png'
      }, {
        path: '/assets/logo2.png'
      }, {
        path: '/assets/logo3.png'
      }]
    }];
  }
};

const galleryTypeDefs = gql`
  type Image {
    path: String
  }

  type Gallery {
    name: String,
    title: String,
    images: [Image]
  }

  extend type Query {
    gallery(name: String!): [Gallery]
  }
`;

const galleryResolvers = {
  Query: {
    gallery: getGallery
  }
};

// naming is up to you as long as the final export is correct
export {
  galleryTypeDefs as customTypeDefs,
  galleryResolvers as customResolvers
};
// gallery.gql
query($name: String!) {
  gallery(name: $name)  {
    name,
    title,
    images {
      path
    }
  }
}

And then you can use it in your code as such:

import client from '@greenwood/plugin-graphql/src/core/client.js';
import GalleryQuery from '../relative/path/to/data/queries/gallery.gql' with { type: 'gql' };

client.query({
  query: GalleryQuery,
  variables: {
    name: 'logos'
  }
}).then((response) => {
  const logos = response.data.gallery[0].images[i];

  logos.forEach((logo) => {
    console.log(logo.path); // /assets/logo1.png, /assets/logo2.png, /assets/logo3.png
  });
});
0.30.0-alpha.8

9 months ago

0.30.0

8 months ago

0.30.0-alpha.7

9 months ago

0.29.4

1 year ago

0.30.0-alpha.3

1 year ago

0.30.0-alpha.6

10 months ago

0.30.0-alpha.4

1 year ago

0.30.0-alpha.5

12 months ago

0.30.0-alpha.2

1 year ago

0.29.3

1 year ago

0.30.0-alpha.1

1 year ago

0.30.0-alpha.0

1 year ago

0.29.2

1 year ago

0.29.1

2 years ago

0.29.0

2 years ago

0.29.0-alpha.1

2 years ago

0.29.0-alpha.4

2 years ago

0.29.0-alpha.5

2 years ago

0.29.0-alpha.2

2 years ago

0.29.0-alpha.3

2 years ago

0.29.0-alpha.6

2 years ago

0.28.5

2 years ago

0.29.0-alpha.0

2 years ago

0.28.4

2 years ago

0.28.3

2 years ago

0.28.2

2 years ago

0.28.1

2 years ago

0.28.0

2 years ago

0.28.0-alpha.5

2 years ago

0.28.0-alpha.4

2 years ago

0.27.5

2 years ago

0.27.4

2 years ago

0.28.0-alpha.3

2 years ago

0.28.0-alpha.1

2 years ago

0.28.0-alpha.2

2 years ago

0.27.0-alpha.3

3 years ago

0.27.0-alpha.7

3 years ago

0.27.0-alpha.6

3 years ago

0.27.0-alpha.5

3 years ago

0.27.0-alpha.4

3 years ago

0.27.2

3 years ago

0.27.1

3 years ago

0.27.0

3 years ago

0.27.3

2 years ago

0.28.0-alpha.0

3 years ago

0.27.0-alpha.2

3 years ago

0.27.0-alpha.1

3 years ago

0.27.0-alpha.0

3 years ago

0.26.2

3 years ago

0.26.1

3 years ago

0.26.0-alpha.0

3 years ago

0.26.0-alpha.1

3 years ago

0.25.2

3 years ago

0.26.0

3 years ago

0.25.1

3 years ago

0.23.0-alpha.0

3 years ago

0.23.0-alpha.1

3 years ago

0.25.0

3 years ago

0.23.1

3 years ago

0.23.0

3 years ago

0.21.1

4 years ago

0.25.0-alpha.0

3 years ago

0.25.0-alpha.1

3 years ago

0.21.0

4 years ago

0.25.0-alpha.2

3 years ago

0.25.0-alpha.3

3 years ago

0.24.2

3 years ago

0.24.1

3 years ago

0.24.0

3 years ago

0.22.1

4 years ago

0.20.3

4 years ago

0.22.0

4 years ago

0.20.1

4 years ago

0.20.0

4 years ago

0.19.4

4 years ago

0.20.0-alpha.0

4 years ago

0.20.0-alpha.1

4 years ago

0.20.2

4 years ago

0.19.0-alpha.0

4 years ago

0.19.0-alpha.3

4 years ago

0.19.0-alpha.2

4 years ago

0.19.0-alpha.1

4 years ago

0.19.0

4 years ago

0.19.1

4 years ago

0.19.2

4 years ago

0.19.3

4 years ago

0.18.0

4 years ago

0.17.0-alpha.0

4 years ago

0.17.0

4 years ago

0.18.0-alpha.0

4 years ago

0.16.1

4 years ago

0.16.0

4 years ago

0.16.0-alpha.3

4 years ago

0.16.0-alpha.2

4 years ago

0.16.0-alpha.1

4 years ago

0.16.0-alpha.0

4 years ago

0.15.3

4 years ago

0.15.2

4 years ago

0.15.0

4 years ago

0.15.1

4 years ago

0.14.2

4 years ago

0.14.1

4 years ago

0.14.0

4 years ago

0.13.0

4 years ago

0.12.3

4 years ago

0.12.4

4 years ago

0.11.0

4 years ago

0.12.0

4 years ago

0.11.1

4 years ago

0.12.1

4 years ago

0.12.2

4 years ago

0.10.1

4 years ago

0.10.0

4 years ago

0.10.0-alpha.10

4 years ago

0.10.0-alpha.9

4 years ago

0.10.0-alpha.8

4 years ago