├── .gitignore ├── LICENSE ├── README.md ├── main.go └── static ├── css └── graphiql.css ├── index.html └── js ├── app-graphiql.js └── graphiql.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Hafiz Ismail 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # golang-graphql-playground 2 | An example Golang GraphQL server written with [graphql-go](https://github.com/graphql-go/graphql) and [graphql-relay-go](https://github.com/graphql-go/relay) 3 | 4 | Try the live demo: http://bit.ly/try-graphql-go 5 | 6 | ### Features 7 | - [graphql-go](https://github.com/graphql-go/graphql): Golang GraphQL library 8 | - [graphql-relay-go](https://github.com/graphql-go/relay): Golang GraphQL library helper to construct Relay-compliant server 9 | - [graphiql](https://github.com/graphql/graphiql): In-browser IDE to explore GraphQL queries 10 | - [Starwars GraphQL Schema](https://github.com/graphql-go/relay/tree/master/examples/starwars): GraphQL example schema defined with Relay capabilities with the help of `graphql-relay-go`. 11 | 12 | ### To run locally 13 | ```bash 14 | # `cd` to project directory 15 | $ cd 16 | 17 | # get all dependencies 18 | $ go get ./... 19 | 20 | # launch server 21 | $ go run main.go 22 | 23 | # Go to http://localhost:8080 on your browser 24 | ``` 25 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/graphql-go/handler" 7 | "github.com/graphql-go/relay/examples/starwars" 8 | ) 9 | 10 | func main() { 11 | 12 | // simplest relay-compliant graphql server HTTP handler 13 | // using Starwars schema from `graphql-relay-go` examples 14 | h := handler.New(&handler.Config{ 15 | Schema: &starwars.Schema, 16 | Pretty: true, 17 | }) 18 | 19 | // static file server to serve Graphiql in-browser editor 20 | fs := http.FileServer(http.Dir("static")) 21 | 22 | http.Handle("/graphql", h) 23 | http.Handle("/", fs) 24 | http.ListenAndServe(":8080", nil) 25 | } 26 | -------------------------------------------------------------------------------- /static/css/graphiql.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | overflow: hidden; 5 | width: 100%; 6 | } 7 | 8 | #graphiql-container { 9 | color: #141823; 10 | width: 100%; 11 | display: -webkit-flex; 12 | display: flex; 13 | -webkit-flex-direction: row; 14 | flex-direction: row; 15 | height: 100%; 16 | font-family: helvetica, arial, sans-serif; 17 | font-size: 14px; 18 | } 19 | 20 | #graphiql-container .editorWrap { 21 | display: -webkit-flex; 22 | display: flex; 23 | -webkit-flex-direction: column; 24 | flex-direction: column; 25 | -webkit-flex: 1; 26 | flex: 1; 27 | } 28 | 29 | #graphiql-container .title { 30 | font-size: 18px; 31 | } 32 | 33 | #graphiql-container .title em { 34 | font-family: georgia; 35 | font-size: 19px; 36 | } 37 | 38 | #graphiql-container .topBarWrap { 39 | display: -webkit-flex; 40 | display: flex; 41 | -webkit-flex-direction: row; 42 | flex-direction: row; 43 | } 44 | 45 | #graphiql-container .topBar { 46 | background: -webkit-linear-gradient(#f7f7f7, #e2e2e2); 47 | background: linear-gradient(#f7f7f7, #e2e2e2); 48 | border-bottom: solid 1px #d0d0d0; 49 | cursor: default; 50 | height: 34px; 51 | padding: 7px 14px 6px; 52 | -webkit-user-select: none; 53 | user-select: none; 54 | display: -webkit-flex; 55 | display: flex; 56 | -webkit-flex-direction: row; 57 | flex-direction: row; 58 | -webkit-flex: 1; 59 | flex: 1; 60 | -webkit-align-items: center; 61 | align-items: center; 62 | } 63 | 64 | #graphiql-container .docExplorerShow { 65 | background: -webkit-linear-gradient(#f7f7f7, #e2e2e2); 66 | background: linear-gradient(#f7f7f7, #e2e2e2); 67 | border: none; 68 | border-bottom: solid 1px #d0d0d0; 69 | border-left: solid 1px rgba(0, 0, 0, 0.2); 70 | color: #3B5998; 71 | cursor: pointer; 72 | font-size: 14px; 73 | outline: 0; 74 | padding: 2px 20px 0 18px; 75 | } 76 | 77 | #graphiql-container .docExplorerShow:before { 78 | border-left: 2px solid #3B5998; 79 | border-top: 2px solid #3B5998; 80 | content: ''; 81 | display: inline-block; 82 | height: 9px; 83 | margin: 0 3px -1px 0; 84 | position: relative; 85 | width: 9px; 86 | -webkit-transform: rotate(-45deg); 87 | transform: rotate(-45deg); 88 | } 89 | 90 | #graphiql-container .editorBar { 91 | display: -webkit-flex; 92 | display: flex; 93 | -webkit-flex-direction: row; 94 | flex-direction: row; 95 | -webkit-flex: 1; 96 | flex: 1; 97 | } 98 | 99 | #graphiql-container .queryWrap { 100 | display: -webkit-flex; 101 | display: flex; 102 | -webkit-flex-direction: column; 103 | flex-direction: column; 104 | -webkit-flex: 1; 105 | flex: 1; 106 | } 107 | 108 | #graphiql-container .resultWrap { 109 | display: -webkit-flex; 110 | display: flex; 111 | -webkit-flex-direction: column; 112 | flex-direction: column; 113 | -webkit-flex: 1; 114 | flex: 1; 115 | border-left: solid 1px #e0e0e0; 116 | } 117 | 118 | #graphiql-container .docExplorerWrap { 119 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.15); 120 | z-index: 3; 121 | position: relative; 122 | background: white; 123 | } 124 | 125 | #graphiql-container .docExplorerResizer { 126 | cursor: col-resize; 127 | height: 100%; 128 | left: -5px; 129 | position: absolute; 130 | top: 0; 131 | width: 10px; 132 | z-index: 10; 133 | } 134 | 135 | #graphiql-container .docExplorerHide { 136 | cursor: pointer; 137 | font-size: 18px; 138 | margin: -7px -8px -6px 0; 139 | padding: 18px 16px 15px 12px; 140 | } 141 | 142 | #graphiql-container .query-editor { 143 | -webkit-flex: 1; 144 | flex: 1; 145 | position: relative; 146 | } 147 | 148 | #graphiql-container .variable-editor { 149 | height: 30px; 150 | display: -webkit-flex; 151 | display: flex; 152 | -webkit-flex-direction: column; 153 | flex-direction: column; 154 | position: relative; 155 | } 156 | 157 | #graphiql-container .variable-editor-title { 158 | background: #eeeeee; 159 | border-bottom: solid 1px #d6d6d6; 160 | border-top: solid 1px #e0e0e0; 161 | color: #777; 162 | font-variant: small-caps; 163 | font-weight: bold; 164 | letter-spacing: 1px; 165 | line-height: 14px; 166 | padding: 6px 0 8px 43px; 167 | text-transform: lowercase; 168 | -webkit-user-select: none; 169 | user-select: none; 170 | } 171 | 172 | #graphiql-container .codemirrorWrap { 173 | -webkit-flex: 1; 174 | flex: 1; 175 | position: relative; 176 | } 177 | 178 | #graphiql-container .result-window { 179 | -webkit-flex: 1; 180 | flex: 1; 181 | position: relative; 182 | } 183 | 184 | #graphiql-container .footer { 185 | background: #f6f7f8; 186 | border-left: solid 1px #e0e0e0; 187 | border-top: solid 1px #e0e0e0; 188 | margin-left: 12px; 189 | position: relative; 190 | } 191 | 192 | #graphiql-container .footer:before { 193 | background: #eeeeee; 194 | bottom: 0; 195 | content: " "; 196 | left: -13px; 197 | position: absolute; 198 | top: -1px; 199 | width: 12px; 200 | } 201 | 202 | #graphiql-container .result-window .CodeMirror { 203 | background: #f6f7f8; 204 | } 205 | 206 | #graphiql-container .result-window .CodeMirror-gutters { 207 | background-color: #eeeeee; 208 | border-color: #e0e0e0; 209 | cursor: col-resize; 210 | } 211 | 212 | #graphiql-container .result-window .CodeMirror-foldgutter, 213 | #graphiql-container .result-window .CodeMirror-foldgutter-open:after, 214 | #graphiql-container .result-window .CodeMirror-foldgutter-folded:after { 215 | padding-left: 3px; 216 | } 217 | 218 | #graphiql-container .execute-button { 219 | background: -webkit-linear-gradient(#fdfdfd, #d2d3d6); 220 | background: linear-gradient(#fdfdfd, #d2d3d6); 221 | border: solid 1px rgba(0,0,0,0.25); 222 | border-radius: 17px; 223 | box-shadow: 0 1px 0 #fff; 224 | cursor: pointer; 225 | fill: #444; 226 | height: 34px; 227 | margin: 0 14px 0 28px; 228 | padding: 0; 229 | width: 34px; 230 | } 231 | 232 | #graphiql-container .execute-button:active { 233 | background: -webkit-linear-gradient(#e6e6e6, #c0c0c0); 234 | background: linear-gradient(#e6e6e6, #c0c0c0); 235 | box-shadow: 236 | 0 1px 0 #fff, 237 | inset 0 0 2px rgba(0, 0, 0, 0.3), 238 | inset 0 0 6px rgba(0, 0, 0, 0.2); 239 | } 240 | 241 | #graphiql-container .execute-button:focus { 242 | outline: 0; 243 | } 244 | 245 | #graphiql-container .CodeMirror-scroll { 246 | -webkit-overflow-scrolling: touch; 247 | } 248 | 249 | #graphiql-container .CodeMirror { 250 | position: absolute; 251 | top: 0; 252 | left: 0; 253 | height: 100%; 254 | width: 100%; 255 | font-size: 13px; 256 | font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace; 257 | color: #141823; 258 | } 259 | 260 | #graphiql-container .CodeMirror-lines { 261 | padding: 20px 0; 262 | } 263 | 264 | .CodeMirror-hint-information .content { 265 | -webkit-box-orient: vertical; 266 | color: #141823; 267 | display: -webkit-box; 268 | font-family: helvetica, arial, sans-serif; 269 | font-size: 13px; 270 | -webkit-line-clamp: 3; 271 | line-height: 16px; 272 | max-height: 48px; 273 | overflow: hidden; 274 | text-overflow: -o-ellipsis-lastline; 275 | } 276 | 277 | .CodeMirror-hint-information .content p:first-child { 278 | margin-top: 0; 279 | } 280 | 281 | .CodeMirror-hint-information .content p:last-child { 282 | margin-bottom: 0; 283 | } 284 | 285 | .CodeMirror-hint-information .infoType { 286 | color: #30a; 287 | margin-right: 0.5em; 288 | display: inline; 289 | cursor: pointer; 290 | } 291 | 292 | .autoInsertedLeaf.cm-property { 293 | padding: 2px 4px 1px; 294 | margin: -2px -4px -1px; 295 | border-radius: 2px; 296 | border-bottom: solid 2px rgba(255, 255, 255, 0); 297 | -webkit-animation-duration: 6s; 298 | -moz-animation-duration: 6s; 299 | animation-duration: 6s; 300 | -webkit-animation-name: insertionFade; 301 | -moz-animation-name: insertionFade; 302 | animation-name: insertionFade; 303 | } 304 | 305 | @-moz-keyframes insertionFade { 306 | from, to { 307 | background: rgba(255, 255, 255, 0); 308 | border-color: rgba(255, 255, 255, 0); 309 | } 310 | 311 | 15%, 85% { 312 | background: #fbffc9; 313 | border-color: #f0f3c0; 314 | } 315 | } 316 | 317 | @-webkit-keyframes insertionFade { 318 | from, to { 319 | background: rgba(255, 255, 255, 0); 320 | border-color: rgba(255, 255, 255, 0); 321 | } 322 | 323 | 15%, 85% { 324 | background: #fbffc9; 325 | border-color: #f0f3c0; 326 | } 327 | } 328 | 329 | @keyframes insertionFade { 330 | from, to { 331 | background: rgba(255, 255, 255, 0); 332 | border-color: rgba(255, 255, 255, 0); 333 | } 334 | 335 | 15%, 85% { 336 | background: #fbffc9; 337 | border-color: #f0f3c0; 338 | } 339 | } 340 | 341 | div.CodeMirror-lint-tooltip { 342 | background-color: white; 343 | color: #141823; 344 | border: 0; 345 | border-radius: 2px; 346 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 347 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 348 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 349 | font-family: helvetica, arial, sans-serif; 350 | font-size: 13px; 351 | line-height: 16px; 352 | padding: 6px 10px; 353 | opacity: 0; 354 | transition: opacity 0.15s; 355 | -moz-transition: opacity 0.15s; 356 | -webkit-transition: opacity 0.15s; 357 | -o-transition: opacity 0.15s; 358 | -ms-transition: opacity 0.15s; 359 | } 360 | 361 | div.CodeMirror-lint-message-error, div.CodeMirror-lint-message-warning { 362 | padding-left: 23px; 363 | } 364 | 365 | /* COLORS */ 366 | 367 | #graphiql-container .CodeMirror-foldmarker { 368 | border-radius: 4px; 369 | background: #08f; 370 | background: -webkit-linear-gradient(#43A8FF, #0F83E8); 371 | background: linear-gradient(#43A8FF, #0F83E8); 372 | 373 | color: white; 374 | -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1); 375 | -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1); 376 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1); 377 | font-family: arial; 378 | line-height: 0; 379 | padding: 0px 4px 1px; 380 | font-size: 12px; 381 | margin: 0 3px; 382 | text-shadow: 0 -1px rgba(0, 0, 0, 0.1); 383 | } 384 | 385 | #graphiql-container div.CodeMirror span.CodeMirror-matchingbracket { 386 | color: #555; 387 | text-decoration: underline; 388 | } 389 | 390 | #graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket { 391 | color: #f00; 392 | } 393 | 394 | /* Comment */ 395 | .cm-comment { 396 | color: #999; 397 | } 398 | 399 | /* Punctuation */ 400 | .cm-punctuation { 401 | color: #555; 402 | } 403 | 404 | /* Keyword */ 405 | .cm-keyword { 406 | color: #B11A04; 407 | } 408 | 409 | /* OperationName, FragmentName */ 410 | .cm-def { 411 | color: #D2054E; 412 | } 413 | 414 | /* FieldName */ 415 | .cm-property { 416 | color: #1F61A0; 417 | } 418 | 419 | /* FieldAlias */ 420 | .cm-qualifier { 421 | color: #1C92A9; 422 | } 423 | 424 | /* ArgumentName and ObjectFieldName */ 425 | .cm-attribute { 426 | color: #8B2BB9; 427 | } 428 | 429 | /* Number */ 430 | .cm-number { 431 | color: #2882F9; 432 | } 433 | 434 | /* String */ 435 | .cm-string { 436 | color: #D64292; 437 | } 438 | 439 | /* Boolean */ 440 | .cm-builtin { 441 | color: #D47509; 442 | } 443 | 444 | /* EnumValue */ 445 | .cm-string-2 { 446 | color: #0B7FC7; 447 | } 448 | 449 | /* Variable */ 450 | .cm-variable { 451 | color: #397D13; 452 | } 453 | 454 | /* Directive */ 455 | .cm-meta { 456 | color: #B33086; 457 | } 458 | 459 | /* Type */ 460 | .cm-atom { 461 | color: #CA9800; 462 | } 463 | /* BASICS */ 464 | 465 | .CodeMirror { 466 | /* Set height, width, borders, and global font properties here */ 467 | font-family: monospace; 468 | height: 300px; 469 | color: black; 470 | } 471 | 472 | /* PADDING */ 473 | 474 | .CodeMirror-lines { 475 | padding: 4px 0; /* Vertical padding around content */ 476 | } 477 | .CodeMirror pre { 478 | padding: 0 4px; /* Horizontal padding of content */ 479 | } 480 | 481 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 482 | background-color: white; /* The little square between H and V scrollbars */ 483 | } 484 | 485 | /* GUTTER */ 486 | 487 | .CodeMirror-gutters { 488 | border-right: 1px solid #ddd; 489 | background-color: #f7f7f7; 490 | white-space: nowrap; 491 | } 492 | .CodeMirror-linenumbers {} 493 | .CodeMirror-linenumber { 494 | padding: 0 3px 0 5px; 495 | min-width: 20px; 496 | text-align: right; 497 | color: #999; 498 | white-space: nowrap; 499 | } 500 | 501 | .CodeMirror-guttermarker { color: black; } 502 | .CodeMirror-guttermarker-subtle { color: #999; } 503 | 504 | /* CURSOR */ 505 | 506 | .CodeMirror div.CodeMirror-cursor { 507 | border-left: 1px solid black; 508 | } 509 | /* Shown when moving in bi-directional text */ 510 | .CodeMirror div.CodeMirror-secondarycursor { 511 | border-left: 1px solid silver; 512 | } 513 | .CodeMirror.cm-fat-cursor div.CodeMirror-cursor { 514 | width: auto; 515 | border: 0; 516 | background: #7e7; 517 | } 518 | .CodeMirror.cm-fat-cursor div.CodeMirror-cursors { 519 | z-index: 1; 520 | } 521 | 522 | .cm-animate-fat-cursor { 523 | width: auto; 524 | border: 0; 525 | -webkit-animation: blink 1.06s steps(1) infinite; 526 | -moz-animation: blink 1.06s steps(1) infinite; 527 | animation: blink 1.06s steps(1) infinite; 528 | } 529 | @-moz-keyframes blink { 530 | 0% { background: #7e7; } 531 | 50% { background: none; } 532 | 100% { background: #7e7; } 533 | } 534 | @-webkit-keyframes blink { 535 | 0% { background: #7e7; } 536 | 50% { background: none; } 537 | 100% { background: #7e7; } 538 | } 539 | @keyframes blink { 540 | 0% { background: #7e7; } 541 | 50% { background: none; } 542 | 100% { background: #7e7; } 543 | } 544 | 545 | /* Can style cursor different in overwrite (non-insert) mode */ 546 | div.CodeMirror-overwrite div.CodeMirror-cursor {} 547 | 548 | .cm-tab { display: inline-block; text-decoration: inherit; } 549 | 550 | .CodeMirror-ruler { 551 | border-left: 1px solid #ccc; 552 | position: absolute; 553 | } 554 | 555 | /* DEFAULT THEME */ 556 | 557 | .cm-s-default .cm-keyword {color: #708;} 558 | .cm-s-default .cm-atom {color: #219;} 559 | .cm-s-default .cm-number {color: #164;} 560 | .cm-s-default .cm-def {color: #00f;} 561 | .cm-s-default .cm-variable, 562 | .cm-s-default .cm-punctuation, 563 | .cm-s-default .cm-property, 564 | .cm-s-default .cm-operator {} 565 | .cm-s-default .cm-variable-2 {color: #05a;} 566 | .cm-s-default .cm-variable-3 {color: #085;} 567 | .cm-s-default .cm-comment {color: #a50;} 568 | .cm-s-default .cm-string {color: #a11;} 569 | .cm-s-default .cm-string-2 {color: #f50;} 570 | .cm-s-default .cm-meta {color: #555;} 571 | .cm-s-default .cm-qualifier {color: #555;} 572 | .cm-s-default .cm-builtin {color: #30a;} 573 | .cm-s-default .cm-bracket {color: #997;} 574 | .cm-s-default .cm-tag {color: #170;} 575 | .cm-s-default .cm-attribute {color: #00c;} 576 | .cm-s-default .cm-header {color: blue;} 577 | .cm-s-default .cm-quote {color: #090;} 578 | .cm-s-default .cm-hr {color: #999;} 579 | .cm-s-default .cm-link {color: #00c;} 580 | 581 | .cm-negative {color: #d44;} 582 | .cm-positive {color: #292;} 583 | .cm-header, .cm-strong {font-weight: bold;} 584 | .cm-em {font-style: italic;} 585 | .cm-link {text-decoration: underline;} 586 | .cm-strikethrough {text-decoration: line-through;} 587 | 588 | .cm-s-default .cm-error {color: #f00;} 589 | .cm-invalidchar {color: #f00;} 590 | 591 | .CodeMirror-composing { border-bottom: 2px solid; } 592 | 593 | /* Default styles for common addons */ 594 | 595 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 596 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 597 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 598 | .CodeMirror-activeline-background {background: #e8f2ff;} 599 | 600 | /* STOP */ 601 | 602 | /* The rest of this file contains styles related to the mechanics of 603 | the editor. You probably shouldn't touch them. */ 604 | 605 | .CodeMirror { 606 | position: relative; 607 | overflow: hidden; 608 | background: white; 609 | } 610 | 611 | .CodeMirror-scroll { 612 | overflow: scroll !important; /* Things will break if this is overridden */ 613 | /* 30px is the magic margin used to hide the element's real scrollbars */ 614 | /* See overflow: hidden in .CodeMirror */ 615 | margin-bottom: -30px; margin-right: -30px; 616 | padding-bottom: 30px; 617 | height: 100%; 618 | outline: none; /* Prevent dragging from highlighting the element */ 619 | position: relative; 620 | } 621 | .CodeMirror-sizer { 622 | position: relative; 623 | border-right: 30px solid transparent; 624 | } 625 | 626 | /* The fake, visible scrollbars. Used to force redraw during scrolling 627 | before actuall scrolling happens, thus preventing shaking and 628 | flickering artifacts. */ 629 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 630 | position: absolute; 631 | z-index: 6; 632 | display: none; 633 | } 634 | .CodeMirror-vscrollbar { 635 | right: 0; top: 0; 636 | overflow-x: hidden; 637 | overflow-y: scroll; 638 | } 639 | .CodeMirror-hscrollbar { 640 | bottom: 0; left: 0; 641 | overflow-y: hidden; 642 | overflow-x: scroll; 643 | } 644 | .CodeMirror-scrollbar-filler { 645 | right: 0; bottom: 0; 646 | } 647 | .CodeMirror-gutter-filler { 648 | left: 0; bottom: 0; 649 | } 650 | 651 | .CodeMirror-gutters { 652 | position: absolute; left: 0; top: 0; 653 | z-index: 3; 654 | } 655 | .CodeMirror-gutter { 656 | white-space: normal; 657 | height: 100%; 658 | display: inline-block; 659 | margin-bottom: -30px; 660 | /* Hack to make IE7 behave */ 661 | *zoom:1; 662 | *display:inline; 663 | } 664 | .CodeMirror-gutter-wrapper { 665 | position: absolute; 666 | z-index: 4; 667 | height: 100%; 668 | } 669 | .CodeMirror-gutter-elt { 670 | position: absolute; 671 | cursor: default; 672 | z-index: 4; 673 | } 674 | .CodeMirror-gutter-wrapper { 675 | -webkit-user-select: none; 676 | -moz-user-select: none; 677 | user-select: none; 678 | } 679 | 680 | .CodeMirror-lines { 681 | cursor: text; 682 | min-height: 1px; /* prevents collapsing before first draw */ 683 | } 684 | .CodeMirror pre { 685 | /* Reset some styles that the rest of the page might have set */ 686 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 687 | border-width: 0; 688 | background: transparent; 689 | font-family: inherit; 690 | font-size: inherit; 691 | margin: 0; 692 | white-space: pre; 693 | word-wrap: normal; 694 | line-height: inherit; 695 | color: inherit; 696 | z-index: 2; 697 | position: relative; 698 | overflow: visible; 699 | -webkit-tap-highlight-color: transparent; 700 | } 701 | .CodeMirror-wrap pre { 702 | word-wrap: break-word; 703 | white-space: pre-wrap; 704 | word-break: normal; 705 | } 706 | 707 | .CodeMirror-linebackground { 708 | position: absolute; 709 | left: 0; right: 0; top: 0; bottom: 0; 710 | z-index: 0; 711 | } 712 | 713 | .CodeMirror-linewidget { 714 | position: relative; 715 | z-index: 2; 716 | overflow: auto; 717 | } 718 | 719 | .CodeMirror-widget {} 720 | 721 | .CodeMirror-code { 722 | outline: none; 723 | } 724 | 725 | /* Force content-box sizing for the elements where we expect it */ 726 | .CodeMirror-scroll, 727 | .CodeMirror-sizer, 728 | .CodeMirror-gutter, 729 | .CodeMirror-gutters, 730 | .CodeMirror-linenumber { 731 | -moz-box-sizing: content-box; 732 | box-sizing: content-box; 733 | } 734 | 735 | .CodeMirror-measure { 736 | position: absolute; 737 | width: 100%; 738 | height: 0; 739 | overflow: hidden; 740 | visibility: hidden; 741 | } 742 | .CodeMirror-measure pre { position: static; } 743 | 744 | .CodeMirror div.CodeMirror-cursor { 745 | position: absolute; 746 | border-right: none; 747 | width: 0; 748 | } 749 | 750 | div.CodeMirror-cursors { 751 | visibility: hidden; 752 | position: relative; 753 | z-index: 3; 754 | } 755 | .CodeMirror-focused div.CodeMirror-cursors { 756 | visibility: visible; 757 | } 758 | 759 | .CodeMirror-selected { background: #d9d9d9; } 760 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 761 | .CodeMirror-crosshair { cursor: crosshair; } 762 | .CodeMirror ::selection { background: #d7d4f0; } 763 | .CodeMirror ::-moz-selection { background: #d7d4f0; } 764 | 765 | .cm-searching { 766 | background: #ffa; 767 | background: rgba(255, 255, 0, .4); 768 | } 769 | 770 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */ 771 | .CodeMirror span { *vertical-align: text-bottom; } 772 | 773 | /* Used to force a border model for a node */ 774 | .cm-force-border { padding-right: .1px; } 775 | 776 | @media print { 777 | /* Hide the cursor when printing */ 778 | .CodeMirror div.CodeMirror-cursors { 779 | visibility: hidden; 780 | } 781 | } 782 | 783 | /* See issue #2901 */ 784 | .cm-tab-wrap-hack:after { content: ''; } 785 | 786 | /* Help users use markselection to safely style text background */ 787 | span.CodeMirror-selectedtext { background: none; } 788 | #graphiql-container .doc-explorer { 789 | background: white; 790 | } 791 | 792 | #graphiql-container .doc-explorer-title-bar { 793 | cursor: default; 794 | display: -webkit-flex; 795 | display: flex; 796 | height: 34px; 797 | line-height: 14px; 798 | padding: 8px 8px 5px; 799 | position: relative; 800 | -webkit-user-select: none; 801 | user-select: none; 802 | } 803 | 804 | #graphiql-container .doc-explorer-title { 805 | padding: 10px 0 10px 10px; 806 | font-weight: bold; 807 | text-align: center; 808 | text-overflow: ellipsis; 809 | white-space: nowrap; 810 | overflow-x: hidden; 811 | -webkit-flex: 1; 812 | flex: 1; 813 | } 814 | 815 | #graphiql-container .doc-explorer-back { 816 | color: #3B5998; 817 | cursor: pointer; 818 | margin: -7px 0 -6px -8px; 819 | overflow-x: hidden; 820 | padding: 17px 12px 16px 16px; 821 | text-overflow: ellipsis; 822 | white-space: nowrap; 823 | } 824 | 825 | #graphiql-container .doc-explorer-back:before { 826 | border-left: 2px solid #3B5998; 827 | border-top: 2px solid #3B5998; 828 | content: ''; 829 | display: inline-block; 830 | height: 9px; 831 | margin: 0 3px -1px 0; 832 | position: relative; 833 | width: 9px; 834 | -webkit-transform: rotate(-45deg); 835 | transform: rotate(-45deg); 836 | } 837 | 838 | #graphiql-container .doc-explorer-rhs { 839 | position: relative; 840 | } 841 | 842 | #graphiql-container .doc-explorer-contents { 843 | position: relative; 844 | height: 100%; 845 | background-color: #ffffff; 846 | border-top: 1px solid #d6d6d6; 847 | padding: 20px 15px; 848 | overflow-y: auto; 849 | min-width: 300px; 850 | } 851 | 852 | #graphiql-container .doc-type-description p:first-child , 853 | #graphiql-container .doc-type-description blockquote:first-child { 854 | margin-top: 0; 855 | } 856 | 857 | #graphiql-container .doc-explorer-contents a { 858 | cursor: pointer; 859 | text-decoration: none; 860 | } 861 | 862 | #graphiql-container .doc-explorer-contents a:hover { 863 | text-decoration: underline; 864 | } 865 | 866 | #graphiql-container .doc-value-description { 867 | padding: 4px 0 8px 12px; 868 | } 869 | 870 | #graphiql-container .doc-category { 871 | margin: 20px 0; 872 | } 873 | 874 | #graphiql-container .doc-category-title { 875 | border-bottom: 1px solid #e0e0e0; 876 | color: #777; 877 | cursor: default; 878 | font-size: 14px; 879 | font-variant: small-caps; 880 | font-weight: bold; 881 | letter-spacing: 1px; 882 | margin-bottom: 10px; 883 | padding: 10px 0; 884 | -webkit-user-select: none; 885 | user-select: none; 886 | } 887 | 888 | #graphiql-container .doc-category-item { 889 | margin: 12px 0; 890 | color: #555; 891 | } 892 | 893 | #graphiql-container .keyword { 894 | color: #B11A04; 895 | } 896 | 897 | #graphiql-container .type-name { 898 | color: #CA9800; 899 | } 900 | 901 | #graphiql-container .field-name { 902 | color: #1F61A0; 903 | } 904 | 905 | #graphiql-container .value-name { 906 | color: #0B7FC7; 907 | } 908 | 909 | #graphiql-container .arg-name { 910 | color: #8B2BB9; 911 | } 912 | 913 | #graphiql-container .arg:after { 914 | content: ', '; 915 | } 916 | 917 | #graphiql-container .arg:last-child:after { 918 | content: ''; 919 | } 920 | .CodeMirror-foldmarker { 921 | color: blue; 922 | text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; 923 | font-family: arial; 924 | line-height: .3; 925 | cursor: pointer; 926 | } 927 | .CodeMirror-foldgutter { 928 | width: .7em; 929 | } 930 | .CodeMirror-foldgutter-open, 931 | .CodeMirror-foldgutter-folded { 932 | cursor: pointer; 933 | } 934 | .CodeMirror-foldgutter-open:after { 935 | content: "\25BE"; 936 | } 937 | .CodeMirror-foldgutter-folded:after { 938 | content: "\25B8"; 939 | } 940 | /* The lint marker gutter */ 941 | .CodeMirror-lint-markers { 942 | width: 16px; 943 | } 944 | 945 | .CodeMirror-lint-tooltip { 946 | background-color: infobackground; 947 | border: 1px solid black; 948 | border-radius: 4px 4px 4px 4px; 949 | color: infotext; 950 | font-family: monospace; 951 | font-size: 10pt; 952 | overflow: hidden; 953 | padding: 2px 5px; 954 | position: fixed; 955 | white-space: pre; 956 | white-space: pre-wrap; 957 | z-index: 100; 958 | max-width: 600px; 959 | opacity: 0; 960 | transition: opacity .4s; 961 | -moz-transition: opacity .4s; 962 | -webkit-transition: opacity .4s; 963 | -o-transition: opacity .4s; 964 | -ms-transition: opacity .4s; 965 | } 966 | 967 | .CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { 968 | background-position: left bottom; 969 | background-repeat: repeat-x; 970 | } 971 | 972 | .CodeMirror-lint-mark-error { 973 | background-image: 974 | url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==") 975 | ; 976 | } 977 | 978 | .CodeMirror-lint-mark-warning { 979 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); 980 | } 981 | 982 | .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { 983 | background-position: center center; 984 | background-repeat: no-repeat; 985 | cursor: pointer; 986 | display: inline-block; 987 | height: 16px; 988 | width: 16px; 989 | vertical-align: middle; 990 | position: relative; 991 | } 992 | 993 | .CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { 994 | padding-left: 18px; 995 | background-position: top left; 996 | background-repeat: no-repeat; 997 | } 998 | 999 | .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { 1000 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII="); 1001 | } 1002 | 1003 | .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { 1004 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII="); 1005 | } 1006 | 1007 | .CodeMirror-lint-marker-multiple { 1008 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC"); 1009 | background-repeat: no-repeat; 1010 | background-position: right bottom; 1011 | width: 100%; height: 100%; 1012 | } 1013 | .CodeMirror-hints { 1014 | background: white; 1015 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1016 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1017 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1018 | font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace; 1019 | font-size: 13px; 1020 | list-style: none; 1021 | margin: 0; 1022 | margin-left: -6px; 1023 | max-height: 14.5em; 1024 | overflow-y: auto; 1025 | overflow: hidden; 1026 | padding: 0; 1027 | position: absolute; 1028 | z-index: 10; 1029 | } 1030 | 1031 | .CodeMirror-hints-wrapper { 1032 | background: white; 1033 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1034 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1035 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1036 | margin-left: -6px; 1037 | position: absolute; 1038 | z-index: 10; 1039 | } 1040 | 1041 | .CodeMirror-hints-wrapper .CodeMirror-hints { 1042 | -webkit-box-shadow: none; 1043 | -moz-box-shadow: none; 1044 | box-shadow: none; 1045 | position: relative; 1046 | margin-left: 0; 1047 | z-index: 0; 1048 | } 1049 | 1050 | .CodeMirror-hint { 1051 | border-top: solid 1px #f7f7f7; 1052 | color: #141823; 1053 | cursor: pointer; 1054 | margin: 0; 1055 | max-width: 300px; 1056 | overflow: hidden; 1057 | padding: 2px 6px; 1058 | white-space: pre; 1059 | } 1060 | 1061 | li.CodeMirror-hint-active { 1062 | background-color: #08f; 1063 | border-top-color: white; 1064 | color: white; 1065 | } 1066 | 1067 | .CodeMirror-hint-information { 1068 | border-top: solid 1px #c0c0c0; 1069 | max-width: 300px; 1070 | padding: 4px 6px; 1071 | position: relative; 1072 | z-index: 1; 1073 | } 1074 | 1075 | .CodeMirror-hint-information:first-child { 1076 | border-bottom: solid 1px #c0c0c0; 1077 | border-top: none; 1078 | margin-bottom: -1px; 1079 | } 1080 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | golang-graphql-playground 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Loading... 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /static/js/app-graphiql.js: -------------------------------------------------------------------------------- 1 | $(function (global) { 2 | /** 3 | * This GraphiQL example illustrates how to use some of GraphiQL's props 4 | * in order to enable reading and updating the URL parameters, making 5 | * link sharing of queries a little bit easier. 6 | * 7 | * This is only one example of this kind of feature, GraphiQL exposes 8 | * various React params to enable interesting integrations. 9 | */ 10 | 11 | // Parse the search string to get url parameters. 12 | var search = window.location.search; 13 | var parameters = {}; 14 | search.substr(1).split('&').forEach(function (entry) { 15 | var eq = entry.indexOf('='); 16 | if (eq >= 0) { 17 | parameters[decodeURIComponent(entry.slice(0, eq))] = 18 | decodeURIComponent(entry.slice(eq + 1)); 19 | } 20 | }); 21 | 22 | // if variables was provided, try to format it. 23 | if (parameters.variables) { 24 | try { 25 | parameters.variables = 26 | JSON.stringify(JSON.parse(query.variables), null, 2); 27 | } catch (e) { 28 | // Do nothing 29 | } 30 | } 31 | 32 | // When the query and variables string is edited, update the URL bar so 33 | // that it can be easily shared 34 | function onEditQuery(newQuery) { 35 | parameters.query = newQuery; 36 | updateURL(); 37 | } 38 | 39 | function onEditVariables(newVariables) { 40 | parameters.variables = newVariables; 41 | updateURL(); 42 | } 43 | 44 | function updateURL() { 45 | var newSearch = '?' + Object.keys(parameters).map(function (key) { 46 | return encodeURIComponent(key) + '=' + 47 | encodeURIComponent(parameters[key]); 48 | }).join('&'); 49 | history.replaceState(null, null, newSearch); 50 | } 51 | 52 | // Defines a GraphQL fetcher using the fetch API. 53 | function graphQLFetcher(graphQLParams) { 54 | return fetch(window.location.origin + '/graphql', { 55 | method: 'post', 56 | headers: { 'Content-Type': 'application/json' }, 57 | body: JSON.stringify(graphQLParams) 58 | }).then(function (response) { 59 | return response.json() 60 | }); 61 | } 62 | 63 | global.renderGraphiql = function (elem) { 64 | // Render into the body. 65 | var toolbar = React.createElement(GraphiQL.Toolbar, {}, [ 66 | "Source available at ", 67 | React.createElement("a", { 68 | href: "https://github.com/sogko/golang-graphql-playground", 69 | }, "github") 70 | ]); 71 | React.render( 72 | React.createElement(GraphiQL, { 73 | fetcher: graphQLFetcher, 74 | query: parameters.query, 75 | variables: parameters.variables, 76 | onEditQuery: onEditQuery, 77 | onEditVariables: onEditVariables, 78 | defaultQuery: 79 | "# Welcome to GraphiQL\n" + 80 | "#\n" + 81 | "# GraphiQL is an in-browser IDE for writing, validating, and\n" + 82 | "# testing GraphQL queries.\n" + 83 | "#\n" + 84 | "# Type queries into this side of the screen, and you will\n" + 85 | "# see intelligent typeaheads aware of the current GraphQL type schema and\n" + 86 | "# live syntax and validation errors highlighted within the text.\n" + 87 | "#\n" + 88 | "# To bring up the auto-complete at any point, just press Ctrl-Space.\n" + 89 | "#\n" + 90 | "# Press the run button above, or Cmd-Enter to execute the query, and the result\n" + 91 | "# will appear in the pane to the right.\n\n" + 92 | "query RebelsShipsQuery {\n rebels {\n name\n ships(first: 1) {\n edges {\n" + 93 | " node {\n name \n }\n }\n }\n }\n}" 94 | }, toolbar), 95 | elem 96 | ); 97 | } 98 | }(window)) 99 | --------------------------------------------------------------------------------