...
1 package playground
2
3 import (
4 "encoding/json"
5 "fmt"
6 "html/template"
7 "net/http"
8 )
9
10
11 var apolloSandboxPage = template.Must(template.New("ApolloSandbox").Parse(`<!doctype html>
12 <html>
13
14 <head>
15 <meta charset="utf-8">
16 <title>{{.title}}</title>
17 <meta name="viewport" content="width=device-width,initial-scale=1">
18 <link rel="icon" href="https://embeddable-sandbox.cdn.apollographql.com/_latest/public/assets/favicon-dark.png">
19 <style>
20 body {
21 margin: 0;
22 overflow: hidden;
23 }
24 </style>
25 </head>
26
27 <body>
28 <div style="width: 100vw; height: 100vh;" id='embedded-sandbox'></div>
29 <script rel="preload" as="script" crossorigin="anonymous" integrity="{{.mainSRI}}" type="text/javascript" src="https://embeddable-sandbox.cdn.apollographql.com/02e2da0fccbe0240ef03d2396d6c98559bab5b06/embeddable-sandbox.umd.production.min.js"></script>
30 <script>
31 {{- if .endpointIsAbsolute}}
32 const url = {{.endpoint}};
33 {{- else}}
34 const url = location.protocol + '//' + location.host + {{.endpoint}};
35 {{- end}}
36 const options = JSON.parse({{.options}})
37 new window.EmbeddedSandbox({
38 target: '#embedded-sandbox',
39 initialEndpoint: url,
40 persistExplorerState: true,
41 ...options,
42 });
43 </script>
44 </body>
45 </html>`))
46
47
48 func ApolloSandboxHandler(title, endpoint string, opts ...ApolloSandboxOption) http.HandlerFunc {
49 options := &apolloSandboxOptions{
50 HideCookieToggle: true,
51 InitialState: apolloSandboxInitialState{
52 IncludeCookies: true,
53 PollForSchemaUpdates: false,
54 },
55 }
56
57 for _, opt := range opts {
58 opt(options)
59 }
60
61 optionsBytes, err := json.Marshal(options)
62 if err != nil {
63 panic(fmt.Errorf("failed to marshal apollo sandbox options: %w", err))
64 }
65
66 return func(w http.ResponseWriter, r *http.Request) {
67 err := apolloSandboxPage.Execute(w, map[string]interface{}{
68 "title": title,
69 "endpoint": endpoint,
70 "endpointIsAbsolute": endpointHasScheme(endpoint),
71 "mainSRI": "sha256-pYhw/8TGkZxk960PMMpDtjhw9YtKXUzGv6XQQaMJSh8=",
72 "options": string(optionsBytes),
73 })
74 if err != nil {
75 panic(err)
76 }
77 }
78 }
79
80
81 type apolloSandboxOptions struct {
82 HideCookieToggle bool `json:"hideCookieToggle"`
83 EndpointIsEditable bool `json:"endpointIsEditable"`
84 InitialState apolloSandboxInitialState `json:"initialState,omitempty"`
85 }
86
87 type apolloSandboxInitialState struct {
88 IncludeCookies bool `json:"includeCookies"`
89 Document string `json:"document,omitempty"`
90 Variables map[string]any `json:"variables,omitempty"`
91 Headers map[string]any `json:"headers,omitempty"`
92 CollectionId string `json:"collectionId,omitempty"`
93 OperationId string `json:"operationId,omitempty"`
94 PollForSchemaUpdates bool `json:"pollForSchemaUpdates"`
95 SharedHeaders map[string]any `json:"sharedHeaders,omitempty"`
96 }
97
98 type ApolloSandboxOption func(options *apolloSandboxOptions)
99
100
101
102
103 func WithApolloSandboxHideCookieToggle(hideCookieToggle bool) ApolloSandboxOption {
104 return func(options *apolloSandboxOptions) {
105 options.HideCookieToggle = hideCookieToggle
106 }
107 }
108
109
110
111
112 func WithApolloSandboxEndpointIsEditable(endpointIsEditable bool) ApolloSandboxOption {
113 return func(options *apolloSandboxOptions) {
114 options.EndpointIsEditable = endpointIsEditable
115 }
116 }
117
118
119
120
121
122
123
124
125 func WithApolloSandboxInitialStateIncludeCookies(includeCookies bool) ApolloSandboxOption {
126 return func(options *apolloSandboxOptions) {
127 options.InitialState.IncludeCookies = includeCookies
128 }
129 }
130
131
132
133
134 func WithApolloSandboxInitialStateDocument(document string) ApolloSandboxOption {
135 return func(options *apolloSandboxOptions) {
136 options.InitialState.Document = document
137 }
138 }
139
140
141
142
143 func WithApolloSandboxInitialStateVariables(variables map[string]any) ApolloSandboxOption {
144 return func(options *apolloSandboxOptions) {
145 options.InitialState.Variables = variables
146 }
147 }
148
149
150
151
152 func WithApolloSandboxInitialStateHeaders(headers map[string]any) ApolloSandboxOption {
153 return func(options *apolloSandboxOptions) {
154 options.InitialState.Headers = headers
155 }
156 }
157
158
159
160
161 func WithApolloSandboxInitialStateCollectionIdAndOperationId(collectionId, operationId string) ApolloSandboxOption {
162 return func(options *apolloSandboxOptions) {
163 options.InitialState.CollectionId = collectionId
164 options.InitialState.OperationId = operationId
165 }
166 }
167
168
169
170
171 func WithApolloSandboxInitialStatePollForSchemaUpdates(pollForSchemaUpdates bool) ApolloSandboxOption {
172 return func(options *apolloSandboxOptions) {
173 options.InitialState.PollForSchemaUpdates = pollForSchemaUpdates
174 }
175 }
176
177
178
179
180
181
182 func WithApolloSandboxInitialStateSharedHeaders(sharedHeaders map[string]any) ApolloSandboxOption {
183 return func(options *apolloSandboxOptions) {
184 options.InitialState.SharedHeaders = sharedHeaders
185 }
186 }
187
View as plain text