import 'graphiql/src/css/doc-explorer.css'; import type { GraphQLSchema } from 'graphql'; import { load as loadYaml } from 'js-yaml'; import type * as monaco from 'monaco-editor'; import type { SchemaConfig } from 'monaco-graphql/src/typings'; import React from 'react'; import { createRoot } from 'react-dom/client'; import { NamedPage } from 'vj/misc/Page'; import request from 'vj/utils/request'; const defaultQuery = `\ query Example( $name: String! ) { user(uname: $name) { _id uname } }`; const variablesString = 'name: Hydro'; const resultsString = '{}'; const schemaSdlString = `\ """ Loading schema... """`; const page = new NamedPage('api', async () => { const [{ DocExplorer }, { buildClientSchema, getIntrospectionQuery, printSchema }, { load }] = await Promise.all([ import('graphiql/esm/components/DocExplorer'), import('graphql/utilities'), import('vj/components/monaco/loader'), ]); const { monaco } = await load(['graphql', 'json', 'yaml']); const { initializeMode } = await import('monaco-graphql/esm/initializeMode'); const variablesModel = monaco.editor.createModel( variablesString, 'yaml', monaco.Uri.file('/1/variables.yaml'), ); const variablesEditor = monaco.editor.create( document.getElementById('variables') as HTMLElement, { model: variablesModel, language: 'yaml', formatOnPaste: true, formatOnType: true, comments: { insertSpace: true, ignoreEmptyLines: true, }, }, ); const operationModel = monaco.editor.createModel( defaultQuery, 'graphql', monaco.Uri.file('/1/operation.graphql'), ); const operationEditor = monaco.editor.create( document.getElementById('operation') as HTMLElement, { model: operationModel, formatOnPaste: true, formatOnType: true, folding: true, language: 'graphql', }, ); const schemaModel = monaco.editor.createModel( schemaSdlString, 'graphql', monaco.Uri.file('/1/schema.graphqls'), ); const schemaEditor = monaco.editor.create( document.getElementById('schema-sdl') as HTMLElement, { model: schemaModel, formatOnPaste: true, formatOnType: true, folding: true, readOnly: true, language: 'graphql', }, ); const resultsModel = monaco.editor.createModel( resultsString, 'json', monaco.Uri.file('/1/results.json'), ); const resultsEditor = monaco.editor.create( document.getElementById('results') as HTMLElement, { model: resultsModel, language: 'json', wordWrap: 'on', readOnly: true, showFoldingControls: 'always', }, ); const monacoGraphQLAPI = initializeMode({ formattingOptions: { prettierConfig: { printWidth: 120, }, }, }); const toolbar = $('#toolbar')!; toolbar.html(); const executeOpButton = $(''); toolbar.append(executeOpButton); const operationUri = operationModel.uri.toString(); let schema: SchemaConfig; let clientSchema: GraphQLSchema; try { const { data } = await request.post('/api?schema', { query: getIntrospectionQuery(), operationName: 'IntrospectionQuery', }); clientSchema = buildClientSchema(data); schema = { introspectionJSON: data, documentString: printSchema(clientSchema), uri: monaco.Uri.parse('/api?schema').toString(), }; } catch { schemaModel.setValue('"""\nFailed to load schema.\n"""'); } monacoGraphQLAPI.setSchemaConfig([ { ...schema, fileMatch: [operationUri, schemaModel.uri.toString()] }, ]); schemaEditor.setValue(schema.documentString || ''); const operationHandler = async () => { try { resultsEditor.setValue(JSON.stringify({ message: 'Executing...' }, null, 2)); const result = await request.post('/api?schema', { query: operationEditor.getValue(), variables: loadYaml(variablesEditor.getValue()), }); resultsEditor.setValue(JSON.stringify(result, null, 2)); } catch (err) { if (err instanceof Error) { resultsEditor.setValue(err.toString()); } } }; executeOpButton.on('click', operationHandler); executeOpButton.on('touchend', operationHandler); const opAction: monaco.editor.IActionDescriptor = { id: 'graphql-run', label: 'Run Operation', contextMenuOrder: 0, contextMenuGroupId: 'graphql', keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter], run: operationHandler, }; operationEditor.addAction(opAction); variablesEditor.addAction(opAction); resultsEditor.addAction(opAction); createRoot(document.getElementById('docs')).render(); }); export default page;