Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby): allow schema customization #11480

Merged
merged 111 commits into from
Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from 98 commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
9926e2d
Schema refactor WIP
freiksenet Feb 1, 2019
d9e6873
Oops
freiksenet Feb 1, 2019
08ab5c2
First working version
freiksenet Feb 4, 2019
1aef564
First working version
freiksenet Feb 4, 2019
ac49f5b
Almost working site
freiksenet Feb 4, 2019
f369296
progress
freiksenet Feb 5, 2019
6add8d9
WWW working
freiksenet Feb 6, 2019
2e25030
Working add type defs
freiksenet Feb 7, 2019
b532d1b
addResolvers
freiksenet Feb 8, 2019
69162b6
Add node model
stefanprobst Feb 8, 2019
b9af766
Handle NonNull and pass context and info in runQuery
stefanprobst Feb 9, 2019
a5b0d55
Don't fetch resolved id again
stefanprobst Feb 9, 2019
f7d80f0
Minor fixes
stefanprobst Feb 9, 2019
23423db
Make www build with Loki
stefanprobst Feb 9, 2019
6e11926
Fix tests
stefanprobst Feb 10, 2019
ed9314b
Pull out resolving nodes
stefanprobst Feb 10, 2019
79754e6
Fix getExampleValue
stefanprobst Feb 10, 2019
6f1e715
Port exampleValue tests
stefanprobst Feb 10, 2019
12a9819
Fixes for type inference
stefanprobst Feb 10, 2019
0ca1294
Infer errors and stuff
freiksenet Feb 11, 2019
b8d0d6f
Merge remote-tracking branch 'stefanprobst/schema-refactor-new-sp' in…
freiksenet Feb 11, 2019
15df9e3
Lint
freiksenet Feb 11, 2019
9a59b47
More changes
freiksenet Feb 12, 2019
7878818
Fix issue with default resolvers
freiksenet Feb 12, 2019
779cb39
Fix tests
freiksenet Feb 12, 2019
d45c97c
Port more tests
freiksenet Feb 12, 2019
10f1405
Move schema composer creation to separate location
freiksenet Feb 13, 2019
c7b1177
Most tests pass
freiksenet Feb 13, 2019
8dbc6e7
Move tests to better location
freiksenet Feb 13, 2019
bf02578
Readd list sorting option
freiksenet Feb 13, 2019
b6ec46f
Node model as a class
freiksenet Feb 13, 2019
add0666
Model layer tests
freiksenet Feb 13, 2019
da8469d
Fix flow type
freiksenet Feb 14, 2019
e7bb44b
Merge remote-tracking branch 'origin/master' into schema-refactor-new
freiksenet Feb 14, 2019
d002f9c
Restore prepare-nodes improvements
freiksenet Feb 14, 2019
73a1f2d
Fixes
freiksenet Feb 14, 2019
448bcfe
Port more tests (#11757)
stefanprobst Feb 14, 2019
2c0b2cf
Merge remote-tracking branch 'origin/master' into schema-refactor-new
freiksenet Feb 14, 2019
292200f
WIP kitchen sink
freiksenet Feb 14, 2019
1cb0aab
Fix tests for Loki, and minor changes (#11765)
stefanprobst Feb 15, 2019
e512743
Satisfy linter
freiksenet Feb 15, 2019
017bfa1
Mix dates and strings behaviour
freiksenet Feb 15, 2019
ccb0bb6
Test more stuff with runQuery
freiksenet Feb 15, 2019
58297c7
Add resolvers test
freiksenet Feb 15, 2019
1d4272e
Updated API names to match gatsby
freiksenet Feb 18, 2019
7666727
3rd party schema tests
freiksenet Feb 18, 2019
7e0261f
More fixes
freiksenet Feb 18, 2019
7f661eb
Beter example in using-type-defs
freiksenet Feb 18, 2019
3ddcf99
More fixes
freiksenet Feb 18, 2019
ff85e86
Add NodeModel tests (#11880)
stefanprobst Feb 19, 2019
31b11f3
[schema] Better example (#11892)
stefanprobst Feb 19, 2019
0c5e13a
Fix conflicting field issue
freiksenet Feb 19, 2019
a440e8e
Handle multiple return values from setFieldsOnGraphQLNodeType (#12048)
stefanprobst Feb 25, 2019
c310140
Fix conflicting fields priority on nested type (#11900)
stefanprobst Feb 25, 2019
c6a7826
Merge remote-tracking branch 'upstream/master' into schema-refactor-new
stefanprobst Feb 26, 2019
4dfc057
Allow field type on third-party type (#11970)
stefanprobst Feb 27, 2019
879cd7b
Make original field resolver available on info (#12159)
stefanprobst Feb 28, 2019
fbfa6b4
[schema] Make output fields non-null (#12097)
stefanprobst Feb 28, 2019
a1c01a6
[schema] Add schema query tests, inference fixes (#12190)
stefanprobst Mar 1, 2019
e344292
[schema] Add default page dependency path (#12220)
stefanprobst Mar 1, 2019
5db668a
Merge remote-tracking branch 'origin/master' into schema-refactor-new
freiksenet Mar 4, 2019
9992c12
chore(release): Publish
freiksenet Mar 4, 2019
ab9ffac
More tests and some fixes
freiksenet Mar 4, 2019
6cc1992
Revert "chore(release): Publish"
freiksenet Mar 4, 2019
b90b05f
Allow custom resolveType (#12309)
stefanprobst Mar 5, 2019
238cc2b
v2.2.0-alpha.0
freiksenet Mar 4, 2019
b706829
More fixes and tests
freiksenet Mar 5, 2019
9269305
More tests, refine infer logic
freiksenet Mar 5, 2019
52d6012
[schema] Make id field on InputObjectType type String (#12335)
stefanprobst Mar 6, 2019
1e58b54
v2.2.0-alpha.1
freiksenet Mar 5, 2019
7eda0b2
Upgrade schema composer
freiksenet Mar 6, 2019
222f3da
v2.2.0-alpha.2
freiksenet Mar 6, 2019
e76e7e8
Fix loxi test issue
freiksenet Mar 6, 2019
fe5fe1d
Add type builders internally
freiksenet Mar 6, 2019
081fa15
Add type builders internally
freiksenet Mar 6, 2019
f3a7cf6
Added type builders to the API
freiksenet Mar 6, 2019
5522c28
v2.2.0-alpha.3
freiksenet Mar 6, 2019
67ee427
[schema] Add NodeModel docs (#12354)
stefanprobst Mar 7, 2019
8628a48
Check for type names reserved for internal use (#12373)
stefanprobst Mar 7, 2019
4e09a7d
Allow custom scalars in input filter (#12375)
stefanprobst Mar 7, 2019
3e06835
Correctly camelcase connections (#12378)
stefanprobst Mar 7, 2019
587e9ef
v2.2.0-alpha.4
freiksenet Mar 7, 2019
16dab78
v2.2.0-alpha.5
freiksenet Mar 7, 2019
5a9a5f0
[schema] Remove empty input fields (#12380)
stefanprobst Mar 8, 2019
6c86d28
[schema] Add code frame to SDL parsing error (#12401)
stefanprobst Mar 8, 2019
ef567f0
Merge branch 'master' into schema-refactor-new
freiksenet Mar 8, 2019
582bd94
v2.2.0-alpha.6
freiksenet Mar 8, 2019
d61a776
Add blog post
freiksenet Mar 12, 2019
3f3e8fe
Don't use npx in example README
muescha Mar 16, 2019
71c391f
Update docs for new documentationjs version (#12615)
stefanprobst Mar 18, 2019
75da5e5
Merge remote-tracking branch 'origin/master' into schema-refactor-new
freiksenet Mar 18, 2019
1bc4013
v2.2.0-rc.1
freiksenet Mar 18, 2019
0a3a750
Revert "v2.2.0-rc.1"
freiksenet Mar 18, 2019
59a2dd2
Remove extra dep
freiksenet Mar 18, 2019
511abb3
Fix date
freiksenet Mar 18, 2019
f46154b
chore(blog): add schema customization blog post release (#12522)
DSchau Mar 18, 2019
582db20
Update blog as per review
freiksenet Mar 18, 2019
50ed38b
Docs
freiksenet Mar 18, 2019
4a6b108
Update docs/blog/2019-03-18-releasing-new-schema-customization/index.md
stefanprobst Mar 18, 2019
ecf5656
Add tweet
freiksenet Mar 18, 2019
0a48280
Update docs/blog/2019-03-18-releasing-new-schema-customization/index.md
stefanprobst Mar 18, 2019
3f2c4a0
Merge remote-tracking branch 'origin/master' into schema-refactor-new
freiksenet Mar 18, 2019
5c2b25a
Remove dep
stefanprobst Mar 18, 2019
c7c7ae0
Move tweet
freiksenet Mar 18, 2019
78cbab4
[schema] Ignore empty strings in example value creation (#12646)
stefanprobst Mar 19, 2019
7d48322
Add tests
freiksenet Mar 19, 2019
196ef58
Fix snapshot
freiksenet Mar 19, 2019
09f0d91
v2.2.0-rc.2
freiksenet Mar 19, 2019
4dcb431
Revert "v2.2.0-rc.2"
freiksenet Mar 19, 2019
54ff3b6
Change blog date
freiksenet Mar 19, 2019
04f7694
use <PROJECT_ROOT> in fixture (#12662)
pieh Mar 19, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions docs/blog/2019-03-18-releasing-new-schema-customization/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: New Schema Customization API - Available in Gatsby 2.2.0
date: 2019-03-18
author: Mikhail Novikov
tags:
- schema
- graphql
---

Two weeks ago, we announced our plans for a [new schema customization API](/blog/2019-03-04-new-schema-customization/). Today we are making this set of new APIs and enhancements available to all in `gatsby`@`2.2.0`.

First, install the latest and greatest version of `gatsby`, like so:

```shell
npm install gatsby --save
```

Next, continue reading below to see if any of the great, new features we've enabled scratch a particular itch. We feel very confident they will 💜

# Recap of schema customization

Before this change, the Gatsby GraphQL schema was generated automatically from the data that the user added to Gatsby. While very convenient and easy to start, changes to the data could cause changes to the schema, which could cause breakage in unrelated locations. Those bugs were confusing and hard to debug. To alleviate this problem, we've added a schema customization API that lets you customize, fix, and enhance types in your Gatsby GraphQL schema.

There are two new APIs, `createTypes` and `createResolvers`.

## `createTypes`

`createTypes` can be used to define, fix, or extend a Gatsby GraphQL type that represents some of your app's data. Think of it like an escape hatch to politely inform Gatsby of your data's shape.

```js:title=gatsby-node.js
exports.sourceNodes = ({ actions }) => {
const { createTypes } = actions
const typeDefs = `
type AuthorJson implements Node {
name: String
birthday: Date
}
`
createTypes(typeDefs)
}
```

After adding this to your [gatsby-node](/docs/gatsby-project-structure/#files) file, the `AuthorJson` type will always have fields name and birthday, regardless of the automatically inferred data shape. The rest of the fields will still be inferred normally, allowing you to enjoy the default benefits of Gatsby schema inference.

## `createResolvers`

`createResolvers` allows doing additional customization after all schema processing has been finished. Thus it can be used to add fields to any types, including root types like `Query` and types from third party schemas.

```js:title=gatsby-node.js
createResolvers({
Query: {
allAuthorFullNames: {
type: `[String!]!`,
resolve(source, args, context, info) {
const authors = context.nodeModel.getAllNodes({
type: `AuthorJson`,
})
return authors.map(author => author.name)
},
},
},
})
```

## The Type Builder API

While `createTypes` accepts `graphql-js` types along with a [Schema Definition Language (SDL)](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) string, we've also added an option to use `graphql-js` types so that users could create types with resolvers. However, `graphql-js` is somewhat verbose and it can be hard to refer to types that don't yet exist or don't exist in a current scope. Therefore, we decided to add another programmatic API that combines brevity of SDL with flexibility of `graphql-js`.
freiksenet marked this conversation as resolved.
Show resolved Hide resolved

We refer to this API as the _Type Builder API_. It is available in the `schema` field of the arguments object passed to [Gatsby Node APIs](/docs/node-apis/).

```js:title=gatsby-node.js
exports.sourceNodes = ({ actions, schema }) => {
const { createTypes } = actions
createTypes([
schema.buildObjectType({
name: `CommentJson`,
fields: {
text: `String!`,
blog: {
type: `BlogJson`,
resolve(parent, args, context) {
return context.nodeModel.getNodeById({
id: parent.author,
type: `BlogJson`,
})
},
},
author: {
type: `AuthorJson`,
resolve(parent, args, context) {
return context.nodeModel.getNodeById({
id: parent.author,
type: `AuthorJson`,
})
},
},
},
interfaces: [`Node`],
}),
])
}
```

# Potential for Breaking Changes

We have tried to avoid any breaking changes in this refactor of the underlying GraphQL layer, testing it in notable Gatsby sites and ensuring all tests were passing. However, there are areas where we needed to introduce more stable naming, and in these instances it _could_ be possible that a breaking change was introduced if you were relying on this undocumented API.

Specifically, before this refactor Gatsby type names weren't stable. They could have names like `frontmatter_2` because of some quirks in our schema generation. Now the types names are **stable** and **defined**. For a `Node`, it's always a Pascal Camel Cased name of the `Node` type (for example, `AllMarkdownRemark`). For an inline object, it's the name of the node plus the name of the field, again Pascal Camel Cased. So `frontmatter_2` would be available as `MarkdownRemarkFrontmatter` now. If you've had fragments referring to some types by their old names, you may need to change it to new names, e.g.:
freiksenet marked this conversation as resolved.
Show resolved Hide resolved

```diff
- fragment someFragment on frontmatter_2 {
+ fragment someFragment on MarkdownRemarkFrontmatter {
title
}
```

Another change relates to inference. Previously, ordering of the Nodes in your data source could affect which type Gatsby inferred. Now, we always consider all possible types, thus you might experience type conflicts for conflicting data sources. They can be solved by either fixing the data or defining a type using new schema customization APIs that we've exposed.

# Wrap-up

As next steps, we will work on adding more convenient tooling to "freeze" your schema type definitions, so that you can quickly start using this feature. We will also be working on improving API docs for this.

We strongly believe that these new APIs are the foundation of an evolutionary leap of the Gatsby GraphQL API. These changes make the GraphQL API more stable, more robust, and more easily customizable. They will enable further customization and use cases, like [theming](/blog/2018-11-11-introducing-gatsby-themes/) and more still that we haven't even envisioned yet. We truly can't wait to see the great things you build and how you use these new APIs and improvements powered by Gatsby and its improved GraphQL layer.

## Additional Resources

- [Meta issue](https://github.com/gatsbyjs/gatsby/issues/12272) for bug reports
- [API docs for createTypes](/docs/actions/#createTypes)
- [API docs for createResolvers](/docs/node-apis/#createResolvers)
- [API docs for node model](/docs/node-model)
- [Using type definitions example](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-type-definitions)
1 change: 1 addition & 0 deletions examples/gatsbygram/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"gatsby-transformer-json": "^2.1.1",
"gatsby-transformer-sharp": "^2.1.1",
"glamor": "^2.20.40",
"graphql-compose": "^5.10.1",
"instagram-screen-scrape": "^2.0.0",
"lodash": "^4.17.10",
"mkdirp": "^0.5.1",
Expand Down
69 changes: 69 additions & 0 deletions examples/using-type-definitions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# dotenv environment variables file
.env

# gatsby files
.cache/
public

# Mac files
.DS_Store

# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity
5 changes: 5 additions & 0 deletions examples/using-type-definitions/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"trailingComma": "es5"
}
22 changes: 22 additions & 0 deletions examples/using-type-definitions/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2015 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

97 changes: 97 additions & 0 deletions examples/using-type-definitions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
<p align="center">
<a href="https://www.gatsbyjs.org">
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
</a>
</p>
<h1 align="center">
Gatsby's default starter
</h1>

Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.

_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._

## 🚀 Quick start

1. **Create a Gatsby site.**

Use the Gatsby CLI to create a new site, specifying the default starter.

```sh
# create a new Gatsby site using the default starter
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
```

1. **Start developing.**

Navigate into your new site’s directory and start it up.

```sh
cd my-default-starter/
gatsby develop
```

1. **Open the source code and start editing!**

Your site is now running at `http://localhost:8000`!

_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._

Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!

## 🧐 What's inside?

A quick look at the top-level files and directories you'll see in a Gatsby project.

.
├── node_modules
├── src
├── .gitignore
├── .prettierrc
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package-lock.json
├── package.json
└── README.md

1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.

2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.

3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.

4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.

5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.

6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).

7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.

8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.

9. **`LICENSE`**: Gatsby is licensed under the MIT license.

10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).**

11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project.

12. **`README.md`**: A text file containing useful reference information about your project.

## 🎓 Learning Gatsby

Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:

- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.

- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.

## 💫 Deploy

[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)

<!-- AUTO-GENERATED-CONTENT:END -->
26 changes: 26 additions & 0 deletions examples/using-type-definitions/gatsby-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
},
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `./src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `./src/data/`,
},
},
],
}
Loading