├── .npmignore
├── dist
├── WebpackLogger.js
├── getRelayCompilerPluginHooks.js
├── getFilepathsFromGlob.js
├── getSchemaSource.js
├── createRaiseErrorsReporter.js
├── getWriter.js
└── index.js
├── .gitignore
├── .eslintrc
├── .flowconfig
├── src
├── WebpackLogger.js
├── getFilepathsFromGlob.js
├── getSchemaSource.js
├── getRelayCompilerPluginHooks.js
├── createRaiseErrorsReporter.js
├── getWriter.js
└── index.js
├── test
├── fixtureProject
│ ├── src
│ │ ├── entry.js
│ │ ├── components
│ │ │ ├── HomeItem.js
│ │ │ ├── Home.js
│ │ │ ├── App.js
│ │ │ └── About.js
│ │ └── mutations
│ │ │ └── updateFirstNameMutation.js
│ ├── .babelrc.js
│ ├── createWebpackConfig.js
│ └── schema.json
├── support
│ ├── createTempFixtureProject.js
│ └── normaliseConfigForWebpackVersion.js
├── hooks.test.js
├── invalidArgs.test.js
├── normalCase.test.js
└── __snapshots__
│ └── normalCase.test.js.snap
├── .github
└── workflows
│ └── build.yml
├── LICENSE
├── package.json
└── README.md
/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.log
3 |
--------------------------------------------------------------------------------
/dist/WebpackLogger.js:
--------------------------------------------------------------------------------
1 | "use strict";
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /test/temp
3 | /reports
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "standard",
5 | "airbnb-base"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | .*/test/.*
3 |
4 | [include]
5 |
6 | [libs]
7 |
8 | [options]
9 | esproposal.optional_chaining=enable
10 |
11 | [version]
12 | ^0.120.0
13 |
--------------------------------------------------------------------------------
/src/WebpackLogger.js:
--------------------------------------------------------------------------------
1 | export interface WebpackLogger {
2 | log(any): void;
3 | info(any): void;
4 | warn(any): void;
5 | error(any): void;
6 | debug(any): void;
7 | }
8 |
--------------------------------------------------------------------------------
/test/fixtureProject/src/entry.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import App from './components/App'
4 |
5 | ReactDOM.render(, document.getElementById('main'))
6 |
--------------------------------------------------------------------------------
/test/support/createTempFixtureProject.js:
--------------------------------------------------------------------------------
1 | import { copySync, removeSync } from 'fs-extra'
2 | import path from "path"
3 |
4 | export default function(name) {
5 | const normalCaseDir = path.resolve(__dirname, '..', 'fixtureProject')
6 | const tempDir = path.resolve(__dirname, '..', 'temp', name)
7 | removeSync(tempDir)
8 | copySync(normalCaseDir, tempDir)
9 | return tempDir
10 | }
11 |
--------------------------------------------------------------------------------
/test/support/normaliseConfigForWebpackVersion.js:
--------------------------------------------------------------------------------
1 | /* global require */
2 |
3 | const webpackMajorVersion = Number(
4 | require('webpack/package.json').version.split('.')[0]
5 | )
6 |
7 | if (isNaN(webpackMajorVersion)) {
8 | throw new Error('Cannot parse webpack major version')
9 | }
10 |
11 | export default config => {
12 | if (webpackMajorVersion < 4) {
13 | delete config.mode
14 | }
15 | return config
16 | }
17 |
--------------------------------------------------------------------------------
/test/fixtureProject/.babelrc.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | "env": {
5 | "artifactDirectoryTest": {
6 | "plugins": [
7 | ["relay", {
8 | "artifactDirectory": path.resolve(__dirname, "src", "__generated__")
9 | }]
10 | ],
11 | }
12 | },
13 | "plugins": ["relay"],
14 | "presets": [
15 | "@babel/preset-react",
16 | "@babel/preset-env"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/test/fixtureProject/src/components/HomeItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { graphql, createFragmentContainer } from 'react-relay'
3 |
4 | const HomeItem = ({ person: { id, fullName } }) => (
5 |
6 | {fullName}
7 |
8 | )
9 |
10 | export default createFragmentContainer(
11 | HomeItem,
12 | graphql`
13 | fragment HomeItem_person on Person {
14 | id
15 | fullName
16 | }
17 | `
18 | )
19 |
--------------------------------------------------------------------------------
/test/fixtureProject/src/components/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { graphql, createFragmentContainer } from 'react-relay'
3 | import HomeItem from './HomeItem'
4 |
5 | const Home = ({ people }) => (
6 |
7 |
Home
8 |
9 | {people.map(person => (
10 |
11 | ))}
12 |
13 |
14 | )
15 |
16 | export default createFragmentContainer(
17 | Home,
18 | graphql`
19 | fragment Home_people on Person @relay(plural: true) {
20 | id
21 | ...HomeItem_person
22 | }
23 | `
24 | )
25 |
--------------------------------------------------------------------------------
/src/getFilepathsFromGlob.js:
--------------------------------------------------------------------------------
1 | import glob from 'fast-glob';
2 |
3 | export default function getFilepathsFromGlob(
4 | baseDir,
5 | options: {
6 | extensions: Array,
7 | include: Array,
8 | exclude: Array
9 | },
10 | ): Array {
11 | const { extensions, include, exclude } = options;
12 | const patterns = include.map((inc) => `${inc}/*.+(${extensions.join('|')})`);
13 |
14 | return glob.sync(patterns, {
15 | cwd: baseDir,
16 | bashNative: [],
17 | onlyFiles: true,
18 | dot: true, // match behavior of watchman from relay-compiler
19 | ignore: exclude,
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/test/fixtureProject/src/mutations/updateFirstNameMutation.js:
--------------------------------------------------------------------------------
1 | import { commitMutation, graphql } from 'react-relay'
2 |
3 | const mutation = graphql`
4 | mutation updateFirstNameMutation($id: ID!, $firstName: String!) {
5 | updateFirstName(id: $id, firstName: $firstName) {
6 | person {
7 | firstName
8 | fullName
9 | }
10 | }
11 | }
12 | `
13 |
14 | export default (environment, variables) => {
15 | return new Promise((resolve, reject) => {
16 | commitMutation(environment, {
17 | mutation,
18 | variables,
19 | onError: reject,
20 | onCompleted: resolve
21 | })
22 | })
23 | }
24 |
--------------------------------------------------------------------------------
/test/fixtureProject/createWebpackConfig.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = ({ relayCompilerWebpackPlugin, plugins = [] }) => ({
4 | mode: 'production',
5 | context: __dirname,
6 | entry: './src/entry.js',
7 | output: {
8 | path: path.resolve('dist'),
9 | filename: 'index.js'
10 | },
11 | performance: {
12 | hints: false
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.js$/,
18 | exclude: path.join(__dirname, 'node_modules'),
19 | use: [{ loader: 'babel-loader' }]
20 | }
21 | ]
22 | },
23 | plugins: [relayCompilerWebpackPlugin, ...plugins]
24 | })
25 |
--------------------------------------------------------------------------------
/src/getSchemaSource.js:
--------------------------------------------------------------------------------
1 | // @flow
2 |
3 | import fs from 'fs';
4 | import { buildClientSchema, printSchema, Source } from 'graphql';
5 | import path from 'path';
6 |
7 | // Taken from relay-compiler/bin/RelayCompilerMain.js
8 | export default function getSchemaSource(schemaPath: string): Source {
9 | let source = fs.readFileSync(schemaPath, 'utf8');
10 | if (path.extname(schemaPath) === '.json') {
11 | source = printSchema(buildClientSchema(JSON.parse(source).data));
12 | }
13 | source = `
14 | directive @include(if: Boolean) on FRAGMENT_SPREAD | FIELD
15 | directive @skip(if: Boolean) on FRAGMENT_SPREAD | FIELD
16 |
17 | ${source}
18 | `;
19 | return new Source(source, schemaPath);
20 | }
21 |
--------------------------------------------------------------------------------
/dist/getRelayCompilerPluginHooks.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = _default;
7 |
8 | var _tapable = require("tapable");
9 |
10 | const relayCompilerPluginHooksMap = new WeakMap();
11 |
12 | function createRelayCompilerPluginHooks() {
13 | return {
14 | beforeWrite: new _tapable.AsyncSeriesWaterfallHook(['pluginArgs']),
15 | afterWrite: new _tapable.AsyncSeriesWaterfallHook(['pluginArgs'])
16 | };
17 | }
18 |
19 | function _default(compilation) {
20 | let hooks = relayCompilerPluginHooksMap.get(compilation);
21 |
22 | if (!hooks) {
23 | hooks = createRelayCompilerPluginHooks();
24 | relayCompilerPluginHooksMap.set(compilation, hooks);
25 | }
26 |
27 | return hooks;
28 | }
--------------------------------------------------------------------------------
/dist/getFilepathsFromGlob.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = getFilepathsFromGlob;
7 |
8 | var _fastGlob = _interopRequireDefault(require("fast-glob"));
9 |
10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11 |
12 | function getFilepathsFromGlob(baseDir, options) {
13 | const {
14 | extensions,
15 | include,
16 | exclude
17 | } = options;
18 | const patterns = include.map(inc => `${inc}/*.+(${extensions.join('|')})`);
19 | return _fastGlob.default.sync(patterns, {
20 | cwd: baseDir,
21 | bashNative: [],
22 | onlyFiles: true,
23 | dot: true,
24 | // match behavior of watchman from relay-compiler
25 | ignore: exclude
26 | });
27 | }
--------------------------------------------------------------------------------
/test/fixtureProject/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Home from './Home'
3 | import About from './About'
4 | import { graphql, QueryRenderer } from 'react-relay'
5 |
6 | export default () => (
7 | {
17 | if (error) {
18 | console.error(error)
19 | return Error
20 | }
21 |
22 | if (!props) {
23 | return Loading
24 | }
25 |
26 | const { people } = props
27 | return (
28 |
32 | )
33 | }}
34 | />
35 | )
36 |
--------------------------------------------------------------------------------
/src/getRelayCompilerPluginHooks.js:
--------------------------------------------------------------------------------
1 | // @flow
2 |
3 | import { AsyncSeriesWaterfallHook } from 'tapable';
4 | import type { Compilation } from 'webpack';
5 |
6 | const relayCompilerPluginHooksMap = new WeakMap();
7 |
8 | export interface PluginHooks {
9 | beforeWrite: AsyncSeriesWaterfallHook,
10 | afterWrite: AsyncSeriesWaterfallHook
11 | }
12 |
13 | function createRelayCompilerPluginHooks(): PluginHooks {
14 | return {
15 | beforeWrite: new AsyncSeriesWaterfallHook(['pluginArgs']),
16 | afterWrite: new AsyncSeriesWaterfallHook(['pluginArgs']),
17 | };
18 | }
19 |
20 | export default function (compilation: Compilation): PluginHooks {
21 | let hooks = relayCompilerPluginHooksMap.get(compilation);
22 | if (!hooks) {
23 | hooks = createRelayCompilerPluginHooks();
24 | relayCompilerPluginHooksMap.set(compilation, hooks);
25 | }
26 | return hooks;
27 | }
28 |
--------------------------------------------------------------------------------
/dist/getSchemaSource.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = getSchemaSource;
7 |
8 | var _fs = _interopRequireDefault(require("fs"));
9 |
10 | var _graphql = require("graphql");
11 |
12 | var _path = _interopRequireDefault(require("path"));
13 |
14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15 |
16 | // Taken from relay-compiler/bin/RelayCompilerMain.js
17 | function getSchemaSource(schemaPath) {
18 | let source = _fs.default.readFileSync(schemaPath, 'utf8');
19 |
20 | if (_path.default.extname(schemaPath) === '.json') {
21 | source = (0, _graphql.printSchema)((0, _graphql.buildClientSchema)(JSON.parse(source).data));
22 | }
23 |
24 | source = `
25 | directive @include(if: Boolean) on FRAGMENT_SPREAD | FIELD
26 | directive @skip(if: Boolean) on FRAGMENT_SPREAD | FIELD
27 |
28 | ${source}
29 | `;
30 | return new _graphql.Source(source, schemaPath);
31 | }
--------------------------------------------------------------------------------
/dist/createRaiseErrorsReporter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = createRaiseErrorsReporter;
7 |
8 | // Was using a ConsoleReporter with quiet true (which is essentially a no-op)
9 | // This implements graphql-compiler GraphQLReporter
10 | // https://github.com/facebook/relay/blob/v1.7.0/packages/graphql-compiler/reporters/GraphQLReporter.js
11 | // Wasn't able to find a way to import the GraphQLReporter interface to declare that it is
12 | // implemented
13 | function createRaiseErrorsReporter(logger) {
14 | return {
15 | reportMessage(message) {
16 | if (logger) logger.log(message);else console.log(message); // eslint-disable-line no-console
17 | },
18 |
19 | /* eslint-disable no-unused-vars */
20 | reportTime(name, ms) {// process.stdout.write('Report time: ' + name + ' ' + ms + '\n');
21 | },
22 |
23 | /* eslint-enable no-unused-vars */
24 | reportError(caughtLocation, error) {
25 | // process.stdout.write('Report error: ' + caughtLocation + ' ' + error.toString() + '\n');
26 | throw error;
27 | }
28 |
29 | };
30 | }
--------------------------------------------------------------------------------
/src/createRaiseErrorsReporter.js:
--------------------------------------------------------------------------------
1 | // Was using a ConsoleReporter with quiet true (which is essentially a no-op)
2 | // This implements graphql-compiler GraphQLReporter
3 | // https://github.com/facebook/relay/blob/v1.7.0/packages/graphql-compiler/reporters/GraphQLReporter.js
4 | // Wasn't able to find a way to import the GraphQLReporter interface to declare that it is
5 | // implemented
6 |
7 | import type { WebpackLogger } from './WebpackLogger';
8 |
9 | export default function createRaiseErrorsReporter(logger?: WebpackLogger) {
10 | return {
11 | reportMessage(message: string): void {
12 | if (logger) logger.log(message);
13 | else console.log(message); // eslint-disable-line no-console
14 | },
15 |
16 | /* eslint-disable no-unused-vars */
17 | reportTime(name: string, ms: number): void {
18 | // process.stdout.write('Report time: ' + name + ' ' + ms + '\n');
19 | },
20 | /* eslint-enable no-unused-vars */
21 |
22 | reportError(caughtLocation: string, error: Error): void {
23 | // process.stdout.write('Report error: ' + caughtLocation + ' ' + error.toString() + '\n');
24 | throw error;
25 | },
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | deploy:
10 | name: Build on Node ${{ matrix.node_version }}, Webpack ${{ matrix.webpack_version }}
11 | strategy:
12 | matrix:
13 | webpack_version: [3, 4, 5]
14 | node_version: [10, 12, 14, 15, 16]
15 |
16 | runs-on: ubuntu-18.04
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 | - name: Get yarn cache directory path
21 | id: yarn-cache-dir-path
22 | run: echo "::set-output name=dir::$(yarn cache dir)"
23 | - uses: actions/cache@v2
24 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
25 | with:
26 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
27 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
28 | restore-keys: |
29 | ${{ runner.os }}-yarn-
30 | - name: Setup Node
31 | uses: actions/setup-node@v1
32 | with:
33 | node-version: ${{ matrix.node_version }}
34 | - name: Install Yarn Deps
35 | run: |
36 | yarn
37 | yarn remove webpack
38 | yarn add webpack@${{ env.webpack_version }}
39 | - name: Build
40 | run: yarn build
41 |
--------------------------------------------------------------------------------
/src/getWriter.js:
--------------------------------------------------------------------------------
1 | // @flow
2 |
3 | import { FileWriter, IRTransforms } from 'relay-compiler';
4 | import type { WriteFilesOptions } from 'relay-compiler';
5 |
6 | export type WriterConfig = {
7 | outputDir?: string,
8 | baseDir: string,
9 | customScalars?: any
10 | }
11 |
12 | const {
13 | commonTransforms,
14 | codegenTransforms,
15 | fragmentTransforms,
16 | printTransforms,
17 | queryTransforms,
18 | schemaExtensions,
19 | } = IRTransforms;
20 |
21 | // Taken from relay-compiler/bin/RelayCompilerMain.js
22 | export default (languagePlugin: any, config: WriterConfig) => ({
23 | onlyValidate,
24 | schema,
25 | documents,
26 | baseDocuments,
27 | sourceControl,
28 | reporter,
29 | }: WriteFilesOptions) => FileWriter.writeAll({
30 | config: {
31 | customScalars: {},
32 | ...config,
33 | compilerTransforms: {
34 | commonTransforms,
35 | codegenTransforms,
36 | fragmentTransforms,
37 | printTransforms,
38 | queryTransforms,
39 | },
40 | formatModule: languagePlugin.formatModule,
41 | optionalInputFieldsForFlow: [],
42 | schemaExtensions,
43 | useHaste: false,
44 | extension: languagePlugin.outputExtension,
45 | typeGenerator: languagePlugin.typeGenerator,
46 | },
47 | onlyValidate,
48 | schema,
49 | baseDocuments,
50 | documents,
51 | reporter,
52 | sourceControl,
53 | });
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, ThusFresh Inc
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/test/fixtureProject/src/components/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { graphql, QueryRenderer } from 'react-relay'
3 | import updateFirstNameMutation from '../mutations/updateFirstNameMutation'
4 |
5 | export default ({ id, relayEnvironment }) => {
6 | const onSubmit = e => {
7 | e.preventDefault()
8 |
9 | updateFirstNameMutation(relayEnvironment, {
10 | id,
11 | firstName: e.target.firstName.value
12 | })
13 | }
14 |
15 | return (
16 | {
29 | if (!props) {
30 | return Loading
31 | }
32 |
33 | const { personById } = props
34 | if (!personById) {
35 | return No match
36 | }
37 | return (
38 |
39 |
About
40 |
41 | Id: {personById.id}
42 |
43 | Name: {personById.fullName}
44 |
45 |
46 |
56 |
57 |
58 | )
59 | }}
60 | />
61 | )
62 | }
63 |
--------------------------------------------------------------------------------
/dist/getWriter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = void 0;
7 |
8 | var _relayCompiler = require("relay-compiler");
9 |
10 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
11 |
12 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
13 |
14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15 |
16 | const {
17 | commonTransforms,
18 | codegenTransforms,
19 | fragmentTransforms,
20 | printTransforms,
21 | queryTransforms,
22 | schemaExtensions
23 | } = _relayCompiler.IRTransforms; // Taken from relay-compiler/bin/RelayCompilerMain.js
24 |
25 | var _default = (languagePlugin, config) => ({
26 | onlyValidate,
27 | schema,
28 | documents,
29 | baseDocuments,
30 | sourceControl,
31 | reporter
32 | }) => _relayCompiler.FileWriter.writeAll({
33 | config: _objectSpread(_objectSpread({
34 | customScalars: {}
35 | }, config), {}, {
36 | compilerTransforms: {
37 | commonTransforms,
38 | codegenTransforms,
39 | fragmentTransforms,
40 | printTransforms,
41 | queryTransforms
42 | },
43 | formatModule: languagePlugin.formatModule,
44 | optionalInputFieldsForFlow: [],
45 | schemaExtensions,
46 | useHaste: false,
47 | extension: languagePlugin.outputExtension,
48 | typeGenerator: languagePlugin.typeGenerator
49 | }),
50 | onlyValidate,
51 | schema,
52 | baseDocuments,
53 | documents,
54 | reporter,
55 | sourceControl
56 | });
57 |
58 | exports.default = _default;
--------------------------------------------------------------------------------
/test/hooks.test.js:
--------------------------------------------------------------------------------
1 | /* global jest, describe, it, beforeEach */
2 | /* eslint-env jest */
3 | import webpack from 'webpack'
4 | import path from 'path'
5 | import rimraf from 'rimraf'
6 | import RelayCompilerWebpackPlugin from '../src/index'
7 | import normaliseConfigForWebpackVersion from './support/normaliseConfigForWebpackVersion'
8 | import createTempFixtureProject from './support/createTempFixtureProject'
9 | import { removeSync } from 'fs-extra'
10 |
11 | jest.setTimeout(30000)
12 |
13 | const DEFAULT_NODE_ENV = process.env.NODE_ENV
14 |
15 | describe('RelayCompilerWebpackPlugin', () => {
16 | let fixtureDir
17 | let createWebpackConfig
18 | let srcDir
19 |
20 | beforeEach(() => {
21 | process.env.NODE_ENV = DEFAULT_NODE_ENV
22 | fixtureDir = createTempFixtureProject('hooks')
23 | createWebpackConfig = require(fixtureDir + '/createWebpackConfig')
24 | srcDir = path.join(fixtureDir, 'src')
25 | })
26 |
27 | afterEach(() => {
28 | removeSync(fixtureDir)
29 | })
30 |
31 | it('Calls hooks appropriately', done => {
32 | const beforeWriteSpy = jest.fn()
33 | const afterWriteSpy = jest.fn()
34 | const relayCompilerWebpackPlugin = new RelayCompilerWebpackPlugin({
35 | schema: path.resolve(fixtureDir, 'schema.json'),
36 | src: srcDir
37 | })
38 |
39 | const plugin = {
40 | apply (compiler) {
41 | const setUpHooks = (compilation) => {
42 | const hooks = RelayCompilerWebpackPlugin.getHooks(compilation)
43 | hooks.beforeWrite.tapPromise('test-hooks', async () => {
44 | beforeWriteSpy()
45 | })
46 |
47 | hooks.afterWrite.tapPromise('test-hooks', async (result) => {
48 | afterWriteSpy(result)
49 | })
50 | }
51 |
52 | if (compiler.hooks) {
53 | compiler.hooks.compilation.tap('TestHooksPlugin', setUpHooks)
54 | } else {
55 | compiler.plugin('compilation', setUpHooks)
56 | }
57 | }
58 | }
59 |
60 | const webpackConfig = normaliseConfigForWebpackVersion(
61 | createWebpackConfig({
62 | relayCompilerWebpackPlugin,
63 | plugins: [plugin]
64 | })
65 | )
66 |
67 | webpack(webpackConfig, (err, stats) => {
68 | expect(err).toBeFalsy()
69 | expect(stats.compilation.errors).toHaveLength(0)
70 | expect(stats.compilation.warnings).toHaveLength(0)
71 |
72 | expect(beforeWriteSpy).toHaveBeenCalledTimes(1)
73 | expect(afterWriteSpy).toHaveBeenCalledTimes(1)
74 | expect(afterWriteSpy).toHaveBeenCalledWith('HAS_CHANGES')
75 | done()
76 | })
77 | })
78 | })
79 |
--------------------------------------------------------------------------------
/test/invalidArgs.test.js:
--------------------------------------------------------------------------------
1 | /* global jest, describe, it, beforeEach */
2 | /* eslint-env jest */
3 | import path from 'path'
4 | import RelayCompilerWebpackPlugin from '../src/index'
5 | import normaliseConfigForWebpackVersion from './support/normaliseConfigForWebpackVersion'
6 | import webpack from 'webpack'
7 | import createTempFixtureProject from './support/createTempFixtureProject'
8 | import { removeSync } from 'fs-extra'
9 |
10 | jest.setTimeout(20000)
11 |
12 | describe('RelayCompilerWebpackPlugin', () => {
13 | let fixtureDir
14 | let createWebpackConfig
15 | let srcDir
16 |
17 | beforeEach(() => {
18 | fixtureDir = createTempFixtureProject('invalidArgs')
19 | createWebpackConfig = require(fixtureDir + '/createWebpackConfig')
20 | srcDir = path.join(fixtureDir, 'src')
21 | })
22 |
23 | afterEach(() => {
24 | removeSync(fixtureDir)
25 | })
26 |
27 | it('throws if an empty constructor', () => {
28 | expect(() => new RelayCompilerWebpackPlugin()).toThrow(
29 | 'You must provide options to RelayCompilerWebpackPlugin.'
30 | )
31 | })
32 |
33 | it("throws if the schema isn't found", () => {
34 | const schema = path.join(fixtureDir, 'schema-doesnt-exist.json')
35 |
36 | expect(() => new RelayCompilerWebpackPlugin({ schema, src: srcDir })).toThrow(
37 | `Could not find the [schema] provided (${schema})`
38 | )
39 | })
40 |
41 | it('throws if no schema provided', () => {
42 | expect(() => new RelayCompilerWebpackPlugin({ src: srcDir })).toThrow(
43 | 'You must provide a Relay Schema.'
44 | )
45 | })
46 |
47 | it('throws if invalid schema provided', done => {
48 | const webpackConfig = normaliseConfigForWebpackVersion(
49 | createWebpackConfig({ RelayCompilerWebpackPlugin })
50 | )
51 | webpackConfig.plugins = [
52 | new RelayCompilerWebpackPlugin({
53 | src: srcDir,
54 | schema: path.resolve(__dirname, '..', 'package.json')
55 | })
56 | ]
57 |
58 | webpack(webpackConfig, (err, stats) => {
59 | expect(err).toBeFalsy()
60 | expect(stats.compilation.errors).toHaveLength(5)
61 | expect(stats.compilation.warnings).toHaveLength(0)
62 | stats.compilation.errors
63 | .map(e => e.message)
64 | .forEach(message =>
65 | expect(message).toEqual(
66 | expect.stringContaining(
67 | 'Error: Invalid or incomplete introspection result.'
68 | )
69 | )
70 | )
71 | done()
72 | })
73 | })
74 |
75 | it('throws if no src provided', () => {
76 | const schema = path.join(fixtureDir, 'schema.json')
77 |
78 | expect(() => new RelayCompilerWebpackPlugin({ schema })).toThrow(
79 | 'You must provide a Relay `src` path.'
80 | )
81 | })
82 |
83 | it("throws if source isn't found", () => {
84 | const src = path.join(fixtureDir, 'src-doesnt-exist')
85 | const schema = path.join(fixtureDir, 'schema.json')
86 |
87 | expect(() => new RelayCompilerWebpackPlugin({ src, schema })).toThrow(
88 | `Could not find the [src] provided (${src})`
89 | )
90 | })
91 | })
92 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "relay-compiler-webpack-plugin",
3 | "version": "9.1.0",
4 | "description": "Automatically run the Relay Compiler from Webpack",
5 | "keywords": [
6 | "relay",
7 | "webpack",
8 | "webpack3",
9 | "webpack4",
10 | "webpack5",
11 | "react",
12 | "reactjs",
13 | "relay-compiler",
14 | "graphql"
15 | ],
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/danielholmes/relay-compiler-webpack-plugin"
19 | },
20 | "main": "dist/index.js",
21 | "jsnext/main": "src/index.js",
22 | "files": [
23 | "dist"
24 | ],
25 | "author": "Daniel Holmes",
26 | "license": "BSD-3-Clause",
27 | "scripts": {
28 | "clean": "rimraf dist",
29 | "flow": "flow",
30 | "lint": "eslint --fix 'src/**/*.js'",
31 | "lint:check": "eslint 'src/**/*.js'",
32 | "test": "jest test --env node",
33 | "test:update": "jest test --env node -u",
34 | "test:coverage": "jest test --env node --coverage --coverageDirectory ./reports src",
35 | "compile": "babel src --out-dir dist",
36 | "build": "npm-run-all --parallel flow lint:check test --sequential compile",
37 | "prepublishOnly": "run-s clean build"
38 | },
39 | "peerDependencies": {
40 | "relay-compiler": ">=8.0.0",
41 | "webpack": ">=3.0.0",
42 | "graphql": ">=14.0.0"
43 | },
44 | "dependencies": {
45 | "fast-glob": "^3.1.0",
46 | "tapable": "^1.1.3"
47 | },
48 | "devDependencies": {
49 | "@babel/cli": "^7.13.16",
50 | "@babel/core": "^7.14.2",
51 | "@babel/plugin-proposal-class-properties": "^7.13.0",
52 | "@babel/preset-env": "^7.14.2",
53 | "@babel/preset-flow": "^7.13.13",
54 | "@babel/preset-react": "^7.13.13",
55 | "@types/relay-compiler": "^7.0.2",
56 | "@types/tapable": "^1.0.4",
57 | "@types/webpack": "^4.41.28",
58 | "babel-core": "^7.0.0-bridge.0",
59 | "babel-eslint": "^10.1.0",
60 | "babel-jest": "^26.6.3",
61 | "babel-loader": "^8.2.2",
62 | "babel-plugin-relay": "^8.0.0",
63 | "eslint": "^7.26.0",
64 | "eslint-config-airbnb-base": "^14.2.1",
65 | "eslint-config-standard": "^16.0.2",
66 | "eslint-plugin-flowtype": "^5.7.2",
67 | "eslint-plugin-import": "^2.23.2",
68 | "eslint-plugin-node": "^11.1.0",
69 | "eslint-plugin-promise": "^5.1.0",
70 | "eslint-plugin-standard": "^5.0.0",
71 | "flow-bin": "^0.120.0",
72 | "graphql": "^14.0.0",
73 | "fs-extra": "^8.1.0",
74 | "jest": "^26.6.3",
75 | "npm-run-all": "^4.1.5",
76 | "react": "^16.11.0",
77 | "react-dom": "^16.11.0",
78 | "react-relay": "^8.0.0",
79 | "relay-compiler": "^8.0.0",
80 | "rimraf": "^3.0.0",
81 | "standard": "^16.0.3",
82 | "webpack": "^4.46.0"
83 | },
84 | "babel": {
85 | "presets": [
86 | [
87 | "@babel/preset-env",
88 | {
89 | "targets": {
90 | "node": "8.0"
91 | }
92 | }
93 | ],
94 | "@babel/preset-flow"
95 | ],
96 | "plugins": [
97 | "@babel/plugin-proposal-class-properties"
98 | ]
99 | },
100 | "jest": {
101 | "watchPathIgnorePatterns": [
102 | "dist/"
103 | ],
104 | "coveragePathIgnorePatterns": [
105 | "/node_modules/",
106 | "/test/"
107 | ]
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Relay Compiler Webpack Plugin
2 |
3 | [](https://badge.fury.io/js/relay-compiler-webpack-plugin)
4 | [](https://travis-ci.org/relay-tools/relay-compiler-webpack-plugin)
5 | 
6 |
7 | Are you running Relay Modern? Are you annoyed with constantly running the `relay-compiler` to generate code, especially
8 | if you're already running Webpack?
9 |
10 | Well be annoyed no more! Simply install this plugin to automatically hook into Webpack's build process to generate these
11 | files for you.
12 |
13 |
14 | ## Installation
15 |
16 | 1. Add this to your project:
17 |
18 | ```sh
19 | yarn add --dev relay-compiler-webpack-plugin graphql
20 | # Or if you're using npm
21 | npm install --save-dev relay-compiler-webpack-plugin graphql
22 | ```
23 |
24 | 2. Add the plugin to your Webpack configuration:
25 |
26 | ```javascript
27 | // const RelayCompilerLanguageTypescript = require('relay-compiler-language-typescript').default
28 | const RelayCompilerWebpackPlugin = require('relay-compiler-webpack-plugin')
29 | const path = require('path')
30 |
31 | module.exports = {
32 | // ... Your existing Webpack configuration
33 | plugins: [
34 | // ...
35 | new RelayCompilerWebpackPlugin({
36 | // languagePlugin: RelayCompilerLanguageTypescript,
37 | schema: path.resolve(__dirname, './relative/path/to/schema.graphql'), // or schema.json
38 | src: path.resolve(__dirname, './relative/path/to/source/files'),
39 | })
40 | ]
41 | // ...
42 | }
43 | ```
44 | Note: TypeScript projects also needs to add the TypeScript language plugin as shown in the commented out lines in the above snippet.
45 |
46 | 3. :tada:
47 |
48 |
49 | ### Gotchas
50 |
51 | If there are multiple versions of GraphQL in your dependency tree it will cause schema validation errors. To get around
52 | this, ensure you have the same graphql version as your relay-compiler version depends on. To assist this you can
53 | [install dependencies as flat](https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-flat) which ensures only
54 | one version of each dependency.
55 |
56 |
57 | ### Plugin hooks
58 |
59 | `relay-compiler-webpack-plugin` exposes a few [tapable](https://github.com/webpack/tapable/tree/master) hooks, for plugins or tooling to use.
60 |
61 | - `beforeWrite` called before the plugin starts to compile queries
62 | - `afterWrite(compileResult)`: called after writing is complete
63 |
64 | ```js
65 | class MyPlugin {
66 | apply (compiler) {
67 | compiler.hooks.compilation.tap('MyPlugin', async (compilation) => {
68 | RelayCompilerWebpackPlugin.getHooks(compilation).afterWrite.tapPromise(
69 | 'MyPlugin', // <-- Set a meaningful name for stacktraces
70 | async (compileResult) => {
71 | if (compileResult === 'HAS_CHANGES') {
72 | await doSomething()
73 | }
74 | }
75 | )
76 | })
77 | }
78 | }
79 | ```
80 |
81 | ## Example Project
82 |
83 | To see an example of its usage within a project, see
84 | [relay-compiler-webpack-plugin-example](https://github.com/danielholmes/relay-compiler-webpack-plugin-example).
85 |
86 |
87 | ## Development
88 |
89 | Running tests:
90 |
91 | ```bash
92 | yarn test
93 | ```
94 |
95 | Running tests with coverage:
96 |
97 | ```bash
98 | yarn test:coverage
99 | ```
100 |
101 |
102 | ## License
103 |
104 | Relay Compiler Webpack Plugin may be redistributed according to the [BSD 3-Clause License](LICENSE).
105 |
--------------------------------------------------------------------------------
/test/normalCase.test.js:
--------------------------------------------------------------------------------
1 | /* global jest, describe, it, beforeEach */
2 | /* eslint-env jest */
3 | import webpack from 'webpack'
4 | import fs from 'fs'
5 | import path from 'path'
6 | import RelayCompilerWebpackPlugin from '../src/index'
7 | import normaliseConfigForWebpackVersion from './support/normaliseConfigForWebpackVersion'
8 | import createTempFixtureProject from './support/createTempFixtureProject'
9 | import { removeSync } from 'fs-extra'
10 |
11 | // TODO: Move to jest setupTests or something like that
12 | jest.setTimeout(30000)
13 |
14 | const DEFAULT_NODE_ENV = process.env.NODE_ENV
15 |
16 | describe('RelayCompilerWebpackPlugin', () => {
17 | let fixtureDir
18 | let createWebpackConfig
19 |
20 | beforeEach(() => {
21 | process.env.NODE_ENV = DEFAULT_NODE_ENV
22 | fixtureDir = createTempFixtureProject('normalCase')
23 | createWebpackConfig = require(fixtureDir + '/createWebpackConfig')
24 | })
25 |
26 | afterEach(() => {
27 | process.env.NODE_ENV = DEFAULT_NODE_ENV
28 | removeSync(fixtureDir)
29 | })
30 |
31 | it('generates graphql files correctly for a normal example', done => {
32 | const relayCompilerWebpackPlugin = new RelayCompilerWebpackPlugin({
33 | schema: path.resolve(fixtureDir, 'schema.json'),
34 | src: path.resolve(fixtureDir, 'src')
35 | })
36 |
37 | const webpackConfig = normaliseConfigForWebpackVersion(
38 | createWebpackConfig({ relayCompilerWebpackPlugin })
39 | )
40 |
41 | webpack(webpackConfig, (err, stats) => {
42 | expect(err).toBeFalsy()
43 | expect(stats.compilation.errors).toHaveLength(0)
44 | expect(stats.compilation.warnings).toHaveLength(0)
45 |
46 | const expectedFiles = [
47 | path.join(
48 | 'mutations',
49 | '__generated__',
50 | 'updateFirstNameMutation.graphql.js'
51 | ),
52 | path.join(
53 | 'components',
54 | '__generated__',
55 | 'HomeItem_person.graphql.js'
56 | ),
57 | path.join(
58 | 'components',
59 | '__generated__',
60 | 'Home_people.graphql.js'
61 | ),
62 | path.join(
63 | 'components',
64 | '__generated__',
65 | 'AppQuery.graphql.js'
66 | ),
67 | path.join(
68 | 'components',
69 | '__generated__',
70 | 'AboutQuery.graphql.js'
71 | )
72 | ]
73 | expectedFiles.forEach(generatedSrcPath => {
74 | const absPath = path.resolve(fixtureDir, 'src', generatedSrcPath)
75 | expect(fs.existsSync(absPath)).toBe(true)
76 | expect(fs.readFileSync(absPath, 'utf8')).toMatchSnapshot()
77 | })
78 |
79 | done()
80 | })
81 | })
82 |
83 | it('generates graphql files correctly for a normal example with --artifactDirectory option', done => {
84 | const relayCompilerWebpackPlugin = new RelayCompilerWebpackPlugin({
85 | schema: path.resolve(fixtureDir, 'schema.json'),
86 | src: path.resolve(fixtureDir, 'src'),
87 | artifactDirectory: path.resolve(fixtureDir, 'src', '__generated__')
88 | })
89 |
90 | const webpackConfig = normaliseConfigForWebpackVersion(
91 | createWebpackConfig({ relayCompilerWebpackPlugin })
92 | )
93 |
94 | process.env.NODE_ENV = 'artifactDirectoryTest'
95 | webpack(webpackConfig, (err, stats) => {
96 | expect(err).toBeFalsy()
97 | if (stats.compilation.logging) {
98 | expect(stats.compilation.logging.get('RelayCompilerPlugin')).toHaveLength(2)
99 | }
100 |
101 | expect(stats.compilation.errors).toHaveLength(0)
102 | expect(stats.compilation.warnings).toHaveLength(0)
103 |
104 | const expectedFiles = [
105 | 'updateFirstNameMutation.graphql.js',
106 | 'HomeItem_person.graphql.js',
107 | 'Home_people.graphql.js',
108 | 'AppQuery.graphql.js',
109 | 'AboutQuery.graphql.js'
110 | ]
111 | expectedFiles.forEach(fileName => {
112 | const generatedFilepath = path.resolve(
113 | fixtureDir, 'src', '__generated__', fileName
114 | )
115 | expect(fs.existsSync(generatedFilepath)).toBe(true)
116 | expect(fs.readFileSync(generatedFilepath, 'utf8')).toMatchSnapshot()
117 | })
118 |
119 | done()
120 | })
121 | })
122 | })
123 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _relayCompiler = require("relay-compiler");
4 |
5 | var _RelayLanguagePluginJavaScript = _interopRequireDefault(require("relay-compiler/lib/language/javascript/RelayLanguagePluginJavaScript"));
6 |
7 | var _RelaySourceModuleParser = _interopRequireDefault(require("relay-compiler/lib/core/RelaySourceModuleParser"));
8 |
9 | var _fs = _interopRequireDefault(require("fs"));
10 |
11 | var _path = _interopRequireDefault(require("path"));
12 |
13 | var _webpack = require("webpack");
14 |
15 | var _getSchemaSource = _interopRequireDefault(require("./getSchemaSource"));
16 |
17 | var _getWriter = _interopRequireDefault(require("./getWriter"));
18 |
19 | var _getFilepathsFromGlob = _interopRequireDefault(require("./getFilepathsFromGlob"));
20 |
21 | var _getRelayCompilerPluginHooks = _interopRequireDefault(require("./getRelayCompilerPluginHooks"));
22 |
23 | var _createRaiseErrorsReporter = _interopRequireDefault(require("./createRaiseErrorsReporter"));
24 |
25 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26 |
27 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
28 |
29 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
30 |
31 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
32 |
33 | const {
34 | schemaExtensions
35 | } = _relayCompiler.IRTransforms;
36 | const isWebpack5 = parseInt(_webpack.version, 10) === 5;
37 |
38 | function createParserConfigs({
39 | baseDir,
40 | getParser,
41 | sourceParserName,
42 | languagePlugin,
43 | include,
44 | exclude,
45 | schema,
46 | extensions
47 | }) {
48 | const sourceModuleParser = (0, _RelaySourceModuleParser.default)(languagePlugin.findGraphQLTags);
49 | const fileOptions = {
50 | extensions,
51 | include,
52 | exclude
53 | };
54 | return {
55 | [sourceParserName]: {
56 | baseDir,
57 | getFileFilter: sourceModuleParser.getFileFilter,
58 | getParser: getParser || sourceModuleParser.getParser,
59 | getSchemaSource: () => (0, _getSchemaSource.default)(schema),
60 | schemaExtensions,
61 | filepaths: (0, _getFilepathsFromGlob.default)(baseDir, fileOptions)
62 | },
63 | graphql: {
64 | baseDir,
65 | getParser: _relayCompiler.DotGraphQLParser.getParser,
66 | getSchemaSource: () => (0, _getSchemaSource.default)(schema),
67 | schemaExtensions,
68 | filepaths: (0, _getFilepathsFromGlob.default)(baseDir, _objectSpread(_objectSpread({}, fileOptions), {}, {
69 | extensions: ['graphql']
70 | }))
71 | }
72 | };
73 | }
74 |
75 | class RelayCompilerWebpackPlugin {
76 | constructor(options) {
77 | _defineProperty(this, "parserConfigs", void 0);
78 |
79 | _defineProperty(this, "writerConfigs", void 0);
80 |
81 | _defineProperty(this, "languagePlugin", void 0);
82 |
83 | _defineProperty(this, "options", void 0);
84 |
85 | if (!options) {
86 | throw new Error('You must provide options to RelayCompilerWebpackPlugin.');
87 | }
88 |
89 | if (!options.schema) {
90 | throw new Error('You must provide a Relay Schema.');
91 | }
92 |
93 | if (typeof options.schema === 'string' && !_fs.default.existsSync(options.schema)) {
94 | throw new Error(`Could not find the [schema] provided (${options.schema}).`);
95 | }
96 |
97 | if (!options.src) {
98 | throw new Error('You must provide a Relay `src` path.');
99 | }
100 |
101 | if (!_fs.default.existsSync(options.src)) {
102 | throw new Error(`Could not find the [src] provided (${options.src})`);
103 | }
104 |
105 | this.options = options;
106 | }
107 |
108 | createWriterConfigs({
109 | sourceParserName,
110 | languagePlugin,
111 | config
112 | }) {
113 | return {
114 | [languagePlugin.outputExtension]: {
115 | writeFiles: (0, _getWriter.default)(languagePlugin, config),
116 | isGeneratedFile: filePath => {
117 | if (filePath.endsWith(`.graphql.${languagePlugin.outputExtension}`)) {
118 | if (this.options.artifactDirectory) {
119 | return filePath.startsWith(this.options.artifactDirectory);
120 | }
121 |
122 | return filePath.includes('__generated__');
123 | }
124 |
125 | return false;
126 | },
127 | parser: sourceParserName,
128 | baseParsers: ['graphql']
129 | }
130 | };
131 | }
132 |
133 | async compile(issuer, request, compilation, hooks) {
134 | let logger; // webpack 4.38+
135 |
136 | if (compilation.getLogger) {
137 | logger = compilation.getLogger('RelayCompilerPlugin');
138 | }
139 |
140 | const reporter = this.options.getReporter ? this.options.getReporter(logger) : (0, _createRaiseErrorsReporter.default)(logger); // Can this be set up in constructor and use same instance every time?
141 |
142 | const runner = new _relayCompiler.Runner({
143 | parserConfigs: this.parserConfigs,
144 | writerConfigs: this.writerConfigs,
145 | reporter,
146 | onlyValidate: false,
147 | skipPersist: true
148 | });
149 | return hooks.beforeWrite.promise().then(() => runner.compile(this.languagePlugin.outputExtension)).then(compileResult => hooks.afterWrite.promise(compileResult));
150 | }
151 |
152 | cachedCompiler(compilation) {
153 | const hooks = (0, _getRelayCompilerPluginHooks.default)(compilation);
154 | let result;
155 | return (issuer, request) => {
156 | if (!result) result = this.compile(issuer, request, compilation, hooks);
157 | return result;
158 | };
159 | }
160 |
161 | runCompile(compile, result, callback) {
162 | const passResult = isWebpack5 ? undefined : result;
163 |
164 | if (result && result.contextInfo.issuer && (this.options.artifactDirectory || result.request.match(/__generated__/))) {
165 | const request = _path.default.resolve(_path.default.dirname(result.contextInfo.issuer), result.request);
166 |
167 | if (this.options.artifactDirectory && !request.startsWith(this.options.artifactDirectory)) {
168 | callback(null, passResult);
169 | return;
170 | }
171 |
172 | compile(result.contextInfo.issuer, request).then(() => callback(null, passResult)).catch(error => callback(error));
173 | return;
174 | }
175 |
176 | callback(null, passResult);
177 | }
178 |
179 | apply(compiler) {
180 | const {
181 | options
182 | } = this;
183 |
184 | const language = (options.languagePlugin || _RelayLanguagePluginJavaScript.default)();
185 |
186 | const extensions = options.extensions !== undefined ? options.extensions : language.inputExtensions;
187 | const sourceParserName = extensions.join('/');
188 | const include = options.include !== undefined ? options.include : ['**'];
189 | const exclude = options.exclude !== undefined ? options.exclude : ['**/node_modules/**', '**/__mocks__/**', '**/__tests__/**', '**/__generated__/**'];
190 | this.parserConfigs = createParserConfigs({
191 | sourceParserName,
192 | languagePlugin: language,
193 | include,
194 | exclude,
195 | schema: options.schema,
196 | getParser: options.getParser,
197 | baseDir: options.src,
198 | extensions
199 | });
200 | this.writerConfigs = this.createWriterConfigs({
201 | sourceParserName,
202 | languagePlugin: language,
203 | config: _objectSpread(_objectSpread({}, options.config), {}, {
204 | outputDir: options.artifactDirectory,
205 | baseDir: options.src
206 | })
207 | });
208 | this.languagePlugin = language;
209 |
210 | if (compiler.hooks) {
211 | compiler.hooks.compilation.tap('RelayCompilerWebpackPlugin', (compilation, params) => {
212 | const compile = this.cachedCompiler(compilation);
213 | params.normalModuleFactory.hooks.beforeResolve.tapAsync('RelayCompilerWebpackPlugin', (result, callback) => {
214 | this.runCompile(compile, result, callback);
215 | });
216 | });
217 | } else {
218 | compiler.plugin('compilation', (compilation, params) => {
219 | const compile = this.cachedCompiler(compilation);
220 | params.normalModuleFactory.plugin('before-resolve', (result, callback) => {
221 | this.runCompile(compile, result, callback);
222 | });
223 | });
224 | }
225 | }
226 |
227 | }
228 |
229 | _defineProperty(RelayCompilerWebpackPlugin, "getHooks", _getRelayCompilerPluginHooks.default);
230 |
231 | module.exports = RelayCompilerWebpackPlugin;
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // @flow
2 |
3 | import { DotGraphQLParser, IRTransforms, Runner } from 'relay-compiler';
4 | import RelayLanguagePluginJavaScript from 'relay-compiler/lib/language/javascript/RelayLanguagePluginJavaScript';
5 | import RelaySourceModuleParser from 'relay-compiler/lib/core/RelaySourceModuleParser';
6 |
7 | import fs from 'fs';
8 | import path from 'path';
9 |
10 | import { version } from 'webpack';
11 | import type { Compiler, Compilation } from 'webpack';
12 | import type { PluginInterface } from 'relay-compiler/lib/language/RelayLanguagePluginInterface';
13 | import getSchemaSource from './getSchemaSource';
14 | import getWriter from './getWriter';
15 | import getFilepathsFromGlob from './getFilepathsFromGlob';
16 | import getRelayCompilerPluginHooks from './getRelayCompilerPluginHooks';
17 | import type { WriterConfig } from './getWriter';
18 | import type { PluginHooks } from './getRelayCompilerPluginHooks';
19 | import type { WebpackLogger } from './WebpackLogger';
20 | import createRaiseErrorsReporter from './createRaiseErrorsReporter';
21 |
22 | const { schemaExtensions } = IRTransforms;
23 |
24 | type RelayCompilerWebpackPluginOptions = {
25 | schema: string,
26 | src: string,
27 | getParser?: Function,
28 | extensions: Array,
29 | include: Array,
30 | exclude: Array,
31 | languagePlugin?: () => PluginInterface,
32 | artifactDirectory?: string,
33 | getReporter?: (logger?: WebpackLogger) => any,
34 | config: any
35 | }
36 |
37 | const isWebpack5 = parseInt(version, 10) === 5;
38 |
39 | function createParserConfigs({
40 | baseDir,
41 | getParser,
42 | sourceParserName,
43 | languagePlugin,
44 | include,
45 | exclude,
46 | schema,
47 | extensions,
48 | }: {
49 | baseDir: string,
50 | getParser?: Function,
51 | sourceParserName: string,
52 | languagePlugin: PluginInterface,
53 | schema: string,
54 | include: Array,
55 | exclude: Array,
56 | extensions: Array
57 | }) {
58 | const sourceModuleParser = RelaySourceModuleParser(
59 | languagePlugin.findGraphQLTags,
60 | );
61 |
62 | const fileOptions = { extensions, include, exclude };
63 |
64 | return {
65 | [sourceParserName]: {
66 | baseDir,
67 | getFileFilter: sourceModuleParser.getFileFilter,
68 | getParser: getParser || sourceModuleParser.getParser,
69 | getSchemaSource: () => getSchemaSource(schema),
70 | schemaExtensions,
71 | filepaths: getFilepathsFromGlob(baseDir, fileOptions),
72 | },
73 | graphql: {
74 | baseDir,
75 | getParser: DotGraphQLParser.getParser,
76 | getSchemaSource: () => getSchemaSource(schema),
77 | schemaExtensions,
78 | filepaths: getFilepathsFromGlob(baseDir, {
79 | ...fileOptions,
80 | extensions: ['graphql'],
81 | }),
82 | },
83 | };
84 | }
85 |
86 | class RelayCompilerWebpackPlugin {
87 | parserConfigs: {}
88 |
89 | writerConfigs: {}
90 |
91 | languagePlugin: PluginInterface
92 |
93 | options: RelayCompilerWebpackPluginOptions
94 |
95 | static getHooks = getRelayCompilerPluginHooks
96 |
97 | constructor(options: RelayCompilerWebpackPluginOptions) {
98 | if (!options) {
99 | throw new Error('You must provide options to RelayCompilerWebpackPlugin.');
100 | }
101 |
102 | if (!options.schema) {
103 | throw new Error('You must provide a Relay Schema.');
104 | }
105 |
106 | if (typeof options.schema === 'string' && !fs.existsSync(options.schema)) {
107 | throw new Error(
108 | `Could not find the [schema] provided (${options.schema}).`,
109 | );
110 | }
111 |
112 | if (!options.src) {
113 | throw new Error('You must provide a Relay `src` path.');
114 | }
115 |
116 | if (!fs.existsSync(options.src)) {
117 | throw new Error(`Could not find the [src] provided (${options.src})`);
118 | }
119 |
120 | this.options = options;
121 | }
122 |
123 | createWriterConfigs({
124 | sourceParserName,
125 | languagePlugin,
126 | config,
127 | }: {
128 | sourceParserName: string,
129 | languagePlugin: PluginInterface,
130 | config: WriterConfig,
131 | }) {
132 | return {
133 | [languagePlugin.outputExtension]: {
134 | writeFiles: getWriter(languagePlugin, config),
135 | isGeneratedFile: (filePath: string) => {
136 | if (filePath.endsWith(`.graphql.${languagePlugin.outputExtension}`)) {
137 | if (this.options.artifactDirectory) {
138 | return filePath.startsWith(this.options.artifactDirectory);
139 | }
140 | return filePath.includes('__generated__');
141 | }
142 |
143 | return false;
144 | },
145 | parser: sourceParserName,
146 | baseParsers: ['graphql'],
147 | },
148 | };
149 | }
150 |
151 | async compile(
152 | issuer: string,
153 | request: string,
154 | compilation: Compilation,
155 | hooks: PluginHooks,
156 | ): Promise {
157 | let logger;
158 |
159 | // webpack 4.38+
160 | if (compilation.getLogger) {
161 | logger = compilation.getLogger('RelayCompilerPlugin');
162 | }
163 |
164 | const reporter = this.options.getReporter
165 | ? this.options.getReporter(logger)
166 | : createRaiseErrorsReporter(logger);
167 |
168 | // Can this be set up in constructor and use same instance every time?
169 | const runner = new Runner({
170 | parserConfigs: this.parserConfigs,
171 | writerConfigs: this.writerConfigs,
172 | reporter,
173 | onlyValidate: false,
174 | skipPersist: true,
175 | });
176 |
177 | return hooks.beforeWrite.promise()
178 | .then(() => runner.compile(this.languagePlugin.outputExtension))
179 | .then((compileResult) => hooks.afterWrite.promise(compileResult));
180 | }
181 |
182 | cachedCompiler(compilation: Compilation) {
183 | const hooks = getRelayCompilerPluginHooks(compilation);
184 | let result;
185 | return (issuer: string, request: string) => {
186 | if (!result) result = this.compile(issuer, request, compilation, hooks);
187 | return result;
188 | };
189 | }
190 |
191 | runCompile(
192 | compile: (issuer: string, request: string) => any,
193 | result: any,
194 | callback: (error: Error | null, value: string | typeof undefined) => void,
195 | ) {
196 | const passResult = isWebpack5 ? undefined : result;
197 |
198 | if (
199 | result
200 | && result.contextInfo.issuer
201 | && (this.options.artifactDirectory || result.request.match(/__generated__/))
202 | ) {
203 | const request = path.resolve(
204 | path.dirname(result.contextInfo.issuer),
205 | result.request,
206 | );
207 |
208 | if (this.options.artifactDirectory && !request.startsWith(this.options.artifactDirectory)) {
209 | callback(null, passResult);
210 | return;
211 | }
212 |
213 | compile(result.contextInfo.issuer, request)
214 | .then(() => callback(null, passResult))
215 | .catch((error) => callback(error));
216 |
217 | return;
218 | }
219 |
220 | callback(null, passResult);
221 | }
222 |
223 | apply(compiler: Compiler) {
224 | const { options } = this;
225 | const language = (options.languagePlugin || RelayLanguagePluginJavaScript)();
226 |
227 | const extensions = options.extensions !== undefined
228 | ? options.extensions
229 | : language.inputExtensions;
230 | const sourceParserName = extensions.join('/');
231 | const include = options.include !== undefined ? options.include : ['**'];
232 | const exclude = options.exclude !== undefined
233 | ? options.exclude
234 | : [
235 | '**/node_modules/**',
236 | '**/__mocks__/**',
237 | '**/__tests__/**',
238 | '**/__generated__/**',
239 | ];
240 |
241 | this.parserConfigs = createParserConfigs({
242 | sourceParserName,
243 | languagePlugin: language,
244 | include,
245 | exclude,
246 | schema: options.schema,
247 | getParser: options.getParser,
248 | baseDir: options.src,
249 | extensions,
250 | });
251 |
252 | this.writerConfigs = this.createWriterConfigs({
253 | sourceParserName,
254 | languagePlugin: language,
255 | config: {
256 | ...options.config,
257 | outputDir: options.artifactDirectory,
258 | baseDir: options.src,
259 | },
260 | });
261 |
262 | this.languagePlugin = language;
263 |
264 | if (compiler.hooks) {
265 | compiler.hooks.compilation.tap(
266 | 'RelayCompilerWebpackPlugin',
267 | (compilation: Compilation, params) => {
268 | const compile = this.cachedCompiler(compilation);
269 | params.normalModuleFactory.hooks.beforeResolve.tapAsync(
270 | 'RelayCompilerWebpackPlugin',
271 | (result, callback) => {
272 | this.runCompile(compile, result, callback);
273 | },
274 | );
275 | },
276 | );
277 | } else {
278 | compiler.plugin('compilation', (compilation: Compilation, params) => {
279 | const compile = this.cachedCompiler(compilation);
280 | params.normalModuleFactory.plugin(
281 | 'before-resolve',
282 | (result, callback) => {
283 | this.runCompile(compile, result, callback);
284 | },
285 | );
286 | });
287 | }
288 | }
289 | }
290 |
291 | module.exports = RelayCompilerWebpackPlugin;
292 |
--------------------------------------------------------------------------------
/test/__snapshots__/normalCase.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example 1`] = `
4 | "/**
5 | * @flow
6 | * @relayHash 5bd09d29f21e8c7772312a5d6d361bdd
7 | */
8 |
9 | /* eslint-disable */
10 |
11 | 'use strict';
12 |
13 | /*::
14 | import type { ConcreteRequest } from 'relay-runtime';
15 | export type updateFirstNameMutationVariables = {|
16 | id: string,
17 | firstName: string,
18 | |};
19 | export type updateFirstNameMutationResponse = {|
20 | +updateFirstName: {|
21 | +person: {|
22 | +firstName: string,
23 | +fullName: string,
24 | |}
25 | |}
26 | |};
27 | export type updateFirstNameMutation = {|
28 | variables: updateFirstNameMutationVariables,
29 | response: updateFirstNameMutationResponse,
30 | |};
31 | */
32 |
33 |
34 | /*
35 | mutation updateFirstNameMutation(
36 | $id: ID!
37 | $firstName: String!
38 | ) {
39 | updateFirstName(id: $id, firstName: $firstName) {
40 | person {
41 | firstName
42 | fullName
43 | id
44 | }
45 | }
46 | }
47 | */
48 |
49 | const node/*: ConcreteRequest*/ = (function(){
50 | var v0 = [
51 | {
52 | \\"kind\\": \\"LocalArgument\\",
53 | \\"name\\": \\"id\\",
54 | \\"type\\": \\"ID!\\",
55 | \\"defaultValue\\": null
56 | },
57 | {
58 | \\"kind\\": \\"LocalArgument\\",
59 | \\"name\\": \\"firstName\\",
60 | \\"type\\": \\"String!\\",
61 | \\"defaultValue\\": null
62 | }
63 | ],
64 | v1 = [
65 | {
66 | \\"kind\\": \\"Variable\\",
67 | \\"name\\": \\"firstName\\",
68 | \\"variableName\\": \\"firstName\\"
69 | },
70 | {
71 | \\"kind\\": \\"Variable\\",
72 | \\"name\\": \\"id\\",
73 | \\"variableName\\": \\"id\\"
74 | }
75 | ],
76 | v2 = {
77 | \\"kind\\": \\"ScalarField\\",
78 | \\"alias\\": null,
79 | \\"name\\": \\"firstName\\",
80 | \\"args\\": null,
81 | \\"storageKey\\": null
82 | },
83 | v3 = {
84 | \\"kind\\": \\"ScalarField\\",
85 | \\"alias\\": null,
86 | \\"name\\": \\"fullName\\",
87 | \\"args\\": null,
88 | \\"storageKey\\": null
89 | };
90 | return {
91 | \\"kind\\": \\"Request\\",
92 | \\"fragment\\": {
93 | \\"kind\\": \\"Fragment\\",
94 | \\"name\\": \\"updateFirstNameMutation\\",
95 | \\"type\\": \\"Mutation\\",
96 | \\"metadata\\": null,
97 | \\"argumentDefinitions\\": (v0/*: any*/),
98 | \\"selections\\": [
99 | {
100 | \\"kind\\": \\"LinkedField\\",
101 | \\"alias\\": null,
102 | \\"name\\": \\"updateFirstName\\",
103 | \\"storageKey\\": null,
104 | \\"args\\": (v1/*: any*/),
105 | \\"concreteType\\": \\"UpdateFirstNameOutput\\",
106 | \\"plural\\": false,
107 | \\"selections\\": [
108 | {
109 | \\"kind\\": \\"LinkedField\\",
110 | \\"alias\\": null,
111 | \\"name\\": \\"person\\",
112 | \\"storageKey\\": null,
113 | \\"args\\": null,
114 | \\"concreteType\\": \\"Person\\",
115 | \\"plural\\": false,
116 | \\"selections\\": [
117 | (v2/*: any*/),
118 | (v3/*: any*/)
119 | ]
120 | }
121 | ]
122 | }
123 | ]
124 | },
125 | \\"operation\\": {
126 | \\"kind\\": \\"Operation\\",
127 | \\"name\\": \\"updateFirstNameMutation\\",
128 | \\"argumentDefinitions\\": (v0/*: any*/),
129 | \\"selections\\": [
130 | {
131 | \\"kind\\": \\"LinkedField\\",
132 | \\"alias\\": null,
133 | \\"name\\": \\"updateFirstName\\",
134 | \\"storageKey\\": null,
135 | \\"args\\": (v1/*: any*/),
136 | \\"concreteType\\": \\"UpdateFirstNameOutput\\",
137 | \\"plural\\": false,
138 | \\"selections\\": [
139 | {
140 | \\"kind\\": \\"LinkedField\\",
141 | \\"alias\\": null,
142 | \\"name\\": \\"person\\",
143 | \\"storageKey\\": null,
144 | \\"args\\": null,
145 | \\"concreteType\\": \\"Person\\",
146 | \\"plural\\": false,
147 | \\"selections\\": [
148 | (v2/*: any*/),
149 | (v3/*: any*/),
150 | {
151 | \\"kind\\": \\"ScalarField\\",
152 | \\"alias\\": null,
153 | \\"name\\": \\"id\\",
154 | \\"args\\": null,
155 | \\"storageKey\\": null
156 | }
157 | ]
158 | }
159 | ]
160 | }
161 | ]
162 | },
163 | \\"params\\": {
164 | \\"operationKind\\": \\"mutation\\",
165 | \\"name\\": \\"updateFirstNameMutation\\",
166 | \\"id\\": null,
167 | \\"text\\": \\"mutation updateFirstNameMutation(\\\\n $id: ID!\\\\n $firstName: String!\\\\n) {\\\\n updateFirstName(id: $id, firstName: $firstName) {\\\\n person {\\\\n firstName\\\\n fullName\\\\n id\\\\n }\\\\n }\\\\n}\\\\n\\",
168 | \\"metadata\\": {}
169 | }
170 | };
171 | })();
172 | // prettier-ignore
173 | (node/*: any*/).hash = '8ea2fcfefe6dc15aea4c7e70663a11d8';
174 | module.exports = node;
175 | "
176 | `;
177 |
178 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example 2`] = `
179 | "/**
180 | * @flow
181 | */
182 |
183 | /* eslint-disable */
184 |
185 | 'use strict';
186 |
187 | /*::
188 | import type { ReaderFragment } from 'relay-runtime';
189 | import type { FragmentReference } from \\"relay-runtime\\";
190 | declare export opaque type HomeItem_person$ref: FragmentReference;
191 | declare export opaque type HomeItem_person$fragmentType: HomeItem_person$ref;
192 | export type HomeItem_person = {|
193 | +id: string,
194 | +fullName: string,
195 | +$refType: HomeItem_person$ref,
196 | |};
197 | export type HomeItem_person$data = HomeItem_person;
198 | export type HomeItem_person$key = {
199 | +$data?: HomeItem_person$data,
200 | +$fragmentRefs: HomeItem_person$ref,
201 | ...
202 | };
203 | */
204 |
205 |
206 | const node/*: ReaderFragment*/ = {
207 | \\"kind\\": \\"Fragment\\",
208 | \\"name\\": \\"HomeItem_person\\",
209 | \\"type\\": \\"Person\\",
210 | \\"metadata\\": null,
211 | \\"argumentDefinitions\\": [],
212 | \\"selections\\": [
213 | {
214 | \\"kind\\": \\"ScalarField\\",
215 | \\"alias\\": null,
216 | \\"name\\": \\"id\\",
217 | \\"args\\": null,
218 | \\"storageKey\\": null
219 | },
220 | {
221 | \\"kind\\": \\"ScalarField\\",
222 | \\"alias\\": null,
223 | \\"name\\": \\"fullName\\",
224 | \\"args\\": null,
225 | \\"storageKey\\": null
226 | }
227 | ]
228 | };
229 | // prettier-ignore
230 | (node/*: any*/).hash = 'bd415f20a6f47ec9a0098ed50db4d1df';
231 | module.exports = node;
232 | "
233 | `;
234 |
235 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example 3`] = `
236 | "/**
237 | * @flow
238 | */
239 |
240 | /* eslint-disable */
241 |
242 | 'use strict';
243 |
244 | /*::
245 | import type { ReaderFragment } from 'relay-runtime';
246 | type HomeItem_person$ref = any;
247 | import type { FragmentReference } from \\"relay-runtime\\";
248 | declare export opaque type Home_people$ref: FragmentReference;
249 | declare export opaque type Home_people$fragmentType: Home_people$ref;
250 | export type Home_people = $ReadOnlyArray<{|
251 | +id: string,
252 | +$fragmentRefs: HomeItem_person$ref,
253 | +$refType: Home_people$ref,
254 | |}>;
255 | export type Home_people$data = Home_people;
256 | export type Home_people$key = $ReadOnlyArray<{
257 | +$data?: Home_people$data,
258 | +$fragmentRefs: Home_people$ref,
259 | ...
260 | }>;
261 | */
262 |
263 |
264 | const node/*: ReaderFragment*/ = {
265 | \\"kind\\": \\"Fragment\\",
266 | \\"name\\": \\"Home_people\\",
267 | \\"type\\": \\"Person\\",
268 | \\"metadata\\": {
269 | \\"plural\\": true
270 | },
271 | \\"argumentDefinitions\\": [],
272 | \\"selections\\": [
273 | {
274 | \\"kind\\": \\"ScalarField\\",
275 | \\"alias\\": null,
276 | \\"name\\": \\"id\\",
277 | \\"args\\": null,
278 | \\"storageKey\\": null
279 | },
280 | {
281 | \\"kind\\": \\"FragmentSpread\\",
282 | \\"name\\": \\"HomeItem_person\\",
283 | \\"args\\": null
284 | }
285 | ]
286 | };
287 | // prettier-ignore
288 | (node/*: any*/).hash = 'e4f600a68462819c933487c314d53ed6';
289 | module.exports = node;
290 | "
291 | `;
292 |
293 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example 4`] = `
294 | "/**
295 | * @flow
296 | * @relayHash d299eee1fc201946b5e3b7ea7f83bb73
297 | */
298 |
299 | /* eslint-disable */
300 |
301 | 'use strict';
302 |
303 | /*::
304 | import type { ConcreteRequest } from 'relay-runtime';
305 | type Home_people$ref = any;
306 | export type AppQueryVariables = {||};
307 | export type AppQueryResponse = {|
308 | +people: ?$ReadOnlyArray{|
309 | +$fragmentRefs: Home_people$ref
310 | |}>
311 | |};
312 | export type AppQuery = {|
313 | variables: AppQueryVariables,
314 | response: AppQueryResponse,
315 | |};
316 | */
317 |
318 |
319 | /*
320 | query AppQuery {
321 | people {
322 | ...Home_people
323 | id
324 | }
325 | }
326 |
327 | fragment HomeItem_person on Person {
328 | id
329 | fullName
330 | }
331 |
332 | fragment Home_people on Person {
333 | id
334 | ...HomeItem_person
335 | }
336 | */
337 |
338 | const node/*: ConcreteRequest*/ = {
339 | \\"kind\\": \\"Request\\",
340 | \\"fragment\\": {
341 | \\"kind\\": \\"Fragment\\",
342 | \\"name\\": \\"AppQuery\\",
343 | \\"type\\": \\"Query\\",
344 | \\"metadata\\": null,
345 | \\"argumentDefinitions\\": [],
346 | \\"selections\\": [
347 | {
348 | \\"kind\\": \\"LinkedField\\",
349 | \\"alias\\": null,
350 | \\"name\\": \\"people\\",
351 | \\"storageKey\\": null,
352 | \\"args\\": null,
353 | \\"concreteType\\": \\"Person\\",
354 | \\"plural\\": true,
355 | \\"selections\\": [
356 | {
357 | \\"kind\\": \\"FragmentSpread\\",
358 | \\"name\\": \\"Home_people\\",
359 | \\"args\\": null
360 | }
361 | ]
362 | }
363 | ]
364 | },
365 | \\"operation\\": {
366 | \\"kind\\": \\"Operation\\",
367 | \\"name\\": \\"AppQuery\\",
368 | \\"argumentDefinitions\\": [],
369 | \\"selections\\": [
370 | {
371 | \\"kind\\": \\"LinkedField\\",
372 | \\"alias\\": null,
373 | \\"name\\": \\"people\\",
374 | \\"storageKey\\": null,
375 | \\"args\\": null,
376 | \\"concreteType\\": \\"Person\\",
377 | \\"plural\\": true,
378 | \\"selections\\": [
379 | {
380 | \\"kind\\": \\"ScalarField\\",
381 | \\"alias\\": null,
382 | \\"name\\": \\"id\\",
383 | \\"args\\": null,
384 | \\"storageKey\\": null
385 | },
386 | {
387 | \\"kind\\": \\"ScalarField\\",
388 | \\"alias\\": null,
389 | \\"name\\": \\"fullName\\",
390 | \\"args\\": null,
391 | \\"storageKey\\": null
392 | }
393 | ]
394 | }
395 | ]
396 | },
397 | \\"params\\": {
398 | \\"operationKind\\": \\"query\\",
399 | \\"name\\": \\"AppQuery\\",
400 | \\"id\\": null,
401 | \\"text\\": \\"query AppQuery {\\\\n people {\\\\n ...Home_people\\\\n id\\\\n }\\\\n}\\\\n\\\\nfragment HomeItem_person on Person {\\\\n id\\\\n fullName\\\\n}\\\\n\\\\nfragment Home_people on Person {\\\\n id\\\\n ...HomeItem_person\\\\n}\\\\n\\",
402 | \\"metadata\\": {}
403 | }
404 | };
405 | // prettier-ignore
406 | (node/*: any*/).hash = '09882a000717ccc4afa2102269b7f17f';
407 | module.exports = node;
408 | "
409 | `;
410 |
411 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example 5`] = `
412 | "/**
413 | * @flow
414 | * @relayHash fa2411483bd3de9f45b5ba00eb49a2b7
415 | */
416 |
417 | /* eslint-disable */
418 |
419 | 'use strict';
420 |
421 | /*::
422 | import type { ConcreteRequest } from 'relay-runtime';
423 | export type AboutQueryVariables = {|
424 | id: string
425 | |};
426 | export type AboutQueryResponse = {|
427 | +personById: ?{|
428 | +id: string,
429 | +firstName: string,
430 | +fullName: string,
431 | |}
432 | |};
433 | export type AboutQuery = {|
434 | variables: AboutQueryVariables,
435 | response: AboutQueryResponse,
436 | |};
437 | */
438 |
439 |
440 | /*
441 | query AboutQuery(
442 | $id: ID!
443 | ) {
444 | personById(id: $id) {
445 | id
446 | firstName
447 | fullName
448 | }
449 | }
450 | */
451 |
452 | const node/*: ConcreteRequest*/ = (function(){
453 | var v0 = [
454 | {
455 | \\"kind\\": \\"LocalArgument\\",
456 | \\"name\\": \\"id\\",
457 | \\"type\\": \\"ID!\\",
458 | \\"defaultValue\\": null
459 | }
460 | ],
461 | v1 = [
462 | {
463 | \\"kind\\": \\"LinkedField\\",
464 | \\"alias\\": null,
465 | \\"name\\": \\"personById\\",
466 | \\"storageKey\\": null,
467 | \\"args\\": [
468 | {
469 | \\"kind\\": \\"Variable\\",
470 | \\"name\\": \\"id\\",
471 | \\"variableName\\": \\"id\\"
472 | }
473 | ],
474 | \\"concreteType\\": \\"Person\\",
475 | \\"plural\\": false,
476 | \\"selections\\": [
477 | {
478 | \\"kind\\": \\"ScalarField\\",
479 | \\"alias\\": null,
480 | \\"name\\": \\"id\\",
481 | \\"args\\": null,
482 | \\"storageKey\\": null
483 | },
484 | {
485 | \\"kind\\": \\"ScalarField\\",
486 | \\"alias\\": null,
487 | \\"name\\": \\"firstName\\",
488 | \\"args\\": null,
489 | \\"storageKey\\": null
490 | },
491 | {
492 | \\"kind\\": \\"ScalarField\\",
493 | \\"alias\\": null,
494 | \\"name\\": \\"fullName\\",
495 | \\"args\\": null,
496 | \\"storageKey\\": null
497 | }
498 | ]
499 | }
500 | ];
501 | return {
502 | \\"kind\\": \\"Request\\",
503 | \\"fragment\\": {
504 | \\"kind\\": \\"Fragment\\",
505 | \\"name\\": \\"AboutQuery\\",
506 | \\"type\\": \\"Query\\",
507 | \\"metadata\\": null,
508 | \\"argumentDefinitions\\": (v0/*: any*/),
509 | \\"selections\\": (v1/*: any*/)
510 | },
511 | \\"operation\\": {
512 | \\"kind\\": \\"Operation\\",
513 | \\"name\\": \\"AboutQuery\\",
514 | \\"argumentDefinitions\\": (v0/*: any*/),
515 | \\"selections\\": (v1/*: any*/)
516 | },
517 | \\"params\\": {
518 | \\"operationKind\\": \\"query\\",
519 | \\"name\\": \\"AboutQuery\\",
520 | \\"id\\": null,
521 | \\"text\\": \\"query AboutQuery(\\\\n $id: ID!\\\\n) {\\\\n personById(id: $id) {\\\\n id\\\\n firstName\\\\n fullName\\\\n }\\\\n}\\\\n\\",
522 | \\"metadata\\": {}
523 | }
524 | };
525 | })();
526 | // prettier-ignore
527 | (node/*: any*/).hash = '244cfa95d89768b907f6815ff6a3007d';
528 | module.exports = node;
529 | "
530 | `;
531 |
532 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example with --artifactDirectory option 1`] = `
533 | "/**
534 | * @flow
535 | * @relayHash 5bd09d29f21e8c7772312a5d6d361bdd
536 | */
537 |
538 | /* eslint-disable */
539 |
540 | 'use strict';
541 |
542 | /*::
543 | import type { ConcreteRequest } from 'relay-runtime';
544 | export type updateFirstNameMutationVariables = {|
545 | id: string,
546 | firstName: string,
547 | |};
548 | export type updateFirstNameMutationResponse = {|
549 | +updateFirstName: {|
550 | +person: {|
551 | +firstName: string,
552 | +fullName: string,
553 | |}
554 | |}
555 | |};
556 | export type updateFirstNameMutation = {|
557 | variables: updateFirstNameMutationVariables,
558 | response: updateFirstNameMutationResponse,
559 | |};
560 | */
561 |
562 |
563 | /*
564 | mutation updateFirstNameMutation(
565 | $id: ID!
566 | $firstName: String!
567 | ) {
568 | updateFirstName(id: $id, firstName: $firstName) {
569 | person {
570 | firstName
571 | fullName
572 | id
573 | }
574 | }
575 | }
576 | */
577 |
578 | const node/*: ConcreteRequest*/ = (function(){
579 | var v0 = [
580 | {
581 | \\"kind\\": \\"LocalArgument\\",
582 | \\"name\\": \\"id\\",
583 | \\"type\\": \\"ID!\\",
584 | \\"defaultValue\\": null
585 | },
586 | {
587 | \\"kind\\": \\"LocalArgument\\",
588 | \\"name\\": \\"firstName\\",
589 | \\"type\\": \\"String!\\",
590 | \\"defaultValue\\": null
591 | }
592 | ],
593 | v1 = [
594 | {
595 | \\"kind\\": \\"Variable\\",
596 | \\"name\\": \\"firstName\\",
597 | \\"variableName\\": \\"firstName\\"
598 | },
599 | {
600 | \\"kind\\": \\"Variable\\",
601 | \\"name\\": \\"id\\",
602 | \\"variableName\\": \\"id\\"
603 | }
604 | ],
605 | v2 = {
606 | \\"kind\\": \\"ScalarField\\",
607 | \\"alias\\": null,
608 | \\"name\\": \\"firstName\\",
609 | \\"args\\": null,
610 | \\"storageKey\\": null
611 | },
612 | v3 = {
613 | \\"kind\\": \\"ScalarField\\",
614 | \\"alias\\": null,
615 | \\"name\\": \\"fullName\\",
616 | \\"args\\": null,
617 | \\"storageKey\\": null
618 | };
619 | return {
620 | \\"kind\\": \\"Request\\",
621 | \\"fragment\\": {
622 | \\"kind\\": \\"Fragment\\",
623 | \\"name\\": \\"updateFirstNameMutation\\",
624 | \\"type\\": \\"Mutation\\",
625 | \\"metadata\\": null,
626 | \\"argumentDefinitions\\": (v0/*: any*/),
627 | \\"selections\\": [
628 | {
629 | \\"kind\\": \\"LinkedField\\",
630 | \\"alias\\": null,
631 | \\"name\\": \\"updateFirstName\\",
632 | \\"storageKey\\": null,
633 | \\"args\\": (v1/*: any*/),
634 | \\"concreteType\\": \\"UpdateFirstNameOutput\\",
635 | \\"plural\\": false,
636 | \\"selections\\": [
637 | {
638 | \\"kind\\": \\"LinkedField\\",
639 | \\"alias\\": null,
640 | \\"name\\": \\"person\\",
641 | \\"storageKey\\": null,
642 | \\"args\\": null,
643 | \\"concreteType\\": \\"Person\\",
644 | \\"plural\\": false,
645 | \\"selections\\": [
646 | (v2/*: any*/),
647 | (v3/*: any*/)
648 | ]
649 | }
650 | ]
651 | }
652 | ]
653 | },
654 | \\"operation\\": {
655 | \\"kind\\": \\"Operation\\",
656 | \\"name\\": \\"updateFirstNameMutation\\",
657 | \\"argumentDefinitions\\": (v0/*: any*/),
658 | \\"selections\\": [
659 | {
660 | \\"kind\\": \\"LinkedField\\",
661 | \\"alias\\": null,
662 | \\"name\\": \\"updateFirstName\\",
663 | \\"storageKey\\": null,
664 | \\"args\\": (v1/*: any*/),
665 | \\"concreteType\\": \\"UpdateFirstNameOutput\\",
666 | \\"plural\\": false,
667 | \\"selections\\": [
668 | {
669 | \\"kind\\": \\"LinkedField\\",
670 | \\"alias\\": null,
671 | \\"name\\": \\"person\\",
672 | \\"storageKey\\": null,
673 | \\"args\\": null,
674 | \\"concreteType\\": \\"Person\\",
675 | \\"plural\\": false,
676 | \\"selections\\": [
677 | (v2/*: any*/),
678 | (v3/*: any*/),
679 | {
680 | \\"kind\\": \\"ScalarField\\",
681 | \\"alias\\": null,
682 | \\"name\\": \\"id\\",
683 | \\"args\\": null,
684 | \\"storageKey\\": null
685 | }
686 | ]
687 | }
688 | ]
689 | }
690 | ]
691 | },
692 | \\"params\\": {
693 | \\"operationKind\\": \\"mutation\\",
694 | \\"name\\": \\"updateFirstNameMutation\\",
695 | \\"id\\": null,
696 | \\"text\\": \\"mutation updateFirstNameMutation(\\\\n $id: ID!\\\\n $firstName: String!\\\\n) {\\\\n updateFirstName(id: $id, firstName: $firstName) {\\\\n person {\\\\n firstName\\\\n fullName\\\\n id\\\\n }\\\\n }\\\\n}\\\\n\\",
697 | \\"metadata\\": {}
698 | }
699 | };
700 | })();
701 | // prettier-ignore
702 | (node/*: any*/).hash = '8ea2fcfefe6dc15aea4c7e70663a11d8';
703 | module.exports = node;
704 | "
705 | `;
706 |
707 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example with --artifactDirectory option 2`] = `
708 | "/**
709 | * @flow
710 | */
711 |
712 | /* eslint-disable */
713 |
714 | 'use strict';
715 |
716 | /*::
717 | import type { ReaderFragment } from 'relay-runtime';
718 | import type { FragmentReference } from \\"relay-runtime\\";
719 | declare export opaque type HomeItem_person$ref: FragmentReference;
720 | declare export opaque type HomeItem_person$fragmentType: HomeItem_person$ref;
721 | export type HomeItem_person = {|
722 | +id: string,
723 | +fullName: string,
724 | +$refType: HomeItem_person$ref,
725 | |};
726 | export type HomeItem_person$data = HomeItem_person;
727 | export type HomeItem_person$key = {
728 | +$data?: HomeItem_person$data,
729 | +$fragmentRefs: HomeItem_person$ref,
730 | ...
731 | };
732 | */
733 |
734 |
735 | const node/*: ReaderFragment*/ = {
736 | \\"kind\\": \\"Fragment\\",
737 | \\"name\\": \\"HomeItem_person\\",
738 | \\"type\\": \\"Person\\",
739 | \\"metadata\\": null,
740 | \\"argumentDefinitions\\": [],
741 | \\"selections\\": [
742 | {
743 | \\"kind\\": \\"ScalarField\\",
744 | \\"alias\\": null,
745 | \\"name\\": \\"id\\",
746 | \\"args\\": null,
747 | \\"storageKey\\": null
748 | },
749 | {
750 | \\"kind\\": \\"ScalarField\\",
751 | \\"alias\\": null,
752 | \\"name\\": \\"fullName\\",
753 | \\"args\\": null,
754 | \\"storageKey\\": null
755 | }
756 | ]
757 | };
758 | // prettier-ignore
759 | (node/*: any*/).hash = 'bd415f20a6f47ec9a0098ed50db4d1df';
760 | module.exports = node;
761 | "
762 | `;
763 |
764 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example with --artifactDirectory option 3`] = `
765 | "/**
766 | * @flow
767 | */
768 |
769 | /* eslint-disable */
770 |
771 | 'use strict';
772 |
773 | /*::
774 | import type { ReaderFragment } from 'relay-runtime';
775 | import type { HomeItem_person$ref } from \\"./HomeItem_person.graphql\\";
776 | import type { FragmentReference } from \\"relay-runtime\\";
777 | declare export opaque type Home_people$ref: FragmentReference;
778 | declare export opaque type Home_people$fragmentType: Home_people$ref;
779 | export type Home_people = $ReadOnlyArray<{|
780 | +id: string,
781 | +$fragmentRefs: HomeItem_person$ref,
782 | +$refType: Home_people$ref,
783 | |}>;
784 | export type Home_people$data = Home_people;
785 | export type Home_people$key = $ReadOnlyArray<{
786 | +$data?: Home_people$data,
787 | +$fragmentRefs: Home_people$ref,
788 | ...
789 | }>;
790 | */
791 |
792 |
793 | const node/*: ReaderFragment*/ = {
794 | \\"kind\\": \\"Fragment\\",
795 | \\"name\\": \\"Home_people\\",
796 | \\"type\\": \\"Person\\",
797 | \\"metadata\\": {
798 | \\"plural\\": true
799 | },
800 | \\"argumentDefinitions\\": [],
801 | \\"selections\\": [
802 | {
803 | \\"kind\\": \\"ScalarField\\",
804 | \\"alias\\": null,
805 | \\"name\\": \\"id\\",
806 | \\"args\\": null,
807 | \\"storageKey\\": null
808 | },
809 | {
810 | \\"kind\\": \\"FragmentSpread\\",
811 | \\"name\\": \\"HomeItem_person\\",
812 | \\"args\\": null
813 | }
814 | ]
815 | };
816 | // prettier-ignore
817 | (node/*: any*/).hash = 'e4f600a68462819c933487c314d53ed6';
818 | module.exports = node;
819 | "
820 | `;
821 |
822 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example with --artifactDirectory option 4`] = `
823 | "/**
824 | * @flow
825 | * @relayHash ae570241219ec7981a375a9d6bb66a2c
826 | */
827 |
828 | /* eslint-disable */
829 |
830 | 'use strict';
831 |
832 | /*::
833 | import type { ConcreteRequest } from 'relay-runtime';
834 | import type { Home_people$ref } from \\"./Home_people.graphql\\";
835 | export type AppQueryVariables = {||};
836 | export type AppQueryResponse = {|
837 | +people: ?$ReadOnlyArray{|
838 | +$fragmentRefs: Home_people$ref
839 | |}>
840 | |};
841 | export type AppQuery = {|
842 | variables: AppQueryVariables,
843 | response: AppQueryResponse,
844 | |};
845 | */
846 |
847 |
848 | /*
849 | query AppQuery {
850 | people {
851 | ...Home_people
852 | id
853 | }
854 | }
855 |
856 | fragment HomeItem_person on Person {
857 | id
858 | fullName
859 | }
860 |
861 | fragment Home_people on Person {
862 | id
863 | ...HomeItem_person
864 | }
865 | */
866 |
867 | const node/*: ConcreteRequest*/ = {
868 | \\"kind\\": \\"Request\\",
869 | \\"fragment\\": {
870 | \\"kind\\": \\"Fragment\\",
871 | \\"name\\": \\"AppQuery\\",
872 | \\"type\\": \\"Query\\",
873 | \\"metadata\\": null,
874 | \\"argumentDefinitions\\": [],
875 | \\"selections\\": [
876 | {
877 | \\"kind\\": \\"LinkedField\\",
878 | \\"alias\\": null,
879 | \\"name\\": \\"people\\",
880 | \\"storageKey\\": null,
881 | \\"args\\": null,
882 | \\"concreteType\\": \\"Person\\",
883 | \\"plural\\": true,
884 | \\"selections\\": [
885 | {
886 | \\"kind\\": \\"FragmentSpread\\",
887 | \\"name\\": \\"Home_people\\",
888 | \\"args\\": null
889 | }
890 | ]
891 | }
892 | ]
893 | },
894 | \\"operation\\": {
895 | \\"kind\\": \\"Operation\\",
896 | \\"name\\": \\"AppQuery\\",
897 | \\"argumentDefinitions\\": [],
898 | \\"selections\\": [
899 | {
900 | \\"kind\\": \\"LinkedField\\",
901 | \\"alias\\": null,
902 | \\"name\\": \\"people\\",
903 | \\"storageKey\\": null,
904 | \\"args\\": null,
905 | \\"concreteType\\": \\"Person\\",
906 | \\"plural\\": true,
907 | \\"selections\\": [
908 | {
909 | \\"kind\\": \\"ScalarField\\",
910 | \\"alias\\": null,
911 | \\"name\\": \\"id\\",
912 | \\"args\\": null,
913 | \\"storageKey\\": null
914 | },
915 | {
916 | \\"kind\\": \\"ScalarField\\",
917 | \\"alias\\": null,
918 | \\"name\\": \\"fullName\\",
919 | \\"args\\": null,
920 | \\"storageKey\\": null
921 | }
922 | ]
923 | }
924 | ]
925 | },
926 | \\"params\\": {
927 | \\"operationKind\\": \\"query\\",
928 | \\"name\\": \\"AppQuery\\",
929 | \\"id\\": null,
930 | \\"text\\": \\"query AppQuery {\\\\n people {\\\\n ...Home_people\\\\n id\\\\n }\\\\n}\\\\n\\\\nfragment HomeItem_person on Person {\\\\n id\\\\n fullName\\\\n}\\\\n\\\\nfragment Home_people on Person {\\\\n id\\\\n ...HomeItem_person\\\\n}\\\\n\\",
931 | \\"metadata\\": {}
932 | }
933 | };
934 | // prettier-ignore
935 | (node/*: any*/).hash = '09882a000717ccc4afa2102269b7f17f';
936 | module.exports = node;
937 | "
938 | `;
939 |
940 | exports[`RelayCompilerWebpackPlugin generates graphql files correctly for a normal example with --artifactDirectory option 5`] = `
941 | "/**
942 | * @flow
943 | * @relayHash fa2411483bd3de9f45b5ba00eb49a2b7
944 | */
945 |
946 | /* eslint-disable */
947 |
948 | 'use strict';
949 |
950 | /*::
951 | import type { ConcreteRequest } from 'relay-runtime';
952 | export type AboutQueryVariables = {|
953 | id: string
954 | |};
955 | export type AboutQueryResponse = {|
956 | +personById: ?{|
957 | +id: string,
958 | +firstName: string,
959 | +fullName: string,
960 | |}
961 | |};
962 | export type AboutQuery = {|
963 | variables: AboutQueryVariables,
964 | response: AboutQueryResponse,
965 | |};
966 | */
967 |
968 |
969 | /*
970 | query AboutQuery(
971 | $id: ID!
972 | ) {
973 | personById(id: $id) {
974 | id
975 | firstName
976 | fullName
977 | }
978 | }
979 | */
980 |
981 | const node/*: ConcreteRequest*/ = (function(){
982 | var v0 = [
983 | {
984 | \\"kind\\": \\"LocalArgument\\",
985 | \\"name\\": \\"id\\",
986 | \\"type\\": \\"ID!\\",
987 | \\"defaultValue\\": null
988 | }
989 | ],
990 | v1 = [
991 | {
992 | \\"kind\\": \\"LinkedField\\",
993 | \\"alias\\": null,
994 | \\"name\\": \\"personById\\",
995 | \\"storageKey\\": null,
996 | \\"args\\": [
997 | {
998 | \\"kind\\": \\"Variable\\",
999 | \\"name\\": \\"id\\",
1000 | \\"variableName\\": \\"id\\"
1001 | }
1002 | ],
1003 | \\"concreteType\\": \\"Person\\",
1004 | \\"plural\\": false,
1005 | \\"selections\\": [
1006 | {
1007 | \\"kind\\": \\"ScalarField\\",
1008 | \\"alias\\": null,
1009 | \\"name\\": \\"id\\",
1010 | \\"args\\": null,
1011 | \\"storageKey\\": null
1012 | },
1013 | {
1014 | \\"kind\\": \\"ScalarField\\",
1015 | \\"alias\\": null,
1016 | \\"name\\": \\"firstName\\",
1017 | \\"args\\": null,
1018 | \\"storageKey\\": null
1019 | },
1020 | {
1021 | \\"kind\\": \\"ScalarField\\",
1022 | \\"alias\\": null,
1023 | \\"name\\": \\"fullName\\",
1024 | \\"args\\": null,
1025 | \\"storageKey\\": null
1026 | }
1027 | ]
1028 | }
1029 | ];
1030 | return {
1031 | \\"kind\\": \\"Request\\",
1032 | \\"fragment\\": {
1033 | \\"kind\\": \\"Fragment\\",
1034 | \\"name\\": \\"AboutQuery\\",
1035 | \\"type\\": \\"Query\\",
1036 | \\"metadata\\": null,
1037 | \\"argumentDefinitions\\": (v0/*: any*/),
1038 | \\"selections\\": (v1/*: any*/)
1039 | },
1040 | \\"operation\\": {
1041 | \\"kind\\": \\"Operation\\",
1042 | \\"name\\": \\"AboutQuery\\",
1043 | \\"argumentDefinitions\\": (v0/*: any*/),
1044 | \\"selections\\": (v1/*: any*/)
1045 | },
1046 | \\"params\\": {
1047 | \\"operationKind\\": \\"query\\",
1048 | \\"name\\": \\"AboutQuery\\",
1049 | \\"id\\": null,
1050 | \\"text\\": \\"query AboutQuery(\\\\n $id: ID!\\\\n) {\\\\n personById(id: $id) {\\\\n id\\\\n firstName\\\\n fullName\\\\n }\\\\n}\\\\n\\",
1051 | \\"metadata\\": {}
1052 | }
1053 | };
1054 | })();
1055 | // prettier-ignore
1056 | (node/*: any*/).hash = '244cfa95d89768b907f6815ff6a3007d';
1057 | module.exports = node;
1058 | "
1059 | `;
1060 |
--------------------------------------------------------------------------------
/test/fixtureProject/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "__schema": {
4 | "queryType": {
5 | "name": "Query"
6 | },
7 | "mutationType": {
8 | "name": "Mutation"
9 | },
10 | "subscriptionType": null,
11 | "types": [
12 | {
13 | "kind": "OBJECT",
14 | "name": "Query",
15 | "description": null,
16 | "fields": [
17 | {
18 | "name": "people",
19 | "description": null,
20 | "args": [],
21 | "type": {
22 | "kind": "LIST",
23 | "name": null,
24 | "ofType": {
25 | "kind": "OBJECT",
26 | "name": "Person",
27 | "ofType": null
28 | }
29 | },
30 | "isDeprecated": false,
31 | "deprecationReason": null
32 | },
33 | {
34 | "name": "personById",
35 | "description": null,
36 | "args": [
37 | {
38 | "name": "id",
39 | "description": null,
40 | "type": {
41 | "kind": "NON_NULL",
42 | "name": null,
43 | "ofType": {
44 | "kind": "SCALAR",
45 | "name": "ID",
46 | "ofType": null
47 | }
48 | },
49 | "defaultValue": null
50 | }
51 | ],
52 | "type": {
53 | "kind": "OBJECT",
54 | "name": "Person",
55 | "ofType": null
56 | },
57 | "isDeprecated": false,
58 | "deprecationReason": null
59 | }
60 | ],
61 | "inputFields": null,
62 | "interfaces": [],
63 | "enumValues": null,
64 | "possibleTypes": null
65 | },
66 | {
67 | "kind": "OBJECT",
68 | "name": "Person",
69 | "description": null,
70 | "fields": [
71 | {
72 | "name": "id",
73 | "description": null,
74 | "args": [],
75 | "type": {
76 | "kind": "NON_NULL",
77 | "name": null,
78 | "ofType": {
79 | "kind": "SCALAR",
80 | "name": "ID",
81 | "ofType": null
82 | }
83 | },
84 | "isDeprecated": false,
85 | "deprecationReason": null
86 | },
87 | {
88 | "name": "firstName",
89 | "description": null,
90 | "args": [],
91 | "type": {
92 | "kind": "NON_NULL",
93 | "name": null,
94 | "ofType": {
95 | "kind": "SCALAR",
96 | "name": "String",
97 | "ofType": null
98 | }
99 | },
100 | "isDeprecated": false,
101 | "deprecationReason": null
102 | },
103 | {
104 | "name": "lastName",
105 | "description": null,
106 | "args": [],
107 | "type": {
108 | "kind": "NON_NULL",
109 | "name": null,
110 | "ofType": {
111 | "kind": "SCALAR",
112 | "name": "String",
113 | "ofType": null
114 | }
115 | },
116 | "isDeprecated": false,
117 | "deprecationReason": null
118 | },
119 | {
120 | "name": "fullName",
121 | "description": null,
122 | "args": [],
123 | "type": {
124 | "kind": "NON_NULL",
125 | "name": null,
126 | "ofType": {
127 | "kind": "SCALAR",
128 | "name": "String",
129 | "ofType": null
130 | }
131 | },
132 | "isDeprecated": false,
133 | "deprecationReason": null
134 | }
135 | ],
136 | "inputFields": null,
137 | "interfaces": [],
138 | "enumValues": null,
139 | "possibleTypes": null
140 | },
141 | {
142 | "kind": "SCALAR",
143 | "name": "ID",
144 | "description": "The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"4\"`) or integer (such as `4`) input value will be accepted as an ID.",
145 | "fields": null,
146 | "inputFields": null,
147 | "interfaces": null,
148 | "enumValues": null,
149 | "possibleTypes": null
150 | },
151 | {
152 | "kind": "SCALAR",
153 | "name": "String",
154 | "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.",
155 | "fields": null,
156 | "inputFields": null,
157 | "interfaces": null,
158 | "enumValues": null,
159 | "possibleTypes": null
160 | },
161 | {
162 | "kind": "OBJECT",
163 | "name": "Mutation",
164 | "description": null,
165 | "fields": [
166 | {
167 | "name": "updateFirstName",
168 | "description": null,
169 | "args": [
170 | {
171 | "name": "id",
172 | "description": null,
173 | "type": {
174 | "kind": "NON_NULL",
175 | "name": null,
176 | "ofType": {
177 | "kind": "SCALAR",
178 | "name": "ID",
179 | "ofType": null
180 | }
181 | },
182 | "defaultValue": null
183 | },
184 | {
185 | "name": "firstName",
186 | "description": null,
187 | "type": {
188 | "kind": "NON_NULL",
189 | "name": null,
190 | "ofType": {
191 | "kind": "SCALAR",
192 | "name": "String",
193 | "ofType": null
194 | }
195 | },
196 | "defaultValue": null
197 | }
198 | ],
199 | "type": {
200 | "kind": "NON_NULL",
201 | "name": null,
202 | "ofType": {
203 | "kind": "OBJECT",
204 | "name": "UpdateFirstNameOutput",
205 | "ofType": null
206 | }
207 | },
208 | "isDeprecated": false,
209 | "deprecationReason": null
210 | }
211 | ],
212 | "inputFields": null,
213 | "interfaces": [],
214 | "enumValues": null,
215 | "possibleTypes": null
216 | },
217 | {
218 | "kind": "OBJECT",
219 | "name": "UpdateFirstNameOutput",
220 | "description": null,
221 | "fields": [
222 | {
223 | "name": "person",
224 | "description": null,
225 | "args": [],
226 | "type": {
227 | "kind": "NON_NULL",
228 | "name": null,
229 | "ofType": {
230 | "kind": "OBJECT",
231 | "name": "Person",
232 | "ofType": null
233 | }
234 | },
235 | "isDeprecated": false,
236 | "deprecationReason": null
237 | }
238 | ],
239 | "inputFields": null,
240 | "interfaces": [],
241 | "enumValues": null,
242 | "possibleTypes": null
243 | },
244 | {
245 | "kind": "OBJECT",
246 | "name": "__Schema",
247 | "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",
248 | "fields": [
249 | {
250 | "name": "types",
251 | "description": "A list of all types supported by this server.",
252 | "args": [],
253 | "type": {
254 | "kind": "NON_NULL",
255 | "name": null,
256 | "ofType": {
257 | "kind": "LIST",
258 | "name": null,
259 | "ofType": {
260 | "kind": "NON_NULL",
261 | "name": null,
262 | "ofType": {
263 | "kind": "OBJECT",
264 | "name": "__Type",
265 | "ofType": null
266 | }
267 | }
268 | }
269 | },
270 | "isDeprecated": false,
271 | "deprecationReason": null
272 | },
273 | {
274 | "name": "queryType",
275 | "description": "The type that query operations will be rooted at.",
276 | "args": [],
277 | "type": {
278 | "kind": "NON_NULL",
279 | "name": null,
280 | "ofType": {
281 | "kind": "OBJECT",
282 | "name": "__Type",
283 | "ofType": null
284 | }
285 | },
286 | "isDeprecated": false,
287 | "deprecationReason": null
288 | },
289 | {
290 | "name": "mutationType",
291 | "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
292 | "args": [],
293 | "type": {
294 | "kind": "OBJECT",
295 | "name": "__Type",
296 | "ofType": null
297 | },
298 | "isDeprecated": false,
299 | "deprecationReason": null
300 | },
301 | {
302 | "name": "subscriptionType",
303 | "description": "If this server support subscription, the type that subscription operations will be rooted at.",
304 | "args": [],
305 | "type": {
306 | "kind": "OBJECT",
307 | "name": "__Type",
308 | "ofType": null
309 | },
310 | "isDeprecated": false,
311 | "deprecationReason": null
312 | },
313 | {
314 | "name": "directives",
315 | "description": "A list of all directives supported by this server.",
316 | "args": [],
317 | "type": {
318 | "kind": "NON_NULL",
319 | "name": null,
320 | "ofType": {
321 | "kind": "LIST",
322 | "name": null,
323 | "ofType": {
324 | "kind": "NON_NULL",
325 | "name": null,
326 | "ofType": {
327 | "kind": "OBJECT",
328 | "name": "__Directive",
329 | "ofType": null
330 | }
331 | }
332 | }
333 | },
334 | "isDeprecated": false,
335 | "deprecationReason": null
336 | }
337 | ],
338 | "inputFields": null,
339 | "interfaces": [],
340 | "enumValues": null,
341 | "possibleTypes": null
342 | },
343 | {
344 | "kind": "OBJECT",
345 | "name": "__Type",
346 | "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",
347 | "fields": [
348 | {
349 | "name": "kind",
350 | "description": null,
351 | "args": [],
352 | "type": {
353 | "kind": "NON_NULL",
354 | "name": null,
355 | "ofType": {
356 | "kind": "ENUM",
357 | "name": "__TypeKind",
358 | "ofType": null
359 | }
360 | },
361 | "isDeprecated": false,
362 | "deprecationReason": null
363 | },
364 | {
365 | "name": "name",
366 | "description": null,
367 | "args": [],
368 | "type": {
369 | "kind": "SCALAR",
370 | "name": "String",
371 | "ofType": null
372 | },
373 | "isDeprecated": false,
374 | "deprecationReason": null
375 | },
376 | {
377 | "name": "description",
378 | "description": null,
379 | "args": [],
380 | "type": {
381 | "kind": "SCALAR",
382 | "name": "String",
383 | "ofType": null
384 | },
385 | "isDeprecated": false,
386 | "deprecationReason": null
387 | },
388 | {
389 | "name": "fields",
390 | "description": null,
391 | "args": [
392 | {
393 | "name": "includeDeprecated",
394 | "description": null,
395 | "type": {
396 | "kind": "SCALAR",
397 | "name": "Boolean",
398 | "ofType": null
399 | },
400 | "defaultValue": "false"
401 | }
402 | ],
403 | "type": {
404 | "kind": "LIST",
405 | "name": null,
406 | "ofType": {
407 | "kind": "NON_NULL",
408 | "name": null,
409 | "ofType": {
410 | "kind": "OBJECT",
411 | "name": "__Field",
412 | "ofType": null
413 | }
414 | }
415 | },
416 | "isDeprecated": false,
417 | "deprecationReason": null
418 | },
419 | {
420 | "name": "interfaces",
421 | "description": null,
422 | "args": [],
423 | "type": {
424 | "kind": "LIST",
425 | "name": null,
426 | "ofType": {
427 | "kind": "NON_NULL",
428 | "name": null,
429 | "ofType": {
430 | "kind": "OBJECT",
431 | "name": "__Type",
432 | "ofType": null
433 | }
434 | }
435 | },
436 | "isDeprecated": false,
437 | "deprecationReason": null
438 | },
439 | {
440 | "name": "possibleTypes",
441 | "description": null,
442 | "args": [],
443 | "type": {
444 | "kind": "LIST",
445 | "name": null,
446 | "ofType": {
447 | "kind": "NON_NULL",
448 | "name": null,
449 | "ofType": {
450 | "kind": "OBJECT",
451 | "name": "__Type",
452 | "ofType": null
453 | }
454 | }
455 | },
456 | "isDeprecated": false,
457 | "deprecationReason": null
458 | },
459 | {
460 | "name": "enumValues",
461 | "description": null,
462 | "args": [
463 | {
464 | "name": "includeDeprecated",
465 | "description": null,
466 | "type": {
467 | "kind": "SCALAR",
468 | "name": "Boolean",
469 | "ofType": null
470 | },
471 | "defaultValue": "false"
472 | }
473 | ],
474 | "type": {
475 | "kind": "LIST",
476 | "name": null,
477 | "ofType": {
478 | "kind": "NON_NULL",
479 | "name": null,
480 | "ofType": {
481 | "kind": "OBJECT",
482 | "name": "__EnumValue",
483 | "ofType": null
484 | }
485 | }
486 | },
487 | "isDeprecated": false,
488 | "deprecationReason": null
489 | },
490 | {
491 | "name": "inputFields",
492 | "description": null,
493 | "args": [],
494 | "type": {
495 | "kind": "LIST",
496 | "name": null,
497 | "ofType": {
498 | "kind": "NON_NULL",
499 | "name": null,
500 | "ofType": {
501 | "kind": "OBJECT",
502 | "name": "__InputValue",
503 | "ofType": null
504 | }
505 | }
506 | },
507 | "isDeprecated": false,
508 | "deprecationReason": null
509 | },
510 | {
511 | "name": "ofType",
512 | "description": null,
513 | "args": [],
514 | "type": {
515 | "kind": "OBJECT",
516 | "name": "__Type",
517 | "ofType": null
518 | },
519 | "isDeprecated": false,
520 | "deprecationReason": null
521 | }
522 | ],
523 | "inputFields": null,
524 | "interfaces": [],
525 | "enumValues": null,
526 | "possibleTypes": null
527 | },
528 | {
529 | "kind": "ENUM",
530 | "name": "__TypeKind",
531 | "description": "An enum describing what kind of type a given `__Type` is.",
532 | "fields": null,
533 | "inputFields": null,
534 | "interfaces": null,
535 | "enumValues": [
536 | {
537 | "name": "SCALAR",
538 | "description": "Indicates this type is a scalar.",
539 | "isDeprecated": false,
540 | "deprecationReason": null
541 | },
542 | {
543 | "name": "OBJECT",
544 | "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
545 | "isDeprecated": false,
546 | "deprecationReason": null
547 | },
548 | {
549 | "name": "INTERFACE",
550 | "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
551 | "isDeprecated": false,
552 | "deprecationReason": null
553 | },
554 | {
555 | "name": "UNION",
556 | "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
557 | "isDeprecated": false,
558 | "deprecationReason": null
559 | },
560 | {
561 | "name": "ENUM",
562 | "description": "Indicates this type is an enum. `enumValues` is a valid field.",
563 | "isDeprecated": false,
564 | "deprecationReason": null
565 | },
566 | {
567 | "name": "INPUT_OBJECT",
568 | "description": "Indicates this type is an input object. `inputFields` is a valid field.",
569 | "isDeprecated": false,
570 | "deprecationReason": null
571 | },
572 | {
573 | "name": "LIST",
574 | "description": "Indicates this type is a list. `ofType` is a valid field.",
575 | "isDeprecated": false,
576 | "deprecationReason": null
577 | },
578 | {
579 | "name": "NON_NULL",
580 | "description": "Indicates this type is a non-null. `ofType` is a valid field.",
581 | "isDeprecated": false,
582 | "deprecationReason": null
583 | }
584 | ],
585 | "possibleTypes": null
586 | },
587 | {
588 | "kind": "SCALAR",
589 | "name": "Boolean",
590 | "description": "The `Boolean` scalar type represents `true` or `false`.",
591 | "fields": null,
592 | "inputFields": null,
593 | "interfaces": null,
594 | "enumValues": null,
595 | "possibleTypes": null
596 | },
597 | {
598 | "kind": "OBJECT",
599 | "name": "__Field",
600 | "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",
601 | "fields": [
602 | {
603 | "name": "name",
604 | "description": null,
605 | "args": [],
606 | "type": {
607 | "kind": "NON_NULL",
608 | "name": null,
609 | "ofType": {
610 | "kind": "SCALAR",
611 | "name": "String",
612 | "ofType": null
613 | }
614 | },
615 | "isDeprecated": false,
616 | "deprecationReason": null
617 | },
618 | {
619 | "name": "description",
620 | "description": null,
621 | "args": [],
622 | "type": {
623 | "kind": "SCALAR",
624 | "name": "String",
625 | "ofType": null
626 | },
627 | "isDeprecated": false,
628 | "deprecationReason": null
629 | },
630 | {
631 | "name": "args",
632 | "description": null,
633 | "args": [],
634 | "type": {
635 | "kind": "NON_NULL",
636 | "name": null,
637 | "ofType": {
638 | "kind": "LIST",
639 | "name": null,
640 | "ofType": {
641 | "kind": "NON_NULL",
642 | "name": null,
643 | "ofType": {
644 | "kind": "OBJECT",
645 | "name": "__InputValue",
646 | "ofType": null
647 | }
648 | }
649 | }
650 | },
651 | "isDeprecated": false,
652 | "deprecationReason": null
653 | },
654 | {
655 | "name": "type",
656 | "description": null,
657 | "args": [],
658 | "type": {
659 | "kind": "NON_NULL",
660 | "name": null,
661 | "ofType": {
662 | "kind": "OBJECT",
663 | "name": "__Type",
664 | "ofType": null
665 | }
666 | },
667 | "isDeprecated": false,
668 | "deprecationReason": null
669 | },
670 | {
671 | "name": "isDeprecated",
672 | "description": null,
673 | "args": [],
674 | "type": {
675 | "kind": "NON_NULL",
676 | "name": null,
677 | "ofType": {
678 | "kind": "SCALAR",
679 | "name": "Boolean",
680 | "ofType": null
681 | }
682 | },
683 | "isDeprecated": false,
684 | "deprecationReason": null
685 | },
686 | {
687 | "name": "deprecationReason",
688 | "description": null,
689 | "args": [],
690 | "type": {
691 | "kind": "SCALAR",
692 | "name": "String",
693 | "ofType": null
694 | },
695 | "isDeprecated": false,
696 | "deprecationReason": null
697 | }
698 | ],
699 | "inputFields": null,
700 | "interfaces": [],
701 | "enumValues": null,
702 | "possibleTypes": null
703 | },
704 | {
705 | "kind": "OBJECT",
706 | "name": "__InputValue",
707 | "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",
708 | "fields": [
709 | {
710 | "name": "name",
711 | "description": null,
712 | "args": [],
713 | "type": {
714 | "kind": "NON_NULL",
715 | "name": null,
716 | "ofType": {
717 | "kind": "SCALAR",
718 | "name": "String",
719 | "ofType": null
720 | }
721 | },
722 | "isDeprecated": false,
723 | "deprecationReason": null
724 | },
725 | {
726 | "name": "description",
727 | "description": null,
728 | "args": [],
729 | "type": {
730 | "kind": "SCALAR",
731 | "name": "String",
732 | "ofType": null
733 | },
734 | "isDeprecated": false,
735 | "deprecationReason": null
736 | },
737 | {
738 | "name": "type",
739 | "description": null,
740 | "args": [],
741 | "type": {
742 | "kind": "NON_NULL",
743 | "name": null,
744 | "ofType": {
745 | "kind": "OBJECT",
746 | "name": "__Type",
747 | "ofType": null
748 | }
749 | },
750 | "isDeprecated": false,
751 | "deprecationReason": null
752 | },
753 | {
754 | "name": "defaultValue",
755 | "description": "A GraphQL-formatted string representing the default value for this input value.",
756 | "args": [],
757 | "type": {
758 | "kind": "SCALAR",
759 | "name": "String",
760 | "ofType": null
761 | },
762 | "isDeprecated": false,
763 | "deprecationReason": null
764 | }
765 | ],
766 | "inputFields": null,
767 | "interfaces": [],
768 | "enumValues": null,
769 | "possibleTypes": null
770 | },
771 | {
772 | "kind": "OBJECT",
773 | "name": "__EnumValue",
774 | "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",
775 | "fields": [
776 | {
777 | "name": "name",
778 | "description": null,
779 | "args": [],
780 | "type": {
781 | "kind": "NON_NULL",
782 | "name": null,
783 | "ofType": {
784 | "kind": "SCALAR",
785 | "name": "String",
786 | "ofType": null
787 | }
788 | },
789 | "isDeprecated": false,
790 | "deprecationReason": null
791 | },
792 | {
793 | "name": "description",
794 | "description": null,
795 | "args": [],
796 | "type": {
797 | "kind": "SCALAR",
798 | "name": "String",
799 | "ofType": null
800 | },
801 | "isDeprecated": false,
802 | "deprecationReason": null
803 | },
804 | {
805 | "name": "isDeprecated",
806 | "description": null,
807 | "args": [],
808 | "type": {
809 | "kind": "NON_NULL",
810 | "name": null,
811 | "ofType": {
812 | "kind": "SCALAR",
813 | "name": "Boolean",
814 | "ofType": null
815 | }
816 | },
817 | "isDeprecated": false,
818 | "deprecationReason": null
819 | },
820 | {
821 | "name": "deprecationReason",
822 | "description": null,
823 | "args": [],
824 | "type": {
825 | "kind": "SCALAR",
826 | "name": "String",
827 | "ofType": null
828 | },
829 | "isDeprecated": false,
830 | "deprecationReason": null
831 | }
832 | ],
833 | "inputFields": null,
834 | "interfaces": [],
835 | "enumValues": null,
836 | "possibleTypes": null
837 | },
838 | {
839 | "kind": "OBJECT",
840 | "name": "__Directive",
841 | "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",
842 | "fields": [
843 | {
844 | "name": "name",
845 | "description": null,
846 | "args": [],
847 | "type": {
848 | "kind": "NON_NULL",
849 | "name": null,
850 | "ofType": {
851 | "kind": "SCALAR",
852 | "name": "String",
853 | "ofType": null
854 | }
855 | },
856 | "isDeprecated": false,
857 | "deprecationReason": null
858 | },
859 | {
860 | "name": "description",
861 | "description": null,
862 | "args": [],
863 | "type": {
864 | "kind": "SCALAR",
865 | "name": "String",
866 | "ofType": null
867 | },
868 | "isDeprecated": false,
869 | "deprecationReason": null
870 | },
871 | {
872 | "name": "locations",
873 | "description": null,
874 | "args": [],
875 | "type": {
876 | "kind": "NON_NULL",
877 | "name": null,
878 | "ofType": {
879 | "kind": "LIST",
880 | "name": null,
881 | "ofType": {
882 | "kind": "NON_NULL",
883 | "name": null,
884 | "ofType": {
885 | "kind": "ENUM",
886 | "name": "__DirectiveLocation",
887 | "ofType": null
888 | }
889 | }
890 | }
891 | },
892 | "isDeprecated": false,
893 | "deprecationReason": null
894 | },
895 | {
896 | "name": "args",
897 | "description": null,
898 | "args": [],
899 | "type": {
900 | "kind": "NON_NULL",
901 | "name": null,
902 | "ofType": {
903 | "kind": "LIST",
904 | "name": null,
905 | "ofType": {
906 | "kind": "NON_NULL",
907 | "name": null,
908 | "ofType": {
909 | "kind": "OBJECT",
910 | "name": "__InputValue",
911 | "ofType": null
912 | }
913 | }
914 | }
915 | },
916 | "isDeprecated": false,
917 | "deprecationReason": null
918 | },
919 | {
920 | "name": "onOperation",
921 | "description": null,
922 | "args": [],
923 | "type": {
924 | "kind": "NON_NULL",
925 | "name": null,
926 | "ofType": {
927 | "kind": "SCALAR",
928 | "name": "Boolean",
929 | "ofType": null
930 | }
931 | },
932 | "isDeprecated": true,
933 | "deprecationReason": "Use `locations`."
934 | },
935 | {
936 | "name": "onFragment",
937 | "description": null,
938 | "args": [],
939 | "type": {
940 | "kind": "NON_NULL",
941 | "name": null,
942 | "ofType": {
943 | "kind": "SCALAR",
944 | "name": "Boolean",
945 | "ofType": null
946 | }
947 | },
948 | "isDeprecated": true,
949 | "deprecationReason": "Use `locations`."
950 | },
951 | {
952 | "name": "onField",
953 | "description": null,
954 | "args": [],
955 | "type": {
956 | "kind": "NON_NULL",
957 | "name": null,
958 | "ofType": {
959 | "kind": "SCALAR",
960 | "name": "Boolean",
961 | "ofType": null
962 | }
963 | },
964 | "isDeprecated": true,
965 | "deprecationReason": "Use `locations`."
966 | }
967 | ],
968 | "inputFields": null,
969 | "interfaces": [],
970 | "enumValues": null,
971 | "possibleTypes": null
972 | },
973 | {
974 | "kind": "ENUM",
975 | "name": "__DirectiveLocation",
976 | "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",
977 | "fields": null,
978 | "inputFields": null,
979 | "interfaces": null,
980 | "enumValues": [
981 | {
982 | "name": "QUERY",
983 | "description": "Location adjacent to a query operation.",
984 | "isDeprecated": false,
985 | "deprecationReason": null
986 | },
987 | {
988 | "name": "MUTATION",
989 | "description": "Location adjacent to a mutation operation.",
990 | "isDeprecated": false,
991 | "deprecationReason": null
992 | },
993 | {
994 | "name": "SUBSCRIPTION",
995 | "description": "Location adjacent to a subscription operation.",
996 | "isDeprecated": false,
997 | "deprecationReason": null
998 | },
999 | {
1000 | "name": "FIELD",
1001 | "description": "Location adjacent to a field.",
1002 | "isDeprecated": false,
1003 | "deprecationReason": null
1004 | },
1005 | {
1006 | "name": "FRAGMENT_DEFINITION",
1007 | "description": "Location adjacent to a fragment definition.",
1008 | "isDeprecated": false,
1009 | "deprecationReason": null
1010 | },
1011 | {
1012 | "name": "FRAGMENT_SPREAD",
1013 | "description": "Location adjacent to a fragment spread.",
1014 | "isDeprecated": false,
1015 | "deprecationReason": null
1016 | },
1017 | {
1018 | "name": "INLINE_FRAGMENT",
1019 | "description": "Location adjacent to an inline fragment.",
1020 | "isDeprecated": false,
1021 | "deprecationReason": null
1022 | },
1023 | {
1024 | "name": "SCHEMA",
1025 | "description": "Location adjacent to a schema definition.",
1026 | "isDeprecated": false,
1027 | "deprecationReason": null
1028 | },
1029 | {
1030 | "name": "SCALAR",
1031 | "description": "Location adjacent to a scalar definition.",
1032 | "isDeprecated": false,
1033 | "deprecationReason": null
1034 | },
1035 | {
1036 | "name": "OBJECT",
1037 | "description": "Location adjacent to an object type definition.",
1038 | "isDeprecated": false,
1039 | "deprecationReason": null
1040 | },
1041 | {
1042 | "name": "FIELD_DEFINITION",
1043 | "description": "Location adjacent to a field definition.",
1044 | "isDeprecated": false,
1045 | "deprecationReason": null
1046 | },
1047 | {
1048 | "name": "ARGUMENT_DEFINITION",
1049 | "description": "Location adjacent to an argument definition.",
1050 | "isDeprecated": false,
1051 | "deprecationReason": null
1052 | },
1053 | {
1054 | "name": "INTERFACE",
1055 | "description": "Location adjacent to an interface definition.",
1056 | "isDeprecated": false,
1057 | "deprecationReason": null
1058 | },
1059 | {
1060 | "name": "UNION",
1061 | "description": "Location adjacent to a union definition.",
1062 | "isDeprecated": false,
1063 | "deprecationReason": null
1064 | },
1065 | {
1066 | "name": "ENUM",
1067 | "description": "Location adjacent to an enum definition.",
1068 | "isDeprecated": false,
1069 | "deprecationReason": null
1070 | },
1071 | {
1072 | "name": "ENUM_VALUE",
1073 | "description": "Location adjacent to an enum value definition.",
1074 | "isDeprecated": false,
1075 | "deprecationReason": null
1076 | },
1077 | {
1078 | "name": "INPUT_OBJECT",
1079 | "description": "Location adjacent to an input object type definition.",
1080 | "isDeprecated": false,
1081 | "deprecationReason": null
1082 | },
1083 | {
1084 | "name": "INPUT_FIELD_DEFINITION",
1085 | "description": "Location adjacent to an input object field definition.",
1086 | "isDeprecated": false,
1087 | "deprecationReason": null
1088 | }
1089 | ],
1090 | "possibleTypes": null
1091 | }
1092 | ],
1093 | "directives": [
1094 | {
1095 | "name": "skip",
1096 | "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
1097 | "locations": [
1098 | "FIELD",
1099 | "FRAGMENT_SPREAD",
1100 | "INLINE_FRAGMENT"
1101 | ],
1102 | "args": [
1103 | {
1104 | "name": "if",
1105 | "description": "Skipped when true.",
1106 | "type": {
1107 | "kind": "NON_NULL",
1108 | "name": null,
1109 | "ofType": {
1110 | "kind": "SCALAR",
1111 | "name": "Boolean",
1112 | "ofType": null
1113 | }
1114 | },
1115 | "defaultValue": null
1116 | }
1117 | ]
1118 | },
1119 | {
1120 | "name": "include",
1121 | "description": "Directs the executor to include this field or fragment only when the `if` argument is true.",
1122 | "locations": [
1123 | "FIELD",
1124 | "FRAGMENT_SPREAD",
1125 | "INLINE_FRAGMENT"
1126 | ],
1127 | "args": [
1128 | {
1129 | "name": "if",
1130 | "description": "Included when true.",
1131 | "type": {
1132 | "kind": "NON_NULL",
1133 | "name": null,
1134 | "ofType": {
1135 | "kind": "SCALAR",
1136 | "name": "Boolean",
1137 | "ofType": null
1138 | }
1139 | },
1140 | "defaultValue": null
1141 | }
1142 | ]
1143 | },
1144 | {
1145 | "name": "deprecated",
1146 | "description": "Marks an element of a GraphQL schema as no longer supported.",
1147 | "locations": [
1148 | "FIELD_DEFINITION",
1149 | "ENUM_VALUE"
1150 | ],
1151 | "args": [
1152 | {
1153 | "name": "reason",
1154 | "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).",
1155 | "type": {
1156 | "kind": "SCALAR",
1157 | "name": "String",
1158 | "ofType": null
1159 | },
1160 | "defaultValue": "\"No longer supported\""
1161 | }
1162 | ]
1163 | }
1164 | ]
1165 | }
1166 | }
1167 | }
--------------------------------------------------------------------------------