Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

simplify monaco-graphql-react-vite example, fix sending variables #3140

Merged
merged 5 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 79 additions & 89 deletions examples/monaco-graphql-react-vite/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
import React, { useEffect } from 'react';
import { ReactElement, useEffect, useRef, useState, StrictMode } from 'react';
import { getIntrospectionQuery, IntrospectionQuery } from 'graphql';
import { Uri, editor, KeyMod, KeyCode, languages } from 'monaco-editor';
import { initializeMode } from 'monaco-graphql/src/initializeMode';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { createGraphiQLFetcher, SyncFetcherResult } from '@graphiql/toolkit';
import * as JSONC from 'jsonc-parser';
import { debounce } from './debounce';

const fetcher = createGraphiQLFetcher({
url: 'https://api.spacex.land/graphql/',
url: 'https://countries.trevorblades.com',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previous endpoint is no longer works

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh ok! let's add a default query for this new schema perhaps?

we can also use our own to make sure it continues working

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the default query too!

query($code: ID!) {
country(code: $code) {
awsRegion
native
phone
}
}`;

});

const defaultOperations =
localStorage.getItem('operations') ??
`
# cmd/ctrl + return/enter will execute the op,
`# cmd/ctrl + return/enter will execute the op,
# same in variables editor below
# also available via context menu & f1 command palette

query($limit: Int!) {
payloads(limit: $limit) {
customer
}
}
`;
query($code: ID!) {
country(code: $code) {
awsRegion
native
phone
}
}`;

const defaultVariables =
localStorage.getItem('variables') ??
`
{
// limit will appear here as autocomplete,
// and because the default value is 0, will
// complete as such
$1
}
`;

const getSchema = async () =>
fetcher({
`{
// 'code' will appear here as autocomplete,
// and because the default value is 0, will
// complete as such
$1
}`;
Copy link
Collaborator Author

@dimaMachina dimaMachina Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why but I don't get autocomplete for variable code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@B2o5T my bad, I can't remember what went wrong here, it has to do with an option that needs to be enabled somewhere, let's remove for now


async function getSchema(): Promise<SyncFetcherResult> {
return fetcher({
query: getIntrospectionQuery(),
operationName: 'IntrospectionQuery',
});
}

const getOrCreateModel = (uri: string, value: string) => {
function getOrCreateModel(uri: string, value: string): editor.ITextModel {
return (
editor.getModel(Uri.file(uri)) ??
editor.createModel(value, uri.split('.').pop(), Uri.file(uri))
);
};
}

const execOperation = async function () {
async function execOperation(): Promise<void> {
const variables = editor.getModel(Uri.file('variables.json'))!.getValue();
const operations = editor.getModel(Uri.file('operation.graphql'))!.getValue();
const resultsModel = editor.getModel(Uri.file('results.json'));
// @ts-expect-error
const result = await fetcher({
query: operations,
variables: JSON.stringify(JSONC.parse(variables)),
variables: JSONC.parse(variables),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here was a mistake, we should pass object and not string

Copy link
Member

@acao acao Jun 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm,,, this used to work! but perhaps we changed this in monaco-graphql

});
// TODO: this demo only supports a single iteration for http GET/POST,
// no multipart or subscriptions yet.
// @ts-expect-error
const data = await result.next();

resultsModel?.setValue(JSON.stringify(data.value, null, 2));
};
}

const queryAction = {
id: 'graphql-run',
Expand All @@ -82,23 +80,17 @@ languages.json.jsonDefaults.setDiagnosticsOptions({
trailingCommas: 'ignore',
});

const createEditor = (
ref: React.MutableRefObject<null>,
options: editor.IStandaloneEditorConstructionOptions,
) => editor.create(ref.current as unknown as HTMLElement, options);

export default function App() {
const opsRef = React.useRef(null);
const varsRef = React.useRef(null);
const resultsRef = React.useRef(null);
const [queryEditor, setQueryEditor] =
React.useState<editor.IStandaloneCodeEditor | null>(null);
const [variablesEditor, setVariablesEditor] =
React.useState<editor.IStandaloneCodeEditor | null>(null);
const [resultsViewer, setResultsViewer] =
React.useState<editor.IStandaloneCodeEditor | null>(null);
const [schema, setSchema] = React.useState<unknown | null>(null);
const [loading, setLoading] = React.useState(false);
type Editor = editor.IStandaloneCodeEditor | null;

export default function App(): ReactElement {
const operationsRef = useRef<HTMLDivElement>(null);
const variablesRef = useRef<HTMLDivElement>(null);
const resultsRef = useRef<HTMLDivElement>(null);
const [queryEditor, setQueryEditor] = useState<Editor>(null);
const [variablesEditor, setVariablesEditor] = useState<Editor>(null);
const [resultsViewer, setResultsViewer] = useState<Editor>(null);
const [schema, setSchema] = useState<IntrospectionQuery | null>(null);
const [loading, setLoading] = useState(false);

/**
* Create the models & editors
Expand All @@ -110,7 +102,7 @@ export default function App() {

if (!queryEditor) {
setQueryEditor(
createEditor(opsRef, {
editor.create(operationsRef.current!, {
theme: 'vs-dark',
model: queryModel,
language: 'graphql',
Expand All @@ -119,15 +111,15 @@ export default function App() {
}
if (!variablesEditor) {
setVariablesEditor(
createEditor(varsRef, {
editor.create(variablesRef.current!, {
theme: 'vs-dark',
model: variablesModel,
}),
);
}
if (!resultsViewer) {
setResultsViewer(
createEditor(resultsRef, {
editor.create(resultsRef.current!, {
theme: 'vs-dark',
model: resultsModel,
readOnly: true,
Expand Down Expand Up @@ -156,52 +148,50 @@ export default function App() {
* Handle the initial schema load
*/
useEffect(() => {
if (!schema && !loading) {
acao marked this conversation as resolved.
Show resolved Hide resolved
setLoading(true);
void getSchema()
.then(data => {
if (!('data' in data)) {
throw new Error(
'this demo does not support subscriptions or http multipart yet',
);
}
initializeMode({
diagnosticSettings: {
validateVariablesJSON: {
[Uri.file('operation.graphql').toString()]: [
Uri.file('variables.json').toString(),
],
},
jsonDiagnosticSettings: {
validate: true,
schemaValidation: 'error',
// set these again, because we are entirely re-setting them here
allowComments: true,
trailingCommas: 'ignore',
},
},
schemas: [
{
introspectionJSON: data.data as unknown as IntrospectionQuery,
uri: 'myschema.graphql',
},
if (schema || loading) {
return;
}
setLoading(true);

void getSchema().then(data => {
const introspectionJSON =
'data' in data && (data.data as unknown as IntrospectionQuery);

if (!introspectionJSON) {
throw new Error(
'this demo does not support subscriptions or http multipart yet',
);
}
initializeMode({
diagnosticSettings: {
validateVariablesJSON: {
[Uri.file('operation.graphql').toString()]: [
Uri.file('variables.json').toString(),
],
});
},
jsonDiagnosticSettings: {
validate: true,
schemaValidation: 'error',
// set these again, because we are entirely re-setting them here
allowComments: true,
trailingCommas: 'ignore',
},
},
schemas: [{ introspectionJSON, uri: 'myschema.graphql' }],
});

setSchema(data.data);
})
.then(() => setLoading(false));
acao marked this conversation as resolved.
Show resolved Hide resolved
}
setSchema(introspectionJSON);
setLoading(false);
});
}, [schema, loading]);

return (
<div id="wrapper">
<StrictMode>
<div id="left-pane" className="pane">
<div ref={opsRef} className="editor" />
<div ref={varsRef} className="editor" />
</div>
<div id="right-pane" className="pane">
<div ref={resultsRef} className="editor" />
<div ref={operationsRef} className="editor" />
<div ref={variablesRef} className="editor" />
</div>
</div>
<div ref={resultsRef} id="right-pane" className="pane editor" />
</StrictMode>
);
}
4 changes: 2 additions & 2 deletions examples/monaco-graphql-react-vite/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ body {
height: 100vh;
}

#wrapper {
#root {
display: flex;
flex-direction: row;
height: 97.7vh;
Expand All @@ -22,6 +22,6 @@ body {
height: 50%;
}

#right-pane .editor {
#right-pane.editor {
height: 100%;
}
11 changes: 2 additions & 9 deletions examples/monaco-graphql-react-vite/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import React from 'react';
import ReactDOM from 'react-dom';

import { render } from 'react-dom';
import App from './App';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root'),
);
render(<App />, document.getElementById('root'));
56 changes: 27 additions & 29 deletions examples/monaco-graphql-webpack/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,36 +143,34 @@ async function render() {
* monaco-graphql itself doesn't do anything with handling operations yet, but it may soon!
*/

const getOperationHandler = () => {
return async () => {
try {
const operation = operationEditor.getValue();
const variables = variablesEditor.getValue();
const body: { variables?: string; query: string } = {
query: operation,
};
// parse the variables with JSONC, so we can have comments!
const parsedVariables = JSONC.parse(variables);
if (parsedVariables && Object.keys(parsedVariables).length) {
body.variables = JSON.stringify(parsedVariables, null, 2);
}
const result = await fetch(schemaFetcher.currentSchema.value, {
method: 'POST',
headers: {
'content-type': 'application/json',
...schemaFetcher.currentSchema?.headers,
},
body: JSON.stringify(body, null, 2),
});

const resultText = await result.text();
resultsEditor.setValue(JSON.stringify(JSON.parse(resultText), null, 2));
} catch (err) {
if (err instanceof Error) {
resultsEditor.setValue(err.toString());
}
const getOperationHandler = () => async () => {
acao marked this conversation as resolved.
Show resolved Hide resolved
try {
const operation = operationEditor.getValue();
const variables = variablesEditor.getValue();
const body: { variables?: string; query: string } = {
query: operation,
};
// parse the variables with JSONC, so we can have comments!
const parsedVariables = JSONC.parse(variables);
if (parsedVariables && Object.keys(parsedVariables).length) {
body.variables = JSON.stringify(parsedVariables, null, 2);
}
};
const result = await fetch(schemaFetcher.currentSchema.value, {
method: 'POST',
headers: {
'content-type': 'application/json',
...schemaFetcher.currentSchema?.headers,
},
body: JSON.stringify(body, null, 2),
});

const resultText = await result.text();
resultsEditor.setValue(JSON.stringify(JSON.parse(resultText), null, 2));
} catch (err) {
if (err instanceof Error) {
resultsEditor.setValue(err.toString());
}
}
};

const operationHandler = getOperationHandler();
Expand Down