Skip to content

Commit d63801f

Browse files
LekoArtsTallTedthomasheyenbrock
authored
feat: Add @graphiql/plugin-code-exporter (#2758)
* initial * update cspell * integrate into example * update props * get things working * add styling * add icon, svg example, inline snippets * Update packages/graphiql-plugin-code-exporter/README.md Co-authored-by: Ted Thibodeau Jr <[email protected]> * Update packages/graphiql-plugin-code-exporter/README.md Co-authored-by: Ted Thibodeau Jr <[email protected]> * review comments no1 - deduplication - vite bundle config - move package to devDep - remove wrapper react component - eslint thingy * review comments no2 Co-authored-by: Thomas Heyenbrock <[email protected]> * css nesting * fix default codeMirrorTheme issue * fix dropdown styles * add doc explorer style resets * adjust width of plugin pane and code exporter editor * add changesets Co-authored-by: Ted Thibodeau Jr <[email protected]> Co-authored-by: Thomas Heyenbrock <[email protected]>
1 parent 1a62b67 commit d63801f

File tree

23 files changed

+730
-38
lines changed

23 files changed

+730
-38
lines changed

.changeset/dirty-melons-burn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphiql': patch
3+
---
4+
5+
Fix the width of the plugin pane

.changeset/real-boxes-sleep.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphiql/plugin-code-exporter': minor
3+
---
4+
5+
Add code exported plugin

custom-words.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ timsuchanek
5959
urigo
6060
wincent
6161
yoshiakis
62+
Leko
63+
LekoArts
6264

6365

6466
// packages and tools

examples/graphiql-webpack/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
"start": "cross-env NODE_ENV=development webpack-dev-server"
1010
},
1111
"dependencies": {
12+
"@graphiql/plugin-code-exporter": "^0.0.1",
13+
"@graphiql/plugin-explorer": "^0.1.3",
1214
"@graphiql/toolkit": "^0.8.0",
1315
"graphiql": "^2.0.11",
1416
"graphql": "^16.4.0",
1517
"graphql-ws": "^5.5.5",
16-
"react": "^17.0.2"
18+
"react": "^17.0.2",
19+
"regenerator-runtime": "^0.13.9"
1720
},
1821
"devDependencies": {
1922
"@babel/plugin-proposal-class-properties": "^7.8.3",
Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,93 @@
1-
import React from 'react';
1+
import 'regenerator-runtime/runtime.js';
2+
3+
import * as React from 'react';
24
import { render } from 'react-dom';
35
import GraphiQL from 'graphiql';
6+
import { useExplorerPlugin } from '@graphiql/plugin-explorer';
7+
import { useExporterPlugin } from '@graphiql/plugin-code-exporter';
8+
49
import 'graphiql/graphiql.css';
10+
import '@graphiql/plugin-explorer/dist/style.css';
11+
import '@graphiql/plugin-code-exporter/dist/style.css';
12+
13+
const removeQueryName = query =>
14+
query.replace(
15+
/^[^{(]+([{(])/,
16+
(_match, openingCurlyBracketsOrParenthesis) =>
17+
`query ${openingCurlyBracketsOrParenthesis}`,
18+
);
19+
20+
const getQuery = (arg, spaceCount) => {
21+
const { operationDataList } = arg;
22+
const { query } = operationDataList[0];
23+
const anonymousQuery = removeQueryName(query);
24+
return (
25+
` `.repeat(spaceCount) +
26+
anonymousQuery.replace(/\n/g, `\n` + ` `.repeat(spaceCount))
27+
);
28+
};
29+
30+
const exampleSnippetOne = {
31+
name: `Example One`,
32+
language: `JavaScript`,
33+
codeMirrorMode: `jsx`,
34+
options: [],
35+
generate: arg => `export const query = graphql\`
36+
${getQuery(arg, 2)}
37+
\`
38+
`,
39+
};
40+
41+
const exampleSnippetTwo = {
42+
name: `Example Two`,
43+
language: `JavaScript`,
44+
codeMirrorMode: `jsx`,
45+
options: [],
46+
generate: arg => `import { graphql } from 'graphql'
47+
48+
export const query = graphql\`
49+
${getQuery(arg, 2)}
50+
\`
51+
`,
52+
};
53+
54+
const snippets = [exampleSnippetOne, exampleSnippetTwo];
55+
56+
const App = () => {
57+
const [query, setQuery] = React.useState('');
58+
const explorerPlugin = useExplorerPlugin({
59+
query,
60+
onEdit: setQuery,
61+
});
62+
const exporterPlugin = useExporterPlugin({
63+
query,
64+
snippets,
65+
});
566

6-
const Logo = () => <span>My Corp</span>;
7-
8-
// See GraphiQL Readme - Advanced Usage section for more examples like this
9-
GraphiQL.Logo = Logo;
10-
11-
const App = () => (
12-
<GraphiQL
13-
style={{ height: '100vh' }}
14-
headerEditorEnabled
15-
fetcher={async (graphQLParams, options) => {
16-
const data = await fetch(
17-
'https://swapi-graphql.netlify.app/.netlify/functions/index',
18-
{
19-
method: 'POST',
20-
headers: {
21-
Accept: 'application/json',
22-
'Content-Type': 'application/json',
23-
...options.headers,
67+
return (
68+
<GraphiQL
69+
style={{ height: '100vh' }}
70+
query={query}
71+
onEditQuery={setQuery}
72+
plugins={[explorerPlugin, exporterPlugin]}
73+
fetcher={async (graphQLParams, options) => {
74+
const data = await fetch(
75+
'https://swapi-graphql.netlify.app/.netlify/functions/index',
76+
{
77+
method: 'POST',
78+
headers: {
79+
Accept: 'application/json',
80+
'Content-Type': 'application/json',
81+
...options.headers,
82+
},
83+
body: JSON.stringify(graphQLParams),
84+
credentials: 'same-origin',
2485
},
25-
body: JSON.stringify(graphQLParams),
26-
credentials: 'same-origin',
27-
},
28-
);
29-
return data.json().catch(() => data.text());
30-
}}
31-
/>
32-
);
86+
);
87+
return data.json().catch(() => data.text());
88+
}}
89+
/>
90+
);
91+
};
3392

3493
render(<App />, document.getElementById('root'));

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"npm": "please_use_yarn_instead"
3333
},
3434
"scripts": {
35-
"build": "yarn build:clean && yarn build:packages && yarn build:graphiql-react && yarn build:graphiql-plugin-explorer && yarn build:graphiql",
35+
"build": "yarn build:clean && yarn build:packages && yarn build:graphiql-react && yarn build:graphiql-plugin-explorer && yarn build:graphiql-plugin-code-exporter && yarn build:graphiql",
3636
"build-bundles": "yarn prebuild-bundles && wsrun -p -m -s build-bundles",
3737
"build-bundles-clean": "rimraf '{packages,examples,plugins}/**/{bundle,cdn,webpack}' && yarn workspace graphiql run build-bundles-clean",
3838
"build-clean": "wsrun -m build-clean ",
@@ -41,6 +41,7 @@
4141
"build:clean": "yarn tsc --clean && yarn tsc --clean resources/tsconfig.graphiql.json",
4242
"build:graphiql": "yarn tsc resources/tsconfig.graphiql.json",
4343
"build:graphiql-plugin-explorer": "yarn workspace @graphiql/plugin-explorer run build",
44+
"build:graphiql-plugin-code-exporter": "yarn workspace @graphiql/plugin-code-exporter run build",
4445
"build:graphiql-react": "yarn workspace @graphiql/react run build",
4546
"build:packages": "yarn tsc",
4647
"build:watch": "yarn tsc --watch",
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["plugin:react/jsx-runtime"]
3+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
types
14+
*.local
15+
16+
# Editor directories and files
17+
.vscode/*
18+
!.vscode/extensions.json
19+
.idea
20+
.DS_Store
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# @graphiql/plugin-code-exporter
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# GraphiQL Code Exporter Plugin
2+
3+
This package provides a plugin that integrates the [GraphiQL Code Exporter](https://github.com/OneGraph/graphiql-code-exporter) into the GraphiQL UI.
4+
5+
## Install
6+
7+
Use your favorite package manager to install the package:
8+
9+
```sh
10+
npm i -S @graphiql/plugin-code-exporter
11+
```
12+
13+
The following packages are peer dependencies, so make sure you have them installed as well:
14+
15+
```sh
16+
npm i -S react react-dom graphql
17+
```
18+
19+
## Usage
20+
21+
See [GraphiQL Code Exporter README](https://github.com/OneGraph/graphiql-code-exporter) for all details on available `props` and how to [create snippets](https://github.com/OneGraph/graphiql-code-exporter#snippets).
22+
23+
```jsx
24+
import { useCodeExporterPlugin } from '@graphiql/plugin-code-exporter';
25+
import { createGraphiQLFetcher } from '@graphiql/toolkit';
26+
import { GraphiQL } from 'graphiql';
27+
import { useState } from 'react';
28+
29+
import 'graphiql/graphiql.css';
30+
import '@graphiql/plugin-code-exporter/dist/style.css';
31+
32+
const fetcher = createGraphiQLFetcher({
33+
url: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
34+
});
35+
36+
/*
37+
Example code for snippets. See https://github.com/OneGraph/graphiql-code-exporter#snippets for details
38+
*/
39+
40+
const removeQueryName = query =>
41+
query.replace(
42+
/^[^{(]+([{(])/,
43+
(_match, openingCurlyBracketsOrParenthesis) =>
44+
`query ${openingCurlyBracketsOrParenthesis}`,
45+
);
46+
47+
const getQuery = (arg, spaceCount) => {
48+
const { operationDataList } = arg;
49+
const { query } = operationDataList[0];
50+
const anonymousQuery = removeQueryName(query);
51+
return (
52+
` `.repeat(spaceCount) +
53+
anonymousQuery.replace(/\n/g, `\n` + ` `.repeat(spaceCount))
54+
);
55+
};
56+
57+
const exampleSnippetOne = {
58+
name: `Example One`,
59+
language: `JavaScript`,
60+
codeMirrorMode: `jsx`,
61+
options: [],
62+
generate: arg => `export const query = graphql\`
63+
${getQuery(arg, 2)}
64+
\`
65+
`,
66+
};
67+
68+
const exampleSnippetTwo = {
69+
name: `Example Two`,
70+
language: `JavaScript`,
71+
codeMirrorMode: `jsx`,
72+
options: [],
73+
generate: arg => `import { graphql } from 'graphql'
74+
75+
export const query = graphql\`
76+
${getQuery(arg, 2)}
77+
\`
78+
`,
79+
};
80+
81+
const snippets = [exampleSnippetOne, exampleSnippetTwo];
82+
83+
function GraphiQLWithExplorer() {
84+
const [query, setQuery] = useState(DEFAULT_QUERY);
85+
const exporterPlugin = useCodeExporterPlugin({
86+
query,
87+
snippets,
88+
codeMirrorTheme: 'graphiql',
89+
});
90+
return (
91+
<GraphiQL
92+
fetcher={fetcher}
93+
query={query}
94+
onEditQuery={setQuery}
95+
plugins={[exporterPlugin]}
96+
/>
97+
);
98+
}
99+
```
100+
101+
## CDN bundles
102+
103+
You can also use this plugin when using the [CDN bundle](../../examples/graphiql-cdn) to render GraphiQL. Check out the [example HTML file](examples/index.html) that shows how you can do this.

0 commit comments

Comments
 (0)