+87
-34
api/src/graphql/handler.rs
+87
-34
api/src/graphql/handler.rs
···
66
66
Ok(schema.execute(req.into_inner()).await.into())
67
67
}
68
68
69
-
/// GraphQL Playground UI handler
70
-
/// Configures the playground with the slice URI in headers
69
+
/// GraphiQL UI handler
70
+
/// Configures GraphiQL with the slice URI in headers
71
71
pub async fn graphql_playground(
72
72
Query(params): Query<GraphQLParams>,
73
73
) -> Result<Html<String>, (StatusCode, String)> {
···
78
78
)
79
79
})?;
80
80
81
-
// Create playground with pre-configured headers
82
-
let playground_html = format!(
83
-
r#"<!DOCTYPE html>
84
-
<html>
85
-
<head>
86
-
<meta charset=utf-8 />
87
-
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
88
-
<title>Slices GraphQL Playground</title>
89
-
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/graphql-playground-react/build/static/css/index.css" />
90
-
<link rel="shortcut icon" href="//cdn.jsdelivr.net/npm/graphql-playground-react/build/favicon.png" />
91
-
<script src="//cdn.jsdelivr.net/npm/graphql-playground-react/build/static/js/middleware.js"></script>
92
-
</head>
93
-
<body>
94
-
<div id="root"></div>
95
-
<script>
96
-
window.addEventListener('load', function (event) {{
97
-
GraphQLPlayground.init(document.getElementById('root'), {{
98
-
endpoint: '/graphql',
99
-
settings: {{
100
-
'request.credentials': 'omit',
101
-
}},
102
-
tabs: [{{
103
-
endpoint: '/graphql',
104
-
headers: {{
105
-
'X-Slice-Uri': '{}'
106
-
}}
107
-
}}]
108
-
}})
109
-
}})
110
-
</script>
111
-
</body>
81
+
// Create GraphiQL with pre-configured headers using React 19 and modern ESM
82
+
let graphiql_html = format!(
83
+
r#"<!doctype html>
84
+
<html lang="en">
85
+
<head>
86
+
<meta charset="UTF-8" />
87
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
88
+
<title>Slices GraphiQL</title>
89
+
<style>
90
+
body {{
91
+
margin: 0;
92
+
}}
93
+
94
+
#graphiql {{
95
+
height: 100dvh;
96
+
}}
97
+
98
+
.loading {{
99
+
height: 100%;
100
+
display: flex;
101
+
align-items: center;
102
+
justify-content: center;
103
+
font-size: 4rem;
104
+
}}
105
+
</style>
106
+
<link rel="stylesheet" href="https://esm.sh/graphiql/dist/style.css" />
107
+
<link
108
+
rel="stylesheet"
109
+
href="https://esm.sh/@graphiql/plugin-explorer/dist/style.css"
110
+
/>
111
+
<script type="importmap">
112
+
{{
113
+
"imports": {{
114
+
"react": "https://esm.sh/react@19.1.0",
115
+
"react/": "https://esm.sh/react@19.1.0/",
116
+
117
+
"react-dom": "https://esm.sh/react-dom@19.1.0",
118
+
"react-dom/": "https://esm.sh/react-dom@19.1.0/",
119
+
120
+
"graphiql": "https://esm.sh/graphiql?standalone&external=react,react-dom,@graphiql/react,graphql",
121
+
"graphiql/": "https://esm.sh/graphiql/",
122
+
"@graphiql/plugin-explorer": "https://esm.sh/@graphiql/plugin-explorer?standalone&external=react,@graphiql/react,graphql",
123
+
"@graphiql/react": "https://esm.sh/@graphiql/react?standalone&external=react,react-dom,graphql,@graphiql/toolkit,@emotion/is-prop-valid",
124
+
125
+
"@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit?standalone&external=graphql",
126
+
"graphql": "https://esm.sh/graphql@16.11.0",
127
+
"@emotion/is-prop-valid": "data:text/javascript,"
128
+
}}
129
+
}}
130
+
</script>
131
+
<script type="module">
132
+
import React from 'react';
133
+
import ReactDOM from 'react-dom/client';
134
+
import {{ GraphiQL, HISTORY_PLUGIN }} from 'graphiql';
135
+
import {{ createGraphiQLFetcher }} from '@graphiql/toolkit';
136
+
import {{ explorerPlugin }} from '@graphiql/plugin-explorer';
137
+
import 'graphiql/setup-workers/esm.sh';
138
+
139
+
const fetcher = createGraphiQLFetcher({{
140
+
url: '/graphql',
141
+
headers: {{
142
+
'X-Slice-Uri': '{}'
143
+
}}
144
+
}});
145
+
const plugins = [HISTORY_PLUGIN, explorerPlugin()];
146
+
147
+
function App() {{
148
+
return React.createElement(GraphiQL, {{
149
+
fetcher,
150
+
plugins,
151
+
defaultEditorToolsVisibility: true,
152
+
}});
153
+
}}
154
+
155
+
const container = document.getElementById('graphiql');
156
+
const root = ReactDOM.createRoot(container);
157
+
root.render(React.createElement(App));
158
+
</script>
159
+
</head>
160
+
<body>
161
+
<div id="graphiql">
162
+
<div class="loading">Loading…</div>
163
+
</div>
164
+
</body>
112
165
</html>"#,
113
166
slice_uri.replace("'", "\\'").replace("\"", "\\\"")
114
167
);
115
168
116
-
Ok(Html(playground_html))
169
+
Ok(Html(graphiql_html))
117
170
}
118
171
119
172
/// Gets schema from cache or builds it if not cached