Parcourir la source

docs: Enable embedded mode for GraphiqlPlugin

This will allow us to use GraphiQL in the Vendure docs. Relates to #3496
Michael Bromley il y a 8 mois
Parent
commit
2acfc2b285

+ 2 - 2
packages/graphiql-plugin/README.md

@@ -19,13 +19,13 @@ yarn add @vendure/graphiql-plugin
 Add the plugin to your Vendure config:
 
 ```typescript
-import { GraphiQLPlugin } from '@vendure/graphiql-plugin';
+import { GraphiqlPlugin } from '@vendure/graphiql-plugin';
 import { VendureConfig } from '@vendure/core';
 
 export const config: VendureConfig = {
     // ... other config
     plugins: [
-        GraphiQLPlugin.init({
+        GraphiqlPlugin.init({
             route: 'graphiql', // Optional, defaults to 'graphiql'
         }),
         // ... other plugins

+ 23 - 2
packages/graphiql-plugin/src/plugin.ts

@@ -26,18 +26,39 @@ import { GraphiqlPluginOptions } from './types';
  * ## Installation
  *
  * ```ts
- * import { GraphiQLPlugin } from '\@vendure/graphiql-plugin';
+ * import { GraphiqlPlugin } from '\@vendure/graphiql-plugin';
  *
  * const config: VendureConfig = {
  *   // Add an instance of the plugin to the plugins array
  *   plugins: [
- *     GraphiQLPlugin.init({
+ *     GraphiqlPlugin.init({
  *       route: 'graphiql', // Optional, defaults to 'graphiql'
  *     }),
  *   ],
  * };
  * ```
  *
+ * ## Custom API paths
+ *
+ * By default, the plugin automatically reads the Admin API and Shop API paths from your Vendure configuration.
+ *
+ * If you need to override these paths, you can specify them explicitly:
+ *
+ * ```typescript
+ * GraphiQLPlugin.init({
+ *     route: 'my-custom-route', // defaults to `graphiql`
+ * });
+ * ```
+ *
+ * ## Query parameters
+ *
+ * You can add the following query parameters to the GraphiQL URL:
+ *
+ * - `?query=...` - Pre-populate the query editor with a GraphQL query.
+ * - `?embeddedMode=true` - This renders the editor in embedded mode, which hides the header and
+ *    the API switcher. This is useful for embedding GraphiQL in other applications such as documentation.
+ *    In this mode, the editor also does not persist changes across reloads.
+ *
  * @docsCategory core plugins/GraphiqlPlugin
  */
 @VendurePlugin({

+ 15 - 4
packages/graphiql-plugin/src/ui/App.tsx

@@ -1,17 +1,27 @@
 import { createGraphiQLFetcher } from '@graphiql/toolkit';
 import { GraphiQL } from 'graphiql';
 import 'graphiql/graphiql.css';
+import './overrides.css';
 import React, { useCallback } from 'react';
+import { embeddedModeStorage } from './embedded-mode-storage';
 
 interface AppProps {
     apiType: 'admin' | 'shop';
 }
 
 const App: React.FC<AppProps> = ({ apiType }) => {
-    const { adminApiUrl, shopApiUrl } = window.GRAPHIQL_SETTINGS;
+    const { adminApiUrl, shopApiUrl } = window.GRAPHIQL_SETTINGS ?? {
+        adminApiUrl: 'http://localhost:3000/admin-api',
+        shopApiUrl: 'http://localhost:3000/shop-api',
+    };
     const apiUrl = apiType === 'admin' ? adminApiUrl : shopApiUrl;
     const apiName = apiType === 'admin' ? 'Admin API' : 'Shop API';
 
+    const params = new URLSearchParams(window.location.search);
+    const query = params.get('query') ?? undefined;
+    const embeddedMode = params.get('embeddedMode') === 'true';
+    const storage = embeddedMode ? embeddedModeStorage : undefined;
+
     const fetcher = useCallback(() => {
         return createGraphiQLFetcher({
             url: apiUrl,
@@ -30,7 +40,7 @@ const App: React.FC<AppProps> = ({ apiType }) => {
 
     return (
         <div className="graphiql-app">
-            <div className="vendure-header">
+            {!embeddedMode ? <div className="vendure-header">
                 <h1>Vendure GraphiQL - {apiName}</h1>
                 <div className="switch-api">
                     <span>Switch API:</span>
@@ -55,9 +65,10 @@ const App: React.FC<AppProps> = ({ apiType }) => {
                         Shop API
                     </a>
                 </div>
-            </div>
+            </div> : null}
             <div className="graphiql-wrapper">
-                <GraphiQL fetcher={fetcher()} defaultEditorToolsVisibility={true} />
+                <GraphiQL className={embeddedMode ? 'embedded-mode' : undefined} fetcher={fetcher()} storage={storage}
+                          defaultEditorToolsVisibility={embeddedMode ? false : true} query={query} />
             </div>
         </div>
     );

+ 22 - 0
packages/graphiql-plugin/src/ui/embedded-mode-storage.ts

@@ -0,0 +1,22 @@
+import { Storage } from '@graphiql/toolkit';
+
+/**
+ * A storage implementation that does nothing,
+ * because in embedded mode we don't want to
+ * persist anything.
+ */
+export const embeddedModeStorage: Storage = {
+    clear(): void {
+        /* empty */
+    },
+    getItem(key: string): string | null {
+        return null;
+    },
+    length: 0,
+    removeItem(key: string): void {
+        return;
+    },
+    setItem(key: string, value: string) {
+        return;
+    },
+};

+ 15 - 0
packages/graphiql-plugin/src/ui/overrides.css

@@ -0,0 +1,15 @@
+.graphiql-container.embedded-mode {
+    --sidebar-width: 0px;
+    border-radius: var(--border-radius-12);
+}
+.graphiql-container.embedded-mode .graphiql-sidebar {
+    padding: 0;
+}
+
+.graphiql-container.embedded-mode .graphiql-sessions {
+    margin: 0;
+}
+
+.graphiql-container.embedded-mode .graphiql-logo {
+    display: none;
+}

+ 2 - 1
packages/graphiql-plugin/tsconfig.json

@@ -6,6 +6,7 @@
         "noLib": false,
         "skipLibCheck": true,
         "sourceMap": true,
-        "lib": ["dom"]
+        "lib": ["dom"],
+        "jsx": "react-jsx"
     }
 }