diff --git a/graphcoolPlayground.go b/graphcoolPlayground.go index 43be574..97a3f3b 100644 --- a/graphcoolPlayground.go +++ b/graphcoolPlayground.go @@ -6,15 +6,59 @@ import ( "net/http" ) +type EditorCursorShape string + +const ( + Line EditorCursorShape = "line" + Block EditorCursorShape = "block" + Underline EditorCursorShape = "underline" +) + +type EditorTheme string + +const ( + Dark EditorTheme = "dark" + Light EditorTheme = "light" +) + +type RequestCredentials string + +const ( + Omit RequestCredentials = "omit" + Include RequestCredentials = "include" + SameOrigin RequestCredentials = "same-origin" +) + +type PlaygroundSettings struct { + EditorCursorShape EditorCursorShape `json:"editor.cursorShape,omitempty"` + EditorFontFamily string `json:"editor.fontFamily,omitempty"` + EditorFontSize float64 `json:"editor.fontSize,omitempty"` + EditorReuseHeaders bool `json:"editor.reuseHeaders,omitempty"` + EditorTheme EditorTheme `json:"editor.theme,omitempty"` + GeneralBetaUpdates bool `json:"general.betaUpdates,omitempty"` + PrettierPrintWidth float64 `json:"prettier.printWidth,omitempty"` + PrettierTabWidth float64 `json:"prettier.tabWidth,omitempty"` + PrettierUseTabs bool `json:"prettier.useTabs,omitempty"` + RequestCredentials RequestCredentials `json:"request.credentials,omitempty"` + RequestGlobalHeaders map[string]string `json:"request.globalHeaders,omitempty"` + SchemaPollingEnable bool `json:"schema.polling.enable,omitempty"` + SchemaPollingEndpointFilter string `json:"schema.polling.endpointFilter,omitempty"` + SchemaPollingInterval float64 `json:"schema.polling.interval,omitempty"` + SchemaDisableComments bool `json:"schema.disableComments,omitempty"` + TracingHideTracingResponse bool `json:"tracing.hideTracingResponse,omitempty"` + TracingTracingSupported bool `json:"tracing.tracingSupported,omitempty"` +} + type playgroundData struct { PlaygroundVersion string Endpoint string SubscriptionEndpoint string SetTitle bool + Settings *PlaygroundSettings } // renderPlayground renders the Playground GUI -func renderPlayground(w http.ResponseWriter, r *http.Request) { +func (h *Handler) renderPlayground(w http.ResponseWriter, r *http.Request) { t := template.New("Playground") t, err := t.Parse(graphcoolPlaygroundTemplate) if err != nil { @@ -22,12 +66,23 @@ func renderPlayground(w http.ResponseWriter, r *http.Request) { return } + var endpoint string + if h.playground.Endpoint != "" { + // in case the endpoint was explicitly set in the configuration use it here + endpoint = h.playground.Endpoint + } else { + // in case no endpoint was specified assume the graphql api is served under the request's url + endpoint = r.URL.Path + } + d := playgroundData{ PlaygroundVersion: graphcoolPlaygroundVersion, - Endpoint: r.URL.Path, + Endpoint: endpoint, SubscriptionEndpoint: fmt.Sprintf("ws://%v/subscriptions", r.Host), SetTitle: true, + Settings: h.playground.Settings, } + err = t.ExecuteTemplate(w, "index", d) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -99,7 +154,8 @@ add "&raw" to the end of the URL within a browser. // options as 'endpoint' belong here endpoint: {{ .Endpoint }}, subscriptionEndpoint: {{ .SubscriptionEndpoint }}, - setTitle: {{ .SetTitle }} + setTitle: {{ .SetTitle }}, + settings: {{ .Settings }} }) }) diff --git a/graphcoolPlayground_test.go b/graphcoolPlayground_test.go index 8d42fc4..0f87a75 100644 --- a/graphcoolPlayground_test.go +++ b/graphcoolPlayground_test.go @@ -62,9 +62,11 @@ func TestRenderPlayground(t *testing.T) { req.Header.Set("Accept", tc.accept) h := handler.New(&handler.Config{ - Schema: &testutil.StarWarsSchema, - GraphiQL: false, - Playground: tc.playgroundEnabled, + Schema: &testutil.StarWarsSchema, + GraphiQL: false, + Playground: &handler.PlaygroundConfig{ + Enabled: tc.playgroundEnabled, + }, }) rr := httptest.NewRecorder() diff --git a/handler.go b/handler.go index b9a647c..ae430f6 100644 --- a/handler.go +++ b/handler.go @@ -22,11 +22,17 @@ const ( type ResultCallbackFn func(ctx context.Context, params *graphql.Params, result *graphql.Result, responseBody []byte) +type PlaygroundConfig struct { + Enabled bool + Endpoint string + Settings *PlaygroundSettings +} + type Handler struct { Schema *graphql.Schema pretty bool graphiql bool - playground bool + playground *PlaygroundConfig rootObjectFn RootObjectFn resultCallbackFn ResultCallbackFn formatErrorFn func(err error) gqlerrors.FormattedError @@ -158,11 +164,11 @@ func (h *Handler) ContextHandler(ctx context.Context, w http.ResponseWriter, r * } } - if h.playground { + if h.playground != nil && h.playground.Enabled { acceptHeader := r.Header.Get("Accept") _, raw := r.URL.Query()["raw"] if !raw && !strings.Contains(acceptHeader, "application/json") && strings.Contains(acceptHeader, "text/html") { - renderPlayground(w, r) + h.renderPlayground(w, r) return } } @@ -200,7 +206,7 @@ type Config struct { Schema *graphql.Schema Pretty bool GraphiQL bool - Playground bool + Playground *PlaygroundConfig RootObjectFn RootObjectFn ResultCallbackFn ResultCallbackFn FormatErrorFn func(err error) gqlerrors.FormattedError @@ -208,10 +214,12 @@ type Config struct { func NewConfig() *Config { return &Config{ - Schema: nil, - Pretty: true, - GraphiQL: true, - Playground: false, + Schema: nil, + Pretty: true, + GraphiQL: true, + Playground: &PlaygroundConfig{ + Enabled: false, + }, } } diff --git a/handler_test.go b/handler_test.go index 4154b1a..92db1a5 100644 --- a/handler_test.go +++ b/handler_test.go @@ -245,7 +245,7 @@ func TestHandler_BasicQuery_WithFormatErrorFn(t *testing.T) { customFormattedError := gqlerrors.FormattedError{ Message: resolverError.Error(), Locations: []location.SourceLocation{ - location.SourceLocation{ + { Line: 1, Column: 2, },