From 300a5310224addef2bf85e94f70bb1722a7ce569 Mon Sep 17 00:00:00 2001 From: Pascal Senn Date: Sun, 19 Nov 2023 22:30:20 +0100 Subject: [PATCH 1/2] Adds more documentation for bcp --- website/docs.md | 86746 ++++++++++++++++ website/src/docs/bananacakepop/v2/apis.md | 18 - .../bananacakepop/v2/apis/client-registry.md | 175 + .../src/docs/bananacakepop/v2/apis/fusion.md | 205 + .../v2/{ => apis}/images/apis-0.png | Bin .../v2/{ => apis}/images/apis-1.png | Bin .../bananacakepop/v2/apis/images/apis-2.png | Bin 0 -> 72832 bytes .../bananacakepop/v2/apis/images/apis-3.png | Bin 0 -> 181043 bytes .../bananacakepop/v2/apis/images/apis-4.png | Bin 0 -> 181340 bytes .../bananacakepop/v2/apis/images/apis-5.png | Bin 0 -> 123926 bytes .../bananacakepop/v2/apis/images/apis-6.png | Bin 0 -> 254016 bytes .../v2/apis/images/client-registry-1.png | Bin 0 -> 64716 bytes .../v2/apis/images/client-registry-2.png | Bin 0 -> 46145 bytes .../bananacakepop/v2/apis/images/fusion-0.png | Bin 0 -> 199012 bytes .../bananacakepop/v2/apis/images/fusion-1.png | Bin 0 -> 62257 bytes .../bananacakepop/v2/apis/images/fusion-2.png | Bin 0 -> 36937 bytes .../bananacakepop/v2/apis/images/fusion-3.png | Bin 0 -> 73354 bytes .../bananacakepop/v2/apis/images/fusion-4.png | Bin 0 -> 32335 bytes .../bananacakepop/v2/apis/images/fusion-5.png | Bin 0 -> 37485 bytes .../v2/apis/images/operation-reporting-1.png | Bin 0 -> 84164 bytes .../v2/apis/images/operation-reporting-2.png | Bin 0 -> 99878 bytes .../v2/apis/images/schema-registry-0.png | Bin 0 -> 119926 bytes .../v2/apis/images/schema-registry-1.png | Bin 0 -> 59751 bytes .../v2/apis/images/schema-registry-2.png | Bin 0 -> 77457 bytes .../bananacakepop/v2/apis/images/stages-0.png | Bin 0 -> 94541 bytes .../bananacakepop/v2/apis/images/stages-1.png | Bin 0 -> 93788 bytes .../bananacakepop/v2/apis/images/stages-2.png | Bin 0 -> 97845 bytes .../bananacakepop/v2/apis/images/stages-3.png | Bin 0 -> 58527 bytes .../v2/apis/images/telemetry-0.png | Bin 0 -> 180375 bytes .../v2/apis/images/telemetry-1.png | Bin 0 -> 145952 bytes .../v2/apis/images/telemetry-10.png | Bin 0 -> 30448 bytes .../v2/apis/images/telemetry-11.png | Bin 0 -> 71413 bytes .../v2/apis/images/telemetry-12.png | Bin 0 -> 48736 bytes .../v2/apis/images/telemetry-13.png | Bin 0 -> 254160 bytes .../v2/apis/images/telemetry-2.png | Bin 0 -> 102774 bytes .../v2/apis/images/telemetry-3.png | Bin 0 -> 19266 bytes .../v2/apis/images/telemetry-4.png | Bin 0 -> 43297 bytes .../v2/apis/images/telemetry-5.png | Bin 0 -> 15612 bytes .../v2/apis/images/telemetry-6.png | Bin 0 -> 11703 bytes .../v2/apis/images/telemetry-7.png | Bin 0 -> 62167 bytes .../v2/apis/images/telemetry-8.png | Bin 0 -> 31284 bytes .../v2/apis/images/telemetry-9.png | Bin 0 -> 189575 bytes .../bananacakepop/v2/apis/open-telemetry.md | 134 + .../v2/apis/operation-reporting.md | 61 + .../docs/bananacakepop/v2/apis/overview.md | 35 + .../bananacakepop/v2/apis/schema-registry.md | 118 + .../src/docs/bananacakepop/v2/apis/stages.md | 59 + .../src/docs/bananacakepop/v2/bcp-services.md | 2 +- .../v2/schema-client-registry/index.md | 164 - website/src/docs/docs.json | 24 +- 50 files changed, 87553 insertions(+), 188 deletions(-) create mode 100644 website/docs.md delete mode 100644 website/src/docs/bananacakepop/v2/apis.md create mode 100644 website/src/docs/bananacakepop/v2/apis/client-registry.md create mode 100644 website/src/docs/bananacakepop/v2/apis/fusion.md rename website/src/docs/bananacakepop/v2/{ => apis}/images/apis-0.png (100%) rename website/src/docs/bananacakepop/v2/{ => apis}/images/apis-1.png (100%) create mode 100644 website/src/docs/bananacakepop/v2/apis/images/apis-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/apis-3.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/apis-4.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/apis-5.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/apis-6.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/client-registry-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/client-registry-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-0.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-3.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-4.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/fusion-5.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/operation-reporting-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/operation-reporting-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/schema-registry-0.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/schema-registry-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/schema-registry-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/stages-0.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/stages-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/stages-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/stages-3.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-0.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-1.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-10.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-11.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-12.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-13.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-2.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-3.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-4.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-5.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-6.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-7.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-8.png create mode 100644 website/src/docs/bananacakepop/v2/apis/images/telemetry-9.png create mode 100644 website/src/docs/bananacakepop/v2/apis/open-telemetry.md create mode 100644 website/src/docs/bananacakepop/v2/apis/operation-reporting.md create mode 100644 website/src/docs/bananacakepop/v2/apis/overview.md create mode 100644 website/src/docs/bananacakepop/v2/apis/schema-registry.md create mode 100644 website/src/docs/bananacakepop/v2/apis/stages.md delete mode 100644 website/src/docs/bananacakepop/v2/schema-client-registry/index.md diff --git a/website/docs.md b/website/docs.md new file mode 100644 index 00000000000..cc9ba6668b8 --- /dev/null +++ b/website/docs.md @@ -0,0 +1,86746 @@ +--- +title: "ChilliCream License 1.0" +description: "This is the license we use for our proprietary software like Banana Cake Pop." +--- + +# Acceptance + +By using the software, you agree to all of the terms and conditions below. + +# Copyright License + +The licensor grants you a non-exclusive, royalty-free, worldwide, +non-sublicensable, non-transferable license to use, copy, distribute, make +available, and prepare derivative works of the software, in each case subject to +the limitations and conditions below. + +# Limitations + +You may not move, change, disable, or circumvent the license key functionality +in the software, and you may not remove or obscure any functionality in the +software that is protected by the license key. + +You may not alter, remove, or obscure any licensing, copyright, or other notices +of the licensor in the software. Any use of the licensor’s trademarks is subject +to applicable law. + +## Patents + +The licensor grants you a license, under any patent claims the licensor can +license, or becomes able to license, to make, have made, use, sell, offer for +sale, import and have imported the software, in each case subject to the +limitations and conditions in this license. This license does not cover any +patent claims that you cause to be infringed by modifications or additions to +the software. If you or your company make any written claim that the software +infringes or contributes to infringement of any patent, your patent license for +the software granted under these terms ends immediately. If your company makes +such a claim, your patent license ends immediately for work on behalf of your +company. + +# Notices + +You must ensure that anyone who gets a copy of any part of the software from you +also gets a copy of these terms. + +If you modify the software, you must include in any modified copies of the +software prominent notices stating that you have modified the software. + +# No Other Rights + +These terms do not imply any licenses other than those expressly granted in +these terms. + +# Termination + +If you use the software in violation of these terms, such use is not licensed, +and your licenses will automatically terminate. If the licensor provides you +with a notice of your violation, and you cease all violation of this license no +later than 30 days after you receive that notice, your licenses will be +reinstated retroactively. However, if you violate these terms after such +reinstatement, any additional violation of these terms will cause your licenses +to terminate automatically and permanently. + +# No Liability + +_As far as the law allows, the software comes as is, without any warranty or +condition, and the licensor will not be liable to you for any damages arising +out of these terms or the use or nature of the software, under any kind of +legal claim._ + +# Definitions + +The **licensor** is the entity offering these terms, and the **software** is the +software the licensor makes available under these terms, including any portion +of it. + +**you** refers to the individual or entity agreeing to these terms. + +**your company** is any legal entity, sole proprietorship, or other kind of +organization that you work for, plus all organizations that have control over, +are under the control of, or are under common control with that +organization. **control** means ownership of substantially all the assets of an +entity, or the power to direct its management and policies by vote, contract, or +otherwise. Control can be direct or indirect. + +**your licenses** are all the licenses granted to you for the software under +these terms. + +**use** means anything you do with the software requiring one of your licenses. + +**trademark** means trademarks, service marks, and similar rights. +--- +title: Environments +--- + +Environment variable provide a mechanism for reusing specific values across multiple documents. These variables are defined as key-value pairs. + +Frequently used data, like URLs, tokens, and credentials, are commonly centrally managed as environment variable. +By doing so, these values can be referenced in your documents and changed in a single location for all you documents. You can also quickly switch between different values for different environments. + +For instance, you might store your API key as an environment variable, allowing it to be used universally in all your documents. +If the API key changes, you can just update the environment variable without having to manually alter each document. + +You can define multiple environments for a single workspace corresponding to various contexts or project stages (e.g., development, testing, production). The environments can be switched in the status bar. + +When you have different project stages such as such as development (`https://serivce1.dev.company.com`), testing (`https://serivce1.test.company.com`), and production (`https://serivce1.prod.company.com`), you can for example set up the dynamic part of the url as a variable URL and incorporate it in all your urls (`https://serivce1.{{subdomain}}.company.com`). +By switching the active environment in Banana Cake Pop, the base URL will update automatically, streamlining your workflow. +Similarly, identifiers such as client ID and client secret can be defined as environment variable, which make it convenient to work with. + +# Creating Environments +![Screenshot showing the environment](images/env-0.png) +To create a new environment, follow these steps: +1. Click on the environment icon on the left side of your screen. +2. Click the Plus icon to create a new environment. +3. Enter a name for the environment. + +# Rename Environments +![Screenshot showing the environment](images/env-1.png) +You can rename by right-clicking on the environment and selecting the 'Rename' option. + +# Specifying Variables +![Screenshot showing the environment](images/env-2.png) + +To open the environment variable editor, click on the environment you would like to edit. + +1. **Enabled**: If an environment variable is disabled, it will not be used in requests. This state is not synchronized with the server and is only local to the client. This way you can temporarily disable an environment variable without other users being affected. +2. **Name**: The name of the environment variable. This name will be used to reference the variable in your documents. e.g. `{{ClientId}}`, `{{ClientSecret}}` `{{Subdomain}}` +3. **Value**: The value of the environment variable. This value will be substituted in your documents when the environment variable is referenced. +4. **Secret**: If an environment variable is marked as secret, it will be shown as a password field within the Banana Cake Pop interface. This feature is designed to help prevent accidental exposure of the value. Please note that marking a value as secret does not mean it is encrypted; it is simply visually obscured in the user interface. +5. **Apply**: Clicking the 'Apply' button will save the environment variables. + + +# Switching Environments +![Screenshot showing the environment](images/env-3.png) +To switch environments, click on the environment name in the status bar. A dropdown menu will appear, listing all available environments. +After selecting an environment, the environment variables of the selected environment will be active and applied to all documents. + +# Using Variables +![Screenshot showing the environment](images/env-4.png) +Once you have defined an environment variable, you can reference it in your documents by using the following syntax: `{{variable_name}}`. +Environment variable can be employed in a variety of places within Banana Cake Pop, such as URLs, GraphQL Variables, and Connection Settings. When a request is executed, any referenced environment variable will be substituted with their respective values. +--- +title: "Organizations" +--- +This guide will walk you through the features and functionalities of BCP Organizations, a structure designed to help teams and individuals work efficiently and effectively on GraphQL related services. + +# What is an Organization + An organization typically represents an entire entity or a larger unit within an entity. Each organization can host multiple workspaces, allowing further categorization and organization of resources. A workspace might correspond to a specific project, a specific team within the organization, or a group of related APIs. + +Each BCP user has a personal organization. This is a private space for individual work or for projects that are not associated with any team or company organization. The personal organization is not visible to other users, is created by default and cannot be deleted. + +# Creating an Organization + +BCP allows for multiple organizations under one account. To add a new organization, navigate to the organization switcher in the status bar and click on the "Add Organization" button. + +![Screenshot showing the "Add Organization" button in the organization switcher](images/create-0.png) + +You will be redirected to the management portal. Here you can create a new organization by clicking the 'Create' button. + +![Picture showing the create button in the management portal](images/create-1.png) + +Each organization has a unique name and a display name which can be set during creation. +The name must be lowercase and may only include dashes (-) and underscores (_). + +![Screenshot of the create organization screen](images/create-2.png) + +# Managing Organizations +To manage your organizations, you have to open the management portal. + +![Screenshot showing the manage button in the organization switcher](images/manage-0.png) + +In the client app, you can do this by clicking Manage Organizations' and then 'Manage' on the organization that you like to manage. + +You can also navigate to [here](https://identity.chillicream.com/Organizations) to open the management portal and press 'Manage' on the organization that you like to manage. + + +# Switching Organizations +In Banana Cake Pop, you can be signed into multiple organizations at the same time and switch between them in the status bar. The organization switcher also allows you to create new organizations. + +![Screenshot showing the organization switcher in the status bar](images/switch-0.png) + +# Managing Members + +![Screenshot showing the invite user button and the process](images/members-0.png) + +1. The count of members and the number of seats available in your subscription are displayed in the management overview section. (members/total seats) + +2. This list show all the members of the organization and their role. + +3. Members can be invited to join an organization via email. In the management overview section, the 'Invite User' button allows you to send an invitation email containing a join link. + +4. Open invitations are displayed below. You can revoke an invitation by clicking on the 'Cancel' button. Once an invitation is expired, you can resend it by clicking on the 'Resend' button. + +## Joining an Organization +Invited users can join an organization in two ways: + +1. By clicking on the join link they received via email. +1. By opting to join during login on the sign in page. + +During sign-in, the user can select into which organization (join orgs or personal) they want to sign in. + +[Description of visualization: Screenshot showing the organization selection during sign-in] + +# User Roles and Access + +There are three distinct roles within an organization: Owner, Admin, and Collaborator. Each role carries specific permissions: + +| Role | Transfer Ownership | Delete Organization | Invite Users | View Subscriptions | Add Redirect URLs | +| ------------ | ------------------ | ------------------- | ------------ | ------------------ | ----------------- | +| Owner | Yes | Yes | Yes | Yes | Yes | +| Admin | No | No | Yes | Yes | Yes | +| Collaborator | No | No | No | No | No | + +- **Owner:** The owner can transfer ownership, delete the organization, and has all the permissions of an admin. Each organization can only have one owner. + +- **Admin:** Admins can invite users to the organization, view subscriptions, and add redirect URLs. They also have all the permissions of a collaborator. + +- **Collaborator:** Collaborators can log into the organization and leave the organization. They cannot add redirect URLs or invite new users. + +## Managing Permissions + +![Screenshot showing the invite user button and the process](images/members-1.png) + +You can manage the permissions of each member in the member list. + +1. Press the 'Edit' button on the right side of the member list to open the edit dialog. + +2. Select the desired role for the member. + +3. Press the 'Save' button to save the changes. + +4. You can also remove a member from the organization by clicking on the 'Revoke Access' button. + +# Transferring Ownership + +Ownership of the organization can be transferred to any existing member from the management portal. +In the danger zone section, click on the 'Transfer Ownership' button to open the transfer dialog. +![Screenshot showing the transfer ownership button and the process](images/danger-zone-0.png) + +# Redirect URLs + +Each time a user signs into an organization from a new origin, a redirect URL must be added to the organization. + +This security measure is designed to prevent your access tokens from being leaked to any arbitrary site hosted by third parties. + +If the user is a collaborator, they won't have the permissions to add the URL and will see an informative message. An admin, on the other hand, can directly add the URL to the organization. + +You can add the redirect URL in two ways: + +1. By signing in from the new origin. This will trigger a prompt to add the URL to the organization. + +![Screenshot showing the redirect URL prompt](images/redirect-0.png) + +2. By adding the URL directly from the management portal. + +![Screenshot showing the redirect URL prompt](images/redirect-1.png) + +In the portal you have more options to configure the allowed destinations. You can for example allow all localhost origins. Or disable the access to the web UI in the [cloud](https://eat.bananacakepop.com) + +1. Configure the allowed types of origins. +2. Add redirect Urls to the organization. +3. Remove redirect Urls from the organization. +--- +title: "Key Bindings" +--- + +This document provides a list of useful keyboard shortcuts for performing various actions in the application. + +A full list of all available keyboard shortcuts can be found clicking on the 'Keyboard Shortcuts' button in the status bar. +![Screenshot showing the keyboard shortcuts button in the status bar](images/key-bindings-0.png) + +# Mac + +## Application Shortcuts + +- Open New Document Tab: ⌘ + ⌥ + T +- Open New Document Tab from Clipboard: ⌘ + ⌥ + V +- Toggle Sidebar (Collapse/Expand): ⌘ + B +- Open Document Explorer: ⌘ + ⇧ + D +- Open History Explorer: ⌘ + ⇧ + H +- Open Settings: ⌘ + , +- Open Keyboard Shortcuts: ⌘ + K S + +## Document Shortcuts + +- Copy Document to Clipboard as cURL: ⌘ + ⌥ + C +- Close Document: ⌘ + ⌥ + W +- Save Document: ⌘ + S +- Save All Documents: ⌘ + ⌥ + S +- Format Document: ⇧ + ⌥ + F +- Toggle Operation (Run/Cancel): ⌘ + ⌥ + ⏎ +- Reload Schema: ⌘ + ⌥ + R +- Show Operation: ⌘ + ⇧ + O +- Show Schema: ⌘ + ⇧ + S + +# Windows + +## Application Shortcuts + +- Open New Document Tab: CTRL + ALT + T +- Open New Document Tab from Clipboard: Application Key + W (Windows key + W) +- Toggle Sidebar (Collapse/Expand): Application Key + B (Windows key + B) +- Open Document Explorer: CTRL + SHIFT + D +- Open History Explorer: CTRL + SHIFT + H +- Open Settings: Application Key + , (Windows key + comma) +- Open Keyboard Shortcuts: CTRL + K S + +## Document Shortcuts + +- Copy Document to Clipboard as cURL: CTRL + ALT + C +- Close Document: CTRL + ALT + W +- Save Document: CTRL + S +- Save All Documents: CTRL + ALT + S +- Format Document: SHIFT + ALT + F +- Toggle Operation (Run/Cancel): CTRL + ALT + Enter +- Reload Schema: CTRL + ALT + R +- Show Operation: CTRL + SHIFT + O +- Show Schema: CTRL + SHIFT + S + + +--- +title: Settings - Overview +--- + +![Image](images/settings-0.png) + +The Settings section provides users with various customization options. To access the settings, click on the cog icon located in the navigation bar on the left. + +Currently, the most significant setting available is the [Themes](/docs/bananacakepop/v2/settings/themes) feature. This allows users to personalize the appearance and visual style of the application. + +Please note that organization settings are exclusively accessible through the management portal. For more information about organization settings, refer to the [Organizations](/docs/bananacakepop/v2/organizations) documentation. + +--- +title: Settings - Themes +--- + +BCP offers a range of themes to customize the visual appearance of the application. These themes are available as light and dark themes, providing flexibility to suit different user preferences. + +![Theme Sync](./images/theme-0.png) + +By syncing the theme mode with your operating system (OS) settings, BCP can automatically adjust the theme based on your OS's light or dark mode. When you switch between light and dark mode on your OS, the theme in BCP will change accordingly. You can specify a dark theme and a light theme to be used when syncing with your OS settings. You can set a default theme for light mode by clicking on the left side of the theme, or set a default theme for dark mode by clicking on the right side of the theme. + +Here are the available themes: + +**Chilli Cream Blue** ![Chilli Cream Blue](./images/theme-1.png) + +**Chilli Cream White** ![Chilli Cream Light](./images/theme-2.png) + +**GitHub Dark** ![GitHub Dark](./images/theme-3.png) + +**GitHub Light** ![GitHub Light](./images/theme-4.png) + +**GitHub High Contrast Dark** ![GitHub High Contrast Dark](./images/theme-5.png) + +**GitHub High Contrast Light** ![GitHub High Contrast Light](./images/theme-6.png) + +--- +title: Apis +--- + +![Image](images/apis-6.png) +An API within the context of Banana Cake Pop, refers to an representation of your GraphQL Servers. +This representation is more than a mere conceptual framework — it serves as a practical tool that allows you to group your documents and share common settings like connection and authorization parameters among them. + +Additionally, an API forms the foundation for your client registry, schema registry setup and the telemetry. For more detailed information on these features, refer to the [Schema & Client Registry](/docs/bananacakepop/v2/schema-client-registry) guide and the [Telemetry](/docs/bananacakepop/v2/telemetry) guide. + + +# API Types +![Image](images/apis-2.png) + +## API Collection +![Image](images/apis-5.png) + +A compilation of GraphQL Documents with shared connection settings, enabling the grouping of documents for sharing with your t. + +## API Service +![Image](images/apis-3.png) +Incorporates all features of an API Collection and adds the capability to register your schema and clients in the schema registry. It also includes the use of telemetry for service monitoring. This type is ideal for representing a single deployment service or a subgraph. + +## API Gateway +![Image](images/apis-4.png) +Encompasses all the features of the API Service, along with the ability to publish and manage fusion configuration. Additionally, it supports distributed telemetry for comprehensive monitoring of your Gateway. + +# Creating an API +![Image](images/apis-1.png) + +Creating an API in Banana Cake Pop is a user-friendly process. There are three methods available: + +1. Click on the `Create Api` button located at the top of the document explorer toolbar. +2. Right-click within the document explorer and select `New Api` from the context menu. This creates a new API within the currently selected folder. Note: APIs can be organized in folders but cannot be nested within each other. +3. Choose the API Type. Options include `API Collection`, `API Service`, or `API Gateway`. +--- +title: "Schema & Client Registry" +--- + +![Image](images/schema-registry-0.png) +The schema registries is an essential tool for managing your GraphQL APIs. It provides a centralized location for storing, managing, and distributing your GraphQL schema definitions. + +With the schema registry, you can upload and store the schema of your API, making it accessible to your development team and other services. + +![Image](images/schema-registry-1.png) +The schema registry enables you to validate your schemas and clients against previous versions, ensuring that changes to your service do not break existing functionality, deeply integrated into your CI/CD pipeline. + +![Image](images/schema-registry-2.png) +They also maintain a version history, allowing you to track changes over time and revert to previous versions if necessary. + +Together with the client registry, you can maintain the integrity of your API and the services that rely on it, ensuring that they can evolve together without breaking. + +# Understanding Schemas + +In the context of GraphQL APIs, a schema is the blueprint that defines the shape of your data and specifies the capabilities of the API. It outlines the types of queries and mutations that can be executed against your API. + +A schema is more than just a technical specification; it is a contract between your API and your clients. By understanding and managing schema changes, you can ensure that this contract remains valid and that your API and clients can evolve together without breaking. + +Each stage of your API can have one active schema. This active schema is the one against which all requests are validated. + +## Schema Changes + +Changes to the schema can be categorized into three levels of severity based on their potential impact on the clients: safe, dangerous, and breaking. + +1. **Safe**: These changes don't affect the existing functionality. Examples include changes to descriptions or adding a new optional field to a type. Safe changes are generally backward compatible and don't require modifications to existing clients. + +Examples are: +- Adding a new field to an object type +- Adding a new optional argument to a field or directive +- Adding a new type + +2. **Dangerous**: These changes could potentially break existing functionality, depending on how your consumers interact with your API. An example of a dangerous change is adding a new member to an enum. If the client is not prepared to handle the new member, it might result in unexpected behavior. + +Examples are: +- Adding a new member to an enum +- Adding a new implementation to an interface + +3. **Breaking**: These changes will break existing functionality if the affected parts of the schema are being used by clients. Examples include changing the type of a field, adding a required field to an input type, removing a field, or adding a new required argument to a field or directive. + +Examples are: +- Removing a field from an object type +- Changing the type of a field +- Change a non-null field to a nullable field + +Breaking changes need to be managed with care to avoid disruptions to the service. It's important to ensure that all clients can handle these changes before they are introduced. This can be accomplished by versioning your clients and managing the lifecycle of client versions, as described in the section [Understanding Clients](#understanding-clients)]. + +## Extracting the Schema + +Extracting your GraphQL API's schema can be beneficial for various purposes, such as documentation, testing, and version control. Here are some methods to extract the schema: + +### Using Schema Export Command + +One of the simplest ways to extract the schema is by using the `schema export` command. This command exports your current schema into a specified output file. + +```shell +dotnet run -- schema export --output schema.graphql +``` + +For more details about this command and how to setup the command line extension, please refer to the [Command Line Extension documentation](/docs/hotchocolate/v13/server/command-line). + +### Utilizing Snapshot Testing + +If you have already established snapshot testing in your workflow, you can use it to extract the schema. Snapshot tests compare the current schema against a previously saved one. If the schemas differ, the test fails, ensuring unintentional schema changes are detected. + +Additionally, keeping a snapshot test in the repository aids in visualizing schema changes in pull requests. + +Here is a sample snapshot test using [Snapshooter](https://github.com/SwissLife-OSS/snapshooter): + +```csharp +[Fact] +public async Task Schema_Should_Not_Change() +{ + // Arrange + var executor = await new ServiceCollection() + .AddGraphQL() + .AddYourSchema() + .BuildRequestExecutorAsync(); + + // Act + var schema = executor.Schema.Print(); + + // Assert + schema.MatchSnapshot(); +} +``` +# Setting Up a Schema Registry + +To set up a schema registry, first, visit `eat.bananacakepop.com` and sign up for an account. Next, you'll need to download and install Barista, the .NET tool used to manage your schema registry. You can find more information about Barista in the [Barista Documentation](/docs/barista/v1). + +After installing Barista, create a new API either through the Bananacakepop UI or the CLI. In the UI, simply right-click the document explorer and select "New API." If you prefer using the CLI, ensure you're logged in with the command `barista login`, then create a new API with the command `barista api create`. With these steps complete, you are ready to start using the schema registry. + +To get the id of your API, use the command `barista api list`. This command will list all of your APIs, their names, and their ids. You will need the id of your API to perform most operations on the schema registry. + +# Integrating with Continuous Integration + +Integrating the schema registry and into your Continuous Integration/Continuous Deployment (CI/CD) pipeline maximizes their benefits. It ensures that the schemas in your API are always up-to-date and tested against potential breaking changes. + +To interact with the schema registry from the pipeline, you will need a API key. You can generate an api key directly with Barista using the command `barista api-key create`. Make sure to copy the key and store it in a secure location. The key will not be displayed again. + +You can then use the key to authenticate with the schema registry using the `--api-key` option. + +The schema and client registries work hand-in-hand to ensure the smooth functioning of your API. As you make changes to your schema, the schema registry helps manage these changes, preventing inadvertent breaking changes and preserving a history of your schemas. As you validate, upload, and publish new schemas, the client registry ensures that your clients remain compatible with these changes. + +## Understanding the Flow + +The general flow for the schema registry involves three main steps: validating the schema, uploading it to the registry, and publishing it. + +1. **Validate the Schema **: The first step takes place during your Pull Request (PR) build. Here, you validate the schema against the API using the `barista schema validate` command. This ensures that the schema is compatible with the API and will not break existing functionality. + +2. **Upload the Schema**: The second step takes place during your release build. Here, you upload the schema to the registry using the `barista schema upload` command. This command requires the `--tag` and `--api-id` options. The `--tag` option specifies the tag for the schema, and the `--api-id` option specifies the ID of the API to which you are uploading. This command create a new version of the schema with the specified tag. +The tag is a string that can be used to identify the schema. It can be any string, but it is recommended to use a version number, such as `v1` or `v2`; or a commit hash, such as `a1b2c3d4e5f6g7h8i9j0k1l2m3n`. The tag is used to identify the schema when publishing it. + +3. **Publish the Schema **: The third step takes place just before the release. Here, you publish the schema using the `barista schema publish` command. This command requires the `--tag` and `--api-id` options. The `--tag` option specifies the tag for the schema, and the `--api-id` option specifies the ID of the API to which you are uploading. This command publishes the schema with the specified tag, making it the active version for the specified API. +--- +title: Stages +--- + +# Working with Stages + +![Screenshot of the Stages overview](images/stages-0.png) +A stage represents an environment of your service, such as development, staging, or production. Each stage can have an active schema and multiple active client versions. + +Stages are integral to the lifecycle management of your GraphQL APIs. They enable you to manage different environments of your service, such as development, staging, or production. Each stage can have an active schema, multiple active client versions and telemetry reports. The active schema and client versions for a stage represent the current state of your API for that environment. + +Stages in your development workflow can be arranged sequentially to represent progression of changes. For instance, in a simple flow like Development (Dev) - Quality Assurance (QA) - Production (Prod), each stage comes "after" the preceding one. This signifies that changes propagate from "Dev" to "QA", and finally to "Prod" + +## Managing Stages + +If you do not have stages yet, you can go the the `Stages` tab and click on `Use default stages`. This will add a stage `Development` and a stage `Production` to your service. + +![Screenshot of the Stages overview](images/stages-1.png) +You can always edit these stages or add new ones by clicking the `Edit Stages` button. +![Screenshot of the Stages overview](images/stages-2.png) + +The stages dialog allows you to add and edit stages. You can also delete stages, but only if they are not used by any client or schema. + +Stages are edited in a yaml editor. The default configuration looks like this: + +```yaml +dev: # define a stage by adding the identifier as a root node + displayName: Development # add a display name to a stage +prod: + displayName: Production + conditions: + - after: dev # this defines the connection to other stages. production comes after development +``` + +You can easily create more complex stage configurations. For example, if you have two different QA stages, you can define them like this: + +```yaml +dev: + displayName: Development +qa1: + displayName: QA 1 + conditions: + - after: dev +qa2: + displayName: QA 2 + conditions: + - after: dev +prod: + displayName: Production + conditions: + - after: qa1 + - after: qa2 +``` + +This configuration defines two QA stages, `QA 1` and `QA 2`. Both of them come after the `Development` stage. The `Production` stage comes after both QA stages. It will result in the following stage order: + +![Image](images/stages-3.png) + + +--- +title: "Client Registry" +--- + +![Image](images/client-registry-1.png) +The client registries is an important tool for managing your GraphQL Clients. It provides a centralized location for clients and queries. + +You can use the client registry to manage your clients and their queries. It allows you to validate your queries against the schema, ensuring that all the operations defined by a client are compatible with the current schema. This validation step is critical to prevent the execution of invalid queries that might result in runtime errors. + +# Understanding Clients + +A client, in the context of a GraphQL API, is an entity that interacts with the API by defining and executing GraphQL operations. These operations are stored on the API as persisted queries. + +## What is a Persisted Query? + +A persisted query is a GraphQL operation that has been sent to the server, stored, and assigned an unique identifier (hash). Instead of sending the full text of a GraphQL operation to the server for execution, clients can send the hash of the operation, reducing the amount of data transmitted over the network. This practice is particularly beneficial for mobile clients operating in environments with limited network capacity. + +Persisted queries also add an extra layer of security as the server can be configured to only execute operations that have been previously stored, which prevents malicious queries. This is the cheapest and most effective way to secure your GraphQL API from potential attacks. + +![Image](images/client-registry-2.png) +Persisted queries can be inspected in the `Operations` tab. + +## The Role of the Client Registry + +The client registry plays a crucial role in managing these persisted queries. It is used to validate the queries against the schema, ensuring that all the operations defined by a client are compatible with the current schema. This validation step is critical to prevent the execution of invalid queries that might result in runtime errors. + +Additionally, the client registry is responsible for distributing the queries to the GraphQL server. It maintains a mapping of hashes to query keys, informing the server which hash corresponds to which query. This allows the server to efficiently look up and execute the appropriate query when it receives a request from a client. + +## Client Versions + +A client can have multiple versions, with each version containing a different set of persisted queries. This versioning system allows for incremental updates and changes to the client's operations without disrupting the existing functionality. As new versions are released, they can be validated and registered with the client registry, ensuring that they are compatible with the current schema and can be executed by the server. + +By managing client versions and persisted queries, the client registry helps maintain the integrity and smooth operation of your GraphQL API. It ensures that your clients and API can evolve together without breaking, contributing to a more robust and reliable system. + +The number of active client versions can vary depending on the nature of the client. For instance, a website usually has one active client version per stage. However, during deployment, you might temporarily have two active versions as the new version is phased in and the old version is phased out. + +On the other hand, for mobile clients, you often have multiple versions active simultaneously. This is because users may be using different versions of the app, and not all users update their apps at the same time. + +Once a client version is no longer in use, it reaches its end of life. At this point, you can unpublish the client version from the client registry. This will remove its persisted queries from distribution, and they will no longer be validated against the schema. + +## The Operations File + +In the context of GraphQL, the operations file is a structured file that holds a collection of persisted queries for a client. This file serves as a reference for the client to manage and execute specific operations against a GraphQL API. + +### Understanding the Format and Structure + +The operations file typically adopts the JSON format as used by Relay. It comprises key-value pairs, with each pair representing a unique persisted query. The key corresponds to a hash identifier for the query, and the value is the GraphQL query string. Below is an illustrative example of an operations file (`operations.json`): + +```json +{ + "913abc361487c481cf6015841c0eca22": "{ me { username } }", + "0e7cf2125e8eb711b470cc72c73ca77e": "{ me { id } }" + ... +} +``` + +### Compatibility with GraphQL Clients + +Several GraphQL clients have built-in support for this Relay-style operations file format. This compatibility allows for a standardized way of handling persisted queries across different clients. For more details on how various clients implement and work with persisted queries, consider referring to their respective documentation: + +- [StrawberryShake](https://chillicream.com/docs/strawberryshake/v13/performance/persisted-queries) +- [URQL](https://formidable.com/open-source/urql/docs/advanced/persisted-queries/) +- [Relay](https://relay.dev/docs/guides/persisted-queries/) + +# Setting Up a Client Registry + +To set up a client registry, first, visit `eat.bananacakepop.com` and sign up for an account. Next, you'll need to download and install Barista, the .NET tool used to manage your client registry. You can find more information about Barista in the [Barista Documentation](/docs/barista/v1). + +After installing Barista, create a new API either through the Bananacakepop UI or the CLI. In the UI, simply right-click the document explorer and select "New API." If you prefer using the CLI, ensure you're logged in with the command `barista login`, then create a new API with the command `barista api create`. With these steps complete, you are ready to start using the client registry. + +To get the id of your API, use the command `barista api list`. This command will list all of your APIs, their names, and their ids. You will need the id of your API to perform most operations on the schema registry. + +# Integrating with Continuous Integration + +Integrating the client registry into your Continuous Integration/Continuous Deployment (CI/CD) pipeline maximizes their benefits. It ensures that the clients in your API are always up-to-date and tested against potential breaking changes. + +The schema and client registries work hand-in-hand to ensure the smooth functioning of your API. As you make changes to your schema, the schema registry helps manage these changes, preventing inadvertent breaking changes and preserving a history of your schemas. As you validate, upload, and publish new schemas, the client registry ensures that your clients remain compatible with these changes. + +As you release new versions of your clients, the client registry helps manage these versions and the query documents associated with them. By working together, the schema and client registries help maintain the integrity of your API and the services that rely on it, ensuring that they can evolve together without breaking. + +## Understanding the Flow + +The general flow for the client registry involves three main steps: validating the client, uploading it to the registry, and publishing it. + +1. **Validate the Client**: The first step takes place during your Pull Request (PR) build. Here, you validate the client against the API using `barista client validate` command. This ensures that the client is compatible with the API and will not break existing functionality. + +2. **Upload the Client**: The second step takes place during your release build. Here, you upload the client to the registry using the `barista client upload` command. This command requires the `--tag` and `--api-id` options. The `--tag` option specifies the tag for the client, and the `--api-id` option specifies the ID of the API to which you are uploading. This command create a new version of the client with the specified tag. +The tag is a string that can be used to identify the client. It can be any string, but it is recommended to use a version number, such as `v1` or `v2`; or a commit hash, such as `a1b2c3d4e5f6g7h8i9j0k1l2m3n`. The tag is used to identify the client when publishing it. + +3. **Publish the Client **: The third step takes place just before the release. Here, you publish the client using the `barista client publish` commands. This command requires the `--tag` and `--api-id` options. The `--tag` option specifies the tag for the client, and the `--api-id` option specifies the ID of the API to which you are uploading. This command publishes the client with the specified tag, making it the active version for the specified API. +Banana Cake Pop can collect your open telemetry data and visualize your traces in the app. +With telemetry you can get a better understanding of how your application is performing and where you can improve it. +It helps you to understand which resolver is impacting your system the most, which queries are slow and which are fast. + +## Connect your service to the telemetry system + +## 1. Creating an API +All the reporting is done on a per API basis. An api represents one of your deployments. To monitor you services you need to create an API in banana cake pop. +The api needs to be from type "Api Service" or "Api Gateway". + +![Screenshot showing how to create an api In Banana Cake Pop](images/telemetry-1.png) + +## 2. Creating Stages + + + + +To connect your service to the telemetry system, you need to add the nuget package [`BananaCakePop.Services`](https://www.nuget.org/packages/BananaCakePop.Services/) to your project. + +``` +dotnet add package BananaCakePop.Services +``` + +Y + +--- +title: Workspaces +--- + +Workspaces are logical groups within an organization. A workspace could represent a team, a department, or a group of APIs that are related to each other. + +Each workspace has its own APIs, documents, API documents, environments, and more. You cannot share resources between workspaces. + +All members of an organization have default access to all workspaces and can edit the documents within them. In the future we will add more granular permissions to workspaces. + +In Banana Cake Pop, you can switch between workspaces using the status bar. + +![Screenshot showing the workspace and organization switcher in the status bar](images/workspace-0.png) + +At the moment, workspaces can only be created with barista. To create a new workspace, use the `barista workspace create` command. +You can find out more about barista [here](/docs/barista/v1). +--- +title: "Getting Started" +--- +Ready to explore the delicious features of Banana Cake Pop? In this getting started guide, we'll show you how to get up and running with Banana Cake Pop. +You have the option to choose between the convenience of the web app or the enhanced capabilities of the desktop version. We'll guide you through the setup process, so you can start enjoying all that Banana Cake Pop has to offer. + +Get ready to unlock the full potential of GraphQL with Banana Cake Pop. Choose your preferred option and follow the setup instructions to start enjoying the delicious features that Banana Cake Pop has to offer. +# Web App + +To begin your exploration, simply visit [eat.bananacakepop.com](https://eat.bananacakepop.com/) and experience the convenience of Banana Cake Pop's web-based version. This excellent starting point allows you to conveniently probe public GraphQL APIs and access most of the features that Banana Cake Pop offers. For an even more immersive experience, you can also install the web app as a Progressive Web App (PWA) on your device, providing a native-like experience. + +# Desktop App + +You can install the Banana Cake Pop App directly from our [download page](/products/bananacakepop). The download page provides DMG installers for macOS, x64 installers for Windows, and AppImage/Snap installers for Ubuntu and Ubuntu-based Linux distributions. Note that other Linux distributions or installer formats are currently unsupported. + +## Package Managers + +1. **Homebrew**: If you have [Homebrew](https://brew.sh) installed, use this command to install the app: + +```bash +brew install --cask banana-cake-pop +``` + +2. **Windows Package Manager**: For Windows 11 or a supported version of Windows 10 with the [Windows Package Manager](https://docs.microsoft.com/en-us/windows/package-manager/) installed, use: + ```powershell + winget install banana-cake-pop + ``` +3. **Scoop**: To install on Windows 7, 10, or 11 using [Scoop](https://scoop.sh/), run these commands: + ```powershell + scoop bucket add extras + scoop install banana-cake-pop + ``` + +Upon successful installation, follow the steps in the [Your first Query](#your-first-query) guide to execute your first GraphQL query using Banana Cake Pop. + +# Your First Query + +Lets guide you through the process of creating your first GraphQL query document using Banana Cake Pop. + +**Step 1:** Start the Banana Cake Pop application. You should see an interface similar to this: +![Banana Cake Pop - Start](./images/getting-started-0.png) + +**Step 2:** Click on the "Create Document" button to initiate the creation of your first query document. + +**Step 3:** You'll see a new document called 'untitled 1' generated. Simultaneously, the connection settings dialog box will pop up automatically. +Now, input the following link into the 'Schema Endpoint' field: https://workshop.chillicream.com/graphql +It should resemble this: +![Banana Cake Pop - Start](./images/getting-started-1.png) + + +**Step 4:** Click on the 'Apply' button. This will save your settings and close the dialog box. + +**Step 5:** At this point, your screen should look like this: +![Banana Cake Pop - Start](./images/getting-started-2.png) + +Take note of the following key elements: + +1. **Operation Pane:** This is where you will input your queries. +1. **Response Pane:** Here, you will see the output or response of your queries. +1. **Variables Pane:** This is where you can define variables for your query. + + +**Step 6:** The green circle at the top right next to the schema url indicates that you are connected to the GraphQL server and that your schema is fetched. You now have full intellisense for your queries. Copy the following GraphQL query and paste it into the 'Operations' editor area: + +```graphql +{ + sessionById(id: "U2Vzc2lvbgppMQ==") { + title + track { + name + } + startTime + endTime + } +} +``` + +**Step 7:** Click on the 'Run' button. You should see a response with data in the 'Response' area. Congratulations, you have completed a GraphQL query! + +**Step 8:** +Now, let's save your document. + +![Banana Cake Pop - Start](./images/getting-started-3.png) +Sign in to your account by clicking the 'Sign In' button on the user icon in the bottom left corner of the screen. If you don't have an account, you can create a new one. + +**Step 9:** Once you are signed in, save your document by clicking the 'Save' button next to the tabs. Your documents are now synced between your devices. + +![Banana Cake Pop - Start](./images/getting-started-4.png) + +**Step 10:** Great job! You've successfully created, executed, and saved your first GraphQL query using Banana Cake Pop. To learn more about the Banana Cake Pop User Interface, head over to the [Explore the UI](/docs/bananacakepop/v2/explore-the-ui) guide. + +Happy querying! +--- +title: Connect you API +--- + +BananaCake Pop can be smoothly integrated into your HotChocolate server, enabling utilization of the Persisted Query Storage found within the client registry. Your server will establish a connection with BananaCake Pop, retrieving persisted queries based on their unique hashes. Additional information on the client registry can be found [here](/docs/bananacakepop/v2/schema-client-registry). + +## Getting Started +To get started, follow these steps: + +1. Set up a client registry as instructed [here](/docs/bananacakepop/v2/schema-client-registry). + +2. Install the BananaCakePop package from NuGet using the following command: +```bash +dotnet add package BananaCakePop.Services +``` + +3. Configure your services as shown in the following code snippet: +```csharp +var builder = WebApplication.CreateBuilder(args); + +builder.Services + .AddGraphQLServer() + .AddQueryType() + .AddBananaCakePopServices(x => + { + x.ApiId = "VGhpcyBpcyBub3QgYSByZWFsIGFwaSBpZA=="; + x.ApiKey = "Tm9wZSwgdGhpcyBpcyBhbHNvIG5vIHJlYWwga2V5IDspIA=="; + x.Stage = "dev"; + }) + .UseOnlyPersistedQueriesAllowed() // optional + .UsePersistedQueryPipeline(); + +var app = builder.Build(); + +app.MapGraphQL(); + +app.Run(); +``` + +4. Retrieve the API id and API key from Barista using the `barista api list` and `barista api-key create` commands respectively. Instructions for these commands can be found [here](/docs/barista/v1). + +Congratulations! You have successfully integrated BananaCake Pop into your HotChocolate server. You can now publish new versions of your clients and your server will automatically retrieve the latest persisted queries. +--- +title: "Status Bar" +--- + +The status bar is a visual component located at the bottom of the application interface. It is divided into several sections, each providing valuable information to the user. + +![Status Bar](./images/status-1.png) + +1. **Connection Status:** This section indicates whether you are currently connected to the internet or not. When online, it means that any changes you make are being synchronized with the cloud. + +2. **User Info:** The section displays the email of the user who is currently signed in to the application. It helps you identify the user account associated with the active session. + +3. **Selected Organization:** In this section, you can see the name of the organization that is currently selected. Clicking on this section allows you to change the organization or add a new one. +![Status Bar](./images/status-4.png) + +4. **Selected Workspace:** This section shows the currently selected workspace within the chosen organization. By clicking here, you can easily switch to a different workspace, providing seamless navigation between different project environments. +![Status Bar](./images/status-5.png) + +5. **Environment:** This section displays the name of the currently selected environment. Clicking on this section allows you to switch to a different environment or create a new one. +![Status Bar](./images/status-6.png) + +6. **Workspace Synchronization Indicator:** The indicator in this section informs you whether the workspace is currently synchronizing. If synchronization is required or you want to manually trigger the process, you can click here to initiate synchronization. + +7. **Schema Up-to-Date:** This section provides an indicator to show whether the schema, which defines the structure and organization of data within the application, is up to date. + +8. **Keyboard Shortcuts Overlay:** By clicking on this section, you can display an overlay that shows a list of available keyboard shortcuts for efficient navigation and interaction with the application. +![Status Bar](./images/status-3.png) + +9. **Version Information:** This section displays relevant information about the version of the application you are currently using. It helps you identify the installed version and keep track of updates or changes that may be available. +![Status Bar](./images/status-2.png) +--- +title: "Explorer" +--- + +The Explorer is a versatile component utilized in various parts of the application. It serves as a navigation tool for traversing the workspace tree, enabling you to efficiently browse and manage their project's structure. Additionally, the Explorer uses icons to visually represent the type of each item within the workspace. + +![Explorer](./images/explorer-0.png) + +### 1. Quick Actions + +The Explorer offers a set of quick actions that allow users to perform common tasks swiftly. In the provided example, the quick actions enable the creation of a document, folder, or API with just a few clicks. + +### 2. Folder Node + +Folder nodes within the Explorer can be expanded or collapsed by clicking on the arrow associated with them. The icon accompanying each folder node indicates its item type, aiding in quick identification and differentiation. + +### 3. Context Menu + +Right-clicking on an item within the Explorer opens the context menu, which presents a list of actions that can be performed on the selected item. The context menu provides a convenient way to access item-specific operations and functions relevant to the current workspace context. +--- +title: Explore the UI +--- + +![Image](images/eti-01.png) + +Let's explore the main components of the Banana Cake Pop application's user interface: + +1. **Sidebar**: The sidebar contains various icons representing different sections of the application. Interacting with these icons will alter the content displayed in the main area. For instance, in the current view, the highlighted icon indicates that we are in the **Documents** section. For detailed information, please refer to our guide on [Documents](/docs/bananacakepop/v2/documents). + +2. **History**: This section displays the list of recently executed queries. + +3. **Settings**: To modify application preferences, you can navigate to the Settings section. Learn more about it in our [Settings Guide](/docs/bananacakepop/v2/settings). + +4. **User Menu**: This section allows users to sign in/out, manage their accounts, and handle billing. You can read more about account management and billing in the organization section [Organizations](/docs/bananacakepop/v2/organizations). + +5. **Status Bar**: The status bar provides quick access to workspace, organization, and synchronization features. It also displays additional information. More details are provided in our [Status Bar Guide](/docs/bananacakepop/v2/explore-the-ui/status-bar). + +6. **Document Tree**: Here you can manage files, folders, documents, and APIs. Read more about it in the [Explorer](/docs/bananacakepop/v2/explore-the-ui/explorer). + +7. **Main Area**: The main area showcases the content related to the selected section from the sidebar. In this instance, it displays the **Documents** section. +--- +title: "Banana Cake Pop - Express" +--- + +You can easily integrate Banana Cake Pop GraphQL IDE with your server app using the `@chillicream/bananacakepop-express-middleware` package. +You can either use a CDN hosted version of the app or a self-hosted version using the dedicated package. + +# Installation + +First, you need to install this package and the required peer dependencies in your project: + +```bash +npm install @chillicream/bananacakepop-express-middleware --save-dev +# or +yarn add @chillicream/bananacakepop-express-middleware --dev +# or +pnpm add @chillicream/bananacakepop-express-middleware --save-dev +``` + +Note: `@chillicream/bananacakepop-graphql-ide` is optional and only needed if you prefer to self host the app. + +# Usage + +To use the middleware, simply import it and add it to your Express app. + +```javascript +import express from "express"; +import { graphqlHTTP } from "express-graphql"; +import { GraphQLObjectType, GraphQLSchema, GraphQLString } from "graphql"; + +import bcpMiddleware from "@chillicream/bananacakepop-express-middleware"; + +const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: "Query", + fields: { + greeting: { + type: GraphQLString, + resolve(_parent, _args) { + return "Hello, World!"; + }, + }, + }, + }), +}); + +const app = express(); + +app.use( + "/graphql", + + // for `cdn` hosted version + bcpMiddleware({ mode: "cdn" }), + + // for `self` hosted version + // bcpMiddleware({ mode: "self" }), + + graphqlHTTP({ + schema, + graphiql: false, + }) +); + +app.listen(3000, () => { + console.log(`GraphQL on http://localhost:3000/graphql`); +}); +``` + +You can also use it in the `self` mode for a self-hosted version: + +```javascript +bcpMiddleware({ mode: "self" }) // for `self` hosted version +``` + +# Extended configuration + +## Pin a specific version +To pin a specific version instead of using "latest": + +```javascript +bcpMiddleware({ + mode: "cdn", + target: { version: "3.0.0" }, +}); +``` + +## Use your own infrastructure +To use your own infrastructure: + +```javascript +bcpMiddleware({ + mode: "cdn", + target: "https://mycompany.com/bcp", +}); +``` + +## Custom options +To pass options supported by Banana Cake Pop GraphQL IDE: + +```javascript +bcpMiddleware({ + mode: "cdn", + options: { + title: "BCP", + }, +}); +``` + +| Property | Description | Type | +| ----------------------- | ------------------------------------------------------------- | --------------------------------- | +| title | The title of the Banana Cake Pop IDE. | `string` (optional) | +| graphQLDocument | Specifies the GraphQL document (query/mutation/subscription). | `string` (optional) | +| variables | Specifies the variables used in the GraphQL document. | `Record` (optional) | +| includeCookies | If `true`, includes cookies in the request. | `boolean` (optional) | +| httpHeaders | Specifies HTTP headers for the request. | `HttpHeaderDictionary` (optional) | +| endpoint | The GraphQL endpoint. | `string` (optional) | +| useGet | If `true`, uses GET method for sending the request. | `boolean` (optional) | +| useBrowserUrlAsEndpoint | If `true`, uses the browser's URL as the GraphQL endpoint. | `boolean` | +| subscriptionProtocol | Specifies the protocol used for GraphQL subscriptions. | `SubscriptionProtocol` (optional) | + +# Recipes +Below are examples of how to use Banana Cake Pop Express Middleware with different GraphQL server setups. + +## graphql-http +```javascript +import express from "express"; +import { createHandler } from "graphql-http"; +//... rest of the imports + +const app = express(); +//... rest of the app setup + +app.use( + "/graphql", + bcpMiddleware({ mode: "cdn" }), // or bcpMiddleware({ mode: "self" }), + async (req, res) => { + //... rest of the middleware + } +); + +app.listen(3000, () => { + console.log(`GraphQL on http://localhost:3000/graphql`); +}); +``` + +## graphql-yoga +```javascript +import express from "express"; +import { createYoga, createSchema } from "graphql-yoga"; +//... rest of the imports + +const app = express(); +//... rest of the app setup + +app.use( + "/graphql", + bcpMiddleware({ mode: "cdn" }), // or bcpMiddleware({ mode: "self" }), + graphQLServer +); + +app.listen(3000, () => { + console.log(`GraphQL on http://localhost:3000/graphql`); +}); +``` + +## express-graphql +```javascript +import express from "express"; +import { graphqlHTTP } from "express-graphql"; +//... rest of the imports + +const app = express(); +//... rest of the app setup + +app.use( + "/ + +graphql", + bcpMiddleware({ mode: "cdn" }), // or bcpMiddleware({ mode: "self" }), + graphqlHTTP({ + schema, + graphiql: false, + }) +); + +app.listen(3000, () => { + console.log(`GraphQL on http://localhost:3000/graphql`); +}); +``` + +## Apollo Server +```javascript +import { ApolloServer } from "@apollo/server"; +//... rest of the imports + +const app = express(); +//... rest of the app setup + +app.use( + "/graphql", + bcpMiddleware({ mode: "cdn" }), // or bcpMiddleware({ mode: "self" }), + cors(), + bodyParser.json(), + expressMiddleware(server, { + context: async ({ req }) => ({ token: req.headers.token }), + }) +); + +httpServer.listen({ port: 3000 }, () => { + console.log(`GraphQL on http://localhost:3000/graphql`); +}); +``` +--- +title: ".Net Middleware" +--- + +By default, when you map your GraphQL endpoints using `MapGraphQL()`, Banana Cake Pop is automatically served at the `/graphql` endpoint. + +```csharp +app.UseEndpoints(endpoints => +{ + endpoints.MapGraphQL(); +}); +``` + +In the example above, the GraphQL service and Banana Cake Pop are both mapped to the `/graphql` endpoint. + +If you want to serve Banana Cake Pop on a separate endpoint, you can use `MapBananaCakePop()` method: + +```csharp +app.UseEndpoints(endpoints => +{ + endpoints.MapGraphQL(); + endpoints.MapBananaCakePop("/my-graphql-ui"); +}); +``` + +In this configuration, the GraphQL service remains at the `/graphql` endpoint, and Banana Cake Pop is served at the `/my-graphql-ui` endpoint. + +# Disable the Middleware + +In some scenarios, you may not want to serve Banana Cake Pop, e.g., in a production environment. You can disable Banana Cake Pop by setting the `Enable` property to `false`: + +```csharp +endpoints + .MapGraphQL() + .WithOptions( + new GraphQLServerOptions + { + Tool = new GraphQLToolOptions + { + Enable = false + } + }); +``` + +# Serve Modes + +The `ServeMode` property controls which version of Banana Cake Pop to serve. The default mode is `Latest`, serving the most recent version of Banana Cake Pop from a CDN. +You can also serve the embedded version (`Embedded`) of Banana Cake Pop, which is included in the package. + +- `Latest`: Serves the latest version of Banana Cake Pop from a CDN. +- `Insider`: Serves the insider version of Banana Cake Pop from a CDN, allowing preview of upcoming features. +- `Embedded`: Serves the embedded version of Banana Cake Pop that comes with the package. +- `Version(string version)`: Serves a specific version of Banana Cake Pop from the CDN. + +Depending on your environment or preferences, you can choose the appropriate mode: + +```csharp +endpoints + .MapBananaCakePop() + .WithOptions(new GraphQLToolOptions + { + ServeMode = GraphQLToolServeMode.Embedded + }); +``` + +# Configuration Options + +You can tailor Banana Cake Pop to your needs by setting various options via the `GraphQLToolOptions` class. You can specify these options using the `WithOptions()` method in both `MapGraphQL()` and `MapBananaCakePop()` methods. + +| Property | Type | Description | +| ------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| Enable | `bool` | If `false`, disables the Banana Cake Pop tool. | +| ServeMode | `GraphQLToolServeMode` | Defines how Banana Cake Pop is served. Options include `Latest` (default), `Insider`, `Embedded`, and `Version(string version)`. | +| Title | `string` | Specifies the title of the Banana Cake Pop page. | +| Document | `string` | Specifies the default document content. | +| IncludeCookies | `bool` | If `true`, includes cookies in the HTTP call to the GraphQL backend. | +| HttpHeaders | `IHeaderDictionary` | Specifies the default HTTP headers for Banana Cake Pop. | +| HttpMethod | `DefaultHttpMethod` | Specifies the default HTTP method to use. | +| GraphQLEndpoint | `string` | Specifies the GraphQL endpoint. If `UseBrowserUrlAsGraphQLEndpoint` is `true`, it must be a relative path; otherwise, it must be an absolute URL. | +| UseBrowserUrlAsGraphQLEndpoint | `bool` | If `true`, the schema endpoint URL is inferred from the browser URL. | + +Here is an example of how to set these options: + +```csharp +endpoints + .MapBananaCakePop() + .WithOptions(new GraphQLToolOptions + { + ServeMode = GraphQLToolServeMode.Insider, + Title = "My GraphQL API", + Document = "Query { hello }", + GraphQLEndpoint = "/api/graphql", + IncludeCookies = true, + Enable = true + }); +``` +--- +title: "Introduction" +--- + +> Explore, engage and share your thoughts via [slack](http://slack.chillicream.com/) in the **#banana-cake-pop** channel. + +Banana Cake Pop is a tool for developers, simplifying API creation, debugging, and collaboration. It enables effortless execution of GraphQL queries and mutations, with visual schema exploration. The platform emphasizes collaboration through seamless team sharing and synchronization. Banana Cake Pop supports you during the entire API lifecycle with features like the schema and client registry for confident API evolution. + +Are you hungry yet? [Let's get started!](/docs/bananacakepop/v2/getting-started) + +# Features + +1. **GraphQL IDE** +Whether you're building or consuming GraphQL APIs, Banana Cake Pop simplifies the process by allowing you to effortlessly build and execute GraphQL queries and mutations. Its intuitive UI enables you to visualize and explore your GraphQL schemas, making it easier to understand and work with complex structures. The powerful editor provides syntax highlighting, auto-completion, and error highlighting, helping you write GraphQL queries and mutations with ease. + +2. **Collaboration** +Additionally, Banana Cake Pop places a strong emphasis on collaboration. It offers seamless team collaboration features, allowing developers to share documents, API configurations, environment settings and lets you collaborate on projects, and synchronize your work across multiple team members. By facilitating effective communication, Banana Cake Pop ensures that everyone on your team is on the same page, leading to more efficient and coordinated development efforts. + +3. **DevOps** +Banana Cake Pop support you during the entire lifecycle of an API. With its schema and client registry, Banana Cake Pop ensures that your APIs are well-maintained and evolve seamlessly over time. Integrated into your development workflow, Banana Cake Pop helps you manage your APIs effectively, making easy to build and maintain high-quality APIs. + +4. **Schema Registry** +Banana Cake Pop's schema registry acts as a centralized repository for your GraphQL schemas. It allows you to store, version, and manage your schemas effectively. Whenever you make changes to your schema, Banana Cake Pop tracks and documents those changes, making it easy to keep a history of modifications. This ensures that you have full visibility into the evolution of your API, making it easier to understand and troubleshoot issues that may arise during development. + +5. **Client Registry** +The client registry feature of Banana Cake Pop complements the schema registry by providing a centralized location to manage and track the clients that consume your GraphQL APIs. It enables you to register and document all the client applications that interact with your APIs. By maintaining an up-to-date client registry, you can easily identify which clients may be affected by schema changes and take appropriate actions to ensure a smooth transition. + +6. **Intuitive Interface** +Banana Cake Pop provides a user-friendly interface that is easy to navigate, even for those new to GraphQL. Its clean and intuitive design makes it a pleasure to work with, enabling developers to focus on their tasks without unnecessary distractions or complications. + + + +--- +title: Authentication +--- + +Banana Cake pop offers support for various authentication flows. The following guide details how to use these authentication flows to retrieve a token from an identity server and send the Authorization header to the server. + +![BCP Authentication Flow](images/auth-0.png) + +Accessing the authentication settings is straightforward: + +1. Locate the cog icon in the navigation bar on the left side of the screen. +2. Click on the icon to open the authentication settings. + +BCP supports three types of authentication flows: + +- [Basic Authentication](/docs/bananacakepop/v2/documents/authentication#basic-authentication) +- [Bearer Token](/docs/bananacakepop/v2/documents/authentication#bearer-token) +- [OAuth 2.0](/docs/bananacakepop/v2/documents/authentication#oauth-20) + +# Basic Authentication + +Basic Authentication is a built-in authentication scheme of the HTTP protocol. It works by sending HTTP requests with an Authorization header. This header includes the word 'Basic' followed by a space and a base64-encoded string of the format 'username:password'. + +![Basic Authentication Fields](images/auth-1.png) + +When setting up Basic Authentication, you will need to provide the following information: + +- **Username**: The username required for authentication. +- **Password**: The corresponding password for the provided username. +- **Authorization Header**: This is a preview of the header that will be used for authentication. This field is auto-generated based on the inputted username and password. + +Learn more about Basic Authentication [here](https://en.wikipedia.org/wiki/Basic_access_authentication). + +# Bearer Token + +This method involves a client sending a token within the Authorization header. The token is typically generated by the server when a login request is processed. Subsequent requests to protected resources must include this token in the Authorization header. + +![Bearer Token Fields](images/auth-2.png) + +You will need to provide at least the token. The following fields are available: + +- **Token**: The token that will be used for authentication. +- **Prefix**: The prefix for the token. By default, this is set as 'Bearer'. +- **Authorization Header**: A preview of the header that will be used for authentication. This field is auto-generated based on the provided token and prefix. + +Learn more about Bearer Token Authentication [here](https://swagger.io/docs/specification/authentication/bearer-authentication/). +# OAuth 2.0 + +OAuth 2.0 authentication flow is a industry-standard authorization framework. It allows third-party applications to gain limited access to a web service through a server that supports the OAuth 2.0 protocol. Most major identity providers support OAuth 2.0, including Auth0, Okta, AWS Cognito, Azure AD, and more. + +In .NET, OAuth 2.0 is implemented by [Duende IdentityServer](https://duendesoftware.com/products/identityserver) and [OpenIddict](https://documentation.openiddict.com/). + +BCP supports several OAuth 2.0 flows, including: + +- [Authorization Code](https://auth0.com/docs/flows/authorization-code-flow) +- [Client Credentials](https://auth0.com/docs/flows/client-credentials-flow) +- [Resource Owner Password Credentials](https://auth0.com/docs/flows/resource-owner-password-flow) +- [Implicit](https://auth0.com/docs/get-started/authentication-and-authorization-flow/implicit-flow-with-form-post) + +Depending on the selected OAuth 2.0 flow, the fields you need to fill in will vary. + +![OAuth 2.0 Fields](images/auth-3.png) + +The following fields are available required: + +- **[Grant Type](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3)**: This is the method an application uses to obtain an access token. Common values include 'authorization_code', 'client_credentials', 'password', and 'refresh_token'. Each type serves a different use case, such as a web application, machine-to-machine, mobile apps, etc. + +- **Authorization URL**: This is the URL to which your application directs the user in the initial step of the authorization process. It usually looks something like 'https://auth.example.com/authorize'. + +- **Access Token URL**: This is the URL your application uses to obtain the access token from the authorization server. It's typically of the form 'https://auth.example.com/token'. + +- **[Client ID](https://datatracker.ietf.org/doc/html/rfc6749#section-2.2)**: This is a public identifier for your application, issued by the authorization server when you register your application. It's used to identify your application to the user during authorization. + +- **[Client Secret](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1)**: This is a confidential key held by the client application, used to authenticate to the authorization server when using 'client_credentials' or 'authorization_code' grant types. It should be kept confidential and never exposed publicly. + +- **[Use PKCE](https://datatracker.ietf.org/doc/html/rfc7636)**: PKCE (Proof Key for Code Exchange) is a mechanism designed to secure public clients that don't use a client secret. It's highly recommended for mobile and single-page apps. When enabled, it adds an extra step in the authorization process to prevent certain types of attacks. + +- **[Scope](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3)**: These are permissions that the application requests. The value is a list of space-delimited strings, such as 'read:messages write:messages'. 'offline_access' can be requested to get a refresh token. + +- **[Redirect URL](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.2)**: This is the URL to which the authorization server will redirect the user's browser after authorization has been granted. It must match one of the redirect URIs registered with the authorization server. + +- **[Code Challenge Method](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2)**: This field is relevant if PKCE is used. It defines how the code verifier is transformed. 'PLAIN' or 'S256' (SHA256) are common options, with 'S256' being more secure. + +- **[State](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1)**: This is an opaque value that is used to maintain state between the request and the callback, mitigating CSRF attacks. It's a good practice to use a unique value for each authorization request. + +- **[Credentials](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3)**: Defines how client credentials are sent to the server. They can be sent as a Basic Auth Header or in the Request Body. + +- **Header Prefix**: This is the prefix that appears before the token in the Authorization header. The default is 'Bearer', as described in [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750), but it could also be 'Token' or other custom strings. + +- **Audience**: This is the intended audience of the token, typically the identifier of the resource server that should accept the token. + +- **Resource**: The target resource that the application wants to access. + +- **Origin**: This is used in browser-based applications to indicate the origin of the request and mitigate CSRF attacks. + +- **Username**: Required for the 'password' grant type. This is the resource owner's username. + +- **Password**: Also required for the 'password' grant type. This is the resource owner's password. + +- **[Response Type](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.1)**: Indicates what should be returned from the initial request. For 'authorization_code' grant type, this should be 'code'. For the implicit grant type, this would typically be 'token'. + +This comprehensive set of options allows for fine-tuned control of OAuth 2.0 authentication flows in your application. + +Learn more about OAuth 2.0 [here](https://oauth.net/2/). + +## Request a token + +In BCP, you can fetch the authentication token using two different methods: + +1. **Fetch Button in Authentication Settings**: + + Located at the bottom of the authentication settings is a button labeled `Fetch`. Clicking this will retrieve the authentication token. Once the token is fetched, you also have options to `Clear` it or `Refresh` it (if a refresh token was requested). + + In the desktop application, there's an additional feature to `Reset the session on identity server`. This is particularly useful because your authentication session on your identity server is persisted in the browser, meaning you don't need to sign in repeatedly. If you wish to log in as a different user, you can reset your session by clicking this button. + + ![Fetch Button](images/auth-5.png) + +2. **Key Icon in Operations Pane**: + + At the top right of the operations pane, you'll notice a key icon. Clicking this icon initiates the authentication flow. + + ![Key Icon](images/auth-4.png) + +These two methods allow you to conveniently manage and initiate your authentication flows, providing you with flexibility to cater to different use-case scenarios. + +## Redirect URL + +In the context of BCP (Banana Cake Pop), the Redirect URL plays a crucial role, particularly when you're using BCP within a web browser rather than the desktop application. + +The Redirect URL is where your browser is directed to after the authentication process. It must be configured to point back to the URL where BCP is hosted. This is essential because BCP needs to retrieve the authorization code from this URL to exchange it for a token. + +--- +title: Operations Pane +--- + +The Operations Pane provides a comprehensive interface for writing GraphQL queries, mutations, and subscriptions. It offers several features to enhance your development experience. + +![Banana Cake Pop - Operations Pane](./images/operations-0.png) + +# **1. Operations Editor** +The Operations Editor is a text editor within the Operations Pane where you can write your GraphQL queries, mutations, and subscriptions. It provides syntax highlighting, intellisense, and validation to assist you in writing accurate queries. + +# **2. Inline Run Button** +The Inline Run Button allows you to execute your query directly from the Operations Editor. By clicking this button, your query will be sent to the GraphQL server, and the response will be displayed in the Response Pane. + +# **3. Format Button** +The Format Button helps you maintain proper query formatting according to common formatting rules. When clicked, it automatically formats your query and updates the content in the Operations Editor. + +# **4. Run Button** +The Run Button enables you to execute your query with a single click. Similar to the Inline Run Button, clicking this button will send your query to the GraphQL server, and the response will be shown in the Response Pane. + +# **5. Variables Panel** +The Variables Panel allows you to define variables for your query. You can specify the variable name, type, and default value. These variables can then be utilized within your query, making it more dynamic and reusable. + +# **6. Headers Panel** +The Headers Panel enables you to define headers for your query. You can specify the header name and value, which will be included when sending the query to the GraphQL server. This feature is useful for including authentication tokens or other custom headers required by your API. For authentication, you can also use the Authentication Settings feature, which is described in the [Authentication Settings](/docs/bananacakepop/v2/documents/authentication) section. + +# **7. File Upload Panel** +The File Upload Panel provides functionality for uploading files to the GraphQL server. You can specify the file name and contents within this panel. This feature works in conjunction with the `Upload` scalar type, a special type in GraphQL that facilitates file uploads. It follows the multipart form request specification to send files to the GraphQL server. For more details, refer to the [documentation](/docs/hotchocolate/v13/server/files) on file uploads in GraphQL. +--- +title: "Schema Definition" +--- + +![Banana Cake Pop - Schema Definition](./images/definition-0.png) + +The Schema Definition feature in Banana Cake Pop provides you with access to the raw Schema Definition Language (SDL) of your GraphQL server. This section explains how to view and download the SDL using Banana Cake Pop. + +1. SDL Editor + The SDL Editor allows you to explore and examine the SDL of your GraphQL server. You can view the SDL code directly in the editor and analyze the schema structure, types, and fields. + +2. Download SDL + To download the SDL, locate the download icon in the top right-hand corner of the "Schema Definition" area. Clicking on the download icon will initiate the download process, allowing you to save the SDL file locally on your device. +--- +title: Connection Settings +--- + +The Connection Settings in Banana Cake Pop allow you to configure various options related to connecting and communicating with your GraphQL server. This section describes the different settings available and their functionalities. + +![Connection-Settings](./images/connection-settings-0.png) + +# Schema Endpoint +The Schema Endpoint refers to the URL of your GraphQL server. It is the endpoint used to send queries and mutations. Configure this setting with the appropriate URL to establish a connection with your GraphQL server. + +# Subscription Endpoint +The Subscription Endpoint represents the URL used to send subscriptions to the GraphQL server. By default, it is inferred from the Schema Endpoint. Specify the subscription URL if it differs from the Schema Endpoint. + +# SSE Subscription Endpoint +If you utilize SSE (Server-Sent Events) subscriptions, the SSE Subscription Endpoint should be provided. This URL specifies the endpoint for SSE subscriptions. By default, it is inferred from the Schema Endpoint. + +# Subscription Protocol +The Subscription Protocol setting allows you to choose the protocol for handling subscriptions. Banana Cake Pop supports the following options: + +- **Auto**: Banana Cake Pop negotiates the protocol with the server automatically based on server capabilities. +- **GraphQL Websocket**: Banana Cake Pop uses the [graphql-ws](https://github.com/enisdenjo/graphql-ws) protocol for handling subscriptions. +- **GraphQL SSE**: Banana Cake Pop uses the [graphql-sse](https://github.com/enisdenjo/graphql-sse) protocol for handling subscriptions. +- **Apollo Websocket**: Banana Cake Pop uses the deprecated [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws) protocol from Apollo. + +# Use HTTP GET +By enabling the Use HTTP GET option, Banana Cake Pop will use HTTP GET instead of HTTP POST for executing queries and mutations. This can be useful in certain scenarios or for compatibility with specific GraphQL servers. + +# Include Cookies (cross-origin) +Enabling the Include Cookies (cross-origin) option ensures that cookies are included when sending queries and mutations to the GraphQL server. This is particularly relevant in cross-origin situations where cookies are required for authentication or session management. + +The Connection Settings provide you with the flexibility to customize the connection parameters and communication behavior with your GraphQL server. Configure these settings according to your server's requirements and the desired functionality of your application. +--- +title: Documents +--- + +The Document View is a feature that allows users to work with documents and API documents within the application. It provides functionality for executing queries, mutations, and subscriptions. This section describes the various components and functionalities available in the Document View. + +![Image](images/document-0.png) + +# 1. Operations +The Operations section is where you can write and execute your queries, mutations, and subscriptions. It provides a convenient interface for interacting with the GraphQL API. + +# 2. Schema Reference +The Schema Reference section allows you to explore the schema in a tree view or the explorer view. It provides detailed information about the available schema and its components. For more information on using the Schema Reference, refer to the [Schema Reference](/docs/bananacakepop/v2/documents/schema-reference) guide. + +# 3. Schema Definition +The Schema Definition section displays the schema definition in SDL (Schema Definition Language) format. It allows you to inspect the schema structure and understand its various types and fields. Refer to the [Schema Definition](/docs/bananacakepop/v2/documents/schema-definition) guide for further details. + +# 4. Document Status Indicator +The Document Status Indicator visually represents whether the current document is saved or not. A white dot indicates that the document is not saved, while a different icon may indicate a saved or modified state. + +# 5. Query Editor +The Query Editor provides a dedicated space for writing your queries, mutations, and subscriptions. It offers features such as syntax highlighting, auto-completion, and error checking to assist in query composition. Learn more about using the query editor in the [Operations](/docs/bananacakepop/v2/documents/operations) guide. + +# 6. Response Pane +The Response Pane displays the response of your queries, mutations, and subscriptions. It shows the data returned by the API and provides a structured view for easier analysis. Refer to the [Response Pane](/docs/bananacakepop/v2/documents/response) guide for additional information. + +# 7. Schema Indicator +The Schema Indicator is a visual cue that indicates the connection status with the GraphQL server and the successful retrieval of the schema. A green circle represents a connected state. + +# 8. Connected Schema Endpoint +This section displays the currently connected schema endpoint, providing information about the GraphQL server being accessed. + +# 9. Settings +The Document Settings section allows you to configure various settings specific to the document. Refer to the [Connection Settings](/docs/bananacakepop/v2/documents/connection-settings) guide for detailed information about it. You can also configure the authentication settings for the document. Refer to the [Authentication Settings](/docs/bananacakepop/v2/documents/authentication) guide for more details. +--- +title: Response Pane +--- + +The Response Pane is a central feature that is located to the right of the query editor. Its primary function is to display the response of a query that has been executed, but it offers a range of additional features that help in analyzing these responses. + +![Banana Cake Pop - Response Pane](./images/response-0.png) +The pane is divided into two sections: + +1. The upper section displays all response and transport information. +2. The lower section maintains a record of all executed queries related to the current document. +3. Additionally, you can get a brief overview of the response status code, the duration, and the size of the last executed request on the top right of the pane. + +# Response Section +![Banana Cake Pop - Response Pane](./images/response-1.png) +This part of the pane displays the JSON response of the executed query. In case you have deferred results, this view amalgamates all results into one JSON object. For those using subscriptions, this view will display the most recent result of the subscription. + +# Transport Request Body +![Banana Cake Pop - Response Pane](./images/response-2.png) + +Found under a separate tab, this section provides the raw JSON request sent to the server. + +# Transport Details +![Banana Cake Pop - Response Pane](./images/response-3.png) + +This pane provides in-depth details of the request and response. Here is a rundown of the information displayed: + +* **General HTTP Information:** Contains basic information such as the URI, HTTP Method, and Status Code. +* **Request Headers:** Display metadata for the HTTP request, including content-type and user-agent. +* **Response Headers:** Provide information about the HTTP response, such as the content-length, content-security-policy, and strict-transport-security. + +# Transport Error +![Banana Cake Pop - Response Pane](./images/response-4.png) + +This tab displays a JSON representation of any errors returned by the server when the request fails. + +# Logs +![Banana Cake Pop - Response Pane](./images/response-5.png) + +The Logs tab records all logs generated during the execution of a query. This includes all requests, patch responses, subscription results, errors, and warnings. Clicking on a log entry will prompt the editor below to show more details about the log entry. + +# History +![Banana Cake Pop - Response Pane](./images/response-6.png) + +The History tab keeps track of all the queries that have been executed in the current document. Clicking on a history entry will load the corresponding query into the editor, allowing you to review the response. +--- +title: "Schema Reference" +--- + +The Schema Reference feature allows you to inspect and explore the schema of your GraphQL server. It provides valuable information about the available types, fields, and directives within the schema. This section describes the components and functionalities of the Schema Reference. + +# Explorer View +![Explorer View](./images/reference-0.png) + +## 1. View Switcher +The View Switcher allows you to toggle between two different views: the Tree View and the Explorer View. Each view provides a unique way to navigate and explore the schema. You are currently viewing the Explorer View. + +## 2. Selected Type Details +This section displays detailed information about the currently selected type, including its fields and arguments. It offers insights into the structure and properties of the selected type. + +## 3. Summary Information +The Summary Information provides quick statistics about the number of types and directives present in the schema. It offers a high-level overview of the schema's composition. + +## 4. Search Bar +The Search Bar allows you to search for specific types and fields within the schema. You can enter keywords or names to quickly locate relevant components. + +# Tree View +![Tree View](./images/reference-1.png) + +In the Tree View, you start with the root types of the schema, such as Query, Mutation, and Subscription. Clicking on a root type expands it to reveal the available fields associated with that type. By clicking on any field, you can further explore the schema and its nested components. The right side of the interface provides detailed information about the selected field. +--- +title: Subscription +--- + +You can manage your subscriptions directly from the web portal, accessible through [here](https://identity.chillicream.com/Organization) or through manage organization on the client. + +# Creating a Subscription + +When you do not have a subscription yet, you can create on in the 'Subscriptions' section of the management portal. Open the organization in the context of an owner or admin to see this section. +![Screenshot showing the subscription](./images/subscription-2.png) + +Enter the number of seats you want to purchase and click on the 'Create' button. You will be redirected to the billing portal to complete the payment process. +Enter your payment details and click on the 'Subscribe' button to complete the payment process. + +You have the option to pay monthly or annually. Annual payments are discounted. + +You can cancel your subscription at any time. The subscription will remain active until the end of the current billing period. You can also change your subscription plan at any time. Check out the [Changing a Subscription](#changing-a-subscription) section for more information. + + +# Changing a Subscription + +To change your subscription plan, follow these steps: + +1. **Access the Management Portal:** Open the management portal by clicking ['Manage Organizations' -> 'Manage'](/docs/bananacakepop/v2/organizations#managing-organizations) option in the context menu of the bcp or by navigating to [here](https://identity.chillicream.com/Organizations). + +2. **Navigate to Subscriptions:** Within the management portal, click on 'Manage' in the subscription section. +![Screenshot showing the subscription](images/subscription-3.png) + +3. **Adjust Seats:** Here, you can adjust the number of seats that are available in your subscription. Changing this value will affect the number of users who can join your organization. +![Screenshot showing the subscription](images/subscription-4.png) + +# Expiry and Seats + +Banana Cake Pops subscription model allows a certain number of users (seats) to join an organization based on your chosen subscription plan. + +If your subscription expires, all users except the organization owner will be deactivated a few days after the expiration. The deactivated users will regain access once the subscription is renewed. + +If your organization reaches its maximum seat limit, no new users will be able to join the organization. You can manage this by either upgrading your subscription to allow for more seats or by removing existing users from the organization to free up seats. + +# Billing +In the client app you can directly access the billing portal by clicking 'Billing' and managing your running subscriptions: +![Description of visualization: Screenshot showing the subscription](images/subscription-1.png) + +The billing of an organization is currently on a per-user basis. All billing-related aspects, including subscription management and payment processing, are handled securely through Stripe, which you can directly manage from the management portal. + +> Please note that the pricing model and subscription terms are subject to change, and users are advised to stay updated by regularly checking our website or contacting our customer support team. +--- +title: "Schema Configuration" +--- + +Schema stitching and federations do have a lot more potential than just merging root types. +You can remove and rename types and fields, extend types with new resolvers and delegate these resolvers to a domain service. + +# Schema Transformation + +## Rename Types + +The name of a GraphQL type has to be unique. +When you build a standalone GraphQL server, the schema validation will make sure that no name is duplicated. +In case a name is duplicated, an exception is thrown and the schema will not compile. + +This behavior is good for the standalone server but can be an issue in distributed schemas. +Even with domain services covering domain-specific topics, a type may be duplicated. + +To avoid an invalid schema, Hot Chocolate will prefix duplicated types with the schema name and auto resolves name collisions if they are not structurally equal. + +Let us assume we have a product and an inventory service. Both define a type called `Category`: + +```sdl +type Category { + name: String +} +``` + +```sdl +type Category { + name: String + subCategories: [Category!]! +} +``` + +The collision resolver of Hot Chocolate will resolve the following on the stitching layer: + +```sdl +type Category @source(name: "Category", schema: "products") { + name: String! + subCategories: [Category!]! +} + +type inventory_Category @source(name: "Category", schema: "inventory") { + name: String! +} +``` + +Hot Chocolate allows you to rename types to avoid collision auto resolving: + +```sdl +type Category @source(name: "Category", schema: "inventory") { + name: String! +} + +type ProductCategory @source(name: "Category", schema: "products") { + name: String! + subCategories: [ProductCategory!]! +} +``` + +### Schema Stitching + +In schema stitching type renames can be defined on the gateway: + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Products) + .AddRemoteSchema(Inventiory) + .RenameType("Category","ProductCategory", Products); +``` + +### Schema Federations + +In a federated approach, type renames can be done on the domain service: + +```csharp +services + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + .InitializeOnStartup() + .PublishSchemaDefinition( + c => c + .SetName("products") + .RenameType("Category", "ProductCategory") + .AddTypeExtensionsFromFile("./Stitching.graphql") + .PublishToRedis( + "Demo", + sp => sp.GetRequiredService())); +``` + +## Rename Fields + +Similar to type names, also fields can collide. A type can only declare a field once. +When you bundle domain services together, multiple domain services may declare the same field on the query type. + +Let us assume we have a product and an inventory service. Both define a type field called `categories`: + +```sdl +type Query { + categories: [Category!]! +} +``` + +```sdl +type Query { + categories: [ProductCategory!]! +} +``` + +Hot Chocolate will auto-resolve the naming conflict by prefixing the field with the schema name: + +```sdl +type Query { + categories: [ProductCategory!]! @delegate(schema: "products") + inventory_categories: [Category!]! @delegate(schema: "inventory", path: "categories") +} +``` + +Hot Chocolate allows you to rename fields to avoid collision auto resolving: + +```sdl +type Query { + productCategories: [ProductCategory!]! @source(name: "categories", schema: "products") @delegate(schema: "products") + categories: [Category!]! @delegate(schema: "inventory") +} +``` + +### Schema Stitching + +In schema stitching field renames can be defined on the gateway: + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Products) + .AddRemoteSchema(Inventiory) + .RenameField("Query", "categories", "productCategories", schemaName: Products) +``` + +### Schema Federations + +In a federated approach, type renames can be done on the domain service: + +```csharp +services + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + .InitializeOnStartup() + .PublishSchemaDefinition( + c => c + .SetName("products") + .RenameField("Query", "categories", "productCategories") + .AddTypeExtensionsFromFile("./Stitching.graphql") + .PublishToRedis( + "Demo", + sp => sp.GetRequiredService())); +``` + +## Ignore Types + +By default, all types of remote schemas are added to the gateway schema. +This can produce types that are not reachable. +You can remove all not reachable types on the gateway: + +```csharp +services + .AddGraphQLServer() + .AddQueryType(d => d.Name("Query")) + .AddRemoteSchemasFromRedis("Demo", sp => sp.GetRequiredService()) + .ModifyOptions(x => x.RemoveUnreachableTypes = true) +``` + +If you want to remove a specific type from the schema you can also use `IgnoreType` + +### Schema Stitching + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Products) + .AddRemoteSchema(Inventiory) + .IgnoreType("Category", schemaName: Products); +``` + +### Schema Federations + +```csharp +services + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + .InitializeOnStartup() + .PublishSchemaDefinition( + c => c + .SetName("products") + .IgnoreType("Category") + .AddTypeExtensionsFromFile("./Stitching.graphql") + .PublishToRedis( + "Demo", + sp => sp.GetRequiredService())); +``` + +## Ignore Field + +Hot Chocolate has a convenience API to ignore fields of types. +This can be useful when you want to merge root fields of domain services, but ignore some specific fields + +### Schema Stitching + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Products) + .AddRemoteSchema(Inventiory) + .IgnoreField("Query", "categories", Products) + .IgnoreField("Query", "categories", Inventory); +``` + +# Delegation of Resolvers + +The real power of schema stitching is the delegation of resolvers. +You can extend types with fields and redirect calls to a domain service + +Let us assume we have a product and an inventory service. + +The product service defines the following types + +```sdl +type Product { + upc: Int! + name: String! + price: Int! + weight: Int! +} + +type Query { + products: [Product!]! +} +``` + +The inventory service defines the following types + +```sdl +type InventoryInfo { + upc: Int! + isInStock: bool +} + +type Query { + inventoryInfo(upc: Int!): InventoryInfo! + shippingEsitmate(price: Int!, weight: Int!): InventoryInfo! +} +``` + +Resolver delegation allows us to combine these schemas into one cohesive schema. + +We can extend the product type with `inStock` and `shippingEstimate` + +```sdl +extend type Product { + inStock: Boolean @delegate(schema:"inventory", path: "inventoryInfo(upc: $fields:upc).isInStock") + shippingEstimate: Int @delegate(schema:"inventory", path: "shippingEstimate(price: $fields:price weight: $fields:weight)") +} +``` + +This results in the following schema: + +```sdl +type Product { + upc: Int! + name: String! + price: Int! + weight: Int! + inStock: Boolean + shippingEstimate: Int +} + +type Query { + products: [Product!]! +} +``` + +## Delegate Directive + +The `@delegate` directive describes where the remote data is found. + +```sdl +directive @delegate( + "The name of the schema to which this field shall be delegated to" + schema: String + "The path on the schema where delegation points to" + path: String! +) on FIELD_DEFINITION +``` + +The `path` argument can contain references to context data or fields. + +### Field Reference ($fields) + +```sdl +@delegate(path: "inventoryInfo(upc: $fields:upc).isInStock") +``` + +With the `$fields` variable, you can access fields of the type you extend. + +```sdl +type Product { + upc: Int! + name: String! +} + +extend type Product { + inStock: Boolean @delegate(schema:"inventory", path: "inventoryInfo(upc: $fields:upc).isInStock") +} +``` + +### Argument Reference ($arguments) + +```sdl +@delegate(path: "inventoryInfo(upc: $arguments:sku).isInStock") +``` + +With the `$fields` variable you can access fields of the type you extend. + +```sdl +extend type Query { + isProductInStock(sku:String!): Boolean @delegate(schema:"inventory", path: "inventoryInfo(upc: $arguments:upc)") +} +``` + +### Context Data Reference ($contextData) + +Every request contains context data. Context data can be set in resolvers or with a `IHttpRequestInterceptor` + +```sdl +extend type Query { + me: User! @delegate(schema: "users", path: "user(id: $contextData:UserId)") +} +``` + +**UseRequest** + +```csharp +services + .AddGraphQLServer() + .UseRequest(next => context => + { + context.ContextData["UserId"] = context.GetLoggedInUserId(); + return next(context); + }) + ... +``` + +**RequestInterceptor** + +```csharp +public class RequestInterceptor : DefaultHttpRequestInterceptor +{ + public ValueTask OnCreateAsync( + HttpContext context, + IRequestExecutor requestExecutor, + IQueryRequestBuilder requestBuilder, + CancellationToken cancellationToken) + { + string userId = context.GetLoggedInUserId(); + requestBuilder.SetProperty("UserId", userId); + + return base.OnCreateAsync( + context, requestExecutor, requestBuilder, cancellationToken); + } +} +``` + +```csharp +services + .AddGraphQLServer() + .AddHttpRequestInterceptor() + ... +``` + +**Static Context Data** +Context data can also be set directly on the schema builder. + +```csharp +services + .AddGraphQLServer() + .SetContextData("foo", "bar") + ... +``` + +### Scoped Context Data Reference ($scopedContext) + +Scoped context data can be set in a resolver and will be available in all resolvers in the subtree. +You have to use scoped context data when a resolver depends on a field that is higher up than just the parent. +You can use field middlewares to set scoped context data. + +Let's assume you have a message and account service. +The message holds a field `messageInfo` and knows the id of the creator of the message. +You want to extend the `messageInfo` with the user from the account service. + +**Schema** + +```sdl +type Message { + content: String! + createdById: ID! + messageInfo: MessageInfo! +} + +type MessageInfo { + createdAt: DateTime! +} +``` + +**Extensions** + +```sdl +extend type MessageInfo { + createdBy: User @delegate(schema:"accounts", path: "userById(upc: $scopedContextData:upc).isInStock") +} +``` + +**UseField** + +This middleware is executed for each field. + +```csharp +services + .AddGraphQLServer() + .UseField(next => async context => + { + if(context.Field.Type.NamedType() is ObjectType objectType && + objectType.Name.Equals("Message") && + context.Result is IDictionary data && + data.TryGetValue("createdById", out object value)) + { + context.ScopedContextData = + context.ScopedContextData.SetItem("createdById", value); + } + + await next.Invoke(context); + }) +``` + +**Type Interceptor** + +The middleware of `UseField` is executed on each field and created overhead. +It would be better if the middleware is only applied to the field that needs it. +You can use a schema interceptor to apply the middleware to the fields that use it. + +```csharp +public class MessageMiddlwareInterceptor : TypeInterceptor +{ + public override bool CanHandle(ITypeSystemObjectContext context) + { + return context.Type is INamedType { Name: { Value: "Message" } }; + } + public override void OnBeforeCompleteType( + ITypeCompletionContext completionContext, + DefinitionBase? definition, + IDictionary contextData) + { + if (definition is ObjectTypeDefinition otd) + { + var field = otd.Fields + .FirstOrDefault(x => x.Name.Value == "messageInfo"); + if (field is { } messageInfo) + { + messageInfo.MiddlewareComponents.Insert( + 0, + next => async context => + { + if(context.Result is IDictionary data && + data.TryGetValue("createdById", out object value)) + { + context.ScopedContextData = + context.ScopedContextData.SetItem("createdById", value); + } + + await next.Invoke(context); + }); + } + } + } +} +``` + +## Configuration + +You can configure the schema extensions either on the gateway or on the domain service if you use federations. +Type extensions can either be strings, files or resources + +- `AddTypeExtensionFromFile("./Stitching.graphql");` +- `AddTypeExtensionFromResource(assembly, key);` +- `AddTypeExtensionFromString("extend type Product {foo : String}");` + +### Schema Stitching + +**Gateway:** + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Products) + .AddRemoteSchema(Inventory) + // Adds a type extension. + .AddTypeExtensionsFromFile("./Stitching.graphql") +``` + +### Schema Federations + +**Inventory Domain Service:** + +```csharp +services + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + .InitializeOnStartup() + .PublishSchemaDefinition( + c => c + .SetName("inventory") + // Ignores the root types. This removes `inStock` and `shippingEsitmate` + // from the `Query` type of the Gateway + .IgnoreRootTypes() + // Adds a type extension. + .AddTypeExtensionsFromFile("./Stitching.graphql") + .PublishToRedis( + "Demo", + sp => sp.GetRequiredService())); +``` + +If you use the `@delegate` directive in federations you can omit the `schema:` argument. +--- +title: "Schema Federations" +--- + +In schema federations, the extension points of the gateway schema are defined on the downstream services. +Therefore you need to configure federations in two places: the gateway schema and the downstream service. + +The schemas can either be pushed to a Redis cache and then pulled from the gateway or directly be pulled by the gateway from the downstream service. + +# Federation with Redis + +Hot Chocolate uses the Redis cache as a pub/sub system to signal changes on the downstream services. +With a cache, the gateway schema is also more stable and faster in bootstrapping, because it does not require to call all downstream services on startup. + +You will need to add a package reference to `HotChocolate.Stitching.Redis` to all your services: + + + +## Configuration of a domain service + +A domain service has to _publish the schema definition_. +The schema is published on the initialization of the schema. +By default, a schema is lazy and only initialized when the first request is sent. +You can also initialize the schema on startup with `IntitializeOnStartup`. +Every schema requires a unique name. This name is used in several places to reference the schema. +By calling `PublishSchemaDefinition` you can configure how the schema should be published. + +Schemas are published to Redis under a configuration name. The gateway is subscribed to this configuration. +All schemas that are registered under this name, will be discovered by the gateway + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services + // This is the connection multiplexer that redis will use + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + // We initialize the schema on startup so it is published to the redis as soon as possible + .InitializeOnStartup() + // We configure the publish definition + .PublishSchemaDefinition(c => c + // The name of the schema. This name should be unique + .SetName("accounts") + .PublishToRedis( + // The configuration name under which the schema should be published + "Demo", + // The connection multiplexer that should be used for publishing + sp => sp.GetRequiredService())); +} +``` + +## Configuration of the gateway + +The gateway needs HttpClients to fetch the data from the domain services. +You have to register them on the service collection. +The name of the HttpClient has to be the same as the name of the schema it refers to. +As you may use the schema names in several places, it is good practice to store them as constant. + +```csharp +public static class WellKnownSchemaNames +{ + public const string Accounts = "accounts"; + public const string Inventory = "inventory"; + public const string Products = "products"; + public const string Reviews = "reviews"; +} +``` + +```csharp +services.AddHttpClient(Accounts, c => c.BaseAddress = new Uri("http://accounts.service.local/graphql")); +services.AddHttpClient(Inventory, c => c.BaseAddress = new Uri("http://inventory.service.local/graphql")); +services.AddHttpClient(Products, c => c.BaseAddress = new Uri("http://products.service.local/graphql")); +services.AddHttpClient(Reviews, c => c.BaseAddress = new Uri("http://reviews.service.local/graphql")); +``` + +The gateway is subscribed to the Redis cache. +As soon as the domain service has published its schema, the gateway grab the changes and update its own schema. + +```csharp +services + // This is the connection multiplexer that redis will use + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddRemoteSchemasFromRedis("Demo", sp => sp.GetRequiredService()); +``` + +## Example + +You can find a full schema federation example here [Federated Schema with Redis](https://github.com/ChilliCream/hotchocolate-examples/tree/master/misc/Stitching/federated-with-hot-reload) + +# Federation with schema polling + +You can also use federations without a Redis cache. In this case, you cannot hot reload the schema. +The configuration is very much the same as in Redis except the `PublishToRedis` part. +Your schema will expose an additional field. This field is used by the Gateway to fetch the schema definition. + +You will need to add a package reference to `HotChocolate.Stitching` to all your services: + + + +## Configuration of a domain service + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + + services + .AddGraphQLServer() + .AddQueryType() + // We initialize the schema on startup so it is published to the redis as soon as possible + .InitializeOnStartup() + // We configure the publish definition + .PublishSchemaDefinition(c => c + // The name of the schema. This name should be unique + .SetName("accounts")); +} +``` + +## Configuration of the gateway + +With the polling approach, we need to make the schema aware of the domain services. +We can just add the schema with `AddRemoteSchema`. + +```csharp +public static class WellKnownSchemaNames +{ + public const string Accounts = "accounts"; + public const string Inventory = "inventory"; + public const string Products = "products"; + public const string Reviews = "reviews"; +} +``` + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + // register the http clients th + services.AddHttpClient(Accounts, c => c.BaseAddress = new Uri("http://accounts.service.local/graphql")); + services.AddHttpClient(Inventory, c => c.BaseAddress = new Uri("http://inventory.service.local/graphql")); + services.AddHttpClient(Products, c => c.BaseAddress = new Uri("http://products.service.local/graphql")); + services.AddHttpClient(Reviews, c => c.BaseAddress = new Uri("http://reviews.service.local/graphql")); + + services + .AddGraphQLServer() + // add the remote schemas + .AddRemoteSchema(Accounts) + .AddRemoteSchema(Inventory) + .AddRemoteSchema(Products) + .AddRemoteSchema(Reviews); +``` + +## Example + +You can find a full schema federation with polling example here [Federated Schema with polling](https://github.com/ChilliCream/hotchocolate-examples/tree/master/misc/Stitching/federated-with-pull) + +# Configuration + +By default, all the fields that are declared on `Mutation` and `Query` are exposed on the gateway. +In case the schema you do not want to expose the root fields and prefer to define the extension points in an extension file, you can also ignore the root types for a schema on the domain service. + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services + // This is the connection multiplexer that redis will use + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType() + .PublishSchemaDefinition(c => c + .SetName("accounts") + // Ignore the root types of accounts + .IgnoreRootTypes() + // Declares where the type extension is used + .AddTypeExtensionsFromFile("./Stitching.graphql") + .PublishToRedis( + // The configuration name under which the schema should be published + "Demo", + // The connection multiplexer that should be used for publishing + sp => sp.GetRequiredService())); +} +``` + +In case you choose to ignore the root types, make sure to add a `Query` and `Mutation` type to the gateway. +If there are no root types registered on the gateway the schema will be invalid. + +```csharp +services + // This is the connection multiplexer that redis will use + .AddSingleton(ConnectionMultiplexer.Connect("stitching-redis.services.local")) + .AddGraphQLServer() + .AddQueryType(d => d.Name("Query")) + .AddRemoteSchemasFromRedis("Demo", sp => sp.GetRequiredService()); +``` + +For further configuration with extension files, have a look at [Schema Configuration](/docs/hotchocolate/v12/distributed-schema/schema-configuration) +--- +title: "Distributed Schemas" +--- + +The strongly typed nature of a GraphQL schema makes it ideal for distribution. +It is possible to have specialized services that expose a GraphQL schema and bundle them together on a gateway. +There are two common approaches to schema distribution: schema stitching and federated schemas. + +Both approaches allow us to integrate services into one schema by folding types into one another and even renaming or removing parts. +You can also extend types and delegate resolvers to a specific backend service. + +With this, we can create a consistent GraphQL schema that hides the implementation details of our backend services and provides the consumer of our endpoint with the capability to fetch the data they need with one call, no under- or over-fetching and most importantly no repeated fetching + +Every Hot Chocolate GraphQL server can be used for schema stitching or federations. +You can also use both approaches on the same gateway. +You can for example stitch third-party services and use federations for domain services. + +_Schema of the Person Service_ + +```sdl +type Query { + persons: Person +} + +type Person { + id: ID! + name: String! +} +``` + +_Schema of the Address Service_ + +```sdl +type Query { + addressOfPerson(persondId: ID!): Address +} + +type Address { + street: String! + city: String! +} +``` + +_Gateway Service_ + +```sdl +type Query { + persons: Person +} + +type Person { + id: ID! + name: String! + address: Address +} + +type Address { + street: String! + city: String! +} +``` + +# Schema Stitching + +In the scenario of schema stitching, the configuration of the gateway schema is on the gateway itself. +The gateway pulls the schema from the downstream services and can be extended with SDL. +The benefit of this approach is that no configuration on the downstream services is needed. +With this approach, it is possible to also stitch third party GraphQL services. + +Gateway: + +```sdl +extend type Person { + address: Address @delegate(schema: "Address", path:"addressOfPerson(personId: $fields:Id")) +} +``` + +```mermaid +graph TD; + Gateway-->Address; + Gateway-->Person; +``` + +# Federated Schema + +The major difference between schema federation and schema stitching is where the extensions are stored. +In the federated approach, the schema extensions are defined on the federated service. +The domain services push the schema on a cache (like Redis). +The gateway is subscribed to changes from this cache and can hot reload the schema if the configuration of a domain service changes. +It is also possible to set up federations in a pull setup. +In this setup, the downstream services expose a field on their schema to fetch the stitching information. +The gateway then fetches the federation information from the downstream service on startup. +With this setup, you do not need a Redis instance, but lose the ability to hot-reload the schema on a change of the downstream service. + +The benefit of this approach is that the domain services define where they extend the Gateway schema. +This might first seem odd and you could argue that the domain service should not have any knowledge of the gateway schema. +Though in practice many companies see this as a feature rather than a limitation. +As the gateway schema grows, the configuration of the schema on the gateway with schema stitching will become more and more complex. +A change to a downstream service requires also a change to the gateway. This makes development and also deployment a lot more complex. +If teams have sovereignty over different domain services, these teams can work completely independently when you use federations. + +Address Service: + +```sdl +extend type Person { + address: Address @delegate(schema: "Address", path:"addressOfPerson(personId: $fields:Id")) +} +``` + +```mermaid +graph TD; + Gateway-->Address; + Gateway-->Person; + Address-->Redis; + Person-->Redis; + Redis-->Gateway +``` + +# A real world example + +To showcase how schema stitching works and what the problems are let us assume we have a service like Twitter, where a user can post messages. + +Moreover, let us assume we have three teams working on internal micro-/domain-services that handle certain aspects of that service. + +The first service is handling the message stream and has the following schema: + +```sdl +type Query { + messages(userId: ID!): [Message!] + message(messageId: ID!): Message +} + +type Mutation { + newMessage(input: NewMessageInput!): NewMessagePayload! +} + +type Message { + id: ID! + text: String! + createdBy: ID! + createdAt: DateTime! + tags: [String!] +} + +type NewMessageInput { + text: String! + tags: [String!] +} + +type NewMessagePayload { + message: Message +} +``` + +The second service is handling the users of the services and has the following schema: + +```sdl +type Query { + user(userId: ID!): User! + users: [User!] +} + +type Mutation { + newUser(input: NewUserInput!): NewUserPayload! + resetPassword(input: ResetPasswordInput!): ResetPasswordPayload! +} + +type NewUserInput { + username: String! + password: String! +} + +type ResetPasswordInput { + username: String! + password: String! +} + +type NewUserPayload { + user: User +} + +type ResetPasswordPayload { + user: User +} + +type User { + id: ID! + username: String! +} +``` + +Last but not least we have a third service handling the message analytics. In our example case we keep it simple and our analytics service just tracks three different counters per message. The schema for this service looks like the following: + +```sdl +type Query { + analytics(messageId: ID!, type: CounterType!): MessageAnalytics +} + +type MessageAnalytics { + id: ID! + messageId: ID! + count: Int! + type: CounterType! +} + +enum CounterType { + VIEWS + LIKES + REPLIES +} +``` + +With those three separate schemas our UI team would have to fetch from multiple endpoints. + +Even worse for our UI team, in order to build a stream view that shows the message text and the name of the user who posted the message, they would have to first fetch all the messages and could only then fetch the names of the users. + +This is actually one of the very things GraphQL tries to solve. + +With schema stitching or federations the services can be bundled together into one schema: + +```sdl +type Query { + me: User! + messages(userId: ID!): [Message!] + message(messageId: ID!): Message + user(userId: ID!): User! + users: [User!] +} + +type Mutation { + newMessage(input: NewMessageInput!): NewMessagePayload! + newUser(input: NewUserInput!): NewUserPayload! + resetPassword(input: ResetPasswordInput!): ResetPasswordPayload! +} + +type Message { + id: ID! + text: String! + createdBy: User + createdById: ID! + createdAt: DateTime! + tags: [String!] + views: Int! + likes: Int! + replies: Int! +} + +type NewMessageInput { + text: String! + tags: [String!] +} + +type NewMessagePayload { + message: Message +} + +type NewUserInput { + username: String! + password: String! +} + +type ResetPasswordInput { + username: String! + password: String! +} + +type NewUserPayload { + user: User +} + +type ResetPasswordPayload { + user: User +} + +type User { + id: ID! + username: String! + messages: [Message!] +} +``` +--- +title: "Schema Stitching" +--- + +In the centralized approach of schema distribution, all the configuration is done on the gateway. + +Hot Chocolate uses the schema name as an identifier for schemas. This schema name is used to create HTTP clients and references the schema in various places. It is good practice to store these schema names as a constant. + +You will need to add a package reference to `HotChocolate.Stitching` to your gateway: + + + +```csharp +public static class WellKnownSchemaNames +{ + public const string Accounts = "accounts"; + public const string Inventory = "inventory"; + public const string Products = "products"; + public const string Reviews = "reviews"; +} +``` + +The schema names are used to create a HttpClient. You have to register the HttpClients of the schema with `AddHttpClient`. + +```csharp +services.AddHttpClient(Accounts, c => c.BaseAddress = new Uri("http://accounts.service.local/graphql")); +services.AddHttpClient(Inventory, c => c.BaseAddress = new Uri("http://inventory.service.local/graphql")); +services.AddHttpClient(Products, c => c.BaseAddress = new Uri("http://products.service.local/graphql")); +services.AddHttpClient(Reviews, c => c.BaseAddress = new Uri("http://reviews.service.local/graphql")); +``` + +To make your schema aware of the downstream services you have to add them to the schema with `AddRemoteSchema` + +```csharp +services + .AddGraphQLServer() + .AddRemoteSchema(Accounts) + .AddRemoteSchema(Inventory) + .AddRemoteSchema(Products) + .AddRemoteSchema(Reviews) +``` + +By default, all the fields that are declared on `Mutation` and `Query` are exposed on the gateway. +In case the schema you do not want to expose the root fields and prefer to define the extension points in an extension file, you can also ignore the root types for a schema. + +```csharp +services + .AddGraphQLServer() + .AddQueryType(d => d.Name("Query")) + .AddRemoteSchema(Accounts, ignoreRootTypes: true) + .AddRemoteSchema(Inventory, ignoreRootTypes: true) + .AddRemoteSchema(Products, ignoreRootTypes: true) + .AddRemoteSchema(Reviews, ignoreRootTypes: true) + .AddTypeExtensionsFromFile("./Stitching.graphql"); +``` + +For further configuration with extension files, have a look at [Schema Configuration](/docs/hotchocolate/v12/distributed-schema/schema-configuration) + +# Example + +You can find a full schema stitching example here [Centralized Schema Stitching](https://github.com/ChilliCream/hotchocolate-examples/tree/master/misc/Stitching/centralized) +--- +title: "Subscriptions" +--- + +A Subscription type cannot be stitched from downstream services so it must be defined directly in the gateway schema. + +> [Learn more about defining a Subscription type](/docs/hotchocolate/v12/defining-a-schema/subscriptions) + +> Warning: Subscription stitching is coming in v13 + +After adding a Subscription type to the gateway service, you may encounter an error when building the gateway schema. + +```csharp +1. The schema builder was unable to identify the query type of the schema. Either specify which type is the query type or set the schema builder to non-strict validation mode. +``` + +If you turn off strict validation and generate the schema, the `schema` element won't include a `query` field despite a Query type being defined. + +```csharp +services + .AddGraphQLServer() + .ModifyOptions(o => + { + o.StrictValidation = false; + } + ) +``` + +```json +schema { + subscription: Subscription +} + +type Query { + messages: [Message!]! +} +``` + +To resolve this issue, use the Schema Options to specify the `QueryTypeName` and `MutationTypeName`. + +```csharp +services + .AddGraphQLServer() + .ModifyOptions(o => + { + o.QueryTypeName = "Query"; + o.MutationTypeName = "Mutation"; + } + ) +``` + +Generating the schema again results in a valid schema. + +```json +schema { + query: Query + subscription: Subscription +} + +type Query { + messages: [Message!]! +} + +type Subscription { + onMessagePosted: Message! +} +``` +--- +title: "Get started with GraphQL in .NET Core" +description: "In this tutorial, we will walk you through the basics of creating a GraphQL .NET server with Hot Chocolate." +--- + +import { ApiChoiceTabs } from "../../../components/mdx/api-choice-tabs" +import { InputChoiceTabs } from "../../../components/mdx/input-choice-tabs" + +