mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 09:57:41 +03:00 
			
		
		
		
	Improved graphene playground with router query params
This commit is contained in:
		
							parent
							
								
									3c308b90fa
								
							
						
					
					
						commit
						18b66bd8a2
					
				| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
    "copy-webpack-plugin": "^0.2.0",
 | 
					    "copy-webpack-plugin": "^0.2.0",
 | 
				
			||||||
    "es6-promise": "^3.0.2",
 | 
					    "es6-promise": "^3.0.2",
 | 
				
			||||||
    "extract-text-webpack-plugin": "^0.9.1",
 | 
					    "extract-text-webpack-plugin": "^0.9.1",
 | 
				
			||||||
    "gatsby": "^0.7.2",
 | 
					    "gatsby": "^0.7.3",
 | 
				
			||||||
    "graphiql": "^0.4.2",
 | 
					    "graphiql": "^0.4.2",
 | 
				
			||||||
    "graphql": "^0.4.13",
 | 
					    "graphql": "^0.4.13",
 | 
				
			||||||
    "jeet": "^6.1.2",
 | 
					    "jeet": "^6.1.2",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										234
									
								
								docs/playground/GraphenePlayground.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								docs/playground/GraphenePlayground.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,234 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import ReactDOM from 'react-dom';
 | 
				
			||||||
 | 
					import { RouteHandler, Link, State } from 'react-router';
 | 
				
			||||||
 | 
					import CodeMirror from 'codemirror';
 | 
				
			||||||
 | 
					import { graphql } from 'graphql';
 | 
				
			||||||
 | 
					import GraphiQL from 'graphiql';
 | 
				
			||||||
 | 
					import schema from './schema';
 | 
				
			||||||
 | 
					import pypyjs_vm from 'pypyjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'codemirror/mode/python/python';
 | 
				
			||||||
 | 
					import 'codemirror/addon/lint/lint';
 | 
				
			||||||
 | 
					import '../css/playground.styl';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (typeof PUBLIC_PATH === "undefined") {
 | 
				
			||||||
 | 
					  var PUBLIC_PATH = '';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pypyjs_vm.rootURL = `${PUBLIC_PATH}/playground/lib/`;
 | 
				
			||||||
 | 
					pypyjs_vm.cacheKey = 'graphene';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CodeMirror.registerHelper('lint', 'python', function (text, options, editor) {
 | 
				
			||||||
 | 
					  return (options.errors || []).map((error) => {
 | 
				
			||||||
 | 
					    var tokens = editor.getLineTokens(error.line - 1);
 | 
				
			||||||
 | 
					    tokens = tokens.filter((token, pos) => {
 | 
				
			||||||
 | 
					      return !!token.type || token.string.trim().length > 0;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (!tokens) return [];
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      message: `${error.name}: ${error.message}`,
 | 
				
			||||||
 | 
					      severity: 'error',
 | 
				
			||||||
 | 
					      type: 'syntax',
 | 
				
			||||||
 | 
					      from: CodeMirror.Pos(error.line - 1, tokens[0].start),
 | 
				
			||||||
 | 
					      to: CodeMirror.Pos(error.line - 1, tokens[tokens.length-1].end),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function graphQLFetcher(graphQLParams) {
 | 
				
			||||||
 | 
					  return graphql(schema, graphQLParams.query);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var default_interpreter;
 | 
				
			||||||
 | 
					class Playground extends React.Component {
 | 
				
			||||||
 | 
					  constructor() {
 | 
				
			||||||
 | 
					    super();
 | 
				
			||||||
 | 
					    this.state = {pypyjs: false, stdout: '', response:''};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  stdout() {
 | 
				
			||||||
 | 
					    console.log('stdout', arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  componentDidMount() {
 | 
				
			||||||
 | 
					    if (default_interpreter) {
 | 
				
			||||||
 | 
					      this.pypy_interpreter = default_interpreter;
 | 
				
			||||||
 | 
					      this.pypy_interpreter.stdout = this.stdout.bind(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      this.pypy_interpreter = new pypyjs_vm({
 | 
				
			||||||
 | 
					        stdin: function(){},
 | 
				
			||||||
 | 
					        stdout: this.stdout.bind(this),
 | 
				
			||||||
 | 
					        stderr: function(){},
 | 
				
			||||||
 | 
					        rootURL: `${PUBLIC_PATH}/playground/lib/`
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      default_interpreter = this.pypy_interpreter;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.pypyjs = this.pypy_interpreter.ready().then(() => {
 | 
				
			||||||
 | 
					      return this.pypy_interpreter.exec(`
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					import js
 | 
				
			||||||
 | 
					from collections import OrderedDict
 | 
				
			||||||
 | 
					from graphql.core.execution.executor import Executor
 | 
				
			||||||
 | 
					from graphql.core.execution.middlewares.sync import SynchronousExecutionMiddleware
 | 
				
			||||||
 | 
					from graphql.core.error import GraphQLError, format_error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_wrapped(f):
 | 
				
			||||||
 | 
					    if hasattr(f, 'func_closure') and f.func_closure:
 | 
				
			||||||
 | 
					        return get_wrapped(f.func_closure[0].cell_contents)
 | 
				
			||||||
 | 
					    return f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrackResolver(SynchronousExecutionMiddleware):
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def run_resolve_fn(resolver, original_resolver):
 | 
				
			||||||
 | 
					        if resolver.func.__module__ == '__main__':
 | 
				
			||||||
 | 
					            line = get_wrapped(resolver.func).resolver.func_code.co_firstlineno
 | 
				
			||||||
 | 
					            js.globals.markLine(line-3)
 | 
				
			||||||
 | 
					        return SynchronousExecutionMiddleware.run_resolve_fn(resolver, original_resolver)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__graphene_executor = Executor([TrackResolver()], map_type=OrderedDict)
 | 
				
			||||||
 | 
					`);
 | 
				
			||||||
 | 
					    }).then(() => {
 | 
				
			||||||
 | 
					      this.createSchema(this.props.initialSchema);
 | 
				
			||||||
 | 
					    }).then(() => {
 | 
				
			||||||
 | 
					      this.setState({pypyjs: true, response:'"Execute the query for see the results"'});
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    window.markLine = (lineNo) => {
 | 
				
			||||||
 | 
					      this.markLine(lineNo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.editor = CodeMirror(ReactDOM.findDOMNode(this.refs.schemaCode), {
 | 
				
			||||||
 | 
					      value: this.props.initialSchema,
 | 
				
			||||||
 | 
					      mode:  "python",
 | 
				
			||||||
 | 
					      theme: "graphene",
 | 
				
			||||||
 | 
					      lineNumbers: true,
 | 
				
			||||||
 | 
					      tabSize: 4,
 | 
				
			||||||
 | 
					      indentUnit: 4,
 | 
				
			||||||
 | 
					      gutters: ["CodeMirror-linenumbers", "breakpoints"],
 | 
				
			||||||
 | 
					      lint: {
 | 
				
			||||||
 | 
					        errors: [],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    this.editor.on("change", this.onEditorChange.bind(this));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  onEditorChange() {
 | 
				
			||||||
 | 
					    if (this.changeTimeout) {
 | 
				
			||||||
 | 
					      clearTimeout(this.changeTimeout);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.props.onEditSchema) {
 | 
				
			||||||
 | 
					      var value = this.editor.getValue();
 | 
				
			||||||
 | 
					      if (value != this.props.initialSchema) {
 | 
				
			||||||
 | 
					        this.props.onEditSchema(value)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.changeTimeout = setTimeout(() =>
 | 
				
			||||||
 | 
					      this.updateSchema()
 | 
				
			||||||
 | 
					    , 300);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  updateSchema() {
 | 
				
			||||||
 | 
					    this.createSchema(this.editor.getValue());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  createSchema(code) {
 | 
				
			||||||
 | 
					    if (this.previousCode == code) return;
 | 
				
			||||||
 | 
					    console.log('createSchema');
 | 
				
			||||||
 | 
					    this.validSchema = null;
 | 
				
			||||||
 | 
					    this.pypyjs.then(() => {
 | 
				
			||||||
 | 
					      return this.pypy_interpreter.exec(`
 | 
				
			||||||
 | 
					schema = None
 | 
				
			||||||
 | 
					${code}
 | 
				
			||||||
 | 
					assert schema, 'You have to define a schema'
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
					    }).then(() => {
 | 
				
			||||||
 | 
					      console.log('NO ERRORS');
 | 
				
			||||||
 | 
					      this.removeErrors();
 | 
				
			||||||
 | 
					      this.validSchema = true;
 | 
				
			||||||
 | 
					    }, (err) => {
 | 
				
			||||||
 | 
					      this.editor.options.lint.errors = [];
 | 
				
			||||||
 | 
					      console.log('ERRORS', err);
 | 
				
			||||||
 | 
					      this.logError(err);
 | 
				
			||||||
 | 
					      this.validSchema = false;
 | 
				
			||||||
 | 
					    }).then(this.updateGraphiQL.bind(this));
 | 
				
			||||||
 | 
					    this.previousCode = code;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  updateGraphiQL() {
 | 
				
			||||||
 | 
					    if (this.validSchema) {
 | 
				
			||||||
 | 
					      this.refs.graphiql.state.schema = null;
 | 
				
			||||||
 | 
					      this.refs.graphiql.componentDidMount();
 | 
				
			||||||
 | 
					      this.refs.graphiql.forceUpdate();
 | 
				
			||||||
 | 
					      this.refs.graphiql.refs.docExplorer.forceUpdate();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  logError(error) {
 | 
				
			||||||
 | 
					    var lines = error.trace.split('\n');
 | 
				
			||||||
 | 
					    var file_errors = lines.map((errorLine) => {
 | 
				
			||||||
 | 
					      return errorLine.match(/File "<string>", line (\d+)/);
 | 
				
			||||||
 | 
					    }).filter((x) => !! x);
 | 
				
			||||||
 | 
					    if (!file_errors.length) return;
 | 
				
			||||||
 | 
					    var line = parseInt(file_errors[file_errors.length-1][1]);
 | 
				
			||||||
 | 
					    error.line = line-2;
 | 
				
			||||||
 | 
					    if (error.name == "ImportError" && error.message == "No module named django") {
 | 
				
			||||||
 | 
					      error.message = "Django is not supported yet in Playground editor";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.editor.options.lint.errors.push(error);
 | 
				
			||||||
 | 
					    CodeMirror.signal(this.editor, 'change', this.editor);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  removeErrors() {
 | 
				
			||||||
 | 
					    this.editor.options.lint.errors = [];
 | 
				
			||||||
 | 
					    CodeMirror.signal(this.editor, 'change', this.editor);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  fetcher (graphQLParams) {
 | 
				
			||||||
 | 
					    if (!this.validSchema) {
 | 
				
			||||||
 | 
					      return graphQLFetcher(arguments);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.execute(graphQLParams.query);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  execute(query) {
 | 
				
			||||||
 | 
					    // console.log('execute', query);
 | 
				
			||||||
 | 
					    return this.pypyjs.then(() => {
 | 
				
			||||||
 | 
					      var x = `
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					result = __graphene_executor.execute(schema.schema, '''${query}''')
 | 
				
			||||||
 | 
					result_dict = {};
 | 
				
			||||||
 | 
					if result.errors:
 | 
				
			||||||
 | 
					  result_dict['errors'] = [format_error(e) for e in result.errors]
 | 
				
			||||||
 | 
					if result.data:
 | 
				
			||||||
 | 
					  result_dict['data'] = result.data
 | 
				
			||||||
 | 
					result_json = json.dumps(result_dict)
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					      return this.pypy_interpreter.exec(x)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ).then(() =>
 | 
				
			||||||
 | 
					      this.pypy_interpreter.get(`result_json`)
 | 
				
			||||||
 | 
					    ).then((data) => {
 | 
				
			||||||
 | 
					      var json_data = JSON.parse(data);
 | 
				
			||||||
 | 
					      return json_data;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  markLine(lineNo) {
 | 
				
			||||||
 | 
					    console.log(lineNo);
 | 
				
			||||||
 | 
					    var hlLine = this.editor.addLineClass(lineNo, "text", "activeline");
 | 
				
			||||||
 | 
					    // var mark = this.editor.markText({line: lineNo, ch: 0}, {line: lineNo, ch: 10}, {className: "called-function"});
 | 
				
			||||||
 | 
					    setTimeout(() => {
 | 
				
			||||||
 | 
					        this.editor.removeLineClass(lineNo, "text", "activeline");
 | 
				
			||||||
 | 
					    }, 1200);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div className="playground">
 | 
				
			||||||
 | 
					        {!this.state.pypyjs?<div className="loading" />:null}
 | 
				
			||||||
 | 
					        <div className="playground-schema">
 | 
				
			||||||
 | 
					          <header className="playground-schema-header">
 | 
				
			||||||
 | 
					            Schema
 | 
				
			||||||
 | 
					          </header>
 | 
				
			||||||
 | 
					          <div className="playground-schema-editor" ref="schemaCode" />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div className="playground-graphiql">
 | 
				
			||||||
 | 
					            <GraphiQL ref="graphiql" fetcher={this.fetcher.bind(this)} response={this.state.response} onEditQuery={this.props.onEditQuery} query={this.props.initialQuery}/>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = Playground;
 | 
				
			||||||
							
								
								
									
										4
									
								
								docs/playground/examples/hello.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								docs/playground/examples/hello.graphql
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					query {
 | 
				
			||||||
 | 
					  hello
 | 
				
			||||||
 | 
					  ping(to:"Peter")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								docs/playground/examples/hello.schema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								docs/playground/examples/hello.schema.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Query(graphene.ObjectType):
 | 
				
			||||||
 | 
					    hello = graphene.String()
 | 
				
			||||||
 | 
					    ping = graphene.String(to=graphene.String())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resolve_hello(self, args, info):
 | 
				
			||||||
 | 
					        return 'World'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resolve_ping(self, args, info):
 | 
				
			||||||
 | 
					        return 'Pinging {}'.format(args.get('to'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					schema = graphene.Schema(query=Query)
 | 
				
			||||||
| 
						 | 
					@ -60,13 +60,6 @@ if (typeof FunctionPromise === "undefined") {
 | 
				
			||||||
  throw "FunctionPromise object not found";
 | 
					  throw "FunctionPromise object not found";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Some extra goodies for nodejs.
 | 
					 | 
				
			||||||
if (typeof process !== 'undefined') {
 | 
					 | 
				
			||||||
  if (Object.prototype.toString.call(process) === '[object process]') {
 | 
					 | 
				
			||||||
    var fs = require("fs");
 | 
					 | 
				
			||||||
    var path = require("path");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create functions for handling default stdio streams.
 | 
					// Create functions for handling default stdio streams.
 | 
				
			||||||
// These will be shared by all VM instances by default.
 | 
					// These will be shared by all VM instances by default.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,258 +1,150 @@
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import ReactDOM from 'react-dom';
 | 
					import GraphenePlayground from './GraphenePlayground';
 | 
				
			||||||
import { RouteHandler, Link, State } from 'react-router';
 | 
					 | 
				
			||||||
import CodeMirror from 'codemirror';
 | 
					 | 
				
			||||||
import { graphql } from 'graphql';
 | 
					 | 
				
			||||||
import GraphiQL from 'graphiql';
 | 
					 | 
				
			||||||
import schema from './schema';
 | 
					 | 
				
			||||||
import pypyjs_vm from 'pypyjs';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'codemirror/mode/python/python';
 | 
					import _ from 'lodash';
 | 
				
			||||||
import 'codemirror/addon/lint/lint';
 | 
					 | 
				
			||||||
import '../css/playground.styl';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (typeof PUBLIC_PATH === "undefined") {
 | 
					const DEFAULT_CACHE_KEY = 'default';
 | 
				
			||||||
  var PUBLIC_PATH = '';
 | 
					
 | 
				
			||||||
 | 
					function filterObject(object, callback, context) {
 | 
				
			||||||
 | 
					  if (!object) {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  var result = {};
 | 
				
			||||||
 | 
					  for (var name in object) {
 | 
				
			||||||
 | 
					    if (hasOwnProperty.call(object, name) &&
 | 
				
			||||||
 | 
					        callback.call(context, object[name], name, object)) {
 | 
				
			||||||
 | 
					      result[name] = object[name];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pypyjs_vm.rootURL = `${PUBLIC_PATH}/playground/lib/`;
 | 
					 | 
				
			||||||
pypyjs_vm.cacheKey = 'graphene';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var baseCode = `import graphene
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Query(graphene.ObjectType):
 | 
					 | 
				
			||||||
    hello = graphene.String()
 | 
					 | 
				
			||||||
    ping = graphene.String(to=graphene.String())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def resolve_hello(self, args, info):
 | 
					 | 
				
			||||||
        return 'World'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def resolve_ping(self, args, info):
 | 
					 | 
				
			||||||
        return 'Pinging {}'.format(args.get('to'))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
schema = graphene.Schema(query=Query)
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CodeMirror.registerHelper('lint', 'python', function (text, options, editor) {
 | 
					 | 
				
			||||||
  return (options.errors || []).map((error) => {
 | 
					 | 
				
			||||||
    var tokens = editor.getLineTokens(error.line - 1);
 | 
					 | 
				
			||||||
    tokens = tokens.filter((token, pos) => {
 | 
					 | 
				
			||||||
      return !!token.type || token.string.trim().length > 0;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    if (!tokens) return [];
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      message: `${error.name}: ${error.message}`,
 | 
					 | 
				
			||||||
      severity: 'error',
 | 
					 | 
				
			||||||
      type: 'syntax',
 | 
					 | 
				
			||||||
      from: CodeMirror.Pos(error.line - 1, tokens[0].start),
 | 
					 | 
				
			||||||
      to: CodeMirror.Pos(error.line - 1, tokens[tokens.length-1].end),
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// function graphQLFetcher(graphQLParams) {
 | 
					 | 
				
			||||||
//   return fetch('http://swapi.graphene-python.org/graphql', {
 | 
					 | 
				
			||||||
//     method: 'post',
 | 
					 | 
				
			||||||
//     headers: { 'Content-Type': 'application/json' },
 | 
					 | 
				
			||||||
//     body: JSON.stringify(graphQLParams),
 | 
					 | 
				
			||||||
//   }).then(response => response.json());
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
function graphQLFetcher(graphQLParams) {
 | 
					 | 
				
			||||||
  return graphql(schema, graphQLParams.query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// var schema = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function syntaxError() {
 | 
					 | 
				
			||||||
  var marker = document.createElement("div");
 | 
					 | 
				
			||||||
  marker.style.color = "#822";
 | 
					 | 
				
			||||||
  marker.innerHTML = "●";
 | 
					 | 
				
			||||||
  return marker;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var default_interpreter;
 | 
					 | 
				
			||||||
class Playground extends React.Component {
 | 
					class Playground extends React.Component {
 | 
				
			||||||
  constructor() {
 | 
					  componentWillMount() {
 | 
				
			||||||
    super();
 | 
					    var sourceWasInjected = false;
 | 
				
			||||||
    this.state = {pypyjs: false, stdout: '', response:''};
 | 
					    var queryParams = this.context.router.getCurrentQuery();
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  stdout() {
 | 
					 | 
				
			||||||
    console.log('stdout', arguments);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  componentDidMount() {
 | 
					 | 
				
			||||||
    if (default_interpreter) {
 | 
					 | 
				
			||||||
      this.pypy_interpreter = default_interpreter;
 | 
					 | 
				
			||||||
      this.pypy_interpreter.stdout = this.stdout.bind(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      this.pypy_interpreter = new pypyjs_vm({
 | 
					 | 
				
			||||||
        stdin: function(){},
 | 
					 | 
				
			||||||
        stdout: this.stdout.bind(this),
 | 
					 | 
				
			||||||
        stderr: function(){},
 | 
					 | 
				
			||||||
        rootURL: `${PUBLIC_PATH}/playground/lib/`
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      default_interpreter = this.pypy_interpreter;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.pypyjs = this.pypy_interpreter.ready().then(() => {
 | 
					    var {
 | 
				
			||||||
      return this.pypy_interpreter.exec(`
 | 
					      cacheKey,
 | 
				
			||||||
import graphene
 | 
					      noCache,
 | 
				
			||||||
import js
 | 
					    } = queryParams;
 | 
				
			||||||
from collections import OrderedDict
 | 
					    noCache = (noCache !== undefined) && (noCache !== 'false');
 | 
				
			||||||
from graphql.core.execution.executor import Executor
 | 
					    if (noCache) {
 | 
				
			||||||
from graphql.core.execution.middlewares.sync import SynchronousExecutionMiddleware
 | 
					      cacheKey = undefined;
 | 
				
			||||||
from graphql.core.error import GraphQLError, format_error
 | 
					    } else if (!cacheKey) {
 | 
				
			||||||
 | 
					      cacheKey = DEFAULT_CACHE_KEY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.schemaCacheKey = `rp-${cacheKey}-schema`;
 | 
				
			||||||
 | 
					    this.queryCacheKey = `rp-${cacheKey}-query`;
 | 
				
			||||||
 | 
					    this.cacheKey = cacheKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_wrapped(f):
 | 
					    var initialSchema;
 | 
				
			||||||
    if hasattr(f, 'func_closure') and f.func_closure:
 | 
					    var initialQuery;
 | 
				
			||||||
        return get_wrapped(f.func_closure[0].cell_contents)
 | 
					    var storedSchema = localStorage.getItem(this.schemaCacheKey);
 | 
				
			||||||
    return f
 | 
					    var storedQuery = localStorage.getItem(this.queryCacheKey);
 | 
				
			||||||
 | 
					    if (noCache) {
 | 
				
			||||||
class TrackResolver(SynchronousExecutionMiddleware):
 | 
					      // Use case #1
 | 
				
			||||||
    @staticmethod
 | 
					      // We use the noCache param to force a playground to have certain contents.
 | 
				
			||||||
    def run_resolve_fn(resolver, original_resolver):
 | 
					      // eg. static example apps
 | 
				
			||||||
        if resolver.func.__module__ == '__main__':
 | 
					      initialSchema = queryParams.schema || '';
 | 
				
			||||||
            line = get_wrapped(resolver.func).resolver.func_code.co_firstlineno
 | 
					      initialQuery = queryParams.query || '';
 | 
				
			||||||
            js.globals.markLine(line-3)
 | 
					      sourceWasInjected = true;
 | 
				
			||||||
        return SynchronousExecutionMiddleware.run_resolve_fn(resolver, original_resolver)
 | 
					      queryParams = {};
 | 
				
			||||||
 | 
					    } else if (cacheKey === DEFAULT_CACHE_KEY) {
 | 
				
			||||||
__graphene_executor = Executor([TrackResolver()], map_type=OrderedDict)
 | 
					      // Use case #2
 | 
				
			||||||
`);
 | 
					      // The user loaded the playground without a custom cache key.
 | 
				
			||||||
    }).then(() => {
 | 
					      //   Allow code injection via the URL
 | 
				
			||||||
      this.createSchema(baseCode);
 | 
					      //   OR load code from localStorage
 | 
				
			||||||
    }).then(() => {
 | 
					      //   OR prime the playground with some default 'hello world' code
 | 
				
			||||||
      this.setState({pypyjs: true, response:'"Execute the query for see the results"'});
 | 
					      if (queryParams.schema != null) {
 | 
				
			||||||
    });
 | 
					        initialSchema = queryParams.schema;
 | 
				
			||||||
 | 
					        sourceWasInjected = queryParams.schema !== storedSchema;
 | 
				
			||||||
    window.markLine = (lineNo) => {
 | 
					      } else if (storedSchema != null) {
 | 
				
			||||||
      this.markLine(lineNo);
 | 
					        initialSchema = storedSchema;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        initialSchema = require('!raw!./examples/hello.schema.py');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (queryParams.query != null) {
 | 
				
			||||||
 | 
					        initialQuery = queryParams.query;
 | 
				
			||||||
 | 
					        sourceWasInjected = queryParams.query !== storedQuery;
 | 
				
			||||||
 | 
					      } else if (storedQuery != null) {
 | 
				
			||||||
 | 
					        initialQuery = storedQuery;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        initialQuery = require('!raw!./examples/hello.graphql');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      queryParams = filterObject({
 | 
				
			||||||
 | 
					        schema: queryParams.schema,
 | 
				
			||||||
 | 
					        query: queryParams.query,
 | 
				
			||||||
 | 
					      }, v => v !== undefined);
 | 
				
			||||||
 | 
					    } else if (cacheKey) {
 | 
				
			||||||
 | 
					      // Use case #3
 | 
				
			||||||
 | 
					      // Custom cache keys are useful in cases where you want to embed a playground
 | 
				
			||||||
 | 
					      // that features both custom boilerplate code AND saves the developer's
 | 
				
			||||||
 | 
					      // progress, without overwriting the default code cache. eg. a tutorial.
 | 
				
			||||||
 | 
					      if (storedSchema != null) {
 | 
				
			||||||
 | 
					        initialSchema = storedSchema;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        initialSchema = queryParams[`schema_${cacheKey}`];
 | 
				
			||||||
 | 
					        if (initialSchema != null) {
 | 
				
			||||||
 | 
					          sourceWasInjected = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (storedQuery != null) {
 | 
				
			||||||
 | 
					        initialQuery = storedQuery;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        initialQuery = queryParams[`query_${cacheKey}`];
 | 
				
			||||||
 | 
					        if (initialQuery != null) {
 | 
				
			||||||
 | 
					          sourceWasInjected = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      queryParams = {};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    this.changeParams(queryParams);
 | 
				
			||||||
    this.editor = CodeMirror(ReactDOM.findDOMNode(this.refs.schemaCode), {
 | 
					    this.state = {initialSchema, initialQuery, sourceWasInjected};
 | 
				
			||||||
      value: baseCode,
 | 
					    this.queryParams = queryParams;
 | 
				
			||||||
      mode:  "python",
 | 
					 | 
				
			||||||
      theme: "graphene",
 | 
					 | 
				
			||||||
      lineNumbers: true,
 | 
					 | 
				
			||||||
      tabSize: 4,
 | 
					 | 
				
			||||||
      indentUnit: 4,
 | 
					 | 
				
			||||||
      gutters: ["CodeMirror-linenumbers", "breakpoints"],
 | 
					 | 
				
			||||||
      lint: {
 | 
					 | 
				
			||||||
        errors: [],
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    this.editor.on("change", this.onEditorChange.bind(this));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  onEditorChange() {
 | 
					  shouldComponentUpdate() {
 | 
				
			||||||
    if (this.changeTimeout) {
 | 
					    return false;
 | 
				
			||||||
      clearTimeout(this.changeTimeout);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this.changeTimeout = setTimeout(() =>
 | 
					 | 
				
			||||||
      this.updateSchema()
 | 
					 | 
				
			||||||
    , 300);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  updateSchema() {
 | 
					  changeParams(queryParams) {
 | 
				
			||||||
    this.createSchema(this.editor.getValue());
 | 
					    var router = this.context.router;
 | 
				
			||||||
  }
 | 
					    var routeName = router.getCurrentPathname();
 | 
				
			||||||
  createSchema(code) {
 | 
					    var params = router.getCurrentParams();
 | 
				
			||||||
    if (this.previousCode == code) return;
 | 
					    queryParams = _.mapValues(queryParams, encodeURIComponent);
 | 
				
			||||||
    console.log('createSchema');
 | 
					    router.replaceWith(routeName, params, queryParams);
 | 
				
			||||||
    this.validSchema = null;
 | 
					 | 
				
			||||||
    this.pypyjs.then(() => {
 | 
					 | 
				
			||||||
      return this.pypy_interpreter.exec(`
 | 
					 | 
				
			||||||
schema = None
 | 
					 | 
				
			||||||
${code}
 | 
					 | 
				
			||||||
assert schema, 'You have to define a schema'
 | 
					 | 
				
			||||||
`)
 | 
					 | 
				
			||||||
    }).then(() => {
 | 
					 | 
				
			||||||
      console.log('NO ERRORS');
 | 
					 | 
				
			||||||
      this.removeErrors();
 | 
					 | 
				
			||||||
      this.validSchema = true;
 | 
					 | 
				
			||||||
    }, (err) => {
 | 
					 | 
				
			||||||
      this.editor.options.lint.errors = [];
 | 
					 | 
				
			||||||
      console.log('ERRORS', err);
 | 
					 | 
				
			||||||
      this.logError(err);
 | 
					 | 
				
			||||||
      this.validSchema = false;
 | 
					 | 
				
			||||||
      // this.editor.setGutterMarker(5, "breakpoints", syntaxError());
 | 
					 | 
				
			||||||
    }).then(this.updateGraphiQL.bind(this));
 | 
					 | 
				
			||||||
    this.previousCode = code;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  updateGraphiQL() {
 | 
					 | 
				
			||||||
    if (this.validSchema) {
 | 
					 | 
				
			||||||
      this.refs.graphiql.state.schema = null;
 | 
					 | 
				
			||||||
      this.refs.graphiql.componentDidMount();
 | 
					 | 
				
			||||||
      this.refs.graphiql.forceUpdate();
 | 
					 | 
				
			||||||
      this.refs.graphiql.refs.docExplorer.forceUpdate();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  logError(error) {
 | 
					 | 
				
			||||||
    var lines = error.trace.split('\n');
 | 
					 | 
				
			||||||
    var file_errors = lines.map((errorLine) => {
 | 
					 | 
				
			||||||
      return errorLine.match(/File "<string>", line (\d+)/);
 | 
					 | 
				
			||||||
    }).filter((x) => !! x);
 | 
					 | 
				
			||||||
    if (!file_errors.length) return;
 | 
					 | 
				
			||||||
    var line = parseInt(file_errors[file_errors.length-1][1]);
 | 
					 | 
				
			||||||
    error.line = line-2;
 | 
					 | 
				
			||||||
    if (error.name == "ImportError" && error.message == "No module named django") {
 | 
					 | 
				
			||||||
      error.message = "Django is not supported yet in Playground editor";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this.editor.options.lint.errors.push(error);
 | 
					 | 
				
			||||||
    CodeMirror.signal(this.editor, 'change', this.editor);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  removeErrors() {
 | 
					 | 
				
			||||||
    this.editor.options.lint.errors = [];
 | 
					 | 
				
			||||||
    CodeMirror.signal(this.editor, 'change', this.editor);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  fetcher (graphQLParams) {
 | 
					 | 
				
			||||||
    if (!this.validSchema) {
 | 
					 | 
				
			||||||
      return graphQLFetcher(arguments);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return this.execute(graphQLParams.query);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  execute(query) {
 | 
					 | 
				
			||||||
    // console.log('execute', query);
 | 
					 | 
				
			||||||
    return this.pypyjs.then(() => {
 | 
					 | 
				
			||||||
      var x = `
 | 
					 | 
				
			||||||
import json
 | 
					 | 
				
			||||||
result = __graphene_executor.execute(schema.schema, '''${query}''')
 | 
					 | 
				
			||||||
result_dict = {};
 | 
					 | 
				
			||||||
if result.errors:
 | 
					 | 
				
			||||||
  result_dict['errors'] = [format_error(e) for e in result.errors]
 | 
					 | 
				
			||||||
if result.data:
 | 
					 | 
				
			||||||
  result_dict['data'] = result.data
 | 
					 | 
				
			||||||
result_json = json.dumps(result_dict)
 | 
					 | 
				
			||||||
`;
 | 
					 | 
				
			||||||
      return this.pypy_interpreter.exec(x)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    ).then(() =>
 | 
					 | 
				
			||||||
      this.pypy_interpreter.get(`result_json`)
 | 
					 | 
				
			||||||
    ).then((data) => {
 | 
					 | 
				
			||||||
      var json_data = JSON.parse(data);
 | 
					 | 
				
			||||||
      return json_data;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  markLine(lineNo) {
 | 
					 | 
				
			||||||
    console.log(lineNo);
 | 
					 | 
				
			||||||
    var hlLine = this.editor.addLineClass(lineNo, "text", "activeline");
 | 
					 | 
				
			||||||
    // var mark = this.editor.markText({line: lineNo, ch: 0}, {line: lineNo, ch: 10}, {className: "called-function"});
 | 
					 | 
				
			||||||
    setTimeout(() => {
 | 
					 | 
				
			||||||
        this.editor.removeLineClass(lineNo, "text", "activeline");
 | 
					 | 
				
			||||||
    }, 1200);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  render() {
 | 
					  render() {
 | 
				
			||||||
    return (
 | 
					    return (<GraphenePlayground
 | 
				
			||||||
      <div className="playground">
 | 
					      initialSchema={this.state.initialSchema}
 | 
				
			||||||
        {!this.state.pypyjs?<div className="loading" />:null}
 | 
					      initialQuery={this.state.initialQuery}
 | 
				
			||||||
        <div className="playground-schema">
 | 
					      onEditSchema={(source) => {
 | 
				
			||||||
          <header className="playground-schema-header">
 | 
					        localStorage.setItem(this.schemaCacheKey, source);
 | 
				
			||||||
            Schema
 | 
					        if (this.cacheKey === DEFAULT_CACHE_KEY) {
 | 
				
			||||||
          </header>
 | 
					          this.queryParams.schema = source;
 | 
				
			||||||
          <div className="playground-schema-editor" ref="schemaCode" />
 | 
					          if (!this.queryParams.query) {
 | 
				
			||||||
        </div>
 | 
					            this.queryParams.query = this.state.initialQuery;
 | 
				
			||||||
        <div className="playground-graphiql">
 | 
					          }
 | 
				
			||||||
            <GraphiQL ref="graphiql" fetcher={this.fetcher.bind(this)} response={this.state.response} />
 | 
					          this.changeParams(this.queryParams);
 | 
				
			||||||
        </div>
 | 
					        }
 | 
				
			||||||
      </div>
 | 
					      }}
 | 
				
			||||||
    );
 | 
					      onEditQuery={(source) => {
 | 
				
			||||||
 | 
					        localStorage.setItem(this.queryCacheKey, source);
 | 
				
			||||||
 | 
					        if (this.cacheKey === DEFAULT_CACHE_KEY) {
 | 
				
			||||||
 | 
					          this.queryParams.query = source;
 | 
				
			||||||
 | 
					          if (!this.queryParams.schema) {
 | 
				
			||||||
 | 
					            this.queryParams.schema = this.state.initialSchema;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          this.changeParams(this.queryParams);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					    />);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Playground.contextTypes = {
 | 
				
			||||||
 | 
					  router: React.PropTypes.func
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = Playground;
 | 
					module.exports = Playground;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user