diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/404.html b/404.html new file mode 100644 index 000000000..6a9cde8ed --- /dev/null +++ b/404.html @@ -0,0 +1,3340 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found. Try one of the menu links or use the search engine in the top right corner.

+ +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-a-custom-domain-for-apis/index.html b/administer/configure-a-custom-domain-for-apis/index.html new file mode 100644 index 000000000..653fc71a6 --- /dev/null +++ b/administer/configure-a-custom-domain-for-apis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administer/configure-a-custom-domain-for-your-organization/index.html b/administer/configure-a-custom-domain-for-your-organization/index.html new file mode 100644 index 000000000..7e50ecbb6 --- /dev/null +++ b/administer/configure-a-custom-domain-for-your-organization/index.html @@ -0,0 +1,3762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure a Custom Domain for Your Organization - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure a Custom Domain for Your Organization

+

A custom domain is essential for effective branding, discoverability, and credibility of a website. Choreo allows you to easily configure custom domains for your organization, enabling developers to utilize it to configure custom URLs for their components such as API proxies, services, web applications, and webhooks.

+

This section provides an overview of Choreo’s custom domain configuration model and guides you through configuring a custom domain for your organization. It also walks you through utilizing a custom domain to configure a custom URL for a component.

+

Choreo custom domain configuration model

+

Choreo allows organization administrators to add custom domains for their organizations. When an administrator adds custom domains to an organization, component developers can submit requests to utilize the custom domains for their respective components. These requests require approval from the organization administrator. Upon approval, the custom domain and the relevant URL customization become available to the component.

+

Configure a custom domain for an organization

+

Prerequisites

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. +

    Create an organization in Choreo.

    +

    Create an organization in Choreo

    +
  4. +
+

Add a custom domain

+

To add a custom domain for your organization, follow the steps given below:

+
+

Note

+

To add a custom domain, you must have organization administrator privileges.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, click the Organization list.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. Click the URL Settings tab and then click the Active Domains tab.
  8. +
  9. Click + Add Domains.
  10. +
  11. +

    In the Add a Custom Domain pane, do the following:

    +
      +
    1. Enter your domain name.
    2. +
    3. Select the environment to apply the domain name.
    4. +
    5. +

      Select the entity type to apply the domain name.

      +
      +

      Tip

      +

      In this context:

      +
        +
      • The API entity type represents Choreo components exposed via an endpoint, including API Proxy, Service, and Webhook components.
      • +
      • The Web App entity type represents the Web Application component.
      • +
      +
      +
    6. +
    +
  12. +
  13. +

    Take a look at the generated CNAME target value displayed and create a DNS record associating the domain name to the CNAME target value with your DNS provider.

    +

    CNAME target value

    +
    +

    Info

    +

    When you select Developer Portal as the type, the environment is not applicable, and the CNAME alias will be displayed as follows: + Developer Portal CNAME target value

    +
    +
  14. +
  15. +

    Once the CNAME type DNS record is created, click Verify.

    +
    +

    Note

    +

    If the CNAME mapping is correct, the verification completes successfully. It can take some time for the configured CNAME mapping to be globally available.

    +
    +
  16. +
  17. +

    On successful verification of the custom domain, click Next.

    +
  18. +
  19. +

    Select a TLS certificate provider depending on your preference. You can either import the TLS certificates you created for the custom domain or click Let's Encrypt to allow Choreo to generate and manage the certificates for you.

    +
    +

    If you want to import your own certificate, it should adhere to specific guidelines

    +
      +
    • TLS certificate guidelines:
        +
      • It should be issued by a certificate authority (CA) and should contain the domain's public key along with additional information such as the domain name, the company that owns the domain, the certificate's expiration date, and the digital signature of the issuing CA.
      • +
      • It should be an X509 certificate.
      • +
      • It should be in the PEM format.
      • +
      • It should be issued directly or through a wildcard entry for the provided custom URL. For example,
          +
        • For direct issuance, the SSL file must include the exact domain name. For example, if the domain is apis.choreo.dev, the SSL file must include apis.choreo.com.
        • +
        • For wildcard entries, the SSL file should use a wildcard notation to cover all subdomains under the provided URL. For example, if the CNAME is apis.choreo.dev, the SSL file should use *.choreo.dev.
        • +
        +
      • +
      +
    • +
    • TLS key file guidelines:
        +
      • It should be in the PEM format.
      • +
      • It must be encrypted using RSA encryption.
      • +
      +
    • +
    • Certificate chain file guidelines:
        +
      • The chain file, which is essential for some clients to verify the authenticity of a server's SSL/TLS certificate, should contain your domain's SSL/TLS certificate (optional, as this can be provided via the certificate itself) and one or more intermediate certificates in the correct order, leading back to a root certificate.
      • +
      • All certificates in the chain should be X509 certificates in PEM format.
      • +
      +
    • +
    +
    +

    To proceed with this step in this guide, click Let's Encrypt.

    +
  20. +
  21. +

    To save the custom domain, click Add.

    +
  22. +
+

Now, you have successfully added a custom domain for your organization.

+

You can see the added custom domain listed in the Active Domains tab under the URL Settings tab.

+

Active domains

+

The custom domain you added will be available to the entity types in the specified environment. You can request the custom domain when configuring a custom URL for a component.

+
+

Note

+

If you add a custom domain for the Developer Portal type, the customization is applied immediately, and you can access the organization’s Developer Portal via the added domain.

+
+

If you want to view the entity types that use a particular custom domain, click the specific custom domain listed in the Active Domains tab under URL Settings.

+

Configure a custom URL for a component

+

When an organization administrator adds custom domains for specific environments, developers can request any available custom domain to configure a custom URL for a component in a specific environment.

+

Request a custom URL for a component

+

To request a custom URL for your component, follow the steps given below:

+
+

Note

+

Before you request a custom domain for a specific environment, ensure that the component is deployed to that environment.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to customize the URL.
  4. +
  5. In the left navigation menu, click Settings. This opens the component-level settings page.
  6. +
  7. +

    Click the URL Settings tab. This displays the active deployments of the component across different environments and indicates whether a custom URL is configured. If an active custom domain is available to configure a custom URL for a component in a specific environment, the Edit URL Mapping icon in the corresponding Action column becomes enabled.

    +

    Active deployments

    +
  8. +
  9. +

    To configure a custom URL for a component in a specific environment, click the Edit URL Mapping icon under the Action column corresponding to the respective environment. This opens the URL Settings dialog, where you can specify values to request for a custom URL.

    +

    URL settings

    +
  10. +
  11. +

    In the URL Settings dialog, select a domain to configure a custom URL.

    +
    +

    Tip

    +
      +
    • The Domain drop-down lists the available domains for the component. You can request for any listed domain.
    • +
    • If you want to request a custom URL for an API, you must specify an appropriate context path in the Path field. The Path field displays the default context path for the API. You can edit the path depending on your preference.
    • +
    +
    +
  12. +
  13. +

    Click Configure. This creates the custom URL mapping, which you can see under the URL Settings tab. The custom URL request will be in the Pending status until an organization administrator approves the request.

    +

    Pending custom URL request

    +
  14. +
+

Approve a custom URL request

+

When a developer requests a custom URL, the request will be listed in the organization-level settings page under the URL Settings tab.

+

To approve a custom URL mapping, follow the steps given below:

+
+

Note

+

To approve custom URL requests, you must have organization administrator privileges.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, click the Organization list.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. +

    Click the URL Settings tab and then click the Pending URL Requests tab. You will see all the pending URL mapping requests sent by developers.

    +

    Pending URL requests

    +
  8. +
  9. +

    Go to the custom URL you want to approve and click the corresponding Approve URL Mapping icon under the Action column.

    +
  10. +
  11. Review the details and click Approve.
  12. +
+

Once approved, the invoke URL of the component gets replaced with the configured custom URL.

+

Custom URL

+

Now you have successfully utilized the configured custom domain to set up a custom URL for a component.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-a-user-store-with-built-in-idp/index.html b/administer/configure-a-user-store-with-built-in-idp/index.html new file mode 100644 index 000000000..d2bc85fc1 --- /dev/null +++ b/administer/configure-a-user-store-with-built-in-idp/index.html @@ -0,0 +1,3535 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure a User Store with the Built-In Identity Provider - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure a User Store with the Built-In Identity Provider

+

Developers looking to experiment with a complete application development process that includes user authentication and authorization can utilize Choreo's built-in identity provider (IdP). Choreo's built-in identity provider allows you to seamlessly test your application's authentication by setting up test users and groups within Choreo.

+
+

Note

+

Although the built-in IdP facilitates user management support, it is limited to adding users with attributes and groups. Therefore, the built-in IdP user management capabilities are not recommended for use in production.

+
+

Prerequisites

+

Before you try out the steps in this guide, be sure you have administrator rights to your Choreo organization. This permission is essential to configure a user store with the built-in IdP.

+

Configure a Choreo built-in IdP user store

+

Follow the steps given below to configure a Choreo built-in IdP user store for an environment:

+
    +
  1. Go to https://console.choreo.dev/ and sign in.
  2. +
  3. In the Choreo Console top navigation menu, click the Organization list and then click on your organization.
  4. +
  5. In the left navigation menu, click Settings. This takes you to your organization settings.
  6. +
  7. Click the Application Security tab and then click the Identity Providers tab.
  8. +
  9. On the Identity Providers tab, click Manage in the Choreo Built-in Identity Provider pane.
  10. +
  11. In the Manage IdP pane, click on a specific environment tab depending on where you want to configure the built-in IdP user store.
  12. +
  13. You can download the sample User store template file(.csv ) from the User Store section. The template file content is similar to the following:
  14. +
+
username,password,groups,first_name,last_name,email
+"demouser","password1","[manager, engineering]","John","Doe","john@acme.org"
+
+ +
+

Note

+

The provided template file includes a sample user with associated attributes. To add new users, insert additional rows in the .csv file. To include more user attributes, add columns as required in the .csv file.

+
+
    +
  1. Specify appropriate user details in the template file and save it.
  2. +
  3. Select the template file that you saved and click Upload. A successful upload creates the user store and displays the configured users in the Users section.
  4. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/index.html b/administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/index.html new file mode 100644 index 000000000..effef4ae2 --- /dev/null +++ b/administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/index.html @@ -0,0 +1,3545 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Asgardeo as an External IdP - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Asgardeo as an External Identity Provider (IdP)

+

Asgardeo is an identity-as-a-service (IDaaS) solution designed to create seamless login experiences for your applications. Asgardeo seamlessly integrates with Choreo, providing powerful API access control through the use of API scopes. This enables restricting API access to designated user groups. By configuring Asgardeo as an external IdP in Choreo, you can leverage your Asgardeo user stores to manage API access control effectively. This guide walks you through the steps to set up Asgardeo as your external IdP.

+

Prerequisites

+

Before you proceed, be sure to complete the following:

+
    +
  • +

    Create an Asgardeo application. You can follow the Asgardeo guide to register a standard-based application.

    +
  • +
  • +

    Find the well-known URL: + Go to the info tab of the Asgardeo application to view the endpoints and copy the Discovery endpoint.

    +
  • +
  • +

    Find the Client ID: + Go to the Protocol tab of the Asgardeo application and copy the Client ID.

    +
  • +
+

Add Asgardeo as an external IdP in Choreo

+

Follow the steps below to add Asgardeo as an external IdP in Choreo:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. In the header, click the Organization list. This opens the organization-level settings page.
  6. +
  7. Click the Application Security tab and then click the Identity Providers tab.
  8. +
  9. To add an identity provider, click + Identity Provider.
  10. +
  11. Click Asgardeo.
  12. +
  13. In the Asgardeo dialog that opens, specify a name and a description for the IdP.
  14. +
  15. In the Well-Known URL field, paste the well-known URL that you copied from your Asgardeo instance by following the prerequisites.
  16. +
  17. +

    Leave the Apply to all environments checkbox selected. This allows you to use the tokens generated via this IdP to invoke APIs across all environments.

    +
    +

    Note

    +

    If you want to restrict the use of tokens generated via this IdP to invoke APIs in specific environments, clear the Apply to all environments checkbox and select the necessary environments from the Environments list.

    +
    +
  18. +
  19. +

    Click Next. This displays the server endpoints that are useful to implement and configure authentication for your application.

    +
  20. +
  21. Click Add.
  22. +
+

Now you have configured Asgardeo as an external IdP in Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/index.html b/administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/index.html new file mode 100644 index 000000000..64dc7cb14 --- /dev/null +++ b/administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/index.html @@ -0,0 +1,3537 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Azure as an External IdP - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Azure Active Directory (Azure AD) as an External Identity Provider (IdP)

+

In organizations leveraging Microsoft Azure Active Directory (Azure AD) for identity and access management (IAM), integrating it with Choreo offers powerful API access control. This control hinges on the use of API scopes. That is, it enables the restriction of access to a designated group of users. This document guide you step-by-step to configure Azure AD as your external IdP.

+

Prerequisites

+

Before you try out this guide, be sure you have the following:

+
    +
  • An Azure Active Directory account: If you don’t already have one, setup an Azure Active Directory account at https://azure.microsoft.com/en-gb/.
  • +
  • Administrator rights to your Choreo organization: You need this to configure the Azure AD account in your organization.
  • +
+

Add Azure Active Directory as an external IdP in Choreo

+

Follow the steps below to add Azure AD as an IdP in Choreo:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. In the header, click the Organization list. This will open the organization level settings page.
  6. +
  7. On the Application Security tab, click Identity Providers and then click + Identity Provider.
  8. +
  9. Select Microsoft Entra ID (Azure AD) as the Identity Provider.
  10. +
  11. Provide a name and a description for the IdP.
  12. +
  13. +

    To obtain the Well-Known URL of your Azure AD instance, on your Azure account, under Azure Active Directory go to App registrations, and then Endpoints. Copy the URI underOpenID Connect metadata document.

    +
    +

    Info

    +
      +
    • In azure, there are two versions of access tokens available. By default, the IDP applications you create use the v1 access token. Therefore, if you intend to use the v1 access token, when providing the Well-Known URL, omit the v2.0 path segment from the URL. Learn more +For example, convert https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration-> https://login.microsoftonline.com/<tenant-id>/.well-known/openid-configuration
    • +
    • If you intend to work with v2.0, then the IDP application's manifest should be changed as explained in the access tokendocumentation.
    • +
    +
    +
  14. +
  15. +

    Leave the Apply to all environments checkbox selected. However, if you want to restrict the use of the external IdP to a certain environment, you can select them from the Environments list.

    +
  16. +
  17. Review the endpoints and click Next.
  18. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-approvals-for-choreo-workflows/index.html b/administer/configure-approvals-for-choreo-workflows/index.html new file mode 100644 index 000000000..801816517 --- /dev/null +++ b/administer/configure-approvals-for-choreo-workflows/index.html @@ -0,0 +1,3456 @@ + + + + + + + + + + + + + + + + + + + + + + + + Configure Approvals for Choreo Workflows - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Approvals for Choreo Workflows

+

Choreo allows you to configure approval processes for specific workflows within the platform. An approval process for a workflow ensures that critical or sensitive changes are properly managed and controlled.

+

Choreo currently allows you to configure approvals for environment promotion workflows, with support for API subscription approvals coming soon.

+

Permissions to review and respond to approval requests

+

To review and respond to approval requests, a user must have the following permissions. Administrators must ensure that users designated to review and respond to approval requests have these permissions:

+
    +
  • WORKFLOW-MANAGEMENT: Grants access to view and approve workflow requests. Each workflow type has a separate permission.
  • +
  • PROJECT-MANAGEMENT: Grants access to view and approve workflow requests. This is the same permission used to update or delete projects.
  • +
+

Set up an approval process for a workflow

+

To set up an approval process for a workflow, follow these steps:

+
+

Note

+
    +
  • You must have administrator privileges in Choreo to configure workflow approvals.
  • +
  • Administrators can designate specific roles and assignees to review and respond to requests associated with each workflow.
  • +
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, go to the Organization list and select your organization.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. Click the Workflows tab.
  8. +
  9. Click the edit icon corresponding to the workflow for which you want to configure an approval.
  10. +
  11. +

    In the Configure Workflow dialog that opens, select roles and assignees to review and respond to workflow approval requests.

    +
      +
    • In the Roles field, select one or more roles depending on your preference. Any user assigned to these roles can review and respond to requests.
    • +
    • In the Assignees field, select specific users who can review and approve workflow requests. Assignees can be any Choreo user, even if they are not assigned to a selected role.
    • +
    +
    +

    Important

    +

    Currently, there is no validation to ensure that the specified roles and assignees have the necessary permissions to review and respond to requests. If the required permissions are not correctly configured, some users may receive email notifications but will be unable to review the requests.

    +
    +
  12. +
  13. +

    Click Save. This configures and enables the approval process for the workflow.

    +
  14. +
+

Once you configure an approval process for a workflow, developers must submit a request for approval to use the workflow. An authorized assignee must then review and approve the request for a developer to proceed with the task related to the workflow. Depending on the workflow, there can be tasks where the execution may occur automatically upon approval.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-developer-portal-self-sign-up/index.html b/administer/configure-developer-portal-self-sign-up/index.html new file mode 100644 index 000000000..3d79e29b4 --- /dev/null +++ b/administer/configure-developer-portal-self-sign-up/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administer/configure-enterprise-login/index.html b/administer/configure-enterprise-login/index.html new file mode 100644 index 000000000..ff957bbfc --- /dev/null +++ b/administer/configure-enterprise-login/index.html @@ -0,0 +1,3744 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Enterprise Login - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Enterprise Login

+

With Choreo, you can configure enterprise login to allow users from an external identity provider (IdP) to sign in to Choreo seamlessly without changing their credentials.

+

This guide walks you through the steps to configure enterprise login for your organization in Choreo.

+

Prerequisites

+

Before you proceed with the configuration, set up the following:

+
    +
  • A valid email domain for your organization.
  • +
  • Access the Choreo Console at https://console.choreo.dev/ via your Google, GitHub, or Microsoft account. If you are a new user, create an organization with a unique organization name. For example, "Stark Industries".
  • +
+

Configure enterprise login for your Choreo organization

+

To configure enterprise login for your Choreo organization, follow the steps given below:

+
    +
  • +

    If you already have a support account with us, send us your organization name/handle and the email domains specific to your organization through our support portal.

    +
  • +
  • +

    If you do not have a support account with us yet, send an email to choreo-help@wso2.com requesting to enable enterprise login for your organization.

    +
    +

    Tip

    +

    Ensure you include the following information in the request:

    +
      +
    • Organization name or handle. For example, “Stark Industries” or “starkindustries”.
    • +
    • Email domains specific to your organization. For example, “@stark.com”, “@starkindustries.com”, and “@stark.eu.
    • +
    +
    +
    +

    Sample email

    +

    Subject : [Stark Industries] Configure enterprise login

    +

    Hi CS team,

    +

    I need to configure enterprise login for my organization. Can you please do the necessary configurations to proceed?

    +

    My organization details are as follows:

    +
      +
    • Organization name: Stark Industries
    • +
    • Organization handle: starkindustries
    • +
    • Email domains specific to my organization: “@stark.com”, “@starkindustries.com”, and “@stark.eu”
    • +
    +

    Thank you.

    +
    +

    The Choreo support team will perform the necessary configurations and respond to you with a verification code. You must sign in to your domain host account and configure the DNS record for your email domain with the following values:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Name/Host/AliasSpecify @ or leave it blank
    Time to Live (TTL)Keep the default value or use 86400
    Value/Answer/Destinationwso2-domain-verification:<verification_code>
    +
  • +
+

Now, you are ready to bring your own identity to Choreo.

+

Bring your own identity to Choreo

+

When you create an organization in Choreo, an organization with the same name is provisioned for you in Asgardeo. To bring your own identity to Choreo, you must configure a federated enterprise IdP on Asgardeo in the organization that is provisioned for you.

+

Follow the steps given below to configure the federated IdP:

+
    +
  1. Sign in to Asgardeo.
  2. +
  3. To configure a federated enterprise identity provider for your Asgardeo organization, follow the steps in Asgardeo documentation - Add Standard-Based Login.
  4. +
  5. In the Asgardeo Console left navigation menu, click Applications. You will see an application named WSO2_LOGIN_FOR_CHOREO_CONSOLE.
  6. +
  7. Click on the application to edit it.
  8. +
  9. Click the Sign-in Method tab. You can observe the configured connection.
  10. +
+

Now, users in your enterprise IdP can sign in to the Choreo Console using their enterprise IDs.

+

Configure role-based access control for enterprise login

+

To streamline the enterprise login process and grant appropriate permission, Choreo provides the flexibility to configure role-based access control for users who reside in an external IdP.

+

To set up role-based access control for enterprise login within Choreo, follow the steps given below:

+

Prerequisites

+

Before you proceed with the configuration, make sure you complete the following:

+
    +
  1. Configure enterprise login for your organization. For instructions, see Configure enterprise login for your Choreo organization.
  2. +
  3. Ensure your enterprise identity provider includes the group/role attributes in tokens it sends to Asgardeo via the respective protocol.
  4. +
  5. Be sure you have administrator privileges in Choreo.
  6. +
+

Step 1: Configure Asgardeo

+
    +
  1. Sign in to Asgardeo.
  2. +
  3. +

    Configure your IdP as an external IdP in Asgardeo. Depending on your IdP, you can select OpenID Connect or SAML as the protocol between Asgardeo and your IdP.

    +
    +

    Note

    +

    If you are using OpenID Connect, configure the requested scopes accordingly for Asgardeo to get the relevant group/role details from the external IdP.

    +
    +
  4. +
  5. +

    To configure the application, follow the steps given below:

    +
      +
    1. In the Asgardeo Console left navigation menu, click Applications. You will see an application named WSO2_LOGIN_FOR_CHOREO_CONSOLE.
    2. +
    3. Click on the application to edit it.
    4. +
    5. Click the Sign-in Method tab.
    6. +
    7. +

      Configure the IdP for login depending on the protocol you selected:

      + +
    8. +
    9. +

      Click the User Attributes tab.

      +
    10. +
    11. Select the Groups attribute and click the arrow to expand the section. Then, select the Requested checkbox.
    12. +
    13. Click Update.
    14. +
    +
  6. +
  7. +

    To add the user attributes as OpenID Connect scopes, follow the steps given below:

    +
      +
    1. In the Asgardeo Console left navigation menu, click Scopes.
    2. +
    3. In the OpenID Connect Scopes pane, click OpenID to edit it.
    4. +
    5. Click New Attribute and select the Groups attribute.
    6. +
    7. Click Save and then click Save Changes.
    8. +
    +
  8. +
+

Step 2: Map Choreo groups to enterprise IdP groups via the Choreo Console

+
+

Note

+

Before you map Choreo groups to enterprise IdP groups, ensure you meet the following criteria:

+
    +
  • Asgardeo is your key manager.
  • +
  • You have permission to perform actions of the organization administrator role.
  • +
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console, go to the top navigation menu and click Organization. This takes you to the organization's home page.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. In the Access Control tab, click Groups.
  8. +
  9. +

    Click Manage IdP Group Mapping. + Group mapping

    +
  10. +
  11. +

    Click the edit icon corresponding to the Choreo group you want to map to the enterprise IdP group.

    +
  12. +
  13. +

    In the IdP Group Name field, specify the exact name you configured in the enterprise IdP and enter to add it.

    +
    +

    Tip

    +

    If there is a change to the IdP group mapping, it takes effect from the next login session onwards.

    +
    +
  14. +
  15. +

    Click Save.

    +
  16. +
+

By following these steps, you have successfully configured role-based access control for enterprise login in Choreo, allowing users from the external IdP to have the appropriate permission.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/configure-self-sign-up/index.html b/administer/configure-self-sign-up/index.html new file mode 100644 index 000000000..22b059502 --- /dev/null +++ b/administer/configure-self-sign-up/index.html @@ -0,0 +1,3705 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Self-Sign-Up - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Self-Sign-Up

+

With Choreo, you can set up a self-sign-up page for your Developer Portal. The self-sign-up page allows users to easily access your Developer Portal and subscribe to APIs. When you configure self-sign-up, users can create their accounts and access your Developer Portal without any manual intervention from you.

+

This page walks you through the steps to configure self-sign-up for your Developer Portal.

+

Prerequisites

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/ using your Google, GitHub, or Microsoft account.
  2. +
  3. If you are a new user, create an organization with a unique organization name. For example, "Stark Industries".
  4. +
+

Configure Developer Portal self-sign-up

+

To configure self-sign-up, follow the steps given below:

+
    +
  1. +

    Send an email to choreo-help@wso2.com requesting to configure enterprise IdP for the Developer Portal of your organization.

    +
    +

    Tip

    +

    Ensure you include the organization name or handle in the request.

    +
    +
    +

    Sample email

    +

    Subject : [Stark Industries] Configure enterprise IdP for Developer Portal

    +

    Hi CS team,

    +

    I need to configure enterprise IdP for my organization’s Developer Portal to enable self-sign-up. Can you please do the necessary configurations to proceed?

    +

    My organization details are as follows:

    +
      +
    • Organization name: Stark Industries
    • +
    • Organization handle: starkindustries
    • +
    +

    Thank you

    +
    +

    The Choreo support team will perform the necessary configurations and respond to your request.

    +
  2. +
  3. +

    When you receive a response, sign in to Asgardeo using the same credentials that you used to sign in to Choreo.

    +
  4. +
  5. +

    In the Asgardeo Console, click View all applications.

    +

    View all applications

    +

    You will see an application named WSO2_LOGIN_FOR_CHOREO_DEV_PORTAL.

    +

    Applications

    +
  6. +
  7. +

    Click on the application to edit it and enter your organization’s Developer Portal URL as the Access URL of the application. For example, https://devportal.choreo.dev/starkindustries.

    +
  8. +
  9. Click Update.
  10. +
  11. +

    To add user attributes, follow these steps:

    +
    +

    Note

    +

    If you have enabled enterprise login and you want to add the Groups attribute during self-sign-up configuration, avoid making it mandatory. This ensures proper access control and prevents unauthorized privileges. If you make the Groups attribute mandatory, it allows self-signed-up users to specify a group and assume roles associated with it.

    +
    +
      +
    1. Click the User Attributes tab.
    2. +
    3. +

      To add the email as a mandatory user attribute, select Email and click the arrow to expand the section. Then, select the Requested and Mandatory checkboxes.

      +

      Email attribute

      +
    4. +
    5. +

      To add the first name and last name as optional attributes, select Profile and click the arrow to expand the section. Then, select the Requested checkbox for the First Name and the Last Name attributes.

      +

      Profile attribute

      +
    6. +
    7. +

      Click Update.

      +
    8. +
    +
  12. +
  13. +

    To add the user attributes as OpenID Connect scopes, follow these steps:

    +
      +
    1. In the Asgardeo Console left navigation menu, click Scopes.
    2. +
    3. In the OpenID Connect Scopes pane, click OpenID to edit it.
    4. +
    5. Click + New Attribute.
    6. +
    7. Select Email, First Name, and Last Name as the attributes to associate with the OpenID scope.
    8. +
    9. +

      Click Save and then click Save Changes.

      +

      Save attributes as scopes

      +
    10. +
    +
  14. +
  15. +

    To configure basic authentication as the sign-in method, follow these steps:

    +
      +
    1. In the Asgardeo Console left navigation menu, click Applications.
    2. +
    3. In the Applications pane, click the WSO2_LOGIN_FOR_CHOREO_DEV_PORTAL application to edit it.
    4. +
    5. +

      Click the Sign-in Method tab and then click Start with default configuration.

      +

      Add sign-in method

      +
    6. +
    7. +

      Click Update.

      +
    8. +
    +
  16. +
  17. +

    To configure self-registration, follow these steps:

    +
      +
    1. In the Asgardeo Console left navigation menu, click Self Registration.
    2. +
    3. In the Self Registration pane, click Configure.
    4. +
    5. To enable self-registration, turn on the toggle.
    6. +
    7. Select Account verification. This displays a confirmation message to enable account verification.
    8. +
    9. Click Continue.
    10. +
    11. Specify an appropriate value in the Account verification link expiry time field.
    12. +
    13. +

      Click Update.

      +

      Configure self-registration

      +
    14. +
    +
  18. +
+

Once you complete these steps, you will see a sign up link similar to the following in your Developer Portal:

+

Sign-up

+

Users can click LOGIN/SIGN UP and then click Create an account to sign up to access your Developer Portal.

+

Create an account

+

Manage new users

+

To manage users who want to access your Developer Portal via self-sign-up, you have two possible approaches:

+
    +
  • Enable auto-approval for new user registrations: This approach automates the user approval process. When you enable auto-approval, each user who creates an account and signs up to your Developer Portal can access it by default.
  • +
  • Manually approve or reject user accounts: This allows you to review the list of user registrations and manually approve or reject each registration as needed.
  • +
+

Enable auto-approval for new user registrations

+

To automatically approve each new user account registered on your Developer Portal, follow the steps given below:

+
    +
  1. In the Choreo Console, click your username in the top right corner.
  2. +
  3. In the drop-down menu, click Settings. This opens the Organization pane, where you can make necessary changes to organization settings.
  4. +
  5. In the Organization pane, click Self Signups.
  6. +
  7. To enable auto-approval, turn on the toggle.
  8. +
+

Once you enable auto-approval, users can sign in to your Developer Portal and view your APIs and applications immediately after creating an account.

+

Manually approve or reject user accounts

+

If you have not enabled auto-approval, you can manually approve or reject new user registrations. Once a user creates an account, Choreo sends an email to ask the user to confirm the account. To manually approve or reject user accounts, follow the steps given below:

+
    +
  1. In the Choreo Console, click your username in the top right corner.
  2. +
  3. In the drop-down menu, click Settings. This opens the Organization pane, where you can make necessary changes to organization settings.
  4. +
  5. In the Organization pane, click Self Signups. You will see the user accounts listed for approval.
  6. +
  7. +

    To approve a user account, click Approve. To reject an account, click Reject.

    +
      +
    • If you approve an account, the user will receive an email confirming the approval.
    • +
    • +

      If you reject an account, the user will receive an email mentioning that their account is rejected.

      +
      +

      Note

      +

      A rejected user cannot sign up to your Developer Portal using the same account again.

      +
      +
    • +
    +
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/connect-to-an-external-identity-provider/index.html b/administer/connect-to-an-external-identity-provider/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/administer/connect-to-an-external-identity-provider/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administer/control-access-in-the-choreo-console/index.html b/administer/control-access-in-the-choreo-console/index.html new file mode 100644 index 000000000..4572858b8 --- /dev/null +++ b/administer/control-access-in-the-choreo-console/index.html @@ -0,0 +1,3718 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Control Access in the Choreo Console - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Control Access in the Choreo Console

+

In the Choreo Console, you have the ability to manage access to projects and the actions that can be performed within them. Administrators have the capability to restrict project access to specific user groups. This feature is useful when you need certain user groups to have access to particular projects or for a set of projects.

+

Choreo uses Roles, Groups, and a Mapping level to control access to the Choreo Console as follows:

+
    +
  • Role : Role is a collection of permissions. Choreo has a predefined set of roles with permissions assigned to them. Learn more
  • +
  • +

    Group : Group is a collection of users. A user group requires a role or multiple roles to be assigned to it so that the users in those groups get the relevant permissions via the assigned roles. Learn more

    +
  • +
  • +

    Mapping level : A mapping level defines the extent at which a role-group mapping can be done. Choreo has two defined resource levels.

    +
      +
    • Organization : You can assign a role to a group or associate a group with a role within the organization. This ensures that
      + all users in a group inherit the permissions granted by that role across all organizational resources. + For example, if a user has edit_project permission at the organization mapping level, that user can edit all the projects in the organization.
    • +
    • Project : You can assign a role to a group or associate a group with a role within a specific project resource. This ensures + that users in the group inherit the permissions granted by that role only within the context of the specified project. + For example, If a user has edit_project permission at the project mapping level, that user can only edit the specified project.
    • +
    +
  • +
+

In Choreo, authorization operates by assigning a role to a group at a specified level. The level at which the role is assigned determines the extent of permissions granted to users.

+
+

Important

+

Avoid assigning multiple roles to a single user across different projects or levels (organization and project). Such assignments can grant users unintended permission to some projects, allowing them to perform tasks they shouldn't have access to. Therefore, it is recommended to assign only one role to a user across projects or levels to ensure proper access control.

+
+
+

Info

+

In Choreo, organization-level permissions take precedence over project-level permissions.

+
+

To elaborate further, refer to the following diagram.

+

The following diagram depicts a role-group assignment at a specific resource level. In the diagram, an admin user has assigned the Developer role to all members of the Engineering group within the Engineering Project. This grants users in the Engineering group the ability to perform all actions allowed by the Developer role within the Engineering Project.

+

Console access control

+

Sample scenario

+

Now that you understand the basic concepts of access control within the Choreo Console, let’s try out a sample scenario to manage access within a project.

+

Assume you are overseeing the Engineering Project within your organization and you need to grant development access to specific users solely within this project. Here's a step-by-step guide on how to achieve this:

+

Step 1: Create a project

+

Follow the steps given below to create a project:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. +
  3. On the organization home page, click + Create Project.
  4. +
  5. +

    Enter a display name, unique name, and description for the project. You can enter the values given below:

    +
    +

    Info

    +

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Display NameEngineering Project
    Nameengineering-project
    Project DescriptionMy sample project
    +
  6. +
  7. +

    Click Create. This creates the project and takes you to the project home page.

    +
  8. +
+

Step 2: Create a new group

+

Follow the steps given below to create a group with the name Engineering Project Developer:

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your project.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Access Control tab and then click the Groups tab.
  6. +
  7. Click + Create Group.
  8. +
  9. +

    Enter a group name and group description. You can enter the values given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Group NameEngineering Project Developer
    Group DescriptionUsers with development access within the engineering project
    +
  10. +
  11. +

    Click Create.

    +
  12. +
+

Step 3: Assign roles to the group

+

Follow the steps given below to assign the Developer role to the Engineering Project Developer group that you created:

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the Engineering Project that you created.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Access Control tab and then click the Groups tab.
  6. +
  7. On the Groups tab, search for the Engineering Project Developer group and click the corresponding edit icon.
  8. +
  9. Click +Add Roles.
  10. +
  11. In the Add Roles to Group in Project dialog that opens, click the Roles list and select Developer.
  12. +
  13. +

    Click Add. This assigns the Developer role to the group. You should see the mapping level as Project (Engineering Project) as follows, indicating the scope of the mapping:

    +

    Mapping level

    +
  14. +
+

This means that you have granted developer access to users in the Engineering Project Developer group in the scope of the Engineering Project.

+

Now that you have set up access control, you can proceed to add users to the new group.

+

Step 4: Add users to the group

+

There are two approaches you can follow to add users to the group.

+

Add a new user as a project developer

+

Follow the steps given below to add a new user as a project developer:

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your project.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Access Control tab and then click the Users tab.
  6. +
  7. Click +Invite Users.
  8. +
  9. In the Invite Users dialog,
  10. +
  11. Specify the email addresses of the users in the Emails field.
  12. +
  13. Click the Groups list and select Engineering Project Developer.
  14. +
  15. Click Invite.
  16. +
+

Add an existing user as a project developer

+

Follow the steps given below to add an existing user as a project developer:

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your project.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Access Control tab and then click the Users tab.
  6. +
  7. Search for the existing user you want to add to the Engineering Project Developer group.
  8. +
  9. Click the edit icon corresponding to the user.
  10. +
  11. Click +Assign Groups.
  12. +
  13. In the Add Groups to User dialog, click the Groups list and select Engineering Project Developer.
  14. +
  15. Click Add.
  16. +
+
+

Tip

+

Make sure to remove the user from any other groups to avoid granting organization-level access unintentionally.

+
+
+

Note

+
    +
  • Existing groups are already mapped to similar roles at the organization level. Therefore, adding users to those groups or keeping users in them, will give organization-level access to the users.
  • +
  • When users are added to the Engineering Project Developer group, they will only have developer access to the Engineering Project.
  • +
  • You can invite new users or add existing users to new groups within the Engineering Project, and based on their requirements, assign roles like Developer, API Publisher, etc.
  • +
+
+

Now you have successfully set up access control within your project.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/create-api-subscription-plans/index.html b/administer/create-api-subscription-plans/index.html new file mode 100644 index 000000000..3641fa242 --- /dev/null +++ b/administer/create-api-subscription-plans/index.html @@ -0,0 +1,3475 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create API Subscription Plans - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Create API Subscription Plans

+

API subscription plans are essential to control and manage access to APIs. These plans define the rules and limitations on how clients can interact with APIs, ensuring efficient resource utilization and robust security. With the option to set rate limits and burst control, subscription plans allow API providers to manage traffic, prevent misuse, and offer tiered service levels. Organizations can implement subscription plans to provide varying levels of API access, accommodating different user needs and business models, while ensuring optimal performance and security.

+

In Choreo, users with the administrator role can create, update, and delete subscription plans at the organization level.

+
+

Tip

+

Deleting a subscription plan is only possible if there are no active subscriptions associated with it.

+
+

To create an organization-level subscription plan, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, go to the Organization list and select your organization.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. Click the API Management tab and then click Subscription Plans.
  8. +
  9. Click + Add Subscription Plan.
  10. +
  11. +

    In the Create Subscription Plan pane, enter the appropriate values for each field:

    +
    +

    Note

    +
      +
    • In the Name field, you must specify a name to uniquely identify the subscription plan in various contexts. The value is editable only at the time you create the subscription plan. You cannot change the name after you create it.
    • +
    • The Stop on Quota Reach checkbox is selected by default when creating a subscription plan. When selected, requests return an HTTP 429 response if the request count exceeds the limit. If you clear the checkbox, requests are allowed even if the quota is exceeded.
    • +
    • Burst control protects your backend from sudden request spikes and manages API usage. It’s especially useful for subscription plans where the request count is enforced over a long period, to prevent consumers from using their entire quota too quickly. Ensure you select the Burst Control checkbox when the Request Count Time Unit is selected as Hour or Day.
    • +
    +
    +

    Create subscription plan

    +
  12. +
  13. +

    Click Create. This creates the subscription plan and lists it under Subscription Plans.

    +
  14. +
+

After creating subscription plans, users with the API publisher role can assign subscription plans to APIs. API consumers can then choose the appropriate subscription plan during the subscription process depending on their requirements.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/customize-developer-portal-domain/index.html b/administer/customize-developer-portal-domain/index.html new file mode 100644 index 000000000..653fc71a6 --- /dev/null +++ b/administer/customize-developer-portal-domain/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administer/customize-the-developer-portal/index.html b/administer/customize-the-developer-portal/index.html new file mode 100644 index 000000000..d47a4733c --- /dev/null +++ b/administer/customize-the-developer-portal/index.html @@ -0,0 +1,3557 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Customize the Developer Portal - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Customize the Developer Portal

+

The Developer Portal allows API consumers to find and consume APIs with ease. You can change the look and feel of your Developer Portal by changing the theme to match your brand. Doing so will help you give a better developer experience to your users.

+

To customize the Developer Portal theme, follow the steps given below:

+
+

Note

+
    +
  • To customize the Developer Portal theme for an organization, you need to be an admin user of that organization.
  • +
  • You cannot undo a change and restore or revert to a previous version of the theme. However, you can reset it to the default theme.
  • +
+
+
    +
  1. +

    Sign in to the Choreo Console at https://console.choreo.dev/ using a Google/ GitHub/ Microsoft account.

    +
  2. +
  3. +

    In the left pane, click Settings.

    +
  4. +
  5. +

    In the header, click the Organization list. This will open the organization level settings page.

    +
  6. +
  7. +

    In the API Management tab, click Devportal Theme.

    +

    Access Devportal theme

    +

    Once you access the theme, you can customize the Home page, color theme, font, header and footer, logos, etc., by expanding the relevant sections.

    +
  8. +
  9. +

    Make a change to the theme. For example, let's change the title on the Home page and the color theme.

    +
      +
    1. +

      To update the title on the Home page, expand the Home Page section, and in the Title field, change the default text (for example, to Try our APIs!).

      +
    2. +
    3. +

      To update the color theme, expand the Color Palette section, and change the colors as required (for example, change the background color to #C3C5CD and the primary color of the buttons to #086634).

      +
    4. +
    5. +

      Click Preview to view a preview of the Developer Portal with the changes you made. Based on the changes given in the examples, the preview appears as follows.

      +

      Preview of customization

      +
    6. +
    7. +

      Click Save to save your changes as a draft theme.

      +
    8. +
    9. +

      To apply the changes to the Developer Portal, toggle the Go Live switch. To confirm that you want to go live with the changes, click Enable in the message that appears.

      +
    10. +
    +
  10. +
  11. +

    Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.

    +
  12. +
+

The Home page will appear as it did in the preview.

+

Reset the Developer Portal theme

+

To reset the Developer Portal theme to the default theme, follow the steps given below:

+
    +
  1. +

    Sign in to the Choreo Console at https://console.choreo.dev/ using a Google, GitHub, or Microsoft account.

    +
  2. +
  3. +

    In the left pane, click Settings.

    +
  4. +
  5. +

    In the header, click the Organization list. This will open the organization level settings page.

    +
  6. +
  7. +

    In the Organization tab, click Devportal Theme, and then click Reset to Default.

    +
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/inviting-members/index.html b/administer/inviting-members/index.html new file mode 100644 index 000000000..c53f0647d --- /dev/null +++ b/administer/inviting-members/index.html @@ -0,0 +1,3411 @@ + + + + + + + + + + + + + + + + + + + + + + + + Inviting members - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Inviting members

+ +

Inviting users

+

An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/manage-members-of-an-organization/index.html b/administer/manage-members-of-an-organization/index.html new file mode 100644 index 000000000..a219aca3e --- /dev/null +++ b/administer/manage-members-of-an-organization/index.html @@ -0,0 +1,3510 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Members of an Organization - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Members of an Organization

+

An organization in Choreo is a logical grouping of users and user resources. A first-time user must create an organization and be a user of it when signing in to Choreo. Users and resources in an organization cannot access resources in another organization unless an admin of the other organization invites them and adds them as a user of that organization.

+

Inviting users

+

An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

+

Manage user permission

+

For details on how Choreo manages user permission, see Manage user permission.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administer/organization/index.html b/administer/organization/index.html new file mode 100644 index 000000000..82641658e --- /dev/null +++ b/administer/organization/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administer/review-workflow-approval-requests/index.html b/administer/review-workflow-approval-requests/index.html new file mode 100644 index 000000000..902e510bd --- /dev/null +++ b/administer/review-workflow-approval-requests/index.html @@ -0,0 +1,3443 @@ + + + + + + + + + + + + + + + + + + + + + + + + Review Workflow Approval Requests - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Review Workflow Approval Requests

+

In Choreo, administrators can configure approvals for workflows and assign specific users as approvers.

+

If you are assigned as an authorized reviewer for a particular workflow approval request, you will receive an email notification when a request is submitted for approval. The email includes a summary of the request and a link to the Approvals page in the Choreo Console, where you can review the details and either approve or reject the request.

+
+

Note

+
    +
  • Workflow approvals are managed at the project level. If a role with the necessary permissions is assigned in a project context, only members of the user group bound to that role within the specific project will receive notifications for requests made in that project. For example, if you are assigned the Project Admin role (which includes the necessary permissions) for project A, you will only be notified of workflow requests within project A.
  • +
  • Users with organization-level permissions will receive notifications for all workflow requests across any project in the organization.
  • +
+
+

Other approvers within your organization will also receive notifications for workflow requests and may review a request before you. If a request has already been reviewed, it will appear under the Past tab on the Approvals page.

+

Approval requests are submitted on behalf of the team. Once approved, any authorized team member can execute the task. For certain tasks, execution may occur automatically upon approval.

+

View workflow approval requests

+

To view workflow approval requests assigned to you, follow these steps:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, go to the Organization list and select your organization.
  4. +
  5. In the left navigation menu, click Approvals. This opens the Approvals page where you can see all approval requests assigned to you. The Pending tab lists requests that are yet to be reviewed. The Past tab displays requests already reviewed by you or other approvers, as well as requests canceled by the requester.
  6. +
  7. To view details of a specific request, click Review corresponding to it.
  8. +
+

Approve or reject an approval request

+

To approve or reject a request, follow these steps:

+
    +
  1. Follow the instructions in the View workflow approval requests section above to see details of the workflow you want to review. + Alternatively, click the Choreo Console link in the approval request email notification you received. This takes you to the request details in the Choreo Console.
  2. +
  3. Review the request and click Approve or Reject based on your decision.
  4. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/administration/configure-a-custom-domain-for-apis/index.html b/administration/configure-a-custom-domain-for-apis/index.html new file mode 100644 index 000000000..a7c3b5851 --- /dev/null +++ b/administration/configure-a-custom-domain-for-apis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administration/configure-developer-portal-self-sign-up/index.html b/administration/configure-developer-portal-self-sign-up/index.html new file mode 100644 index 000000000..d68d964cb --- /dev/null +++ b/administration/configure-developer-portal-self-sign-up/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administration/configure-enterprise-login/index.html b/administration/configure-enterprise-login/index.html new file mode 100644 index 000000000..e566507ef --- /dev/null +++ b/administration/configure-enterprise-login/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administration/connect-to-an-external-identity-provider/index.html b/administration/connect-to-an-external-identity-provider/index.html new file mode 100644 index 000000000..f37f89935 --- /dev/null +++ b/administration/connect-to-an-external-identity-provider/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administration/customize-developer-portal-domain/index.html b/administration/customize-developer-portal-domain/index.html new file mode 100644 index 000000000..732772748 --- /dev/null +++ b/administration/customize-developer-portal-domain/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/administration/customize-the-developer-portal/index.html b/administration/customize-the-developer-portal/index.html new file mode 100644 index 000000000..dd3604461 --- /dev/null +++ b/administration/customize-the-developer-portal/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/alerts/index.html b/alerts/index.html new file mode 100644 index 000000000..17db144ab --- /dev/null +++ b/alerts/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/api-management/api-governance/default-rulesets/owasp_top_10_doc/index.html b/api-management/api-governance/default-rulesets/owasp_top_10_doc/index.html new file mode 100644 index 000000000..5a4d0a937 --- /dev/null +++ b/api-management/api-governance/default-rulesets/owasp_top_10_doc/index.html @@ -0,0 +1,3717 @@ + + + + + + + + + + + + + + + + + + + + + + + + OWASP Top 10 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

OWASP Top 10

+

A set of rules enforcing OWASP security guidelines to prevent common vulnerabilities and ensure secure coding practices.

+

❌ owasp:api1:2023-no-numeric-ids

+

Use random IDs that cannot be guessed. UUIDs are preferred but any other random string will do.

+
+

❌ owasp:api2:2023-no-http-basic

+

Basic authentication credentials transported over network are more susceptible to interception than other forms of authentication, and as they are not encrypted it means passwords and tokens are more easily leaked.

+
+

❌ owasp:api2:2023-no-api-keys-in-url

+

API Keys are passed in headers, cookies, or query parameters to access APIs. Those keys can be eavesdropped, especially when they are passed in the URL, as logging or history tools will keep track of them and potentially expose them.

+
+

❌ owasp:api2:2023-no-credentials-in-url

+

URL parameters MUST NOT contain credentials such as API key, password, or secret.

+
+

❌ owasp:api2:2023-auth-insecure-schemes

+

There are many HTTP authorization schemes but some of them are now considered insecure, such as negotiating authentication using specifications like NTLM or OAuth v1.

+
+

❌ owasp:api2:2023-jwt-best-practices

+

JSON Web Tokens RFC7519 is a compact, URL-safe, means of representing claims to be transferred between two parties. JWT can be enclosed in encrypted or signed tokens like JWS and JWE.

+

The JOSE IANA registry provides algorithms information.

+

RFC8725 describes common pitfalls in the JWx specifications and in +their implementations, such as: +- the ability to ignore algorithms, eg. {"alg": "none"}; +- using insecure algorithms like RSASSA-PKCS1-v1_5 eg. {"alg": "RS256"}. +An API using JWT should explicit in the description +that the implementation conforms to RFC8725. +

components:
+  securitySchemes:
+    JWTBearer:
+      type: http
+      scheme: bearer
+      bearerFormat: JWT
+      description: |-
+        A bearer token in the format of a JWS and conformato
+        to the specifications included in RFC8725.
+

+
+

❌ owasp:api2:2023-short-lived-access-tokens

+

Using short-lived access tokens is a good practice, and when using OAuth 2 this is done by using refresh tokens. If a malicious actor is able to get hold of an access token then rotation means that token might not work by the time they try to use it, or it could at least reduce how long they are able to perform malicious requests.

+
+

❌ owasp:api4:2023-rate-limit

+

Define proper rate limiting to avoid attackers overloading the API. There are many ways to implement rate-limiting, but most of them involve using HTTP headers, and there are two popular ways to do that:

+

IETF Draft HTTP RateLimit Headers:. https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers//

+

Customer headers like X-Rate-Limit-Limit (Twitter: https://developer.twitter.com/en/docs/twitter-api/rate-limits or X-RateLimit-Limit (GitHub: https://docs.github.com/en/rest/overview/resources-in-the-rest-api)

+
+

❌ owasp:api4:2023-rate-limit-retry-after

+

Define proper rate limiting to avoid attackers overloading the API. Part of that involves setting a Retry-After header so well meaning consumers are not polling and potentially exacerbating problems.

+
+

❌ owasp:api4:2023-array-limit

+

Array size should be limited to mitigate resource exhaustion attacks. This can be done using maxItems. You should ensure that the subschema in items is constrained too.

+
+

❌ owasp:api4:2023-string-limit

+

String size should be limited to mitigate resource exhaustion attacks. This can be done using maxLength, enum or const.

+
+

❌ owasp:api4:2023-integer-limit

+

Integers should be limited to mitigate resource exhaustion attacks. This can be done using minimum and maximum, which can with e.g.: avoiding negative numbers when positive are expected, or reducing unreasonable iterations like doing something 1000 times when 10 is expected.

+
+

❌ owasp:api4:2023-integer-limit-legacy

+

Integers should be limited to mitigate resource exhaustion attacks. This can be done using minimum and maximum, which can with e.g.: avoiding negative numbers when positive are expected, or reducing unreasonable iterations like doing something 1000 times when 10 is expected.

+
+

❌ owasp:api4:2023-integer-format

+

Integers should be limited to mitigate resource exhaustion attacks. Specifying whether int32 or int64 is expected via format.

+
+

❌ owasp:api8:2023-define-cors-origin

+

Setting up CORS headers will control which websites can make browser-based HTTP requests to your API, using either the wildcard "*" to allow any origin, or "null" to disable any origin. Alternatively you can use "Access-Control-Allow-Origin: https://example.com" to indicate that only requests originating from the specified domain (https://example.com) are allowed to access its resources.

+

More about CORS here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.

+
+

❌ owasp:api8:2023-no-scheme-http

+

Server interactions must use the http protocol as it's inherently insecure and can lead to PII and other sensitive information being leaked through traffic sniffing or man-in-the-middle attacks. Use the https or wss schemes instead.

+

Learn more about the importance of TLS (over SSL) here: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html

+
+

❌ owasp:api8:2023-no-server-http

+

Server interactions must not use the http:// as it's inherently insecure and can lead to PII and other sensitive information being leaked through traffic sniffing or man-in-the-middle attacks. Use https:// or wss:// protocols instead.

+

Learn more about the importance of TLS (over SSL) here: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html

+
+

❌ owasp:api9:2023-inventory-access

+

Servers are required to use vendor extension x-internal set to true or false to explicitly explain the audience for the API, which will be picked up by most documentation tools.

+
+

❌ owasp:api9:2023-inventory-environment

+

Make it clear which servers are expected to run as which environment to avoid unexpected problems, exposing test data to the public, or letting bad actors bypass security measures to get to production-like environments.

+
+

⚠️ owasp:api3:2023-no-additionalProperties

+

By default JSON Schema allows additional properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with additionalProperties: false or add maxProperties.

+
+

⚠️ owasp:api3:2023-constrained-additionalProperties

+

By default JSON Schema allows additional properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with additionalProperties: false or add maxProperties

+
+

⚠️ owasp:api3:2023-no-unevaluatedProperties

+

By default JSON Schema allows unevaluated properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with unevaluatedProperties: false or add maxProperties.

+
+

⚠️ owasp:api3:2023-constrained-unevaluatedProperties

+

By default JSON Schema allows unevaluated properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with unevaluatedProperties: false or add maxProperties

+
+

⚠️ owasp:api4:2023-rate-limit-responses-429

+

OWASP API Security recommends defining schemas for all responses, even errors. A HTTP 429 response signals the API client is making too many requests, and will supply information about when to retry so that the client can back off calmly without everything breaking. Defining this response is important not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces. It also ensures your API/framework/gateway actually has rate limiting set up.

+
+

⚠️ owasp:api4:2023-string-restricted

+

To avoid unexpected values being sent or leaked, strings should have a format, RegEx pattern, enum, or const.

+
+

⚠️ owasp:api8:2023-define-error-validation

+

Carefully define schemas for all the API responses, including either 400, 422 or 4XX responses which describe errors caused by invalid requests.

+
+

⚠️ owasp:api8:2023-define-error-responses-401

+

OWASP API Security recommends defining schemas for all responses, even errors. The 401 describes what happens when a request is unauthorized, so its important to define this not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces.

+
+

⚠️ owasp:api8:2023-define-error-responses-500

+

OWASP API Security recommends defining schemas for all responses, even errors. The 500 describes what happens when a request fails with an internal server error, so its important to define this not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces.

+
+

ℹ️ owasp:api7:2023-concerning-url-parameter

+

Using external resources based on user input for webhooks, file fetching from URLs, custom SSO, URL previews, or redirects can lead to a wide variety of security issues.

+

Learn more about Server Side Request Forgery https://owasp.org/API-Security/editions/2023/en/0xa7-server-side-request-forgery/.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/index.html b/api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/index.html new file mode 100644 index 000000000..bf604e7c3 --- /dev/null +++ b/api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/index.html @@ -0,0 +1,3634 @@ + + + + + + + + + + + + + + + + + + + + + + + + WSO2 API Design Guidelines - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

WSO2 API Design Guidelines

+

A guide detailing best practices for creating robust, scalable, and secure APIs, ensuring alignment with industry standards for optimal design.

+

❌ path-casing

+

Paths must be kebab-case, with hyphens separating words.

+

Invalid Example

+

userInfo must be separated with a hyphen.

+
{
+    "/userInfo": {
+        "post: }
+       ....
+}
+
+ +

Valid Example

+
{
+    "/user-info": {
+       "post: }
+       ....
+}
+
+ +
+

❌ paths-no-file-extensions

+

Paths must not include json or xml file extensions.

+

Invalid Example

+

The path contains a .json extension.

+
{
+    "/user.json": {
+       "post: }
+       ....
+}
+
+ +

Valid Example

+
{
+    "/user": {
+       "post: }
+       ....
+}
+
+ +
+

❌ paths-no-http-verbs

+

Verbs such as get, delete, and put must not be included in paths because this information is conveyed by the HTTP method.

+

Invalid Example

+

The path contains the verb get.

+
{
+    "/getUsers": {
+       "post: }
+       ....
+}
+
+ +

Valid Example

+
{
+    "/user": {
+       "post: }
+       ....
+}
+
+ +
+

❌ path-parameters-snake-case

+

Path parameters must be snake_case, with each word separated by an underscore character and the first letter of each word lowercase. Also, the path parameter must not contain digits.

+

Invalid Example

+

The name property on line 9 (userId) must be separated by an underscore character and the I must be lowercase.

+
{
+    "paths": {
+      "/users/{userId}": {
+        "parameters": [
+          {
+            "schema": {
+              "type": "integer"
+            },
+            "name": "userId",
+            "in": "path"
+          }
+        ]
+      }
+    }
+  }
+
+ +

Valid Example

+
{
+    "paths": {
+      "/users/{userId}": {
+        "parameters": [
+          {
+            "schema": {
+              "type": "integer"
+            },
+            "name": "user_id",
+            "in": "path"
+          }
+        ]
+      }
+    }
+  }
+
+ +
+

❌ query-parameters-snake-case

+

Query parameters must be snake_case, with each word separated by an underscore character and the first letter of each word lowercase. Also, the query parameter must not contain digits.

+

Invalid Example

+

The name property on line 8 (user-Id) must be separated by an underscore character and the I must be lowercase.

+
{
+   "parameters": [
+     {
+       "schema": {
+         "type": "string"
+       },
+       "in": "query",
+       "name": "user-Id"
+     }
+   ]
+}
+
+ +

Valid Example

+
{
+    "parameters": [
+      {
+        "schema": {
+          "type": "string"
+        },
+        "in": "query",
+        "name": "user_id"
+      }
+    ]
+ }
+
+ +
+

⚠️ resource-names-plural

+

Resource names should generally be plural.

+

Invalid Example

+
{
+    "paths": {
+      "/user": 
+    }
+  }
+
+ +

Valid Example

+
{
+    "paths": {
+      "/users": 
+    }
+}
+
+ +
+

⚠️ paths-avoid-special-characters

+

Paths should not contain special characters, such as $ & + , ; = ? and @%.

+

Invalid Example

+

The path contains an ampersand.

+
{
+    "/user&info": {
+       "post: }
+       ....
+}
+
+ +

Valid Example

+
{
+    "/user": {
+       "post: }
+       ....
+}
+
+ +
+

ℹ️ server-has-api

+

Server must have /api

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/index.html b/api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/index.html new file mode 100644 index 000000000..5c64da5a0 --- /dev/null +++ b/api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/index.html @@ -0,0 +1,4277 @@ + + + + + + + + + + + + + + + + + + + + + + + + WSO2 Style Guidelines - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

WSO2 Style Guidelines

+

A set of guidelines focused on enforcing uniformity in API style, including naming conventions, formatting, and documentation to ensure clarity and maintainability across all APIs.

+

❌ operation-operationId-valid-in-url

+

Operation IDs must not contain characters that are invalid for URLs.

+

Invalid Example

+

The operationId in this example includes a pipe and space, which are invalid for URLs.

+
{
+  "/users": {
+    "get": {
+      "operationId": "invalid|operationID"
+    }
+  }
+}
+
+ +

Valid Example

+

This operationId is valid for URLs.

+
{
+  "/users": {
+    "get": {
+      "operationId": "this-must-be-unique"
+    }
+  }
+}
+
+ +
+

❌ path-declarations-must-exist

+

Path parameter declarations must not be empty.

+

Invalid Example

+

/users/{}

+

Valid Example

+

/users/{userId}

+
+

❌ paths-no-trailing-slash

+

Paths must not end with a trailing slash.

+

/users and /users/ are separate paths. It's considered bad practice for them to differ based only on a trailing slash. It's usually preferred to not have a trailing slash.

+

Invalid Example

+

The users path ends with a slash.

+
{
+  "/users/": {
+    "post": {}
+  }
+}
+
+ +

Valid Example

+
{
+  "/user": {
+    "post": {}
+  }
+}
+
+ +
+

❌ server-lowercase

+

Server URLs must be lowercase. This standard helps meet industry best practices.

+

Invalid Example

+

The url property uses uppercase letters.

+
{
+  "servers": [
+    {
+      "url": "https://ACME.com/api"
+    }
+  ]
+}
+
+ +

Valid Example

+

The url property is fully lowercase.

+
{
+  "servers": [
+    {
+      "url": "https://acme.com/api"
+    }
+  ]
+}
+
+ +
+

❌ oas2-api-schemes

+

OpenAPI 2 host schemes reflect the transfer protocol of the API. +Host schemes must be present and an array with one or more of these values: +http, https, ws, or wss.

+

Valid Example

+

This example shows that host schemes are http and https.

+
{
+  "schemes": [
+    "http",
+    "https"
+  ]
+}
+
+ +
+

❌ array-items

+

Schemas with type: array, require a sibling items field.

+

Recommended: Yes

+

Good Example

+
TheGoodModel:
+  type: object
+  properties:
+    favoriteColorSets:
+      type: array
+      items:
+        type: array
+        items: {}
+
+ +

Bad Example

+
TheBadModel:
+  type: object
+  properties:
+    favoriteColorSets:
+      type: array
+      items:
+        type: array
+
+ +
+

⚠️ contact-url

+

The contact object should have a valid organization URL.

+

Valid Example

+
{
+  "contact": {
+     ... ,
+     "url": "https://acme.com",
+     ... 
+  },
+
+ +
+

⚠️ contact-email

+

The contact object should have a valid email.

+

Valid Example

+
{
+  "contact": {
+     ... ,
+     "email": "support.contact@acme.com"
+  },
+
+ +
+

⚠️ info-contact

+

The info object should include a contact object.

+

Valid Example

+
{
+  "info": {
+    ... ,
+    "contact": {
+      "name": "ACME Corporation",
+      "url": "https://acme.com",
+      "email": "support.contact@acme.com"
+    }
+  }
+}
+
+ +
+

⚠️ info-description

+

The info object should have a description object.

+

Valid Example

+
{
+  "info": {
+     ... ,
+     "description": "This describes my API."
+  }
+}
+
+ +
+

⚠️ info-license

+

The info object should have a license object.

+

Valid Example

+
{
+  "info": {
+    ... ,
+    "license": {
+      "name": "Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)",
+      "url": "https://creativecommons.org/licenses/by-sa/4.0/"
+    }
+  }
+}
+
+ +
+

⚠️ license-url

+

The license object should include a valid url.

+

Valid Example

+
{
+  "license": {
+    "name": "Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)",
+    "url": "https://creativecommons.org/licenses/by-sa/4.0/"
+  }
+}
+
+ +
+

⚠️ no-eval-in-markdown

+

Markdown descriptions should not contain eval() functions, +which pose a security risk.

+

Invalid Example

+
{
+  "info": {
+    ... ,
+    "description": "API for users. eval()"
+  }
+}
+
+ +
+

⚠️ no-script-tags-in-markdown

+

Markdown descriptions should not contain script tags, which pose a security risk.

+

Invalid Example

+
{
+  "info": {
+    ... ,
+    "description": "API for users. <script>alert(\"You are Hacked\");</script>"
+  }
+}
+
+ +
+

⚠️ openapi-tags-alphabetical

+

Global tags specified at the root OpenAPI Document level should be in alphabetical order based on the name property.

+

Invalid Example

+
{
+  "tags":[
+    {
+      "name":"Z Global Tag"
+    },
+    {
+      "name":"A Global Tag"
+    }
+  ]
+}
+
+ +

Valid Example

+
{
+  "tags":[
+    {
+      "name":"A Global Tag"
+    },
+    {
+      "name":"Z Global Tag"
+    }
+  ]
+}
+
+ +
+

⚠️ openapi-tags

+

At least one global tag should be specified at the root OpenAPI Document level.

+

Valid Example

+
{
+  "tags":[
+    {
+      "name":"Global Tag #1"
+    },
+    {
+      "name":"Global Tag #2"
+    }
+  ]
+}
+
+ +
+

⚠️ operation-description

+

Each operation should have a description.

+

Valid Example

+
{
+  "get": {
+    "description": "Get a list of users."
+  }
+}
+
+ +
+

⚠️ operation-operationId

+

All operations should have an operationId.

+

Valid Example

+
{
+  "get": {
+    "summary": "Get users",
+    "operationId": "get-users"
+  }
+}
+
+ +
+

⚠️ operation-tags

+

At least one tag should be defined for each operation.

+

Valid Example

+
{
+  "get": {
+    "tags": ["Users"]
+  }
+}
+
+ +
+

⚠️ contact-name

+

The contact object should have an organization name.

+

Valid Example

+
{
+  "contact": {
+    "name": "ACME Corporation"
+  }
+}
+
+ +
+

⚠️ path-keys-no-trailing-slash

+

Path keys should not end in forward slashes. This is a best practice for working with web tooling, such as mock servers, code generators, application frameworks, and more.

+

Invalid Example

+
{
+  "/users/": {
+  }
+}
+
+ +

Valid Example

+
{
+  "/users": {
+  }
+}
+
+ +
+

⚠️ path-not-include-query

+

Paths should not include query string items. Instead, add them as parameters with in: query.

+

Invalid Example

+
{
+  "/users/{?id}": {
+  }
+}
+
+ +

Valid Example

+
{
+  "parameters": [
+    {
+      "schema": {
+        "type": "string"
+      },
+      "name": "id",
+      "in": "path",
+      "required": true,
+      "description": "User's ID"
+    }
+  ]
+}
+
+ +
+

⚠️ tag-description

+

Tags defined at the global level should have a description.

+

Valid Example

+
{
+  "tags": [
+    {
+      "name": "Users",
+      "description": "End-user information"
+    }
+  ]
+}
+
+ +
+

⚠️ api-servers

+

A server should be defined at the root document level. This can be localhost, a development server, or a production server.

+

Valid OpenAPI V3 Example

+
{
+  "servers": [
+    {
+      "url": "https://staging.myprodserver.com/v1",
+      "description": "Staging server"
+    },
+    {
+      "url": "https://myprodserver.com/v1",
+      "description": "Production server"
+    }
+  ]
+}
+
+ +

Valid OpenAPI V2 Example

+
{
+  "host": "myprodserver.com",
+  "basePath": "/v2",
+  "schemes": [
+    "https"
+  ]
+}
+
+ +
+

⚠️ server-trailing-slash

+

Server URLs should not end in forward slashes. This is a best practice for working with web tooling, such as mock servers, code generators, application frameworks, and more.

+

Invalid Example

+
{
+  "servers": [
+    {
+      "url": "https://api.openweathermap.org/data/2.5/"
+    }
+  ]
+}
+
+ +

Valid Example

+
{
+  "servers": [
+    {
+      "url": "https://api.openweathermap.org/data/2.5"
+    }
+  ]
+}
+
+ +
+

⚠️ server-not-example

+

Server URLs must not direct to example.com. This helps ensure URLs +are valid before you distribute your API document.

+

Invalid Example

+
{
+  "servers": [
+    {
+      ... ,
+      "url": "https://example.com"
+    }
+  ]
+}
+
+ +

Valid Example

+
{
+  "servers": [
+    {
+      ... ,
+      "url": "https://api.openweathermap.org/data/2.5"
+    }
+  ]
+}
+
+ +
+

⚠️ parameter-description

+

All parameter objects should have a description.

+

Valid Example

+
{
+  "parameters": [
+    {
+      "schema": {
+        "type": "integer"
+      },
+      ... ,
+      ... ,
+      "description": "The number of days to include in the response."
+    }
+  ]
+}
+
+ +
+

⚠️ oas2-anyOf

+

The anyOf keyword is not supported in OAS2. Only allOf is supported.

+

Invalid Example

+
{
+  "schema": {
+    "anyOf": [
+      {
+        "properties": {
+          "firstName": {
+            "type": "string"
+          },
+          "lastName": {
+            "type": "string"
+          }
+        }
+      },
+      {}
+    ]
+  }
+}
+
+ +

Valid Example

+
{
+  "schema": {
+    "type": "object",
+    "properties": {
+      "firstName": {
+        "type": "string"
+      },
+      "lastName": {
+        "type": "string"
+      }
+    }
+  }
+}
+
+ +
+

⚠️ oas2-oneOf

+

The oneOf keyword is not supported in OAS2. Only allOf is supported.

+

Invalid Example

+
{
+  "schema": {
+    "oneOf": [
+      {
+        "properties": {
+          "firstName": {
+            "type": "string"
+          },
+          "lastName": {
+            "type": "string"
+          }
+        }
+      },
+      {}
+    ]
+  }
+}
+
+ +

Valid Example

+
{
+  "schema": {
+    "type": "object",
+    "properties": {
+      "firstName": {
+        "type": "string"
+      },
+      "lastName": {
+        "type": "string"
+      }
+    }
+  }
+}
+
+ +
+

⚠️ oas3-examples-value-or-externalValue

+

The examples object should include a value or externalValue field, but cannot include both.

+

Invalid Example

+

This example includes both a value field and an externalValue field.

+
{
+  "examples": {
+    "example-1": {
+      "value": {
+        "id": "string",
+        "name": "string"
+      },
+      "externalValue": {
+        "id": "string",
+        "name": "string"
+      }
+    }
+  }
+}
+
+ +

Valid Example

+

This example includes only a value field.

+
{
+  "examples": {
+    "example-1": {
+      "value": {
+        "id": "string",
+        "name": "string"
+      }
+    }
+  }
+}
+
+ +
+

⚠️ path-parameters-on-path-only

+

Path parameters should be defined on the path level instead of the operation level.

+

Invalid Example

+

The user_id path parameter on line 8 should not be included with the patch operation.

+
{      
+  "patch": {
+    "parameters": [
+      {
+        "schema": {
+          "type": "integer"
+        },
+        "name": "user_id",
+        "in": "path"
+      }
+    ]
+  }
+}
+
+ +

Valid Example

+

The user-id path parameter is correctly located at the path level.

+
{
+  "paths": {
+    "/users/{userId}": {
+      "parameters": [
+        {
+          "schema": {
+            "type": "integer"
+          },
+          "name": "user_id",
+          "in": "path"
+        }
+      ]
+    }
+  }
+}
+
+ +
+

⚠️ paths-no-query-params

+

Paths should not have query parameters in them. They should be defined separately in the OpenAPI.

+

Invalid Example

+
{
+  "/users/{?id}": {
+
+ +

Valid Example

+
{
+  "parameters": [
+    {
+      "schema": {
+        "type": "string"
+      },
+      "name": "id",
+      "in": "path",
+      "required": true,
+      "description": "User's ID"
+    }
+  ]
+}
+
+ +
+

ℹ️ operation-singular-tag

+

Operation should not have more than a single tag.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-policies/about-api-policies/index.html b/api-management/api-policies/about-api-policies/index.html new file mode 100644 index 000000000..b407ec10e --- /dev/null +++ b/api-management/api-policies/about-api-policies/index.html @@ -0,0 +1,3509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + About API Policies - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

About API Policies

+

API policies are units of business logic that you can apply to modify the flow of API invocations.

+

You can apply a policy to alter the Request, Response, or Error flow of an API invocation before it reaches the backend or the client. For example, you can add a policy to the response flow to transform the payload from JSON to XML and add a header to the response.

+

Inbuilt mediation policies

+

Choreo supports a set of inbuilt mediation policies that can handle common API transformation and mediation tasks. These policies run within a single mediation service, making it straightforward to implement and manage complex mediation logic. The following inbuilt policies are available in Choreo:

+
    +
  • JSON to XML: Transforms a JSON payload in a request or response into XML format. This policy is applicable only to JSON payloads in mediation flows. Applying it to a non-JSON payload terminates the flow. This policy cannot be used more than once on the same resource because the payload will already be converted to XML.
  • +
  • XML to JSON: Converts an XML payload in a request or response into JSON format. This policy is applicable only to XML payloads in mediation flows. Applying it to a non-XML payload terminates the flow. This policy cannot be used more than once on the same resource because the payload will already be converted to JSON.
  • +
  • Remove Query Parameter: Removes specified query parameters from a request. You can use this policy multiple times to remove different parameters. Attempting to remove a non-existent parameter has no effect. If the parameter exists, it will be removed; otherwise, the request proceeds as usual.
  • +
  • Remove Header: Removes specified headers from a request or response. You can attach this policy multiple times to remove multiple headers. The header name must be static, but you can use placeholders to configure different values for different environments. For example, ${headerName}.
  • +
  • Add Query Parameter: Adds query parameters to a request. You can attach this policy multiple times to add various parameters. Adding the same parameter multiple times creates an array of values. The parameter name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${fooValue}.
  • +
  • Add Header: Adds headers to a request or response. If the same header is added multiple times, values are appended rather than overwritten. The header name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${authzHeaderValue}.
  • +
  • Set Header: Sets headers in a request or response, overwriting any existing values. You can attach this policy multiple times to set multiple headers. Each time the same header is set, it replaces the previous value. The header name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${authzHeaderValue}.
  • +
  • Rewrite Resource Path: Modifies the resource path of an HTTP request by replacing the original path with a new relative path. You can apply this policy multiple times, but only the last instance will take effect. The new path must be static, but you can use placeholders to configure different values for different environments. For example, ${myResourcePath}.
  • +
  • Log Message: Logs the payload and headers of a request or response. Attaching this policy multiple times results in duplicate log entries. By default, headers and payloads are not logged. To log them, you can enable Log Headers and Log Payload parameters. To exclude specific headers when logging, you can use the Excluded Headers parameter, which takes a comma-separated list of header names. An error will occur if payload logging is enabled but the payload cannot be read.
  • +
+

These inbuilt mediation policies provide flexibility to manage API requests and responses, allowing for custom transformations and logic without requiring custom code.

+

For details on attaching and managing one or more policies to an API proxy component implementation via the Choreo Console, see Attach and Manage Policies.

+

For details on applying advanced settings on mediation policies, see Apply Advanced Settings on Mediation Policies.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-policies/apply-advanced-settings-on-mediation-policies/index.html b/api-management/api-policies/apply-advanced-settings-on-mediation-policies/index.html new file mode 100644 index 000000000..3a52ffdcc --- /dev/null +++ b/api-management/api-policies/apply-advanced-settings-on-mediation-policies/index.html @@ -0,0 +1,3557 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Apply Advanced Settings on Mediation Policies - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Apply Advanced Settings on Mediation Policies

+

Advanced settings for mediation policies are available for proxy components with an attached mediation policy. For details on attaching a mediation policy to a proxy component, see Attach and Manage Policies.

+

The approach to applying advanced settings depends on whether the proxy component is deployed or not.

+

Mediation policy advanced settings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SettingPurposeHow to applyImpact
HTTP versionBy default, Choreo supports HTTP 1.1. If necessary, you can change to HTTP 1.0 or HTTP 2.0.Specify the required HTTP version in the Advanced Settings field.
HTTP version setting
The mediation application will use the specified HTTP version when interacting with backend services.
Hostname verificationChoreo enables hostname verification by default when using mTLS. You can disable it if necessary.Set the verifyHostname parameter to false in the Advanced Settings field.
Hostname verification setting
Hostname verification will be skipped during mTLS interactions.
Minimum evictable idle timeDetermines how long (in seconds) an outgoing connection remains idle before eviction. The default is 300 seconds.Set the required idle time in the Advanced Settings field.
Minimum evictable idle time setting
Idle connections will be closed and evicted after the defined period.
Detailed access logBy default, logs related to the mediation application are generated and can be viewed as runtime logs. You can disable these logs if necessary.Set the detailedAccessLog parameter in the Advanced Settings field.
Detailed access log setting
Logs related to the mediation application will not be generated.
+

Configure advanced settings for a proxy component

+

To configure advanced settings for a proxy component with an attached mediation policy, follow these steps:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the REST API Proxy component for which you want to configure advanced settings.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Depending on the deployment status of the proxy component, follow one of these steps:
  8. +
  9. If the proxy component is not deployed, go to the Set Up card and click Configure & Deploy.
  10. +
  11. If the proxy component is already deployed, go to the respective environment card depending on the environment you want to apply advanced settings, and then click the Environment Variables icon.
  12. +
  13. In the Configurations pane that opens, expand the Defaultable Configurables section.
  14. +
  15. In the Advanced Settings field, configure the necessary settings as described in the Mediation policy advanced settings section.
  16. +
  17. Click Save & Deploy.
  18. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-policies/attach-and-manage-policies/index.html b/api-management/api-policies/attach-and-manage-policies/index.html new file mode 100644 index 000000000..9474d218d --- /dev/null +++ b/api-management/api-policies/attach-and-manage-policies/index.html @@ -0,0 +1,4002 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Attach and Manage Policies - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Attach and Manage Policies

+

You can easily attach one or more policies to an API proxy component implementation via the Choreo Console. If necessary, you can also rearrange or swap the policies you attach.

+

In Choreo, when you attach a mediation policy to a proxy, the deployment is a two-step process.

+
    +
  1. +

    Deployment initiation:

    +

    If the component to which you want to attach the mediation policy is new, the system creates and commits a new repository with the mediation service code based on the attached policy. This new service is called the mediation application.

    +
  2. +
  3. +

    Deploying the API:

    +

    Once the deployment initiation is complete, you can specify configuration values if any, and proceed to deploy. Choreo builds the generated mediation application and pushes the Docker image to the Docker registry. Finally, Choreo deploys the mediation application with the API Proxy.

    +
  4. +
+

When a mediation policy is attached to a specific flow, the API invocation undergoes the following behavioral modification:

+

Request/Response flow

+
    +
  • +

    In the request path, the requests that pass through the gateway reach the relevant component, and Choreo executes any attached policies to the resource's request path before sending it to the backend.

    +
  • +
  • +

    In the response path, the mediation component receives response messages from the backend, and Choreo executes any mediation policies attached to the Response flow or the Error flow. Then the response is forwarded to the client.

    +
  • +
  • +

    If an error occurs during the execution of policies or due to an internal error, Choreo executes the Error flow and sends an error response to the client.

    +
  • +
+

Attach a policy

+

To attach a policy to the Request, Response, or Error flow of a REST API proxy, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the REST API Proxy component for which you want to attach a policy.
  4. +
  5. In the left navigation menu, click Develop and then click Policies.
  6. +
  7. From the list of resources, expand the resource to which you want to attach the policy.
  8. +
  9. Click Attach Mediation Policy in the respective flow for which you want to attach a policy.
  10. +
  11. In the Policy List pane that opens, click on a required policy to view its details.
  12. +
  13. +

    If the attached policy requires parameter configuration, on the policy pane enter the appropriate values and configure the parameters. To make a parameter a configurable variable, input the value in the ${<variableName>} format. For example, you can use ${name} as an example.

    +

    Configure parameters

    +
  14. +
  15. +

    To attach the policy, click Add.

    +
  16. +
+

After attaching an API Policy, it is necessary to deploy the API for the policy to become active within its corresponding flow. +To deploy the API follow the steps below:

+
    +
  1. +

    In the left navigation menu, click Deploy and then click Configure & Deploy. Choreo performs the mediation application generation step and opens the Configure & Deploy pane.

    +
  2. +
  3. +

    In the Configure & Deploy pane, if you have any configurable variables that require values, specify appropriate values for them.

    +

    Save and deploy values

    +
  4. +
  5. +

    Click Save & Deploy.

    +
  6. +
+

Refresh mediation policies

+

Choreo selectively generates and builds the mediation application code during component deployment depending on specific changes. These changes include:

+
    +
  • Addition, deletion, or modification of API resources.
  • +
  • Attachment, removal, or editing of API mediation policies.
  • +
  • Endpoint modifications via the Develop page.
  • +
  • Initial configuration or removal of backend endpoints or mutual TLS certificates.
  • +
+

If none of the above changes occur during deployment, Choreo skips the code generation and build process of the mediation application.

+
+

Info

+
    +
  • If you want to enforce the code generation and build process of the mediation application in instances where the specified changes do not take place, you must turn on the Refresh Mediation Policies toggle when you configure and deploy the component.
  • +
  • It is useful to enable Refresh Mediation Policies when you want to incorporate the latest Ballerina patches for your generated mediation application. However, this can result in longer deployment times.
  • +
+
+

Implement an API policy

+

Choreo allows you to implement an API policy as a Ballerina project and attach it to an API proxy component.

+
+

Info

+

Supported Ballerina version: 2201.5.5

+
+

To implement a policy, follow the steps given below:

+

Prerequisites

+
    +
  1. Set up Ballerina 2201.5.5.
  2. +
  3. Open the ~/.ballerina/settings.toml file and ensure you have configured an access token to Ballerina Central. If you have not configured an access token, follow the steps given below to configure one:
      +
    1. Generate a token via https://central.ballerina.io/dashboard?tab=token.
    2. +
    3. Download the generated Settings.toml file and copy it to your local ~/.ballerina directory.
    4. +
    +
  4. +
+

Alternatively, you can set the access token via the BALLERINA_CENTRAL_ACCESS_TOKEN environment variable.

+
export BALLERINA_CENTRAL_ACCESS_TOKEN=<access-token> 
+
+ +

Step 1: Initialize a Ballerina project

+

Choreo provides a template to initialize a mediation policy project with all the required configurations. The mediation policy project will be created as a Ballerina project.

+

To create a Ballerina project for the mediation policy using mediation.template as the project template, issue the following command:

+

Format:

+
    bal new -t choreo/mediation.template:1.0.0 <policy-name> 
+
+ +

Example:

+

    bal new -t choreo/mediation.template:1.0.0 validateHeader 
+
+ The Ballerina project that is created should have the following content:

+

Ballerina project

+

Depending on your requirement, you can modify the Ballerina.toml and the Package.md files of the generated project. For example, you can update the org, package, package version, API documentation content, keywords, etc.

+
+

Note

+

To successfully publish to Ballerina Central, make sure you update the org value to your organization name.

+
+
     [package]
+        org = "starkindustries"
+        name = "validateHeader"
+        version = "1.0.0"
+        export = ["validateHeader"]
+        distribution = "2201.5.5"
+        keywords = ["choreo-apim-mediation-policy","choreo-apim-mediation-request-flow","choreo-apim-mediation-response-flow","choreo-apim-mediation-fault-flow"]
+
+ +

Step 2: Implement the policy

+

In this step, you will implement the policy.

+

Let's assume you want to implement a policy to validate an incoming header in the request and the response.

+
    +
  • Request path: If the request header is not present or if the validation fails, you want to log an error and return a 403 Bad Request response to the client.
  • +
  • Response path: You want to log a message to indicate whether the request is valid or not.
  • +
+

To implement the policy, open the policy.bal file in the Ballerina project and update the generated policy stubs(i.e., request, response, or fault) appropriately.

+

The following sections walk you through sample implementations for the Request and Response stubs:

+

Request flow

+

The following is a sample implementation for the request flow:

+
@mediation:RequestFlow
+public function validateRequestHeader(mediation:Context ctx, http:Request req, string headerName, string headerValue) returns http:Response|false|error|() {
+   string|http:HeaderNotFoundError header = req.getHeader(headerName);
+   if (header is http:HeaderNotFoundError) {
+    string message = string `Header ${headerName} is not found`;
+    log:printError(message);
+    return generateResponse(message, http:STATUS_BAD_REQUEST);
+   }
+   if (header != headerValue) {
+    string validationFailedMessage = string `Header validation failed. Expected ${headerValue} but found ${header}`;
+    log:printError(validationFailedMessage);
+    return generateResponse(validationFailedMessage, http:STATUS_BAD_REQUEST);
+    }
+    log:printInfo("Header validation successful");
+    return ();
+};
+
+function generateResponse(string message, int statusCode) returns http:Response {
+    http:Response response = new();
+    response.setTextPayload(message); 
+    response.statusCode = statusCode;
+    return response;
+}
+
+ +

Response flow

+

The following is a sample implementation for the response flow:

+
@mediation:ResponseFlow
+public function validateResponseHeader(mediation:Context ctx, http:Request req, http:Response res, string headerName, string headerValue) returns http:Response|false|error|() { 
+   string|http:HeaderNotFoundError header = res.getHeader(headerName);
+   if (header is http:HeaderNotFoundError) {
+    string message = string `Header ${headerName} is not found`;
+    log:printError(message);
+    return ();
+   }
+   if (header != headerValue) {
+    string validationFailedMessage = string `Header validation failed. Expected ${headerValue} but found ${header}`;
+    log:printError(validationFailedMessage);
+    return ();
+   }
+   return ();
+}
+
+ +

Fault flow

+

In this guide, you are not going to make any changes to the Fault flow. Therefore, you can remove the Fault flow stub from the policy.bal file.

+
+

Note

+

The @mediation:RequestFlow, @mediation:ResponseFlow, and @mediation:FaultFlow annotations are bound with the keywords in the Ballerina.toml. Therefore, the changes you make to the policy stubs should reflect in the Ballerina.toml file. For example, if the policy is applicable only on the request and response paths, you can remove the @mediation:FaultFlow annotation from the policy. Then, you MUST also remove the choreo-apim-mediation-fault-flow keyword from the generated Ballerina.toml file. If you do not do so, the Ballerina compiler will show an error at compile time.

+
+

Publish as a private custom policy

+

Choreo supports publishing a policy as a private custom policy. Publishing a policy as a private custom policy makes the policy inaccessible outside of the organization. To publish a policy as a private custom policy, change the visibility to private prior to pushing the package to Ballerina Central as follows:

+
    +
  1. Open the Ballerina.toml file of your policy.
  2. +
  3. +

    Set the visibility to private by adding the configuration visibility="private". For example:

    +
    [package]
    +   org = "orgName"
    +   name = "packageName"
    +   version = "1.0.2"
    +   export = ["packageName"]
    +   distribution = "2201.5.5"
    +   keywords = ["choreo-apim-mediation-policy","choreo-apim-mediation-request-flow","choreo-apim-mediation-response-flow","choreo-apim-mediation-fault-flow"]
    +   visibility = "private"
    +
    + +
  4. +
  5. +

    Package and publish your policy to Ballerina Central.

    +
  6. +
+

Best practices

+

When implementing a policy, it is essential to follow best practices to ensure efficiency and maintainability. Here are some recommended best practices to follow:

+
    +
  • Organize the source code within the default module of the package. Do not add any additional modules.
  • +
  • A policy implementation can contain any combination of flows. A generated project contains stubs for all three flows: Request, Response, and Fault. You can remove any stub that you do not require. For example, when you create a policy that re-writes the resource paths, you can remove the Response and fault stubs.
  • +
  • The HTTP request/response objects and context record parameters gets passed as references to the policy functions. Therefore, the changes you make to these values persist throughout the policy execution and are propagated to subsequent policies. This behavior allows the request and response objects to accumulate transformations applied by attached policies.
  • +
  • Familiarize yourself with the different return types of policy flows. The following return types are unmodifiable:
      +
    • http:Response - Returns an HTTP response when you terminate the mediation flow prematurely. For example, in the in-flow sequence, the mediation sequence terminates before calling the backend. The mediation policy then sends an HTTP response to the client.
    • +
    • false - Returns false if you want to terminate the mediation sequence with a predefined response (on the Choreo side).
    • +
    • error - Returns an error if you want to terminate the mediation flow and transfer control to the fault flow. The fault flow would then construct an error response and send it to the client.
    • +
    • () - Returns () to signal the successful completion of the policy. Once the proxy has completed executing the policy, it starts to execute the next policy in the sequence.
    • +
    +
  • +
+

Step 3: Publish the policy

+

Once you implement a policy, you must publish it to Ballerina Central.

+

When you attach a policy and deploy an API, Choreo pulls the necessary packages from Ballerina Central and bundles them into the mediation application under the hood. Therefore to use policies in your APIs, you must publish them as public packages.

+

To publish the policy, follow the steps given below:

+
    +
  1. To package the policy before you publish it to Ballerina Central, issue the following command: +
        bal pack 
    +
  2. +
  3. +

    To publish the package to Ballerina Central, issue the following command:

    +
        bal push 
    +
    + +
  4. +
+

Once you publish the package, it will appear as follows in the policy list:

+

Published policy

+

Write unit tests

+

You can write unit tests to test policy functions in a manner similar to how you write unit tests for a regular Ballerina function.

+

The following is a sample unit test for the validateRequestHeader function:

+
import ballerina/http;
+import choreo/mediation;
+import ballerina/test;
+
+
+@test:Config {}
+public function testRequestHeaderValidationFailure() {
+  http:Request req = new;
+  http:Response|false|error|() result = validateRequestHeader(createContext("get", "/test"), req, "testHeader", "test");
+
+
+  if !(result is http:Response) {
+    test:assertFail("Expected http:Response, found " + (typeof result).toString());
+  }
+
+
+  test:assertEquals(result.statusCode, http:STATUS_BAD_REQUEST, "Status code mismatch");
+}
+
+
+function createContext(string httpMethod, string resPath) returns mediation:Context {
+   mediation:ResourcePath originalPath = checkpanic mediation:createImmutableResourcePath(resPath);
+   mediation:Context originalCtx =
+               mediation:createImmutableMediationContext(httpMethod, originalPath.pathSegments(), {}, {});
+   mediation:ResourcePath mutableResPath = checkpanic mediation:createMutableResourcePath(resPath);
+   return mediation:createMutableMediationContext(originalCtx, mutableResPath.pathSegments(), {}, {});
+}
+
+ +

The policy function modifies the same request/response/context instance that you pass to it. You can check the request/response/context instance after calling the policy function to verify changes.

+

Glossary

+

Here are some of the common terms used when working with policies in Choreo:

+

mediation:Context

+

The mediation context is used to pass parameters between policies. It is created per request and you can access it in any of the flows. For example, if a correlation ID needs to be set to the request, you can set it in the context of the request flow and access it in the response or fault flow.

+

The mediation context can include the following functions:

+
# Retrieves the value for the specified key.   
+public function get(string name) returns anydata;
+
+
+# Stores the provided key-value pair. If a mapping exists for the key, the value is overwritten.
+public function put(string name, anydata value);
+
+
+# Removes the entry mapped by the specified key and returns the removed value.
+public function remove(string name) returns anydata;
+
+
+# Retrieves the value for the specified key. If there is no mapping for the key, return the specified
+public function getOrDefault(string name, anydata default) returns anydata;
+
+
+# Checks whether a mapping exists for the specified key.
+public function hasKey(string name) returns boolean;
+
+
+# Returns the `mediation:Context` instance which captured the initial contextual information of the resource,
+# before the mediation flow was invoked. Calling this on an original `mediation:Context` object will return itself.
+public function originalContext() returns Context;
+
+
+# The HTTP method of the resource method
+public function httpMethod() returns string;
+
+
+# Retrieves an instance of `mediation:ResourcePath` which is an API for contextual information on the resource path
+# of this resource. It also contains methods for modifying the resource path as the user sees fit. This resource
+# path is the same path used by the mediation service for deriving the backend endpoint's resource to invoke.
+# Therefore, the default behavior of the mediation service is to invoke a resource in the backend endpoint which
+# has the same relative resource path as the corresponding mediation service resource.
+public function resourcePath() returns ResourcePath;
+
+
+# Sets the given `mediation:ResourcePath` instance as the resource path of this context.
+public function setResourcePath(ResourcePath path);
+
+
+# Adds a mapping between a path param name and a resolved value for it. There need not be a path parameter in the
+# resource path by the name specified in `name` for one to use this method. On its own, the path param values have
+# no bearing on the resource path.
+public function addPathParamValue(string name, PathParamValue value);
+
+
+# Returns the collection of resolved values for the path parameters in this particular context, mapped
+# by the parameter name.
+public function resolvedPathParams() returns map<PathParamValue> & readonly;
+
+
+# Removes the resolved path parameter value which maps to the specified name.
+public function removePathParamValue(string name);
+
+
+# Adds a query parameter to the request to be sent to the backend. If there is already a query parameter by
+# with the same name, the new value will be appended to it, making it an array.
+public function addQueryParam(string name, string value);
+
+
+# Removes the specified query parameter from the request. If the value of the parameter is an array, the whole
+# array will be removed.
+public function removeQueryParam(string name);
+
+
+# Retrieves a map of all the query parameters in the current request context. The returned map is a read-only snapshot
+# of the map of query parameters in the context at the time this method was called.
+public function queryParams() returns map<string[]> & readonly;
+
+ +

Keywords

+

The Ballerina.toml file needs to include the following keywords for the mediation policies to work:

+
    +
  • choreo-apim-mediation-policy: This keyword is a mandatory keyword that is required to identify that the package is a mediation policy type.
  • +
  • choreo-apim-mediation-request-flow: Specifies whether the policy applies to the request flow.
  • +
  • choreo-apim-mediation-response-flow: Specifies whether the policy applies to the response flow.
  • +
  • choreo-apim-mediation-fault-flow: Specifies whether the policy is applicable for the fault flow.
  • +
+

Policy name and description

+

The Package.md file contains information about the policy. Choreo uses this information to render the policy configuring UI. This file is written in Markdown format and should be structured as follows.

+

Format:

+
# <policy-name>
+
+
+## Overview
+
+
+<policy description>
+
+ +

Example:

+
# ValidateHeader
+
+
+## Overview
+
+
+This policy validates the request and response headers with the configured values.
+
+ +

Policy versioning

+

When it comes to policy versioning in Choreo or mediation dependencies, it is important to consider the major version changes in the Ballerina language. For example, transitioning from update 1 to update 2 requires a major version increment, which can introduce significant incompatibilities.

+

Therefore, to ensure compatibility, the recommended approach is to version the policy package in a manner that the major version gets upgraded when the Choreo/mediation dependency version is upgraded to a major version.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/api-policies/index.html b/api-management/api-policies/index.html new file mode 100644 index 000000000..911f55c07 --- /dev/null +++ b/api-management/api-policies/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/api-management/api-rate-limiting/index.html b/api-management/api-rate-limiting/index.html new file mode 100644 index 000000000..1be6e8068 --- /dev/null +++ b/api-management/api-rate-limiting/index.html @@ -0,0 +1,3594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + API Rate Limiting - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

API Rate Limiting

+

API rate limiting is a technique that allows you to control the rate of requests made to an API. Rate limiting helps +prevent system overload and enhances API performance. When you limit the number of requests that can be made in a +specific time frame, you can ensure that your API is available and responsive to all users while protecting it from +malicious attacks.

+

This page walks you through the steps to enable rate limiting for your APIs via Choreo and also provides information on +the rate-limiting options supported by Choreo.

+

Enable rate limiting for an API

+

To enable rate limiting for an API, follow the steps given below:

+
+

Note

+

You can apply rate-limiting settings separately for each environment.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to apply rate limiting.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. +

    Go to the required environment card and click the view icon corresponding to the endpoint for which you want to apply rate limiting.

    +
    +

    Info

    +

    If you are applying rate limiting for an API Proxy component, go to the required environment card, click the setting icon corresponding to API Configuration, and proceed to step 6.

    +
    +
  8. +
  9. +

    In the Endpoint Details pane that opens, click the settings icon.

    +
  10. +
  11. In the Manage section, click Rate Limiting to expand it.
  12. +
  13. Select a Rate Limiting Level depending on your requirement and click Apply.
  14. +
+

API-level rate limiting

+

API-level rate limiting applies the allocated request count for the specified time unit to all operations in the API.

+

Operation-level rate limiting

+

Operation-level rate limiting allows you to configure different rate-limiting values for each operation. You can use this option to define specific rate-limiting values for critical API operations that require an extra layer of protection.

+

Rate-limiting response headers

+

The following table lists the response headers available when you enable rate limiting for your APIs. You can implement necessary rate-limiting scenarios depending on the response header values.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Header NameDescription
x-ratelimit-limitDenotes the request count allocated for the specified time unit.
x-ratelimit-resetProvides the time remaining to start the next rate-limiting time unit.
x-ratelimit-remainingDenotes the remaining request count for the specified time unit.
x-ratelimit-enforcedVisible after exceeding the allocated request count.
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/control-api-visibility/index.html b/api-management/control-api-visibility/index.html new file mode 100644 index 000000000..f8b799940 --- /dev/null +++ b/api-management/control-api-visibility/index.html @@ -0,0 +1,3533 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Control API Visibility - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Control API Visibility

+

By default, the APIs published in Choreo are visible to anyone who visits the Choreo Developer Portal. By default, Choreo sets the visibility of the API to Public. However, developers can control the visibility of their APIs by changing the default option to Private or Restricted.

+

Visibility settings control users from viewing and modifying APIs. API visibility can be one of the following options:

+
    +
  • +

    Public : The API is visible to all in the developer portal.

    +
  • +
  • +

    Private : The API is visible to the users who only sign in to the Developer Portal.

    +
  • +
  • +

    Restricted: The API is visible to only the user that has the roles that you specify. This option helps developers to enforce fine-grained access control to the API.

    +
  • +
+

Change API visibility

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the REST API (Service) for which you want to control API visibility.
  4. +
  5. In the left navigation menu, click Manage and then click API Info.
  6. +
  7. On the API Info page that opens, click the Developer Portal tab.
  8. +
  9. +

    Under General Details, select the required visibility setting from the Visibility list.

    +
    +

    Enable fine-grained role-based access control to the API

    +
      +
    1. To enable fine-grained role-based access control to an API in the Developer Portal, select Restricted from the API visibility list. Once selected, you will see the roles available in your organization in the Visible Roles list.
    2. +
    3. Select any combination of roles. Only the users with the given roles can access the APIs through the Dev Portal.
    4. +
    5. Alternatively, You can create a new role and assign it to an API by following the steps below:
        +
      1. Click + Create New Role in the list.
      2. +
      3. Add the role name and description.
      4. +
      5. Click Next.
      6. +
      7. Assign the relevant permissions to the new role.
      8. +
      9. Click Create.
      10. +
      11. Select the newly created role from the Visible Roles list.
      12. +
      +
    6. +
    +
    +
  10. +
  11. +

    Click Save.

    +
  12. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/documents/index.html b/api-management/documents/index.html new file mode 100644 index 000000000..50fd2f2dd --- /dev/null +++ b/api-management/documents/index.html @@ -0,0 +1,3520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Documents - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Documents

+

When an API consumer signs in to the Choreo Developer Portal to browse APIs, it is not sufficient to just have an API thumbnail along with the name and version of the API. An API consumer would expect to see more details about the API, such as the following:

+
    +
  • A brief description of the API.
  • +
  • How to invoke the API.
  • +
  • The limitations/restrictions of the API.
  • +
  • Version history.
  • +
+

To provide such information that improves the overall visibility of the API, an API developer can add such documentation to an API before publishing it to the Developer Portal.

+

Add documents to an API

+

To add documentation for an API, follow the steps given below.

+
    +
  1. +

    Sign in to the Choreo Console.

    +
  2. +
  3. +

    In the Component Listing pane, click on the component for which you want to add documents.

    +
  4. +
  5. +

    In the left navigation menu, click Manage and then click Documents.

    +
  6. +
  7. +

    Specify a title for the document and provide the content in markdown syntax.

    +
  8. +
  9. +

    Click Add to save the document.

    +
  10. +
+

Depending on the information you need to add to the API, you can add one or more documents.

+

You can also edit existing documents and delete documents if necessary.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/lifecycle-management/index.html b/api-management/lifecycle-management/index.html new file mode 100644 index 000000000..d6fe35aee --- /dev/null +++ b/api-management/lifecycle-management/index.html @@ -0,0 +1,3562 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lifecycle Management - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Lifecycle Management

+

API lifecycle management is an important aspect of API management. The API lifecycle consists of various states that an API passes through, from creation to retirement. In Choreo, there are six distinct lifecycle states: created, pre-released, published, blocked, deprecated, and retired.

+

By leveraging the various lifecycle states, API managers can optimize the development process and ensure that subscribers have access to the latest and most reliable APIs.

+

API lifecycle states

+

The following lifecycle states are applicable to APIs in Choreo:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API lifecycle stateUse caseCorresponding action
CREATEDThe API is created but is not ready for consumption.The API is not visible to subscribers in the Developer Portal.
PRE-RELEASEDA prototype is created for early promotion and consumer testing. You can deploy a new API or a new version of an existing API as a prototype to provide subscribers with an early implementation of the API.The API is published to the Developer Portal as a pre-release.
PUBLISHEDThe API is ready for subscribers to view and subscribe to via the Developer PortalThe API is visible in the Developer Portal and is available for subscription.
BLOCKEDAccess to the API is temporarily blocked.Runtime calls are blocked, and the API is not visible in the Developer Portal.
DEPRECATEDThe old version of an API is moved to this state when a newer version of the API is PUBLISHED.The API is deployed and is available to existing subscribers. New subscriptions are disabled. Existing subscribers can continue to use it as usual until the API is retired.
RETIREDThe API is no longer in use when it is in this state.The API is unpublished and deleted from the Developer Portal.
+

Manage the lifecycle of an API

+

To change the lifecycle state of an API via the Choreo Console, follow the instructions given below:

+
+

Tip

+

You must have publishing privileges to manage the lifecycle states of a component.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to manage the lifecycle.
  4. +
  5. In the left navigation menu, click Manage, and then click Lifecycle.
  6. +
  7. In the Lifecycle Management pane, you will see the lifecycle state transition diagram indicating the current lifecycle state of the component. Just above the lifecycle state transition diagram, The possible lifecycle states you can apply to the component are displayed just above the lifecycle state transition diagram. Click on a required lifecycle state to apply it to the component. For example, if a component is in the Created state, you can click either Pre-release or Publish.
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/manage-api-traffic/assign-subscription-plans-to-apis/index.html b/api-management/manage-api-traffic/assign-subscription-plans-to-apis/index.html new file mode 100644 index 000000000..ad8b76a06 --- /dev/null +++ b/api-management/manage-api-traffic/assign-subscription-plans-to-apis/index.html @@ -0,0 +1,3462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Assign Subscription Plans to APIs - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Assign Subscription Plans to APIs

+

API subscription plans allow API publishers to control and manage access to APIs. These plans define the rules and limitations on how clients can interact with APIs, ensuring efficient resource utilization and robust security.

+

Choreo allows users with the administrator role to create, update, and delete subscription plans at the organization level. For instructions on creating subscription plans, see Create API Subscription Plans.

+

Once created, Choreo allows API publishers to assign subscription plans to APIs, providing different levels of access based on user needs.

+

To assign subscription plans to an API, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to assign subscription plans.
  4. +
  5. In the left navigation menu, click Manage and then click Subscription Plans. This displays the subscription plans available for the component.
  6. +
  7. +

    Enable the Subscription Plan Status toggle corresponding to the subscription plans you want to assign to the API.

    +

    Enable toggle

    +
  8. +
  9. +

    Click Save.

    +
  10. +
+

When an API has subscription plans assigned to it, API consumers can select the plan that best fits their requirements during the subscription process. For details, see Subscribe to an API with a Subscription Plan

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/manage-api-traffic/subscribe-to-an-api-with-a-subscription-plan/index.html b/api-management/manage-api-traffic/subscribe-to-an-api-with-a-subscription-plan/index.html new file mode 100644 index 000000000..a7983238f --- /dev/null +++ b/api-management/manage-api-traffic/subscribe-to-an-api-with-a-subscription-plan/index.html @@ -0,0 +1,3468 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Subscribe to an API with a Subscription Plan - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Subscribe to an API with a Subscription Plan

+

If an API has subscription plans assigned to it, API consumers can select the subscription plan that best fits their requirements at the time of subscribing to the API.

+

To subscribe to an API with a subscription plan, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. In the Developer Portal header, click Applications.
  4. +
  5. On the My Applications page, click on the application you want to use to subscribe to an API.
  6. +
  7. In the left navigation menu, click Subscriptions.
  8. +
  9. In the Subscription Management pane that opens, click + Add APIs.
  10. +
  11. In the Add APIs pane that opens, select the API, API version, and subscription plan with which you want to subscribe to the API.
  12. +
  13. +

    Click Add Subscription.

    +

    Add subscription

    +
  14. +
+

To verify that the subscription plan works as expected, follow the steps given below:

+
    +
  1. In the Developer Portal header, click APIs.
  2. +
  3. Search for the API you subscribed to and click Try Out.
  4. +
  5. +

    Invoke the API until you exceed the request limit set in the subscription plan. You will see that the API throttles further requests once the limit is reached.

    +

    Throttle response

    +
  6. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-management/rename-api-display-name/index.html b/api-management/rename-api-display-name/index.html new file mode 100644 index 000000000..95e1b1be6 --- /dev/null +++ b/api-management/rename-api-display-name/index.html @@ -0,0 +1,3457 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rename API Display Name - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Rename API Display Name

+

Choreo allows you to make one or more endpoints accessible through its service and integration components. These endpoints are published as individual APIs in Choreo, accessible via the Choreo Developer Portal. By default, Choreo assigns an API name by combining the component name and the endpoint name, resulting in the following format: <component name>-<endpoint name>. For example, if you create a component named Ballerina Reading List, the API is displayed as Ballerina Reading List - GraphQL Reading List 591.

+

Choreo provides you with the flexibility to personalize the display name of the API, enhancing its user-friendliness and readability. Once you modify the API display name within the Choreo Console, Choreo applies the change immediately. From there onwards, Choreo displays the published API by this name in the Choreo Developer Portal.

+

Follow the steps below to rename the API display name:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. In the Component Listing pane, click on the component for which you want to rename the API display name. This opens the Overview page of the component.
  4. +
  5. In the left navigation menu, click Manage and then click API Info.
  6. +
  7. On the API Info page that opens, click the Developer Portal tab.
  8. +
  9. Under General Details, specify an appropriate API display name in the Name field.
  10. +
  11. Click Save.
  12. +
+

Now, you can view the updated API display name in the Choreo Developer Portal.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-proxies/api-proxy/index.html b/api-proxies/api-proxy/index.html new file mode 100644 index 000000000..d70b9ed94 --- /dev/null +++ b/api-proxies/api-proxy/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/api-proxies/index.html b/api-proxies/index.html new file mode 100644 index 000000000..d70b9ed94 --- /dev/null +++ b/api-proxies/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/assets/css/blue-palette-alt2.css b/assets/css/blue-palette-alt2.css new file mode 100644 index 000000000..77d55879a --- /dev/null +++ b/assets/css/blue-palette-alt2.css @@ -0,0 +1,79 @@ + +:root { + --md-primary-fg-color: white + --md-primary-fg-color--light: white; + --md-primary-fg-color--dark: #147ecc; + --md-primary-bg-color: #fff; + --md-primary-bg-color--light: #ffffffb3; + --md-accent-fg-color: #033982; + --md-accent-fg-color--transparent: #0339821a; + --md-accent-bg-color: #fff; + --md-accent-bg-color--light: #ffffffb3; + --md-banner: url(../img/banner-for-blue-alt-light.png) no-repeat left top; + --md-default-fg-color: black; + --md-default-fg-color--light: black; + +} +:root { + --md-text-font: 'Source Sans Pro', sans-serif; + --md-code-font: 'Source Sans Pro', sans-serif; +} +/* colors for dark theme */ +[data-md-color-scheme="slate"] { + --md-primary-fg-color: white; + --md-primary-fg-color-header: white; + --md-primary-fg-color-header-text: #f5f6f7; + --md-primary-fg-color-header-text-active: #545cec; + --md-accent-fg-color: #545cec; + --md-default-bg-color: #23272f; + --md-typeset-a-color: #545cec; + --md-banner: url(../img/banner-for-blue-alt-dark.png) no-repeat left top; + --md-hjs-color: rgb(186, 186, 255); + --md-hjs-attr-color: #96ffc5; + --md-hjs-other-color: #f2b4b4; + --md-default-fg-color: white; + --md-default-fg-color--light: white; + + +} +/* colors for the light theme */ +[data-md-color-scheme="default"] { + --md-primary-fg-color-header: #f5f6f7; + --md-primary-fg-color-header-text: black; + --md-primary-fg-color-header-text-active: #545cec; + --md-accent-fg-color: #545cec; + --md-default-bg-color: #ffffff; + --md-typeset-a-color: var(--md-primary-fg-color); + --md-hjs-color: #36464e; + --md-hjs-attr-color: #1aab5b; + --md-hjs-other-color: #a31515; + --md-default-fg-color: black; + --md-default-fg-color--light: black; + +} +.md-tabs { + background-color: var(--md-primary-fg-color-header); + color: var(--md-primary-fg-color-header-text); +} +.md-tabs__link--active, .md-tabs__link:focus, .md-tabs__link:hover { + color: var(--md-primary-fg-color-header-text-active); +} +.hljs-attr { + color: var(--md-hjs-attr-color); +} +.hljs-built_in, .hljs-keyword, .hljs-name, .hljs-selector-tag, .hljs-tag { + color: var( --md-hjs-color); +} +.hljs-addition, .hljs-attribute, .hljs-literal, .hljs-section, .hljs-string, .hljs-template-tag, .hljs-template-variable, .hljs-title, .hljs-type{ + color: var(--md-hjs-other-color); +} + + +.banner-link { + width: 711px; + height: 363px; +} + +.md-header{ + box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.08), inset 0px -1px 0px #E1E2E7; +} \ No newline at end of file diff --git a/assets/css/choreotheme.css b/assets/css/choreotheme.css new file mode 100644 index 000000000..a06fb180f --- /dev/null +++ b/assets/css/choreotheme.css @@ -0,0 +1,745 @@ +.md-tabs__link--active { + font-weight: 600; +} + +.md-typeset h1{ + color: rgb(107, 101, 101); + font-weight: 500; +} + +.md-typeset h2 { + font-weight: 500; + letter-spacing: -.01em; +} + +.md-typeset h3 { + font-weight: 500; + color: #5a5856; +} + +.md-typeset a{ + color: #3841ec !important; +} + +.md-nav__link{ + font-weight: bold; +} + +.md-nav--primary .md-nav__item--nested .md-nav__list .md-nav__link{ + font-weight: normal !important; +} + +.md-nav__item .md-nav__link--active { + color: #3841ec !important; +} + +/* +* Footer styles +*/ +.md-footer { + /* background-color: var(--darkBack); */ +} + +.md-nav__title { + visibility: hidden; +} + +.md-footer-nav__link { + padding-top: 0.5rem; +} + +.md-flex__ellipsis { + font-size: 0.70rem; +} + +.md-footer-nav__direction { + font-size: 0.50rem; +} + +.md-copyright { + display: flex; + flex-direction: row; + width: 100%; +} + +.footer-copyright { + display: flex; + padding-top: 20px; + padding-bottom: 20px; +} + +.footer-copyright-left { + flex: 1; + font-size: 0.60rem; +} + +.footer-copyright-right { + font-size: 0.60rem; +} + +.section02 { + display: flex; + flex: 1; +} +/* Home page specific styles */ +.md-content .section02 .linkWrapper{ + display: flex; + flex-direction: row; +} +.homePageCard { + flex: 1; + padding: 0 10px; + + width: 424px; + height: 384px; + left: 60px; + top: 416px; + + /* White */ + + background: #FFFFFF; + /* Card/Grey/Default */ + + box-shadow: 0px 1px 1px #CBCEDB; + border-radius: 12px; +} + +.homePage h2 { + font-size: 1.2rem; + border-bottom: 0; + margin-top: -5px; +} + +.homePage h3 { + font-size: 1rem; + border-bottom: 0; + font-weight: 600; +} + +.homePage h4 { + margin: 0; +} +.fa-file-arrow-down { + background-image: linear-gradient(160deg, #545cec 0%, #80d0c7 100%); + -webkit-background-clip: text; + -moz-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + font-size: 100px; + } + .banner-link { + background: var(--md-banner); + display: inline-block; + } + + .md-typeset { + font-size: 0.8rem; + } + + .md-nav { + font-size: 0.7rem; + padding-left: 0.5rem; + } + + + + .md-sidebar__scrollwrap { + padding-right: 0; + } + + .md-content { + padding-left: 2rem; + padding-right: 2rem; + } + + .md-content__search_results{ + flex-grow: 1; + min-width: 0; + padding-left: 8rem; + padding-right: 8rem; + } + + .md-container{ + background-image: none; + } + + .md-container-home{ + background-image: url( '../img/home/background.svg' ); +} + + + .cIcon { + height: 18px; + width: 18px; + align-items: center; +} +.cIconContainer { + display: grid; + align-items: right; + grid-template-columns: 90% 10%; + column-gap: 0.5rem ; + padding-top: 1rem; + padding-bottom: 0.9rem; + padding-right: 2rem; +} +.cContentContainer{ + display: grid; + align-items: right; + + padding-top: 0.5rem; + padding-right: 2.5rem; + grid-column-gap: 0.5rem; +} +.md-search-result__list { +text-align: left; +} + +.cText{ + width: 100%; + font-size: 15px; +} + +.cText:hover { + color: #545ce5; + } +.md-icon svg{ +visibility: hidden; +} + +.md-search__input::placeholder { + color: #a8a39f; +} +.md-search__input-home{ + background: #FFFFFF; + box-shadow: 5px 0px 20px 20px rgba(203, 206, 219, 0.2); + border-radius: 12px; + height:2.5rem; + width: 40rem !important; + padding-left: 20px; + font-size: 14px; + width:fit-content; +} +.md-search__input{ + width:fit-content; +} +.md-search__inner-home{ + background-color: white; + width: 40rem; +} +.md-search__inner{ + background-color: white; + } + +.md-search__output-home{ + width: 40rem !important; + } +.cIcon path{ + fill: #545ce5; +} + +.md-main__inner_search{ + +} + +.hIcon{ + background: #F7F8FB; + border-radius: 50%; + padding: 0.6rem; + gap: 10px; + height: 2rem; + width: 2rem; + +} + +.hText{ + font-size: 17px; + padding-top: 0.6rem; + font-weight: 600; +} + +.md-typeset a{ + color: black; +} + +.main{ + background-image: none; +} + +.md-search{ + display: block; + text-align: -webkit-center; + display: block !important; +} + +.md-search__form-home { + border-radius: 0.5rem; + height: 3.5rem; + background-color: transparent !important; + box-shadow: none !important; +} + +.md-search__form { + border-radius: 0.5rem; + background-color: #CBCEDB; +} + +.md-search__form:hover { + border-radius: 0.5rem; + background-color: #CBCEDB; +} + +.md-header{ + color: #545cec; + background-color: white; + display: inline-block; + +} + +.md-icon svg{ + visibility: visible !important; +} + +.md-source__icon svg{ + margin-left: 0.6rem; +} + +.md_home_link_container{ + /* White */ + background: #FFFFFF; + /* Card/Grey/Default */ + box-shadow: 0px 1px 5px #CBCEDB; + border-radius: 12px; + padding-left: 1.2rem; + padding-bottom: 0.7rem; + height: fit-content; + display:block; + +} +.md_home_link_container_row{ + position: relative; + display: flex; + padding-right:5rem; + padding-left: 15dvw; + padding-bottom: 5rem; +} + + +.md-search-result__meta-{} +.md-grid { + margin-left:inherit; + margin-right: inherit; + max-width: 100%; +} + +.md-grid__search { + margin-left:inherit; + margin-right: inherit; + } + +.row2{ + display: contents; +} + +.iconTextcontainer{ + grid-template-columns: 5% 95%; + column-gap: 0.5rem ; + display: grid; + border-bottom: 1px solid #e0e2e980; + border-width: 100%; + margin-bottom: 1.3rem; + padding-bottom: 0.5rem; +} +.spacer_div_verticle{ + height: 1.2rem; +} + +.last_in_card{ + border-bottom: none; + margin-bottom:auto; +} + +.first_column_space{ + height: 2.1rem; +} + +.md_home_column column{ + width: 32%; +} + +.md-search_label{ + padding-top: 0.2rem; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 0dvw; + text-align: center; + color: #a8a39f; +} +.md-search_label2{ +color: #a8a39f; +} + + +@media screen and (max-width: 500px) { + + .md_home_link_container_row{ + display: block; + } + + .spacer_div{ + height: 2rem; + } + + .md-search{ + width: 50% !important; + } + .md-search__inner { + opacity: inherit !important; + width: 15rem; + + } + .md-search__input{ + width: 15rem !important; + padding-left: 0; + + } + .md-search__form{ + padding-left: 0; + } + .md-search_label{ + font-size: 2.5dvw; + padding-top: 0d; + } + .md-header__source { + display: block; + } +} + +@media only screen and (min-width: 60em){ + .md_home_column{ + width: 30%; + } +} + +@-moz-document url-prefix() { + .md-search { + margin-left:25%; + margin-top: -30px; + } + } + + @-moz-document url-prefix() { + .md-search__inner { + margin-top: 29px; + } + } + + @-moz-document url-prefix() { + .md-header__option { + margin-right: -415px; + } + } + + + +.cInlineImage-xsmall { + display: inline-block; + text-align: center; + height:15% !important; + width:20% !important; + border: 1px solid gray; +} + +.cInlineImage-small { + display: inline-block; + text-align: center; + height:45% !important; + width:30% !important; + border: 1px solid gray; +} + + +.cInlineImage-full { + display: inline-block; + text-align: center; + height:75% !important; + width:90% !important; + border: 1px solid gray; +} + +.cInlineImage-threeQuarter { + display: inline-block; + text-align: center; + width:65% !important; + border: 1px solid gray; +} + + +.cInlineImage-70 { + display: inline-block; + text-align: center; + width:70% !important; + border: 1px solid gray; +} + +.cInlineImage-half { + display: inline-block; + text-align: center; + width:50% !important; + border: 1px solid gray; +} + +.cInlineImage-bordered { + display: inline-block; + text-align: center; + border: 1px solid gray; +} + + +@media screen and (max-width: 76.234375em) { + .md-nav--primary,.md-nav--primary .md-nav { + background-color:var(--md-default-bg-color); + display: flex; + flex-direction: column; + height: 100%; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 1 + } + + .md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title { + font-size: .8rem; + line-height: 1.5 + } + + .md-nav--primary .md-nav__title { + background-color: var(--md-default-fg-color--lightest); + color: #545CEC; + cursor: pointer; + height: 5.6rem; + line-height: 2.4rem; + padding: 3rem .8rem .2rem; + position: relative; + white-space: nowrap; + visibility: visible; + + } + + [dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon { + left: .4rem + } + + [dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon { + right: .4rem + } + + .md-nav--primary .md-nav__title .md-nav__icon { + display: block; + height: 1.2rem; + margin: .2rem; + position: absolute; + top: .4rem; + width: 1.2rem; + visibility: visible; + color:#545CEC + } + + .md-nav--primary .md-nav__title .md-nav__icon:after { + background-color: currentcolor; + content: ""; + display: block; + height: 100%; + -webkit-mask-image: var(--md-nav-icon--prev); + mask-image: var(--md-nav-icon--prev); + -webkit-mask-position: center; + mask-position: center; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-size: contain; + mask-size: contain; + width: 100% + } + + .md-nav--primary .md-nav__title~.md-nav__list { + background-color: var(--md-default-bg-color); + box-shadow: 0 .05rem 0 var(--md-default-fg-color--lightest) inset; + overflow-y: auto; + scroll-snap-type: y mandatory; + touch-action: pan-y + } + + .md-nav--primary .md-nav__title~.md-nav__list>:first-child { + border-top: 0 + } + + .md-nav--primary .md-nav__title[for=__drawer] { + background-color: var(--md-primary-fg-color); + color: var(--md-primary-bg-color); + font-weight: 700 + } + + .md-nav--primary .md-nav__title .md-logo { + display: block; + left: .2rem; + margin: .2rem; + padding: 1rem; + position: absolute; + right: .2rem; + top: .2rem; + padding-top: 1rem !important; + } + + .md-nav--primary .md-nav__list { + flex: 1 + } + + .md-nav--primary .md-nav__item { + border-top: .05rem solid var(--md-default-fg-color--lightest) + } + + .md-nav--primary .md-nav__item--active>.md-nav__link { + color: var(--md-typeset-a-color) + } + + .md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover { + color: var(--md-accent-fg-color) + } + + .md-nav--primary .md-nav__link { + margin-top: 0; + padding: .6rem .8rem + } + + .md-nav--primary .md-nav__link svg { + margin-top: .1em + } + + .md-nav--primary .md-nav__link>.md-nav__link { + padding: 0 + } + + [dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon { + margin-right: -.2rem + } + + [dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon { + margin-left: -.2rem + } + + .md-nav--primary .md-nav__link .md-nav__icon { + font-size: 1.2rem; + height: 1.2rem; + width: 1.2rem + } + + .md-nav--primary .md-nav__link .md-nav__icon:after { + background-color: currentcolor; + content: ""; + display: block; + height: 100%; + -webkit-mask-image: var(--md-nav-icon--next); + mask-image: var(--md-nav-icon--next); + -webkit-mask-position: center; + mask-position: center; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-size: contain; + mask-size: contain; + width: 100% + } + + [dir=rtl] .md-nav--primary .md-nav__icon:after { + transform: scale(-1) + } + + .md-nav--primary .md-nav--secondary .md-nav { + background-color: initial; + position: static + } + + [dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link { + padding-left: 1.4rem + } + + [dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link { + padding-right: 1.4rem + } + + [dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link { + padding-left: 2rem + } + + [dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link { + padding-right: 2rem + } + + [dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link { + padding-left: 2.6rem + } + + [dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link { + padding-right: 2.6rem + } + + [dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link { + padding-left: 3.2rem + } + + [dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link { + padding-right: 3.2rem + } + + .md-nav--secondary { + background-color: initial + } + + .md-nav__toggle~.md-nav { + display: flex; + opacity: 0; + transform: translateX(100%); + transition: transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms + } + + [dir=rtl] .md-nav__toggle~.md-nav { + transform: translateX(-100%) + } + + .md-nav__toggle:checked~.md-nav { + opacity: 1; + transform: translateX(0); + transition: transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms + } + + .md-nav__toggle:checked~.md-nav>.md-nav__list { + -webkit-backface-visibility: hidden; + backface-visibility: hidden + } + + .md-search-result__meta{ + width: auto; + } + + .md-search__input-home { + box-shadow: none; + background: none; + padding-left: 0%; + text-align: center; + } + .md-search__output-home{ + width: 100% !important; + } + .md-content__search_results{ + min-width: none; + padding-left: 0%; + padding-right: 0%; + width: inherit; + position: unset !important; + } +} + +@media screen and (max-width: 59.9375em) { + body[data-md-scrolllock] { + } +} diff --git a/assets/css/config-catalog.css b/assets/css/config-catalog.css new file mode 100644 index 000000000..d97df62c4 --- /dev/null +++ b/assets/css/config-catalog.css @@ -0,0 +1,286 @@ +.mb-config-catalog { + display: table; + width: 100%; + max-width: 770px; +} + +.hide-toc .mb-config-catalog { + display: table; + max-width: 1000px; +} + +.mb-config-catalog .superfences-tabs { + flex-direction: column; +} + +.mb-config-catalog .superfences-tabs .tab-selector { + text-align: right; +} + +.mb-config-catalog .superfences-tabs .tab-selector>.icon { + margin-right: 5px; +} + +.mb-config-catalog .superfences-content { + flex-direction: column; + order: 0; +} + +.mb-config-catalog .superfences-tabs>input+label:after { + content: "View Sample"; + cursor: pointer; + font-size: 16px; +} + +.mb-config-catalog .superfences-tabs>input:checked+label:after { + content: "Hide Sample"; + cursor: pointer; + font-size: 16px; +} + +.mb-config-catalog .superfences-tabs .doc-wrapper { + padding: .525rem; +} + +.mb-config-catalog>section { + display: table-row; +} + +.mb-config-catalog>section>.mb-config-options, +.mb-config-catalog>section>.mb-config-example { + display: table-cell; + flex-direction: column; + max-width: 770px; +} + +.hide-toc .mb-config-catalog>section>.mb-config-options, +.hide-toc .mb-config-catalog>section>.mb-config-example { + display: table-cell; + max-width: 1000px; +} + +.mb-config-catalog>section>.mb-config-example>.example-config-wrap { + margin-right: 1em; +} + +.mb-config-catalog .mb-config>.params-wrap { + display: table; + width: 100%; +} + +.mb-config-catalog>section>.mb-config-example>code { + font-weight: bold; + font-size: 105%; +} + + +.mb-config-catalog>section:not(.title)>.mb-config-options { + border-bottom: 1px solid #f5f5f5; + padding-top: 1em; +} + +.mb-config-catalog>section:last-child>.mb-config-options { + border-bottom: none; +} + +.mb-config-catalog>section:not(.title)>.mb-config-example { + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; +} + +.mb-config-catalog>section.title>.mb-config-example { + display: none; +} + +.mb-config-catalog .mb-config-example code, +.mb-config-catalog .mb-config-example pre { + margin: 0; +} + +.mb-config-catalog .mb-config-example:hover .md-clipboard:before { + color: rgba(0, 0, 0, .54); +} + +[data-md-color-accent=deep-orange] .mb-config-catalog .mb-config-example:hover .md-clipboard:active:before, +[data-md-color-accent=deep-orange] .mb-config-catalog .mb-config-example:hover .md-clipboard:hover:before { + color: var(--md-primary-fg-color--light); +} + +.mb-config-catalog>section.title>.mb-config-options>h2 { + margin-bottom: 1rem; +} + +.mb-config-catalog>section>.mb-config-example { + background: #f5f5f5; + width: 35%; + padding: .5em; + vertical-align: top; +} + +.mb-config-catalog>section>.mb-config-example code { + background: transparent; + box-shadow: none; + white-space: pre-line; +} + +.mb-config-catalog .badge-required { + margin: 0 .29412em; + padding: .07353em .3em; + border-radius: .2rem; + background-color: var(--md-primary-fg-color--light); + color: #fff; + font-size: 75%; +} + +.mb-config-catalog .mb-config>.config-wrap { + margin-right: 1em; +} + +.mb-config-catalog .mb-config>.params-wrap { + display: table; + width: 100%; +} + +.mb-config-catalog .mb-config>.config-wrap>code { + font-weight: bold; + font-size: 105%; +} + +.mb-config-catalog .mb-config .param { + display: table-row; +} + +.mb-config-catalog .mb-config .param>.param-name { + display: table-cell; + vertical-align: top; + border-left: 2px solid var(--md-primary-fg-color--light); + box-sizing: border-box; + position: relative; + padding: 1.7em 0; + vertical-align: top; + line-height: 20px; + white-space: nowrap; + font-size: .929em; + font-weight: 400; +} + +.mb-config-catalog .mb-config .param .param-name-wrap { + display: inline-block; + padding-right: 25px; + font-family: Montserrat, sans-serif; +} + +.mb-config-catalog .mb-config .param>.param-name>span::before { + content: ''; + display: inline-block; + width: 2px; + height: 8px; + background-color: var(--md-primary-fg-color--light); + margin: -4px 10px 0; + vertical-align: middle; +} + +.mb-config-catalog .mb-config .param>.param-name>span::after { + content: ''; + position: absolute; + border-top: 2px solid var(--md-primary-fg-color--light); + width: 10px; + left: 0; + top: 2.3em; +} + +.mb-config-catalog .mb-config .param:first-of-type>.param-name::before { + content: ''; + display: block; + position: absolute; + left: -2px; + top: 0; + border-left: 3px solid var(--md-default-bg-color); + height: 34px; +} + +.mb-config-catalog .mb-config .param:last-of-type>.param-name, +.mb-config-catalog .mb-config .param.last>.param-name { + position: relative; +} + +.mb-config-catalog .mb-config .param:last-of-type>.param-name::after, +.mb-config-catalog .mb-config .param.last>.param-name::after { + content: ''; + display: block; + position: absolute; + left: -2px; + border-left: 3px solid #fff; + top: 36px; + background-color: #fff; + bottom: 0; +} + +.mb-config-catalog .mb-config .param>.param-info { + display: table-cell; + width: 100%; + border-bottom: 1px solid #eee; + padding: 10px 10px 10px 0; + box-sizing: border-box; + word-break: break-word; +} + +.mb-config-catalog .mb-config .param-default { + font-size: .95em; +} + +.mb-config-catalog .mb-config .param-type { + color: #b5b5b5; +} + +html .md-typeset .superfences-tabs>label { + color: var(--md-primary-fg-color); + font-weight: normal; + padding: 20px; + border-bottom: 0.05rem dashed var(--md-primary-fg-color--light); +} + +.md-typeset .superfences-tabs { + display: flex; + position: relative; + flex-wrap: wrap; + margin: 1em 0; + border: 0.05rem solid rgba(0,0,0,.07); +} +.md-typeset .superfences-tabs { + border: 0.05rem dashed var(--md-primary-fg-color--light); + border-radius: 5px; +} + +@media only screen and (min-width: 100em) { + .mb-config-catalog .mb-config .param>.param-name>span::before { + margin: 0 10px; + } + + .mb-config-catalog .mb-config .param:first-of-type>.param-name::before { + height: 38px; + } + + .mb-config-catalog .mb-config .param:last-of-type>.param-name::after, + .mb-config-catalog .mb-config .param.last>.param-name::after { + top: 40px; + } +} + +@media (max-width: 767px) { + .mb-config-catalog { + margin-bottom: 3rem; + } + + .mb-config-catalog, + .mb-config-catalog>section, + .mb-config-catalog>section>.mb-config-options, + .mb-config-catalog>section>.mb-config-example { + display: block; + width: 100% !important; + } + + .mb-config-catalog>section:not(.title)>.mb-config-options { + padding-bottom: 1rem; + } +} \ No newline at end of file diff --git a/assets/css/prism.css b/assets/css/prism.css new file mode 100644 index 000000000..1296240b3 --- /dev/null +++ b/assets/css/prism.css @@ -0,0 +1,246 @@ +/* PrismJS 1.20.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+java&plugins=line-highlight */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + + code[class*="language-"], + pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 0.85em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } + + pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, + code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; + } + + pre[class*="language-"]::selection, pre[class*="language-"] ::selection, + code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; + } + + @media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } + } + + /* Code blocks */ + pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; + } + + :not(pre) > code[class*="language-"], + pre[class*="language-"] { + background: #f5f2f0; + } + + /* Inline code */ + :not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; + } + + .token.comment, + .token.prolog, + .token.doctype, + .token.cdata { + color: slategray; + } + + .token.punctuation { + color: #999; + } + + .token.namespace { + opacity: .7; + } + + .token.property, + .token.tag, + .token.boolean, + .token.number, + .token.constant, + .token.symbol, + .token.deleted { + color: #905; + } + + .token.selector, + .token.attr-name, + .token.string, + .token.char, + .token.builtin, + .token.inserted { + color: #690; + } + + .token.operator, + .token.entity, + .token.url, + .language-css .token.string, + .style .token.string { + color: #9a6e3a; + /* This background color was intended by the author of this theme. */ + background: hsla(0, 0%, 100%, .5); + } + + .token.atrule, + .token.attr-value, + .token.keyword { + color: #07a; + } + + .token.function, + .token.class-name { + color: #DD4A68; + } + + .token.regex, + .token.important, + .token.variable { + color: #e90; + } + + .token.important, + .token.bold { + font-weight: bold; + } + .token.italic { + font-style: italic; + } + + .token.entity { + cursor: help; + } + + pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; + } + + .line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; /* Same as .prism’s padding-top */ + + background: hsla(24, 20%, 50%,.08); + background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + + pointer-events: none; + + line-height: inherit; + white-space: pre; + } + +.line-highlight:before, +.line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: hsla(24, 20%, 50%,.4); + color: hsl(24, 20%, 95%); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; +} + +.line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; +} + + .line-numbers .line-highlight:before, + .line-numbers .line-highlight:after { + content: none; + } + + pre[id].linkable-line-numbers span.line-numbers-rows { + pointer-events: all; + } + pre[id].linkable-line-numbers span.line-numbers-rows > span:before { + cursor: pointer; + } + pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before { + background-color: rgba(128, 128, 128, .2); + } + + + + pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; + } + + pre.line-numbers > code { + position: relative; + white-space: inherit; + } + + .line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + } + +.line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; +} + +.line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; +} diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 000000000..ec53c6dee --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1 @@ +@import url("https://fonts.googleapis.com/css?family=Bitter|Open+Sans:400,700");*,*::after,*::before{box-sizing:inherit}*{font:inherit}html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video,hr{margin:0;padding:0;border:0}html{box-sizing:border-box}body{background-color:hsl(0, 0%, 100%);background-color:var(--color-bg, white)}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,main,form legend{display:block}ol,ul{list-style:none}blockquote,q{quotes:none}button,input,textarea,select{margin:0}.btn,.form-control,.link,.reset{background-color:transparent;padding:0;border:0;border-radius:0;color:inherit;line-height:inherit;-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control::-ms-expand{display:none}textarea{resize:vertical;overflow:auto;vertical-align:top}input::-ms-clear{display:none}table{border-collapse:collapse;border-spacing:0}img,video,svg{max-width:100%}:root,[data-theme="default"]{--color-primary-darker:hsl(220, 90%, 36%);--color-primary-darker-h:220;--color-primary-darker-s:90%;--color-primary-darker-l:36%;--color-primary-dark:hsl(220, 90%, 46%);--color-primary-dark-h:220;--color-primary-dark-s:90%;--color-primary-dark-l:46%;--color-primary:hsl(220, 90%, 56%);--color-primary-h:220;--color-primary-s:90%;--color-primary-l:56%;--color-primary-light:hsl(220, 90%, 66%);--color-primary-light-h:220;--color-primary-light-s:90%;--color-primary-light-l:66%;--color-primary-lighter:hsl(220, 90%, 76%);--color-primary-lighter-h:220;--color-primary-lighter-s:90%;--color-primary-lighter-l:76%;--color-accent-darker:hsl(355, 90%, 41%);--color-accent-darker-h:355;--color-accent-darker-s:90%;--color-accent-darker-l:41%;--color-accent-dark:hsl(355, 90%, 51%);--color-accent-dark-h:355;--color-accent-dark-s:90%;--color-accent-dark-l:51%;--color-accent:hsl(355, 90%, 61%);--color-accent-h:355;--color-accent-s:90%;--color-accent-l:61%;--color-accent-light:hsl(355, 90%, 71%);--color-accent-light-h:355;--color-accent-light-s:90%;--color-accent-light-l:71%;--color-accent-lighter:hsl(355, 90%, 81%);--color-accent-lighter-h:355;--color-accent-lighter-s:90%;--color-accent-lighter-l:81%;--color-black:hsl(240, 8%, 12%);--color-black-h:240;--color-black-s:8%;--color-black-l:12%;--color-white:hsl(0, 0%, 100%);--color-white-h:0;--color-white-s:0%;--color-white-l:100%;--color-success-darker:hsl(94, 48%, 36%);--color-success-darker-h:94;--color-success-darker-s:48%;--color-success-darker-l:36%;--color-success-dark:hsl(94, 48%, 46%);--color-success-dark-h:94;--color-success-dark-s:48%;--color-success-dark-l:46%;--color-success:hsl(94, 48%, 56%);--color-success-h:94;--color-success-s:48%;--color-success-l:56%;--color-success-light:hsl(94, 48%, 66%);--color-success-light-h:94;--color-success-light-s:48%;--color-success-light-l:66%;--color-success-lighter:hsl(94, 48%, 76%);--color-success-lighter-h:94;--color-success-lighter-s:48%;--color-success-lighter-l:76%;--color-error-darker:hsl(355, 90%, 41%);--color-error-darker-h:355;--color-error-darker-s:90%;--color-error-darker-l:41%;--color-error-dark:hsl(355, 90%, 51%);--color-error-dark-h:355;--color-error-dark-s:90%;--color-error-dark-l:51%;--color-error:hsl(355, 90%, 61%);--color-error-h:355;--color-error-s:90%;--color-error-l:61%;--color-error-light:hsl(355, 90%, 71%);--color-error-light-h:355;--color-error-light-s:90%;--color-error-light-l:71%;--color-error-lighter:hsl(355, 90%, 81%);--color-error-lighter-h:355;--color-error-lighter-s:90%;--color-error-lighter-l:81%;--color-warning-darker:hsl(46, 100%, 41%);--color-warning-darker-h:46;--color-warning-darker-s:100%;--color-warning-darker-l:41%;--color-warning-dark:hsl(46, 100%, 51%);--color-warning-dark-h:46;--color-warning-dark-s:100%;--color-warning-dark-l:51%;--color-warning:hsl(46, 100%, 61%);--color-warning-h:46;--color-warning-s:100%;--color-warning-l:61%;--color-warning-light:hsl(46, 100%, 71%);--color-warning-light-h:46;--color-warning-light-s:100%;--color-warning-light-l:71%;--color-warning-lighter:hsl(46, 100%, 81%);--color-warning-lighter-h:46;--color-warning-lighter-s:100%;--color-warning-lighter-l:81%;--color-bg:hsl(0, 0%, 100%);--color-bg-h:0;--color-bg-s:0%;--color-bg-l:100%;--color-contrast-lower:hsl(0, 0%, 95%);--color-contrast-lower-h:0;--color-contrast-lower-s:0%;--color-contrast-lower-l:95%;--color-contrast-low:hsl(240, 1%, 83%);--color-contrast-low-h:240;--color-contrast-low-s:1%;--color-contrast-low-l:83%;--color-contrast-medium:hsl(240, 1%, 48%);--color-contrast-medium-h:240;--color-contrast-medium-s:1%;--color-contrast-medium-l:48%;--color-contrast-high:hsl(240, 4%, 20%);--color-contrast-high-h:240;--color-contrast-high-s:4%;--color-contrast-high-l:20%;--color-contrast-higher:hsl(240, 8%, 12%);--color-contrast-higher-h:240;--color-contrast-higher-s:8%;--color-contrast-higher-l:12%}[data-theme]{background-color:hsl(0, 0%, 100%);background-color:var(--color-bg);color:hsl(240, 4%, 20%);color:var(--color-contrast-high)}:root{--space-unit: 1em;--space-xxxxs: calc(0.125*var(--space-unit));--space-xxxs: calc(0.25*var(--space-unit));--space-xxs: calc(0.375*var(--space-unit));--space-xs: calc(0.5*var(--space-unit));--space-sm: calc(0.75*var(--space-unit));--space-md: calc(1.25*var(--space-unit));--space-lg: calc(2*var(--space-unit));--space-xl: calc(3.25*var(--space-unit));--space-xxl: calc(5.25*var(--space-unit));--space-xxxl: calc(8.5*var(--space-unit));--space-xxxxl: calc(13.75*var(--space-unit));--component-padding: var(--space-md)}@supports (--css: variables){@media (min-width: 64rem){:root{--space-unit: 1.25em}}}.margin-top,.margin-top--md{margin-top:1.25em;margin-top:var(--space-md)}.margin-top--xxxxs{margin-top:0.125em;margin-top:var(--space-xxxxs)}.margin-top--xxxs{margin-top:0.25em;margin-top:var(--space-xxxs)}.margin-top--xxs{margin-top:0.375em;margin-top:var(--space-xxs)}.margin-top--xs{margin-top:0.5em;margin-top:var(--space-xs)}.margin-top--sm{margin-top:0.75em;margin-top:var(--space-sm)}.margin-top--lg{margin-top:2em;margin-top:var(--space-lg)}.margin-top--xl{margin-top:3.25em;margin-top:var(--space-xl)}.margin-top--xxl{margin-top:5.25em;margin-top:var(--space-xxl)}.margin-top--xxxl{margin-top:8.5em;margin-top:var(--space-xxxl)}.margin-top--xxxxl{margin-top:13.75em;margin-top:var(--space-xxxxl)}.margin-bottom,.margin-bottom--md{margin-bottom:1.25em;margin-bottom:var(--space-md)}.margin-bottom--xxxxs{margin-bottom:0.125em;margin-bottom:var(--space-xxxxs)}.margin-bottom--xxxs{margin-bottom:0.25em;margin-bottom:var(--space-xxxs)}.margin-bottom--xxs{margin-bottom:0.375em;margin-bottom:var(--space-xxs)}.margin-bottom--xs{margin-bottom:0.5em;margin-bottom:var(--space-xs)}.margin-bottom--sm{margin-bottom:0.75em;margin-bottom:var(--space-sm)}.margin-bottom--lg{margin-bottom:2em;margin-bottom:var(--space-lg)}.margin-bottom--xl{margin-bottom:3.25em;margin-bottom:var(--space-xl)}.margin-bottom--xxl{margin-bottom:5.25em;margin-bottom:var(--space-xxl)}.margin-bottom--xxxl{margin-bottom:8.5em;margin-bottom:var(--space-xxxl)}.margin-bottom--xxxxl{margin-bottom:13.75em;margin-bottom:var(--space-xxxxl)}:root{--container-width-xs: 37.5rem;--container-width-sm: 45rem;--container-width-md: 64rem;--container-width-lg: 80rem;--container-width-xl: 90rem}.container{width:calc(100% - 1.25em);width:calc(100% - 2*var(--component-padding));margin-left:auto;margin-right:auto}.container--full-width{width:100%}.container--xs{max-width:37.5rem;max-width:var(--container-width-xs)}.container--sm{max-width:45rem;max-width:var(--container-width-sm)}.container--md{max-width:64rem;max-width:var(--container-width-md)}.container--lg{max-width:80rem;max-width:var(--container-width-lg)}.container--xl{max-width:90rem;max-width:var(--container-width-xl)}.container--adaptive,.container--adaptive-lg{max-width:37.5rem;max-width:var(--container-width-xs)}@media (min-width: 64rem){.container--adaptive,.container--adaptive-lg{max-width:64rem;max-width:var(--container-width-md)}}@media (min-width: 90rem){.container--adaptive,.container--adaptive-lg{max-width:80rem;max-width:var(--container-width-lg)}}.container--adaptive-sm{max-width:37.5rem;max-width:var(--container-width-xs)}@media (min-width: 64rem){.container--adaptive-sm{max-width:45rem;max-width:var(--container-width-sm)}}.container--adaptive-md{max-width:37.5rem;max-width:var(--container-width-xs)}@media (min-width: 64rem){.container--adaptive-md{max-width:64rem;max-width:var(--container-width-md)}}.container--adaptive-xl{max-width:37.5rem;max-width:var(--container-width-xs)}@media (min-width: 64rem){.container--adaptive-xl{max-width:64rem;max-width:var(--container-width-md)}}@media (min-width: 90rem){.container--adaptive-xl{max-width:90rem;max-width:var(--container-width-xl)}}.grid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.grid>*{background-clip:content-box;-ms-flex-preferred-size:100%;flex-basis:100%}.grid--gap-xs,.grid-gap--xs{margin:-0.5em 0 0 -0.5em;margin:calc(var(--space-xs)*-1) 0 0 calc(var(--space-xs)*-1)}.grid--gap-xs>*,.grid-gap--xs>*{padding:0.5em 0 0 0.5em;padding:var(--space-xs) 0 0 var(--space-xs)}.grid--gap-sm,.grid-gap--sm{margin:-0.75em 0 0 -0.75em;margin:calc(var(--space-sm)*-1) 0 0 calc(var(--space-sm)*-1)}.grid--gap-sm>*,.grid-gap--sm>*{padding:0.75em 0 0 0.75em;padding:var(--space-sm) 0 0 var(--space-sm)}.grid--gap-md,.grid-gap--md{margin:-1.25em 0 0 -1.25em;margin:calc(var(--space-md)*-1) 0 0 calc(var(--space-md)*-1)}.grid--gap-md>*,.grid-gap--md>*{padding:1.25em 0 0 1.25em;padding:var(--space-md) 0 0 var(--space-md)}.grid--gap-lg,.grid-gap--lg{margin:-2em 0 0 -2em;margin:calc(var(--space-lg)*-1) 0 0 calc(var(--space-lg)*-1)}.grid--gap-lg>*,.grid-gap--lg>*{padding:2em 0 0 2em;padding:var(--space-lg) 0 0 var(--space-lg)}.grid--gap-xl,.grid-gap--xl{margin:-3.25em 0 0 -3.25em;margin:calc(var(--space-xl)*-1) 0 0 calc(var(--space-xl)*-1)}.grid--gap-xl>*,.grid-gap--xl>*{padding:3.25em 0 0 3.25em;padding:var(--space-xl) 0 0 var(--space-xl)}.col{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}@media (min-width: 30rem){.col--xs{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--xs-1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--xs-2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--xs-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--xs-4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--xs-5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--xs-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--xs-7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--xs-8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--xs-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--xs-10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--xs-11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--xs-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}}@media (min-width: 37.5rem){.col--sm{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--sm-1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--sm-2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--sm-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--sm-4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--sm-5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--sm-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--sm-7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--sm-8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--sm-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--sm-10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--sm-11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--sm-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}}@media (min-width: 64rem){.col--md{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--md-1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--md-2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--md-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--md-4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--md-5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--md-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--md-7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--md-8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--md-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--md-10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--md-11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--md-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}}@media (min-width: 80rem){.col--lg{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--lg-1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--lg-2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--lg-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--lg-4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--lg-5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--lg-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--lg-7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--lg-8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--lg-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--lg-10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--lg-11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--lg-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}}@media (min-width: 90rem){.col--xl{-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:0;flex-basis:0;max-width:100%}.col--xl-1{-ms-flex-preferred-size:8.33%;flex-basis:8.33%;max-width:8.33%}.col--xl-2{-ms-flex-preferred-size:16.66%;flex-basis:16.66%;max-width:16.66%}.col--xl-3{-ms-flex-preferred-size:25%;flex-basis:25%;max-width:25%}.col--xl-4{-ms-flex-preferred-size:33.33%;flex-basis:33.33%;max-width:33.33%}.col--xl-5{-ms-flex-preferred-size:41.66%;flex-basis:41.66%;max-width:41.66%}.col--xl-6{-ms-flex-preferred-size:50%;flex-basis:50%;max-width:50%}.col--xl-7{-ms-flex-preferred-size:58.33%;flex-basis:58.33%;max-width:58.33%}.col--xl-8{-ms-flex-preferred-size:66.66%;flex-basis:66.66%;max-width:66.66%}.col--xl-9{-ms-flex-preferred-size:75%;flex-basis:75%;max-width:75%}.col--xl-10{-ms-flex-preferred-size:83.33%;flex-basis:83.33%;max-width:83.33%}.col--xl-11{-ms-flex-preferred-size:91.66%;flex-basis:91.66%;max-width:91.66%}.col--xl-12{-ms-flex-preferred-size:100%;flex-basis:100%;max-width:100%}}.flex{display:-ms-flexbox;display:flex}.flex>*{display:inline-block}.flex--wrap{-ms-flex-wrap:wrap;flex-wrap:wrap}.flex--column{-ms-flex-direction:column;flex-direction:column}.flex--end{-ms-flex-pack:end;justify-content:flex-end}.flex--center{-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.flex--center-x{-ms-flex-pack:center;justify-content:center}.flex--center-y{-ms-flex-align:center;align-items:center}.flex--space-between{-ms-flex-pack:justify;justify-content:space-between}.flex--space-around{-ms-flex-pack:distribute;justify-content:space-around}.flex--space-evenly{-ms-flex-pack:space-evenly;justify-content:space-evenly}.flex--grow>*{-ms-flex-positive:1;flex-grow:1}.flex--shrink-none>*{-ms-flex-negative:0;flex-shrink:0}.flex--gap>*,.flex--gap-md>*,.flex-gap>*,.flex-gap--md>*{margin-right:1.25em;margin-right:var(--space-md)}.flex--gap>*:last-child,.flex--gap-md>*:last-child,.flex-gap>*:last-child,.flex-gap--md>*:last-child{margin-right:0}.flex--wrap.flex--gap,.flex--wrap.flex--gap-md,.flex--wrap.flex-gap,.flex--wrap.flex-gap--md{margin-bottom:-1.25em;margin-bottom:calc(-1*var(--space-md))}.flex--wrap.flex--gap>*,.flex--wrap.flex--gap-md>*,.flex--wrap.flex-gap>*,.flex--wrap.flex-gap--md>*{margin-bottom:1.25em;margin-bottom:var(--space-md)}.flex--gap-xxs>*,.flex-gap--xxs>*{margin-right:0.375em;margin-right:var(--space-xxs)}.flex--gap-xxs>*:last-child,.flex-gap--xxs>*:last-child{margin-right:0}.flex--wrap.flex--gap-xxs,.flex--wrap.flex-gap--xxs{margin-bottom:-0.375em;margin-bottom:calc(-1*var(--space-xxs))}.flex--wrap.flex--gap-xxs>*,.flex--wrap.flex-gap--xxs>*{margin-bottom:0.375em;margin-bottom:var(--space-xxs)}.flex--gap-xs>*,.flex-gap--xs>*{margin-right:0.5em;margin-right:var(--space-xs)}.flex--gap-xs>*:last-child,.flex-gap--xs>*:last-child{margin-right:0}.flex--wrap.flex--gap-xs,.flex--wrap.flex-gap--xs{margin-bottom:-0.5em;margin-bottom:calc(-1*var(--space-xs))}.flex--wrap.flex--gap-xs>*,.flex--wrap.flex-gap--xs>*{margin-bottom:0.5em;margin-bottom:var(--space-xs)}.flex--gap-sm>*,.flex-gap--sm>*{margin-right:0.75em;margin-right:var(--space-sm)}.flex--gap-sm>*:last-child,.flex-gap--sm>*:last-child{margin-right:0}.flex--wrap.flex--gap-sm,.flex--wrap.flex-gap--sm{margin-bottom:-0.75em;margin-bottom:calc(-1*var(--space-sm))}.flex--wrap.flex--gap-sm>*,.flex--wrap.flex-gap--sm>*{margin-bottom:0.75em;margin-bottom:var(--space-sm)}.flex--gap-lg>*,.flex-gap--lg>*{margin-right:2em;margin-right:var(--space-lg)}.flex--gap-lg>*:last-child,.flex-gap--lg>*:last-child{margin-right:0}.flex--wrap.flex--gap-lg,.flex--wrap.flex-gap--lg{margin-bottom:-2em;margin-bottom:calc(-1*var(--space-lg))}.flex--wrap.flex--gap-lg>*,.flex--wrap.flex-gap--lg>*{margin-bottom:2em;margin-bottom:var(--space-lg)}.flex--gap-xl>*,.flex-gap--xl>*{margin-right:3.25em;margin-right:var(--space-xl)}.flex--gap-xl>*:last-child,.flex-gap--xl>*:last-child{margin-right:0}.flex--wrap.flex--gap-xl,.flex--wrap.flex-gap--xl{margin-bottom:-3.25em;margin-bottom:calc(-1*var(--space-xl))}.flex--wrap.flex--gap-xl>*,.flex--wrap.flex-gap--xl>*{margin-bottom:3.25em;margin-bottom:var(--space-xl)}.flex-item--end{-ms-flex-item-align:end;align-self:flex-end}.flex-item--grow{-ms-flex-positive:1;flex-grow:1}.flex-item--shrink-none{-ms-flex-negative:0;flex-shrink:0}:root{--radius: 0.25em;--shadow-sm: 0 1px 1px rgba(0, 0, 0, .2), 0 1px 8px rgba(0, 0, 0, .1);--shadow-md: 0 1px 8px rgba(0, 0, 0, .1), 0 8px 24px rgba(0, 0, 0, .15);--shadow-lg: 0 1px 8px rgba(0, 0, 0, .1), 0 16px 48px rgba(0, 0, 0, .1), 0 24px 60px rgba(0, 0, 0, .1);--transition-bounce: cubic-bezier(0.175, 0.885, 0.32, 1.275);--transition-ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);--transition-ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19);--transition-ease-out: cubic-bezier(0.215, 0.61, 0.355, 1)}:root{--font-primary: sans-serif;--text-base-size: 1em;--text-scale-ratio: 1.2;--text-xs: calc(1em/var(--text-scale-ratio)/var(--text-scale-ratio));--text-sm: calc(var(--text-xs)*var(--text-scale-ratio));--text-md: calc(var(--text-sm)*var(--text-scale-ratio)*var(--text-scale-ratio));--text-lg: calc(var(--text-md)*var(--text-scale-ratio));--text-xl: calc(var(--text-lg)*var(--text-scale-ratio));--text-xxl: calc(var(--text-xl)*var(--text-scale-ratio));--text-xxxl: calc(var(--text-xxl)*var(--text-scale-ratio));--body-line-height: 1.4;--heading-line-height: 1.2;--font-primary-capital-letter: 1}@supports (--css: variables){@media (min-width: 64rem){:root{--text-base-size: 1.25em;--text-scale-ratio: 1.25}}}body{font-size:1em;font-size:var(--text-base-size);font-family:'Bitter', sans-serif;font-family:var(--font-primary);color:hsl(240, 4%, 20%);color:var(--color-contrast-high)}h1,h2,h3,h4{color:hsl(240, 8%, 12%);color:var(--color-contrast-higher);line-height:1.2;line-height:var(--heading-line-height)}.text--xxxl{font-size:2.48832em;font-size:var(--text-xxxl)}h1,.text--xxl{font-size:2.0736em;font-size:var(--text-xxl)}h2,.text--xl{font-size:1.728em;font-size:var(--text-xl)}h3,.text--lg{font-size:1.44em;font-size:var(--text-lg)}h4,.text--md{font-size:1.2em;font-size:var(--text-md)}.text--sm,small{font-size:0.83333em;font-size:var(--text-sm)}.text--xs{font-size:0.69444em;font-size:var(--text-xs)}a,.link{color:hsl(220, 90%, 56%);color:var(--color-primary);text-decoration:underline}mark{background-color:hsla(355, 90%, 61%, 0.2);background-color:hsla(var(--color-accent-h), var(--color-accent-s), var(--color-accent-l), 0.2);color:inherit}strong{font-weight:bold}s{text-decoration:line-through}u{text-decoration:underline}.text--subtle,.text-component .text--subtle{color:hsl(240, 1%, 48%);color:var(--color-contrast-medium)}.text--inherit,.text-component .text--inherit{color:inherit}.text-component{--component-body-line-height: calc(var(--body-line-height)*var(--line-height-multiplier, 1));--component-heading-line-height: calc(var(--heading-line-height)*var(--line-height-multiplier, 1));--line-height-multiplier: 1;--text-vspace-multiplier: 1}.text-component h1,.text-component h2,.text-component h3,.text-component h4{line-height:1.2;line-height:var(--component-heading-line-height);margin-bottom:0.25em;margin-bottom:calc(var(--space-xxxs)*var(--text-vspace-multiplier))}.text-component h2,.text-component h3,.text-component h4{margin-top:0.75em;margin-top:calc(var(--space-sm)*var(--text-vspace-multiplier))}.text-component p,.text-component blockquote,.text-component ul li,.text-component ol li{line-height:1.4;line-height:var(--component-body-line-height);color:hsl(240, 4%, 20%);color:var(--color-contrast-high)}.text-component ul,.text-component ol,.text-component p,.text-component blockquote,.text-component .text-component__block,.text-component .text-component__img{margin-bottom:0.75em;margin-bottom:calc(var(--space-sm)*var(--text-vspace-multiplier))}.text-component ul,.text-component ol{padding-left:1em}.text-component ul{list-style-type:disc}.text-component ol{list-style-type:decimal}.text-component em{font-style:italic}.text-component blockquote{padding-left:1em;border-left:4px solid hsl(240, 1%, 83%);border-left:4px solid var(--color-contrast-low)}.text-component hr{background:hsl(240, 1%, 83%);background:var(--color-contrast-low);height:1px;margin:2em auto;margin:calc(var(--space-lg)*var(--text-vspace-multiplier)) auto}.text-component>*:first-child{margin-top:0}.text-component>*:last-child{margin-bottom:0}.article.text-component{--line-height-multiplier: 1.13;--text-vspace-multiplier: 1.2}.text-component__img{text-align:center}.text-component__img img{display:block;margin:0 auto}.text-component__img figcaption{text-align:center;font-size:0.83333em;font-size:var(--text-sm);color:hsl(240, 1%, 48%);color:var(--color-contrast-medium);margin-top:0.5em;margin-top:var(--space-xs)}.text-component__block .text-component__img{margin-bottom:0}@media (min-width: 37.5rem){.text-component__block--left,.text-component__block--right,.text-component__img--left,.text-component__img--right{width:45%}.text-component__block--left img,.text-component__block--right img,.text-component__img--left img,.text-component__img--right img{width:100%}.text-component__block--left,.text-component__img--left{float:left;margin-right:0.75em;margin-right:calc(var(--space-sm)*var(--text-vspace-multiplier, 1))}.text-component__block--right,.text-component__img--right{float:right;margin-left:0.75em;margin-left:calc(var(--space-sm)*var(--text-vspace-multiplier, 1))}}@media (min-width: 90rem){.text-component__block--outset,.text-component__img--outset{width:calc(100% + 10.5em);width:calc(100% + 2*var(--space-xxl))}.text-component__block--outset img,.text-component__img--outset img{width:100%}.text-component__block--outset:not(.text-component__block--right),.text-component__img--outset:not(.text-component__img--right){margin-left:-5.25em;margin-left:calc(-1*var(--space-xxl))}.text-component__block--left,.text-component__block--right,.text-component__img--left,.text-component__img--right{width:50%}.text-component__block--right.text-component__block--outset,.text-component__img--right.text-component__img--outset{margin-right:-5.25em;margin-right:calc(-1*var(--space-xxl))}}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--center{text-align:center}.text--replace{overflow:hidden;color:transparent;text-indent:100%;white-space:nowrap}:root{--icon-xs: 16px;--icon-sm: 24px;--icon-md: 32px;--icon-lg: 48px;--icon-xl: 64px}.icon{display:inline-block;color:hsl(240, 8%, 12%);color:var(--color-contrast-higher);fill:currentColor;height:1em;width:1em;line-height:1}.icon--xs{font-size:16px;font-size:var(--icon-xs)}.icon--sm{font-size:24px;font-size:var(--icon-sm)}.icon--md{font-size:32px;font-size:var(--icon-md)}.icon--lg{font-size:48px;font-size:var(--icon-lg)}.icon--xl{font-size:64px;font-size:var(--icon-xl)}.icon-text{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center}.icon-text>*:nth-child(2){margin-left:0.375em;margin-left:var(--space-xxs)}.icon-text .icon{color:inherit;-ms-flex-negative:0;flex-shrink:0}.icon-text.icon-text-gap--none>*:nth-child(2){margin-left:0}.icon--is-spinning{-webkit-animation:icon-spin 1s infinite linear;animation:icon-spin 1s infinite linear}@-webkit-keyframes icon-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icon-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.icon use{color:inherit;fill:currentColor}:root{--btn-font-size: 1em;--btn-sm: calc(var(--btn-font-size) - 0.2em);--btn-md: calc(var(--btn-font-size) + 0.2em);--btn-lg: calc(var(--btn-font-size) + 0.4em)}.btn{display:-ms-inline-flexbox;display:inline-flex;position:relative;white-space:nowrap;text-decoration:none;line-height:1;padding:0.5em 0.75em;padding:var(--space-xs) var(--space-sm);border-radius:0.25em;font-size:1em;font-size:var(--btn-font-size);-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.btn--primary{background-color:hsl(220, 90%, 56%);background-color:var(--color-primary);color:hsl(0, 0%, 100%);color:var(--color-white);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.btn--subtle{color:hsl(240, 8%, 12%);color:var(--color-contrast-higher);border:1px solid hsl(240, 1%, 83%);border:1px solid var(--color-contrast-low)}.btn--accent{background-color:hsl(355, 90%, 61%);background-color:var(--color-accent);color:hsl(0, 0%, 100%);color:var(--color-white);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.btn--disabled{cursor:not-allowed;box-shadow:none;opacity:0.6}.btn--sm{font-size:0.8em;font-size:var(--btn-sm)}.btn--md{font-size:1.2em;font-size:var(--btn-md)}.btn--lg{font-size:1.4em;font-size:var(--btn-lg)}.btn--full-width{display:-ms-flexbox;display:flex;width:100%}.btn .icon{color:inherit;-ms-flex-negative:0;flex-shrink:0}.btn--icon-text{-ms-flex-align:center;align-items:center}.btn--icon-text>*:nth-child(2){margin-left:0.375em;margin-left:var(--space-xxs)}.btn--icon{padding:0.5em;padding:var(--space-xs)}.form-control{padding:0.5em 0.75em;padding:var(--space-xs) var(--space-sm);background:hsl(0, 0%, 100%);background:var(--color-bg);border:2px solid hsl(240, 1%, 83%);border:2px solid var(--color-contrast-low);width:100%}.form-control:focus{outline:none;border-color:hsl(220, 90%, 56%);border-color:var(--color-primary);--color-shadow: hsla(220, 90%, 56%, 0.2);--color-shadow: hsla(var(--color-primary-h), var(--color-primary-s), var(--color-primary-l), 0.2);box-shadow:undefined;box-shadow:0 0 0 3px var(--color-shadow)}.form-control:focus:focus{box-shadow:0 0 0 3px hsla(220, 90%, 56%, 0.2);box-shadow:0 0 0 3px var(--color-shadow)}.form-control::-webkit-input-placeholder{color:hsl(240, 1%, 48%);color:var(--color-contrast-medium)}.form-control::-moz-placeholder{opacity:1;color:hsl(240, 1%, 48%);color:var(--color-contrast-medium)}.form-control:-ms-input-placeholder{color:hsl(240, 1%, 48%);color:var(--color-contrast-medium)}.form-control:-moz-placeholder{color:hsl(240, 1%, 48%);color:var(--color-contrast-medium)}.form-control[disabled],.form-control[readonly]{cursor:not-allowed}.form-control[aria-invalid="true"]{border-color:hsl(355, 90%, 61%);border-color:var(--color-error)}.form-control[aria-invalid="true"]:focus{--color-shadow: hsla(355, 90%, 61%, 0.2);--color-shadow: hsla(var(--color-error-h), var(--color-error-s), var(--color-error-l), 0.2);box-shadow:undefined;box-shadow:0 0 0 3px var(--color-shadow)}.form-control[aria-invalid="true"]:focus:focus{box-shadow:0 0 0 3px hsla(355, 90%, 61%, 0.2);box-shadow:0 0 0 3px var(--color-shadow)}.form-legend{color:hsl(240, 8%, 12%);color:var(--color-contrast-higher);line-height:1.2;font-size:1.2em;font-size:var(--text-md);margin-bottom:0.375em;margin-bottom:var(--space-xxs)}.form-label{display:inline-block;font-size:0.83333em;font-size:var(--text-sm);margin-bottom:0.25em;margin-bottom:var(--space-xxxs)}.form__msg-error{background-color:hsl(355, 90%, 61%);background-color:var(--color-error);color:hsl(0, 0%, 100%);color:var(--color-white);font-size:0.83333em;font-size:var(--text-sm);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;padding:0.5em;padding:var(--space-xs);margin-top:0.75em;margin-top:var(--space-sm);border-radius:0.25em;position:absolute;clip:rect(1px, 1px, 1px, 1px)}.form__msg-error::before{content:'';position:absolute;left:0.75em;left:var(--space-sm);top:0;-webkit-transform:translateY(-100%);-ms-transform:translateY(-100%);transform:translateY(-100%);width:0;height:0;border:8px solid transparent;border-bottom-color:hsl(355, 90%, 61%);border-bottom-color:var(--color-error)}.form__msg-error--is-visible{position:relative;clip:auto}.radio-list>*,.checkbox-list>*{position:relative;display:-ms-flexbox;display:flex;-ms-flex-align:baseline;align-items:baseline;margin-bottom:0.375em;margin-bottom:var(--space-xxs)}.radio-list>*:last-of-type,.checkbox-list>*:last-of-type{margin-bottom:0}.radio-list label,.checkbox-list label{line-height:1.4;line-height:var(--body-line-height);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-list input,.checkbox-list input{vertical-align:top;margin-right:0.25em;margin-right:var(--space-xxxs);-ms-flex-negative:0;flex-shrink:0}.radio-list.radio-list--inline,.radio-list.checkbox-list--inline,.checkbox-list.radio-list--inline,.checkbox-list.checkbox-list--inline{display:-ms-flexbox;display:flex;margin-bottom:-1.25em;margin-bottom:calc(-1*var(--space-md))}.radio-list.radio-list--inline>*,.radio-list.checkbox-list--inline>*,.checkbox-list.radio-list--inline>*,.checkbox-list.checkbox-list--inline>*{margin:0 1.25em 1.25em 0;margin:0 var(--space-md) var(--space-md) 0}:root{--zindex-header: 2;--zindex-popover: 4;--zindex-fixed-element: 5;--zindex-overlay: 10}@media not all and (min-width: 30rem){.display--xs{display:none !important}}@media (min-width: 30rem){.hide--xs{display:none !important}}@media not all and (min-width: 37.5rem){.display--sm{display:none !important}}@media (min-width: 37.5rem){.hide--sm{display:none !important}}@media not all and (min-width: 64rem){.display--md{display:none !important}}@media (min-width: 64rem){.hide--md{display:none !important}}@media not all and (min-width: 80rem){.display--lg{display:none !important}}@media (min-width: 80rem){.hide--lg{display:none !important}}@media not all and (min-width: 90rem){.display--xl{display:none !important}}@media (min-width: 90rem){.hide--xl{display:none !important}}:root{--display: block}.is-visible{display:block !important;display:var(--display) !important}.is-hidden{display:none !important}.sr-only{position:absolute;clip:rect(1px, 1px, 1px, 1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);width:1px;height:1px;overflow:hidden;padding:0;border:0;white-space:nowrap}:root{--cd-color-1:hsl(53, 29%, 95%);--cd-color-1-h:53;--cd-color-1-s:29%;--cd-color-1-l:95%;--cd-color-2:hsl(330, 13%, 42%);--cd-color-2-h:330;--cd-color-2-s:13%;--cd-color-2-l:42%;--cd-color-3:hsl(5, 76%, 62%);--cd-color-3-h:5;--cd-color-3-s:76%;--cd-color-3-l:62%;--cd-back-to-top-size: 40px;--cd-back-to-top-margin: 20px;--font-primary: 'Bitter', sans-serif;--font-secondary: 'Open Sans', sans-serif}@supports (--css: variables){@media (min-width: 64rem){:root{--cd-back-to-top-size: 60px;--cd-back-to-top-margin: 30px}}}.cd-top{position:fixed;bottom:20px;bottom:var(--cd-back-to-top-margin);right:20px;right:var(--cd-back-to-top-margin);display:inline-block;height:40px;height:var(--cd-back-to-top-size);width:40px;width:var(--cd-back-to-top-size);box-shadow:0 0 10px rgba(0,0,0,0.05);background:url(../img/cd-top-arrow.svg) no-repeat center 50%;background-color:hsla(5, 76%, 62%, 0.8);background-color:hsla(var(--cd-color-3-h), var(--cd-color-3-s), var(--cd-color-3-l), 0.8)}.js .cd-top{visibility:hidden;opacity:0;transition:opacity .3s, visibility .3s, background-color .3s}.js .cd-top--is-visible{visibility:visible;opacity:1}.js .cd-top--fade-out{opacity:.5}.js .cd-top:hover{background-color:hsl(5, 76%, 62%);background-color:var(--cd-color-3);opacity:1}body{background-color:hsl(330, 13%, 42%);background-color:var(--cd-color-2);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.cd-main-header{height:180px;background-color:hsl(330, 13%, 31.92%);background-color:hsl(var(--cd-color-2-h), var(--cd-color-2-s), calc(var(--cd-color-2-l)*0.76));color:hsl(53, 29%, 95%);color:var(--cd-color-1);font-family:'Open Sans', sans-serif;font-family:var(--font-secondary)}.cd-main-header h1{font-weight:bold;color:inherit;text-transform:uppercase}.cd-main-header p{color:hsl(330, 13%, 52.08%);color:hsl(var(--cd-color-2-h), var(--cd-color-2-s), calc(var(--cd-color-2-l)*1.24))}.cd-main-header a{color:hsl(53, 29%, 95%);color:var(--cd-color-1);font-family:'Bitter', sans-serif;font-family:var(--font-primary)}@media (min-width: 64rem){.cd-main-header{height:280px}}.cd-main-content p{color:hsl(53, 29%, 95%);color:var(--cd-color-1)} diff --git a/assets/css/theme.css b/assets/css/theme.css new file mode 100644 index 000000000..7fbe46467 --- /dev/null +++ b/assets/css/theme.css @@ -0,0 +1,554 @@ +/*! + * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + +.md-main .md-sidebar.md-sidebar--primary { + padding-bottom: 80px; +} + +.md-sidebar[data-md-state=lock] { + top: 5.9rem; +} + +.md-main.hide-toc .md-content { + margin-right: 35px; +} + +.md-main.hide-toc .md-sidebar.md-sidebar--secondary { + width: 31px; +} + +.md-sidebar { + padding: 1.45rem 0; +} + +.md-header { + height: 2.6rem; +} + +.md-header-nav__topic { + top: 0; + text-align: left; +} + +[data-md-color-primary=indigo] .md-header { + background-color: #ffffff; + color: #212121; +} + +.md-header-nav__button.md-logo > img { + width: 60px; + margin-top: 3px; +} + +.md-header__version-select { + width: 3.5rem; +} + +.md-header__version-select .md-tabs__link.md-tabs__dropdown-link { + display: inline-block; + padding: .45rem; + margin-top: .35rem; + border-radius: .1rem; +} + +.md-header__version-select .mb-tabs__dropdown .mb-tabs__dropdown-content, +.md-header__distribution-select .mb-tabs__dropdown .mb-tabs__dropdown-content { + background: #e2e2e2; + opacity: 1; +} + +.md-header__version-select .mb-tabs__dropdown .mb-tabs__dropdown-content { + top: .8rem; +} + +@media only screen and (min-width: 76.25em) { + [data-md-color-primary=indigo] .md-tabs { + background-color: #f5f5f5; + box-shadow: 0 0 0.2rem rgba(0,0,0,.1), 0 0.2rem 0.4rem rgba(0,0,0,.2); + } + + .md-main__inner { + padding-top: 3.5rem; + + } + + +} + +@media only screen and (min-width: 76.25em) { +.md-content__inner { + margin: 0 14.2rem 1.2rem !important; +} +} + + + +html .md-typeset .superfences-tabs > label{ + color: #545CEC; + font-weight: normal; +} + +html .md-typeset .superfences-tabs > label:hover { + color: #545CEC; + font-weight: bold; +} + + +.md-search__input { + background-color: #dedede; + padding-left: 3rem; +} + +.md-search__input::placeholder { + color: #404040; +} + +.md-nav-link-wrapper { + display: block; + margin-top: .625em; + transition: color .125s; + text-overflow: ellipsis; + cursor: pointer; + overflow: hidden +} + +.md-nav__item--nested > .md-nav-link-wrapper > .md-nav__link { + display: inline; +} + +.md-nav__item--nested > .md-nav-link-wrapper > .md-nav__link:after { + content: "\E313"; + display: inline-block; + vertical-align: middle; +} + +.md-nav__item--nested .md-nav__toggle:checked ~ .md-nav-link-wrapper > .md-nav__link:after { + -webkit-transform: rotateX(180deg); + transform: rotateX(180deg) +} + +[data-md-color-primary=indigo] .md-nav-link-wrapper a:focus, +[data-md-color-primary=indigo] .md-nav-link-wrapper a:hover { + color: #545CEC; +} + +.hljs-title, +.hljs-section { + color: #545CEC; + font-weight: normal; +} + +.hljs-type, +.hljs-string, +.hljs-number, +.hljs-selector-id, +.hljs-selector-class, +.hljs-quote, +.hljs-template-tag, +.hljs-deletion { + color: #545CEC; +} + +.home_icon { + height: 45px; + margin-right: -12px; + vertical-align: middle; +} + +.home_icon a { + margin-top: 4px; +} + +.home_icon a i { + font-size: 25px; +} + +.md-nav__link[data-md-state=blur] { + color: rgba(0,0,0,.54); +} + + +.nav_link { + color: #fff; + font-size: 34px; + -webkit-transition: right 0.2s linear; + -khtml-transition: right 0.2s linear; + -moz-transition: right 0.2s linear; + -ms-transition: right 0.2s linear; + transition: right 0.2s linear; + z-index: 2; + padding-left: 20px; + opacity: 0.7; + margin-top: 12px; +} + +.toc_icon { + font-size: 21px; + background: #000; + width: 26px; + height: 26px; + line-height: 26px; + border-radius: 50%; + padding-left: 3px; + float: left; + left: -9px; + top: -14px; +} + +.hide-toc .toc_icon { + padding-left: 2px; +} + +.nav_link:hover, +.edit_link.active:hover { + opacity: 1; +} + +.edit_link { + color: #000; + font-size: 24px; + margin-top: 18px; + opacity: 0; + transition: color .25s,opacity .1s; + display: none; +} + +.edit_link.active { + opacity: 0.7; + display: block; +} + +.toc_icon:hover { + opacity: 1; + background: #ff5000; +} + +.md-header-nav { + padding-right: 0; +} + +@media only screen and (min-width: 76.25em) { + .md-search__inner { + margin-right: 0; + } +} + +@media only screen and (min-width: 60em) { + .md-search { + padding-right: 0; + } +} + +@media only screen and (max-width: 76.1875em) { + html .md-nav--primary .md-nav__title--site .md-nav__button { + font-size: 1.9rem; + padding: 0 0 0 .4rem; + height: 2.2rem; + width: 3.6rem; + } + + html .md-nav--primary .md-nav__title { + padding: 2.5rem .8rem .2rem; + line-height: .9rem; + white-space: unset; + background-color: rgba(0,0,0,.01); + border-top: 3px solid #545CEC; + box-shadow: 0 0 0.2rem rgba(0,0,0,.1), 0 0.2rem 0.4rem rgba(0,0,0,.2); + } +} + +@media only screen and (max-width: 76.1875em) { + html [data-md-color-primary=indigo] .md-nav--primary .md-nav__title--site { + background-color: #fff; + box-shadow: 0 0 0.2rem rgba(0,0,0,.1), 0 0.2rem 0.4rem rgba(0,0,0,.2); + color: #212121; + } +} + +.md-footer-nav__inner { + overflow: hidden; +} +.md-footer-nav { + background-color: #f5f5f5; + color: #424242; + margin: 0 13.4rem; + +} + +.md-footer-nav__link { + padding-top: .1rem; + padding-bottom: 0; +} + +.md-footer-nav__inner { + padding: 2px 0; + height: 56px; +} + +.md-footer-nav__direction { + font-size: .65rem; + top: 3px; + color: hsla(0, 0%, 19%, 0.7); +} + +.md-footer-copyright__highlight, +html .md-footer-meta.md-typeset a, +.md-footer-copyright { + color: #424242; +} + +.md-footer-nav__title { + font-size: .75rem; +} + +.md-footer-nav .md-flex__cell { + vertical-align: baseline; +} + +.md-footer-copyright__highlight { + padding-right: 10px; + border-right: 1px solid #9E9E9E; + margin-right: 10px; + display: inline-block; +} + +.md-footer-meta { + background-color: #BDBDBD; +} + +.text--replace { + overflow: hidden; + color: transparent; + text-indent: 100%; + white-space: nowrap +} + +.cd-top { + position: fixed; + bottom: 65px; + right: 20px; + display: inline-block; + height: 40px; + width: 40px; + box-shadow: 0 0 10px rgba(0,0,0,0.05); + background: url(../lib/backtotop/img/cd-top-arrow.svg) no-repeat center 50%; + background-color: hsla(237, 80%, 63%, 0.8); +} + +.js .cd-top { + visibility: hidden; + opacity: 0; + transition: opacity .3s, visibility .3s, background-color .3s +} + +.js .cd-top--is-visible { + visibility: visible; + opacity: 1 +} + +.js .cd-top--fade-out { + opacity: .5 +} + +.js .cd-top:hover { + background-color: hsl(237, 80%, 63%); + opacity: 1 +} + +.md-nav__source { + display: none; +} + +.md-nav--secondary ul > li.md-nav__item { + border-left: 4px solid transparent; + transition: border 500ms; + margin-left: -3px; +} + +.md-sidebar--secondary .md-nav--secondary > ul { + border-left: 2px solid #ccc; + margin-left: 3px; +} + +.md-nav--secondary > ul li.md-nav__item.active { + border-color: #242424 !important; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul { + margin-left: -26px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul > li { + padding-left: 30px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul { + margin-left: -31px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul > li { + padding-left: 45px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul ul { + margin-left: -46px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul ul > li { + padding-left: 60px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul ul ul { + margin-left: -61px; +} + +.md-sidebar--secondary .md-nav--secondary > ul ul ul ul ul > li { + padding-left: 75px; +} + +.md-sidebar--secondary .md-nav--secondary { + padding: 3px 0 0 10px; +} + +.md-sidebar { + position: fixed; +} + +.md-sidebar--secondary .md-nav--secondary .md-nav__item { + padding: 0 0 0 1.1rem; +} + +.md-sidebar--secondary .md-nav--secondary .md-nav__item .md-nav__item { + padding: 0 0 0 1.8rem; +} + +.md-sidebar--secondary .md-nav--secondary .md-nav__title { + padding: 0 2rem; + display: contents; +} + +.md-sidebar__scrollwrap { + width: 12.1rem; +} + +.md-typeset table:not([class]) th { + background-color: #e8e8e8; + color: #4d4d4d; +} + +@media screen and (max-width: 767px) { + .wrapper { + height: 700px; + } +} + +.content { + padding-right: 10px; + width: 100%; + margin: 0 auto; + display: flex; + justify-content: center; + align-items: center; +} + +@media screen and (max-width: 767px) { + .content { + flex-direction: column; + } +} + +.hint { + display: block; + flex-direction: column; + visibility: visible; + text-align: left; +} + +.md-typeset .hint { + margin: 5px 0; +} + + +.md-sidebar ::-webkit-scrollbar { + width: 5px; +} + +.md-sidebar ::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.md-sidebar ::-webkit-scrollbar-thumb { + background: #888; + border-radius: 2.5px; +} + +.md-sidebar__scrollwrap { + margin: 0; +} + +.md-search-loader { + border: 2px solid #f3f3f3; + border-radius: 50%; + border-top: 2px solid #3498db; + width: 25px; + height: 25px; + -webkit-animation: xspin 2s linear infinite; /* Safari */ + animation: xspin 2s linear infinite; + } + +.md-search-loader:before { + content: none !important; + } + +/* Safari */ +@-webkit-keyframes xspin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} + +@keyframes xspin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.ds-suggestions { + font-size: 0.75rem; +} + +/* Title (eg. Bootstrap CDN) */ + .algolia-autocomplete .algolia-docsearch-suggestion--title { + font-weight: bold; + color: #351700 !important; + } + + /* Highlighted text */ + .algolia-autocomplete .algolia-docsearch-suggestion--highlight { + color: #545CEC !important; + background-color: #f1f1f1 !important + } + + .algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple { + background-color: #f1f1f1 !important; + } + + .algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content { + background-color: #f1f1f1 !important; + } + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 000000000..8e5c4ffeb Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 000000000..3f9c568b8 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/img/administer/access-control-to-console.png b/assets/img/administer/access-control-to-console.png new file mode 100644 index 000000000..af8456267 Binary files /dev/null and b/assets/img/administer/access-control-to-console.png differ diff --git a/assets/img/administer/api-with-custom-url.png b/assets/img/administer/api-with-custom-url.png new file mode 100644 index 000000000..d887d56a6 Binary files /dev/null and b/assets/img/administer/api-with-custom-url.png differ diff --git a/assets/img/administer/configure-domain/active-deployments.png b/assets/img/administer/configure-domain/active-deployments.png new file mode 100644 index 000000000..a579c5364 Binary files /dev/null and b/assets/img/administer/configure-domain/active-deployments.png differ diff --git a/assets/img/administer/configure-domain/active-domains.png b/assets/img/administer/configure-domain/active-domains.png new file mode 100644 index 000000000..bbe5c9658 Binary files /dev/null and b/assets/img/administer/configure-domain/active-domains.png differ diff --git a/assets/img/administer/configure-domain/cname-target-value.png b/assets/img/administer/configure-domain/cname-target-value.png new file mode 100644 index 000000000..e45a314b1 Binary files /dev/null and b/assets/img/administer/configure-domain/cname-target-value.png differ diff --git a/assets/img/administer/configure-domain/custom-url.png b/assets/img/administer/configure-domain/custom-url.png new file mode 100644 index 000000000..88bb1ab6b Binary files /dev/null and b/assets/img/administer/configure-domain/custom-url.png differ diff --git a/assets/img/administer/configure-domain/developer-portal-cname-target-value.png b/assets/img/administer/configure-domain/developer-portal-cname-target-value.png new file mode 100644 index 000000000..39bf08102 Binary files /dev/null and b/assets/img/administer/configure-domain/developer-portal-cname-target-value.png differ diff --git a/assets/img/administer/configure-domain/pending-custom-url-request.png b/assets/img/administer/configure-domain/pending-custom-url-request.png new file mode 100644 index 000000000..b9ee4cad0 Binary files /dev/null and b/assets/img/administer/configure-domain/pending-custom-url-request.png differ diff --git a/assets/img/administer/configure-domain/pending-url-requests.png b/assets/img/administer/configure-domain/pending-url-requests.png new file mode 100644 index 000000000..625ceeb60 Binary files /dev/null and b/assets/img/administer/configure-domain/pending-url-requests.png differ diff --git a/assets/img/administer/configure-domain/url-settings.png b/assets/img/administer/configure-domain/url-settings.png new file mode 100644 index 000000000..3997dbf4e Binary files /dev/null and b/assets/img/administer/configure-domain/url-settings.png differ diff --git a/assets/img/administer/create-choreo-organization.png b/assets/img/administer/create-choreo-organization.png new file mode 100644 index 000000000..31f0b4289 Binary files /dev/null and b/assets/img/administer/create-choreo-organization.png differ diff --git a/assets/img/administer/create-custom-domain.png b/assets/img/administer/create-custom-domain.png new file mode 100644 index 000000000..0daf89051 Binary files /dev/null and b/assets/img/administer/create-custom-domain.png differ diff --git a/assets/img/administer/create-subscription-plan.png b/assets/img/administer/create-subscription-plan.png new file mode 100644 index 000000000..7449bcea4 Binary files /dev/null and b/assets/img/administer/create-subscription-plan.png differ diff --git a/assets/img/administer/devportal-theme/access-devportal-theme.png b/assets/img/administer/devportal-theme/access-devportal-theme.png new file mode 100644 index 000000000..94e23e22b Binary files /dev/null and b/assets/img/administer/devportal-theme/access-devportal-theme.png differ diff --git a/assets/img/administer/devportal-theme/preview-of-customization.png b/assets/img/administer/devportal-theme/preview-of-customization.png new file mode 100644 index 000000000..ebad4c61b Binary files /dev/null and b/assets/img/administer/devportal-theme/preview-of-customization.png differ diff --git a/assets/img/administer/devportal-theme/publish-or-discard-developer-portal-changes.png b/assets/img/administer/devportal-theme/publish-or-discard-developer-portal-changes.png new file mode 100644 index 000000000..a54d55593 Binary files /dev/null and b/assets/img/administer/devportal-theme/publish-or-discard-developer-portal-changes.png differ diff --git a/assets/img/administer/enterprise-login/group-mapping.png b/assets/img/administer/enterprise-login/group-mapping.png new file mode 100644 index 000000000..853a54fbc Binary files /dev/null and b/assets/img/administer/enterprise-login/group-mapping.png differ diff --git a/assets/img/administer/enterprise-login/role-mapping.png b/assets/img/administer/enterprise-login/role-mapping.png new file mode 100644 index 000000000..fc3edf843 Binary files /dev/null and b/assets/img/administer/enterprise-login/role-mapping.png differ diff --git a/assets/img/administer/list-custom-domain.png b/assets/img/administer/list-custom-domain.png new file mode 100644 index 000000000..c36093405 Binary files /dev/null and b/assets/img/administer/list-custom-domain.png differ diff --git a/assets/img/administer/mapping-level.png b/assets/img/administer/mapping-level.png new file mode 100644 index 000000000..45ec2e443 Binary files /dev/null and b/assets/img/administer/mapping-level.png differ diff --git a/assets/img/administer/organizations.png b/assets/img/administer/organizations.png new file mode 100644 index 000000000..9b39d7feb Binary files /dev/null and b/assets/img/administer/organizations.png differ diff --git a/assets/img/administer/self-sign-up/add-sign-in-method.png b/assets/img/administer/self-sign-up/add-sign-in-method.png new file mode 100644 index 000000000..224019a4e Binary files /dev/null and b/assets/img/administer/self-sign-up/add-sign-in-method.png differ diff --git a/assets/img/administer/self-sign-up/application.png b/assets/img/administer/self-sign-up/application.png new file mode 100644 index 000000000..1d10ef477 Binary files /dev/null and b/assets/img/administer/self-sign-up/application.png differ diff --git a/assets/img/administer/self-sign-up/approval-pending.png b/assets/img/administer/self-sign-up/approval-pending.png new file mode 100644 index 000000000..9ebd788a5 Binary files /dev/null and b/assets/img/administer/self-sign-up/approval-pending.png differ diff --git a/assets/img/administer/self-sign-up/configure-self-registration.png b/assets/img/administer/self-sign-up/configure-self-registration.png new file mode 100644 index 000000000..ce42abbd2 Binary files /dev/null and b/assets/img/administer/self-sign-up/configure-self-registration.png differ diff --git a/assets/img/administer/self-sign-up/copy-handle.png b/assets/img/administer/self-sign-up/copy-handle.png new file mode 100644 index 000000000..702da487c Binary files /dev/null and b/assets/img/administer/self-sign-up/copy-handle.png differ diff --git a/assets/img/administer/self-sign-up/create-an-account.png b/assets/img/administer/self-sign-up/create-an-account.png new file mode 100644 index 000000000..8d5185136 Binary files /dev/null and b/assets/img/administer/self-sign-up/create-an-account.png differ diff --git a/assets/img/administer/self-sign-up/create-new-organization.png b/assets/img/administer/self-sign-up/create-new-organization.png new file mode 100644 index 000000000..4444f9511 Binary files /dev/null and b/assets/img/administer/self-sign-up/create-new-organization.png differ diff --git a/assets/img/administer/self-sign-up/create-organization.png b/assets/img/administer/self-sign-up/create-organization.png new file mode 100644 index 000000000..c53856db7 Binary files /dev/null and b/assets/img/administer/self-sign-up/create-organization.png differ diff --git a/assets/img/administer/self-sign-up/email-attribute.png b/assets/img/administer/self-sign-up/email-attribute.png new file mode 100644 index 000000000..10bf3bc78 Binary files /dev/null and b/assets/img/administer/self-sign-up/email-attribute.png differ diff --git a/assets/img/administer/self-sign-up/profile-attribute.png b/assets/img/administer/self-sign-up/profile-attribute.png new file mode 100644 index 000000000..d34d3da91 Binary files /dev/null and b/assets/img/administer/self-sign-up/profile-attribute.png differ diff --git a/assets/img/administer/self-sign-up/save-attributes-as-scopes.png b/assets/img/administer/self-sign-up/save-attributes-as-scopes.png new file mode 100644 index 000000000..08b71512b Binary files /dev/null and b/assets/img/administer/self-sign-up/save-attributes-as-scopes.png differ diff --git a/assets/img/administer/self-sign-up/sign-up.png b/assets/img/administer/self-sign-up/sign-up.png new file mode 100644 index 000000000..859bb156b Binary files /dev/null and b/assets/img/administer/self-sign-up/sign-up.png differ diff --git a/assets/img/administer/self-sign-up/user-attributes.png b/assets/img/administer/self-sign-up/user-attributes.png new file mode 100644 index 000000000..897c837f9 Binary files /dev/null and b/assets/img/administer/self-sign-up/user-attributes.png differ diff --git a/assets/img/administer/self-sign-up/view-all-applications.png b/assets/img/administer/self-sign-up/view-all-applications.png new file mode 100644 index 000000000..d839934bc Binary files /dev/null and b/assets/img/administer/self-sign-up/view-all-applications.png differ diff --git a/assets/img/api-management/api-discovery.png b/assets/img/api-management/api-discovery.png new file mode 100644 index 000000000..3e880deef Binary files /dev/null and b/assets/img/api-management/api-discovery.png differ diff --git a/assets/img/api-management/api-policies/add-header.png b/assets/img/api-management/api-policies/add-header.png new file mode 100644 index 000000000..a01ae3965 Binary files /dev/null and b/assets/img/api-management/api-policies/add-header.png differ diff --git a/assets/img/api-management/api-policies/add-policy.png b/assets/img/api-management/api-policies/add-policy.png new file mode 100644 index 000000000..31276398a Binary files /dev/null and b/assets/img/api-management/api-policies/add-policy.png differ diff --git a/assets/img/api-management/api-policies/added-policy.png b/assets/img/api-management/api-policies/added-policy.png new file mode 100644 index 000000000..5451eb32b Binary files /dev/null and b/assets/img/api-management/api-policies/added-policy.png differ diff --git a/assets/img/api-management/api-policies/advanced-settings/detailed-access-log-setting.png b/assets/img/api-management/api-policies/advanced-settings/detailed-access-log-setting.png new file mode 100644 index 000000000..356209025 Binary files /dev/null and b/assets/img/api-management/api-policies/advanced-settings/detailed-access-log-setting.png differ diff --git a/assets/img/api-management/api-policies/advanced-settings/hostname-verification-setting.png b/assets/img/api-management/api-policies/advanced-settings/hostname-verification-setting.png new file mode 100644 index 000000000..f9336ba0b Binary files /dev/null and b/assets/img/api-management/api-policies/advanced-settings/hostname-verification-setting.png differ diff --git a/assets/img/api-management/api-policies/advanced-settings/http-version-setting.png b/assets/img/api-management/api-policies/advanced-settings/http-version-setting.png new file mode 100644 index 000000000..4c1d948b7 Binary files /dev/null and b/assets/img/api-management/api-policies/advanced-settings/http-version-setting.png differ diff --git a/assets/img/api-management/api-policies/advanced-settings/minimum-evictable-idle-time-setting.png b/assets/img/api-management/api-policies/advanced-settings/minimum-evictable-idle-time-setting.png new file mode 100644 index 000000000..9ad89c969 Binary files /dev/null and b/assets/img/api-management/api-policies/advanced-settings/minimum-evictable-idle-time-setting.png differ diff --git a/assets/img/api-management/api-policies/attach-policy.png b/assets/img/api-management/api-policies/attach-policy.png new file mode 100644 index 000000000..604dd52be Binary files /dev/null and b/assets/img/api-management/api-policies/attach-policy.png differ diff --git a/assets/img/api-management/api-policies/ballerina-project.png b/assets/img/api-management/api-policies/ballerina-project.png new file mode 100644 index 000000000..117c3d544 Binary files /dev/null and b/assets/img/api-management/api-policies/ballerina-project.png differ diff --git a/assets/img/api-management/api-policies/ballerina-toml.png b/assets/img/api-management/api-policies/ballerina-toml.png new file mode 100644 index 000000000..fd807e8b3 Binary files /dev/null and b/assets/img/api-management/api-policies/ballerina-toml.png differ diff --git a/assets/img/api-management/api-policies/configurable-values.png b/assets/img/api-management/api-policies/configurable-values.png new file mode 100644 index 000000000..cc0d32ed2 Binary files /dev/null and b/assets/img/api-management/api-policies/configurable-values.png differ diff --git a/assets/img/api-management/api-policies/configure-add-header.png b/assets/img/api-management/api-policies/configure-add-header.png new file mode 100644 index 000000000..d19c7aab5 Binary files /dev/null and b/assets/img/api-management/api-policies/configure-add-header.png differ diff --git a/assets/img/api-management/api-policies/configure-parameters.png b/assets/img/api-management/api-policies/configure-parameters.png new file mode 100644 index 000000000..db8c9d49a Binary files /dev/null and b/assets/img/api-management/api-policies/configure-parameters.png differ diff --git a/assets/img/api-management/api-policies/published-policy.png b/assets/img/api-management/api-policies/published-policy.png new file mode 100644 index 000000000..94805c076 Binary files /dev/null and b/assets/img/api-management/api-policies/published-policy.png differ diff --git a/assets/img/api-management/api-policies/request-response-flow.png b/assets/img/api-management/api-policies/request-response-flow.png new file mode 100644 index 000000000..f5583ebf5 Binary files /dev/null and b/assets/img/api-management/api-policies/request-response-flow.png differ diff --git a/assets/img/api-management/api-policies/save-and-deploy.png b/assets/img/api-management/api-policies/save-and-deploy.png new file mode 100644 index 000000000..32f84a60b Binary files /dev/null and b/assets/img/api-management/api-policies/save-and-deploy.png differ diff --git a/assets/img/api-management/api-policies/select-policy.png b/assets/img/api-management/api-policies/select-policy.png new file mode 100644 index 000000000..85c8d2296 Binary files /dev/null and b/assets/img/api-management/api-policies/select-policy.png differ diff --git a/assets/img/api-management/applications.png b/assets/img/api-management/applications.png new file mode 100644 index 000000000..047490cba Binary files /dev/null and b/assets/img/api-management/applications.png differ diff --git a/assets/img/api-management/authentication.png b/assets/img/api-management/authentication.png new file mode 100644 index 000000000..e77b6b766 Binary files /dev/null and b/assets/img/api-management/authentication.png differ diff --git a/assets/img/api-management/business-plans.png b/assets/img/api-management/business-plans.png new file mode 100644 index 000000000..ec2af36f1 Binary files /dev/null and b/assets/img/api-management/business-plans.png differ diff --git a/assets/img/api-management/developer-portal-home-page.png b/assets/img/api-management/developer-portal-home-page.png new file mode 100644 index 000000000..0c55aea6e Binary files /dev/null and b/assets/img/api-management/developer-portal-home-page.png differ diff --git a/assets/img/api-management/invoke-api.png b/assets/img/api-management/invoke-api.png new file mode 100644 index 000000000..39e4fe37e Binary files /dev/null and b/assets/img/api-management/invoke-api.png differ diff --git a/assets/img/api-management/manage-api-traffic/add-subscription.png b/assets/img/api-management/manage-api-traffic/add-subscription.png new file mode 100644 index 000000000..a6e5e84d3 Binary files /dev/null and b/assets/img/api-management/manage-api-traffic/add-subscription.png differ diff --git a/assets/img/api-management/manage-api-traffic/enable-toggle.png b/assets/img/api-management/manage-api-traffic/enable-toggle.png new file mode 100644 index 000000000..5fbd0630f Binary files /dev/null and b/assets/img/api-management/manage-api-traffic/enable-toggle.png differ diff --git a/assets/img/api-management/manage-api-traffic/throttle-response.png b/assets/img/api-management/manage-api-traffic/throttle-response.png new file mode 100644 index 000000000..720c0ea76 Binary files /dev/null and b/assets/img/api-management/manage-api-traffic/throttle-response.png differ diff --git a/assets/img/api-management/subscription.png b/assets/img/api-management/subscription.png new file mode 100644 index 000000000..83c7d7a77 Binary files /dev/null and b/assets/img/api-management/subscription.png differ diff --git a/assets/img/authentication-and-authorization/associate-certificate.png b/assets/img/authentication-and-authorization/associate-certificate.png new file mode 100644 index 000000000..5bb1282a9 Binary files /dev/null and b/assets/img/authentication-and-authorization/associate-certificate.png differ diff --git a/assets/img/authentication-and-authorization/certificate-details.png b/assets/img/authentication-and-authorization/certificate-details.png new file mode 100644 index 000000000..3470da875 Binary files /dev/null and b/assets/img/authentication-and-authorization/certificate-details.png differ diff --git a/assets/img/authentication-and-authorization/generate-new-key-pair.png b/assets/img/authentication-and-authorization/generate-new-key-pair.png new file mode 100644 index 000000000..b3ee449bd Binary files /dev/null and b/assets/img/authentication-and-authorization/generate-new-key-pair.png differ diff --git a/assets/img/authentication-and-authorization/mutual-ssl-authentication.png b/assets/img/authentication-and-authorization/mutual-ssl-authentication.png new file mode 100644 index 000000000..88530d01a Binary files /dev/null and b/assets/img/authentication-and-authorization/mutual-ssl-authentication.png differ diff --git a/assets/img/authentication-and-authorization/use-own-key-pair.png b/assets/img/authentication-and-authorization/use-own-key-pair.png new file mode 100644 index 000000000..97a3f6cbb Binary files /dev/null and b/assets/img/authentication-and-authorization/use-own-key-pair.png differ diff --git a/assets/img/authentication-and-authorization/view-and-download.png b/assets/img/authentication-and-authorization/view-and-download.png new file mode 100644 index 000000000..07d7679f6 Binary files /dev/null and b/assets/img/authentication-and-authorization/view-and-download.png differ diff --git a/assets/img/choreo-concepts/choreo-environments.png b/assets/img/choreo-concepts/choreo-environments.png new file mode 100644 index 000000000..d20d08bfc Binary files /dev/null and b/assets/img/choreo-concepts/choreo-environments.png differ diff --git a/assets/img/choreo-concepts/deployment-tracks-api-versioning.md.png b/assets/img/choreo-concepts/deployment-tracks-api-versioning.md.png new file mode 100644 index 000000000..c2feab067 Binary files /dev/null and b/assets/img/choreo-concepts/deployment-tracks-api-versioning.md.png differ diff --git a/assets/img/choreo-concepts/deployment-tracks-container-registry.png b/assets/img/choreo-concepts/deployment-tracks-container-registry.png new file mode 100644 index 000000000..8a664e7bf Binary files /dev/null and b/assets/img/choreo-concepts/deployment-tracks-container-registry.png differ diff --git a/assets/img/choreo-concepts/deployment-tracks-source-repo.png b/assets/img/choreo-concepts/deployment-tracks-source-repo.png new file mode 100644 index 000000000..f3b5ec188 Binary files /dev/null and b/assets/img/choreo-concepts/deployment-tracks-source-repo.png differ diff --git a/assets/img/choreo-concepts/environments-and-dataplanes.png b/assets/img/choreo-concepts/environments-and-dataplanes.png new file mode 100644 index 000000000..462e878dc Binary files /dev/null and b/assets/img/choreo-concepts/environments-and-dataplanes.png differ diff --git a/assets/img/choreo-concepts/high-level-view.png b/assets/img/choreo-concepts/high-level-view.png new file mode 100644 index 000000000..9f841fa75 Binary files /dev/null and b/assets/img/choreo-concepts/high-level-view.png differ diff --git a/assets/img/choreo-concepts/marketplace/internal-marketplace.png b/assets/img/choreo-concepts/marketplace/internal-marketplace.png new file mode 100644 index 000000000..0ae990fdb Binary files /dev/null and b/assets/img/choreo-concepts/marketplace/internal-marketplace.png differ diff --git a/assets/img/choreo-concepts/observability-architecture.png b/assets/img/choreo-concepts/observability-architecture.png new file mode 100644 index 000000000..4ed49f253 Binary files /dev/null and b/assets/img/choreo-concepts/observability-architecture.png differ diff --git a/assets/img/choreo-concepts/private-data-plane-architecture.png b/assets/img/choreo-concepts/private-data-plane-architecture.png new file mode 100644 index 000000000..5685d9239 Binary files /dev/null and b/assets/img/choreo-concepts/private-data-plane-architecture.png differ diff --git a/assets/img/choreo-concepts/project.png b/assets/img/choreo-concepts/project.png new file mode 100644 index 000000000..0218664f1 Binary files /dev/null and b/assets/img/choreo-concepts/project.png differ diff --git a/assets/img/choreo-concepts/resource-hierarchy.png b/assets/img/choreo-concepts/resource-hierarchy.png new file mode 100644 index 000000000..7a9fe9dee Binary files /dev/null and b/assets/img/choreo-concepts/resource-hierarchy.png differ diff --git a/assets/img/choreo-concepts/saas-data-plane-architecture.png b/assets/img/choreo-concepts/saas-data-plane-architecture.png new file mode 100644 index 000000000..ff12c89bc Binary files /dev/null and b/assets/img/choreo-concepts/saas-data-plane-architecture.png differ diff --git a/assets/img/choreo-logo.png b/assets/img/choreo-logo.png new file mode 100644 index 000000000..8863b4449 Binary files /dev/null and b/assets/img/choreo-logo.png differ diff --git a/assets/img/consume/add-apis.png b/assets/img/consume/add-apis.png new file mode 100644 index 000000000..1388cce9d Binary files /dev/null and b/assets/img/consume/add-apis.png differ diff --git a/assets/img/consume/api-overview.png b/assets/img/consume/api-overview.png new file mode 100644 index 000000000..fdfe31947 Binary files /dev/null and b/assets/img/consume/api-overview.png differ diff --git a/assets/img/consume/developer-portal-apis.png b/assets/img/consume/developer-portal-apis.png new file mode 100644 index 000000000..365c9a827 Binary files /dev/null and b/assets/img/consume/developer-portal-apis.png differ diff --git a/assets/img/develop-components/deploy/authz-choreo-github-app.png b/assets/img/develop-components/deploy/authz-choreo-github-app.png new file mode 100644 index 000000000..30b86f1ef Binary files /dev/null and b/assets/img/develop-components/deploy/authz-choreo-github-app.png differ diff --git a/assets/img/develop-components/deploy/build-deploy-page-logs.png b/assets/img/develop-components/deploy/build-deploy-page-logs.png new file mode 100644 index 000000000..ef4e889f6 Binary files /dev/null and b/assets/img/develop-components/deploy/build-deploy-page-logs.png differ diff --git a/assets/img/develop-components/deploy/build-deploy-page.png b/assets/img/develop-components/deploy/build-deploy-page.png new file mode 100644 index 000000000..e9b0cb57b Binary files /dev/null and b/assets/img/develop-components/deploy/build-deploy-page.png differ diff --git a/assets/img/develop-components/deploy/create-component-authz-github-page.png b/assets/img/develop-components/deploy/create-component-authz-github-page.png new file mode 100644 index 000000000..a311b5b12 Binary files /dev/null and b/assets/img/develop-components/deploy/create-component-authz-github-page.png differ diff --git a/assets/img/develop-components/deploy/create-component-connected-repo.png b/assets/img/develop-components/deploy/create-component-connected-repo.png new file mode 100644 index 000000000..2ebbdd87d Binary files /dev/null and b/assets/img/develop-components/deploy/create-component-connected-repo.png differ diff --git a/assets/img/develop-components/deploy/deploy-app-config-file-mount.png b/assets/img/develop-components/deploy/deploy-app-config-file-mount.png new file mode 100644 index 000000000..dfa99d6b4 Binary files /dev/null and b/assets/img/develop-components/deploy/deploy-app-config-file-mount.png differ diff --git a/assets/img/develop-components/deploy/deploy-app-config-page.png b/assets/img/develop-components/deploy/deploy-app-config-page.png new file mode 100644 index 000000000..726222052 Binary files /dev/null and b/assets/img/develop-components/deploy/deploy-app-config-page.png differ diff --git a/assets/img/develop-components/deploy/deploy-app-config-type-mount-page.png b/assets/img/develop-components/deploy/deploy-app-config-type-mount-page.png new file mode 100644 index 000000000..007e77a0c Binary files /dev/null and b/assets/img/develop-components/deploy/deploy-app-config-type-mount-page.png differ diff --git a/assets/img/develop-components/deploy/github-repo-access.png b/assets/img/develop-components/deploy/github-repo-access.png new file mode 100644 index 000000000..d1892ee55 Binary files /dev/null and b/assets/img/develop-components/deploy/github-repo-access.png differ diff --git a/assets/img/develop-components/develop-a-rest-api-proxy/rest-api-proxy-response.png b/assets/img/develop-components/develop-a-rest-api-proxy/rest-api-proxy-response.png new file mode 100644 index 000000000..3c7d08c4c Binary files /dev/null and b/assets/img/develop-components/develop-a-rest-api-proxy/rest-api-proxy-response.png differ diff --git a/assets/img/develop-components/develop-a-rest-api-proxy/try-out-response.png b/assets/img/develop-components/develop-a-rest-api-proxy/try-out-response.png new file mode 100644 index 000000000..10d321d31 Binary files /dev/null and b/assets/img/develop-components/develop-a-rest-api-proxy/try-out-response.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/Received-email.png b/assets/img/develop-components/develop-a-scheduled-integration/Received-email.png new file mode 100644 index 000000000..1dfdd37b0 Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/Received-email.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/configurable-variable-as-a-secret.png b/assets/img/develop-components/develop-a-scheduled-integration/configurable-variable-as-a-secret.png new file mode 100644 index 000000000..47414c3d8 Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/configurable-variable-as-a-secret.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/execution_history.png b/assets/img/develop-components/develop-a-scheduled-integration/execution_history.png new file mode 100644 index 000000000..507d5beec Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/execution_history.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/execution_logs.png b/assets/img/develop-components/develop-a-scheduled-integration/execution_logs.png new file mode 100644 index 000000000..f7254cac2 Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/execution_logs.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/total_executions.png b/assets/img/develop-components/develop-a-scheduled-integration/total_executions.png new file mode 100644 index 000000000..017ba2831 Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/total_executions.png differ diff --git a/assets/img/develop-components/develop-a-scheduled-integration/update-secret.png b/assets/img/develop-components/develop-a-scheduled-integration/update-secret.png new file mode 100644 index 000000000..21f815602 Binary files /dev/null and b/assets/img/develop-components/develop-a-scheduled-integration/update-secret.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/clone-a-project.gif b/assets/img/develop-components/develop-using-vs-code/clone-a-project.gif new file mode 100644 index 000000000..c4abb765c Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/clone-a-project.gif differ diff --git a/assets/img/develop-components/develop-using-vs-code/component-details-view.png b/assets/img/develop-components/develop-using-vs-code/component-details-view.png new file mode 100644 index 000000000..7274fef1c Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/component-details-view.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/component-form.png b/assets/img/develop-components/develop-using-vs-code/component-form.png new file mode 100644 index 000000000..aef6aecb5 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/component-form.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/create-a-component.gif b/assets/img/develop-components/develop-using-vs-code/create-a-component.gif new file mode 100644 index 000000000..684fd8a22 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/create-a-component.gif differ diff --git a/assets/img/develop-components/develop-using-vs-code/create-a-project.gif b/assets/img/develop-components/develop-using-vs-code/create-a-project.gif new file mode 100644 index 000000000..a702f274a Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/create-a-project.gif differ diff --git a/assets/img/develop-components/develop-using-vs-code/create-component-btn.png b/assets/img/develop-components/develop-using-vs-code/create-component-btn.png new file mode 100644 index 000000000..e189d6d0f Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/create-component-btn.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/create-project-tree-view.png b/assets/img/develop-components/develop-using-vs-code/create-project-tree-view.png new file mode 100644 index 000000000..ef2034d98 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/create-project-tree-view.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/link-dir-btn.png b/assets/img/develop-components/develop-using-vs-code/link-dir-btn.png new file mode 100644 index 000000000..10541caae Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/link-dir-btn.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/projects-and-orgs.png b/assets/img/develop-components/develop-using-vs-code/projects-and-orgs.png new file mode 100644 index 000000000..e7cc630c9 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/projects-and-orgs.png differ diff --git a/assets/img/develop-components/develop-using-vs-code/push-changes.gif b/assets/img/develop-components/develop-using-vs-code/push-changes.gif new file mode 100644 index 000000000..f3fee8196 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/push-changes.gif differ diff --git a/assets/img/develop-components/develop-using-vs-code/sign-in.png b/assets/img/develop-components/develop-using-vs-code/sign-in.png new file mode 100644 index 000000000..b26fff738 Binary files /dev/null and b/assets/img/develop-components/develop-using-vs-code/sign-in.png differ diff --git a/assets/img/develop-components/micro-integrator/add-server.png b/assets/img/develop-components/micro-integrator/add-server.png new file mode 100644 index 000000000..9228eb6c7 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/add-server.png differ diff --git a/assets/img/develop-components/micro-integrator/click_change_runtime.png b/assets/img/develop-components/micro-integrator/click_change_runtime.png new file mode 100644 index 000000000..4eece91a7 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/click_change_runtime.png differ diff --git a/assets/img/develop-components/micro-integrator/config_file.png b/assets/img/develop-components/micro-integrator/config_file.png new file mode 100644 index 000000000..9c4f34a73 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/config_file.png differ diff --git a/assets/img/develop-components/micro-integrator/define-a-remote-server-instance.png b/assets/img/develop-components/micro-integrator/define-a-remote-server-instance.png new file mode 100644 index 000000000..8506a8485 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/define-a-remote-server-instance.png differ diff --git a/assets/img/develop-components/micro-integrator/env_variables.png b/assets/img/develop-components/micro-integrator/env_variables.png new file mode 100644 index 000000000..588c34bf6 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/env_variables.png differ diff --git a/assets/img/develop-components/micro-integrator/libs_dir.png b/assets/img/develop-components/micro-integrator/libs_dir.png new file mode 100644 index 000000000..70293dedd Binary files /dev/null and b/assets/img/develop-components/micro-integrator/libs_dir.png differ diff --git a/assets/img/develop-components/micro-integrator/openapi_file.png b/assets/img/develop-components/micro-integrator/openapi_file.png new file mode 100644 index 000000000..141bf0e25 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/openapi_file.png differ diff --git a/assets/img/develop-components/micro-integrator/project-runtime-version.png b/assets/img/develop-components/micro-integrator/project-runtime-version.png new file mode 100644 index 000000000..8a0b0ca5b Binary files /dev/null and b/assets/img/develop-components/micro-integrator/project-runtime-version.png differ diff --git a/assets/img/develop-components/micro-integrator/redeploy-project.png b/assets/img/develop-components/micro-integrator/redeploy-project.png new file mode 100644 index 000000000..da340a480 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/redeploy-project.png differ diff --git a/assets/img/develop-components/micro-integrator/runtime_version_in_logs.png b/assets/img/develop-components/micro-integrator/runtime_version_in_logs.png new file mode 100644 index 000000000..0263df2af Binary files /dev/null and b/assets/img/develop-components/micro-integrator/runtime_version_in_logs.png differ diff --git a/assets/img/develop-components/micro-integrator/set-server-url.png b/assets/img/develop-components/micro-integrator/set-server-url.png new file mode 100644 index 000000000..1d2e9348f Binary files /dev/null and b/assets/img/develop-components/micro-integrator/set-server-url.png differ diff --git a/assets/img/develop-components/micro-integrator/specify_runtime_version.png b/assets/img/develop-components/micro-integrator/specify_runtime_version.png new file mode 100644 index 000000000..2c49e91db Binary files /dev/null and b/assets/img/develop-components/micro-integrator/specify_runtime_version.png differ diff --git a/assets/img/develop-components/micro-integrator/update_runtime_version.png b/assets/img/develop-components/micro-integrator/update_runtime_version.png new file mode 100644 index 000000000..754a2545b Binary files /dev/null and b/assets/img/develop-components/micro-integrator/update_runtime_version.png differ diff --git a/assets/img/develop-components/micro-integrator/version-string.png b/assets/img/develop-components/micro-integrator/version-string.png new file mode 100644 index 000000000..2e87c22b9 Binary files /dev/null and b/assets/img/develop-components/micro-integrator/version-string.png differ diff --git a/assets/img/devops-and-ci-cd/configs/create-env-vars.png b/assets/img/devops-and-ci-cd/configs/create-env-vars.png new file mode 100644 index 000000000..76bf9aef3 Binary files /dev/null and b/assets/img/devops-and-ci-cd/configs/create-env-vars.png differ diff --git a/assets/img/devops-and-ci-cd/configs/create-file-mount.png b/assets/img/devops-and-ci-cd/configs/create-file-mount.png new file mode 100644 index 000000000..dbc4294d4 Binary files /dev/null and b/assets/img/devops-and-ci-cd/configs/create-file-mount.png differ diff --git a/assets/img/devops-and-ci-cd/configs/create-or-delete-config.png b/assets/img/devops-and-ci-cd/configs/create-or-delete-config.png new file mode 100644 index 000000000..92595e4e1 Binary files /dev/null and b/assets/img/devops-and-ci-cd/configs/create-or-delete-config.png differ diff --git a/assets/img/devops-and-ci-cd/containers/containers-view.png b/assets/img/devops-and-ci-cd/containers/containers-view.png new file mode 100644 index 000000000..3575c1e77 Binary files /dev/null and b/assets/img/devops-and-ci-cd/containers/containers-view.png differ diff --git a/assets/img/devops-and-ci-cd/containers/edit-container-form.png b/assets/img/devops-and-ci-cd/containers/edit-container-form.png new file mode 100644 index 000000000..431e668b2 Binary files /dev/null and b/assets/img/devops-and-ci-cd/containers/edit-container-form.png differ diff --git a/assets/img/devops-and-ci-cd/containers/example-container-cmd-and-args.png b/assets/img/devops-and-ci-cd/containers/example-container-cmd-and-args.png new file mode 100644 index 000000000..dd40191f0 Binary files /dev/null and b/assets/img/devops-and-ci-cd/containers/example-container-cmd-and-args.png differ diff --git a/assets/img/devops-and-ci-cd/healthchecks/confgure-probes.png b/assets/img/devops-and-ci-cd/healthchecks/confgure-probes.png new file mode 100644 index 000000000..2a219e439 Binary files /dev/null and b/assets/img/devops-and-ci-cd/healthchecks/confgure-probes.png differ diff --git a/assets/img/devops-and-ci-cd/healthchecks/http-get-probe.png b/assets/img/devops-and-ci-cd/healthchecks/http-get-probe.png new file mode 100644 index 000000000..67b20b7a4 Binary files /dev/null and b/assets/img/devops-and-ci-cd/healthchecks/http-get-probe.png differ diff --git a/assets/img/devops-and-ci-cd/runtime/container-conditions-and-events.png b/assets/img/devops-and-ci-cd/runtime/container-conditions-and-events.png new file mode 100644 index 000000000..6e6ebc9d2 Binary files /dev/null and b/assets/img/devops-and-ci-cd/runtime/container-conditions-and-events.png differ diff --git a/assets/img/devops-and-ci-cd/runtime/realtime-container-logs.png b/assets/img/devops-and-ci-cd/runtime/realtime-container-logs.png new file mode 100644 index 000000000..7c4816a1d Binary files /dev/null and b/assets/img/devops-and-ci-cd/runtime/realtime-container-logs.png differ diff --git a/assets/img/devops-and-ci-cd/runtime/running-instaces.png b/assets/img/devops-and-ci-cd/runtime/running-instaces.png new file mode 100644 index 000000000..d7b5ef080 Binary files /dev/null and b/assets/img/devops-and-ci-cd/runtime/running-instaces.png differ diff --git a/assets/img/devops-and-ci-cd/runtime/runtime-view.png b/assets/img/devops-and-ci-cd/runtime/runtime-view.png new file mode 100644 index 000000000..23067d6b9 Binary files /dev/null and b/assets/img/devops-and-ci-cd/runtime/runtime-view.png differ diff --git a/assets/img/devops-and-ci-cd/scaling/free-user-scaling-view.png b/assets/img/devops-and-ci-cd/scaling/free-user-scaling-view.png new file mode 100644 index 000000000..f3f8b398e Binary files /dev/null and b/assets/img/devops-and-ci-cd/scaling/free-user-scaling-view.png differ diff --git a/assets/img/devops-and-ci-cd/scaling/paid-user-scaling-view.png b/assets/img/devops-and-ci-cd/scaling/paid-user-scaling-view.png new file mode 100644 index 000000000..3250e7229 Binary files /dev/null and b/assets/img/devops-and-ci-cd/scaling/paid-user-scaling-view.png differ diff --git a/assets/img/devops-and-ci-cd/scaling/scale-to-zero-in-deploy-view.png b/assets/img/devops-and-ci-cd/scaling/scale-to-zero-in-deploy-view.png new file mode 100644 index 000000000..11d22aea9 Binary files /dev/null and b/assets/img/devops-and-ci-cd/scaling/scale-to-zero-in-deploy-view.png differ diff --git a/assets/img/devops-and-ci-cd/scaling/scale-to-zero-view.png b/assets/img/devops-and-ci-cd/scaling/scale-to-zero-view.png new file mode 100644 index 000000000..12395e247 Binary files /dev/null and b/assets/img/devops-and-ci-cd/scaling/scale-to-zero-view.png differ diff --git a/assets/img/devops-and-ci-cd/scaling/scaling-view.png b/assets/img/devops-and-ci-cd/scaling/scaling-view.png new file mode 100644 index 000000000..b15fd4b4a Binary files /dev/null and b/assets/img/devops-and-ci-cd/scaling/scaling-view.png differ diff --git a/assets/img/devops-and-ci-cd/storage/create-emptydir-step-1.png b/assets/img/devops-and-ci-cd/storage/create-emptydir-step-1.png new file mode 100644 index 000000000..195d93575 Binary files /dev/null and b/assets/img/devops-and-ci-cd/storage/create-emptydir-step-1.png differ diff --git a/assets/img/devops-and-ci-cd/storage/create-emptydir-step-2.png b/assets/img/devops-and-ci-cd/storage/create-emptydir-step-2.png new file mode 100644 index 000000000..cd0f157b4 Binary files /dev/null and b/assets/img/devops-and-ci-cd/storage/create-emptydir-step-2.png differ diff --git a/assets/img/devops-and-ci-cd/storage/create-pv.png b/assets/img/devops-and-ci-cd/storage/create-pv.png new file mode 100644 index 000000000..2b3fec733 Binary files /dev/null and b/assets/img/devops-and-ci-cd/storage/create-pv.png differ diff --git a/assets/img/devops-and-ci-cd/tailscale/deployment-architecture.png b/assets/img/devops-and-ci-cd/tailscale/deployment-architecture.png new file mode 100644 index 000000000..a374cd9e6 Binary files /dev/null and b/assets/img/devops-and-ci-cd/tailscale/deployment-architecture.png differ diff --git a/assets/img/devops-and-ci-cd/tailscale/tailscale-proxy-deployment.png b/assets/img/devops-and-ci-cd/tailscale/tailscale-proxy-deployment.png new file mode 100644 index 000000000..3bf922675 Binary files /dev/null and b/assets/img/devops-and-ci-cd/tailscale/tailscale-proxy-deployment.png differ diff --git a/assets/img/home/api.svg b/assets/img/home/api.svg new file mode 100644 index 000000000..35dc0fd96 --- /dev/null +++ b/assets/img/home/api.svg @@ -0,0 +1,51 @@ + + + F1A0D09C-FEEE-4A54-85E1-A855E3EA6101 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/home/background.svg b/assets/img/home/background.svg new file mode 100644 index 000000000..0eebd957b --- /dev/null +++ b/assets/img/home/background.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/home/integrations.svg b/assets/img/home/integrations.svg new file mode 100644 index 000000000..c103c2dda --- /dev/null +++ b/assets/img/home/integrations.svg @@ -0,0 +1,64 @@ + + + 4F5E6E6F-B415-4ADA-9652-3B49FA42ABC7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/home/services.svg b/assets/img/home/services.svg new file mode 100644 index 000000000..c872e0377 --- /dev/null +++ b/assets/img/home/services.svg @@ -0,0 +1,44 @@ + + + 22DF9AED-2B69-4219-9962-05EE2516A253 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/img/logo.png b/assets/img/logo.png new file mode 100644 index 000000000..8699b7ba8 Binary files /dev/null and b/assets/img/logo.png differ diff --git a/assets/img/monitoring-and-insights/alerts/alert-configuration.png b/assets/img/monitoring-and-insights/alerts/alert-configuration.png new file mode 100644 index 000000000..c7e5d1b02 Binary files /dev/null and b/assets/img/monitoring-and-insights/alerts/alert-configuration.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/alert-summary.png b/assets/img/monitoring-and-insights/api-insights/alert-summary.png new file mode 100644 index 000000000..1c3f08eaf Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/alert-summary.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/alerts-page-full.png b/assets/img/monitoring-and-insights/api-insights/alerts-page-full.png new file mode 100644 index 000000000..864882f7f Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/alerts-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/api-usage-timeline.png b/assets/img/monitoring-and-insights/api-insights/api-usage-timeline.png new file mode 100644 index 000000000..832770d7e Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/api-usage-timeline.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/cache-latency.png b/assets/img/monitoring-and-insights/api-insights/cache-latency.png new file mode 100644 index 000000000..12b4b9db2 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/cache-latency.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/cache-page-full.png b/assets/img/monitoring-and-insights/api-insights/cache-page-full.png new file mode 100644 index 000000000..d17da46f8 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/cache-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/cache-statistics.png b/assets/img/monitoring-and-insights/api-insights/cache-statistics.png new file mode 100644 index 000000000..e25182be2 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/cache-statistics.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/choreo-system-home.png b/assets/img/monitoring-and-insights/api-insights/choreo-system-home.png new file mode 100644 index 000000000..4967b3785 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/choreo-system-home.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/configured-report.png b/assets/img/monitoring-and-insights/api-insights/configured-report.png new file mode 100644 index 000000000..9b80ad526 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/configured-report.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/create-application-wizard.png b/assets/img/monitoring-and-insights/api-insights/create-application-wizard.png new file mode 100644 index 000000000..87f17894c Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/create-application-wizard.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/create-application.png b/assets/img/monitoring-and-insights/api-insights/create-application.png new file mode 100644 index 000000000..365d45184 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/create-application.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-report-sample.png b/assets/img/monitoring-and-insights/api-insights/custom-report-sample.png new file mode 100644 index 000000000..80a904824 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-report-sample.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-report.png b/assets/img/monitoring-and-insights/api-insights/custom-report.png new file mode 100644 index 000000000..b5b6250a4 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-report.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-reports-step-1.png b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-1.png new file mode 100644 index 000000000..66ab5f1ff Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-1.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-reports-step-2-to-4.png b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-2-to-4.png new file mode 100644 index 000000000..d53b5ece9 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-2-to-4.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-reports-step-5.png b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-5.png new file mode 100644 index 000000000..09d043c53 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-5.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-reports-step-6.png b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-6.png new file mode 100644 index 000000000..137060be3 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-6.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/custom-reports-step-7.png b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-7.png new file mode 100644 index 000000000..5d9dc0982 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/custom-reports-step-7.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/devices-page-full.png b/assets/img/monitoring-and-insights/api-insights/devices-page-full.png new file mode 100644 index 000000000..79624227f Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/devices-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/endpoints.png b/assets/img/monitoring-and-insights/api-insights/endpoints.png new file mode 100644 index 000000000..a822d8060 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/endpoints.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/error-by-status-code.png b/assets/img/monitoring-and-insights/api-insights/error-by-status-code.png new file mode 100644 index 000000000..ab92c8ccc Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/error-by-status-code.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/error-category-graph.png b/assets/img/monitoring-and-insights/api-insights/error-category-graph.png new file mode 100644 index 000000000..929bf4856 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/error-category-graph.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/error-category-table.png b/assets/img/monitoring-and-insights/api-insights/error-category-table.png new file mode 100644 index 000000000..2839d6d8c Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/error-category-table.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/error-heatmap.png b/assets/img/monitoring-and-insights/api-insights/error-heatmap.png new file mode 100644 index 000000000..f8adc218a Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/error-heatmap.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/error-page-full.png b/assets/img/monitoring-and-insights/api-insights/error-page-full.png new file mode 100644 index 000000000..5f47b8a8b Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/error-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/generate-credentials.png b/assets/img/monitoring-and-insights/api-insights/generate-credentials.png new file mode 100644 index 000000000..b8f10ff04 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/generate-credentials.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/geomap-hit-count-scale.png b/assets/img/monitoring-and-insights/api-insights/geomap-hit-count-scale.png new file mode 100644 index 000000000..ec7298261 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/geomap-hit-count-scale.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/geomap-page-full.png b/assets/img/monitoring-and-insights/api-insights/geomap-page-full.png new file mode 100644 index 000000000..e4afd9743 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/geomap-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/geomap-requests-by-country.png b/assets/img/monitoring-and-insights/api-insights/geomap-requests-by-country.png new file mode 100644 index 000000000..00b63f6b6 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/geomap-requests-by-country.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/insights-download-report.svg b/assets/img/monitoring-and-insights/api-insights/insights-download-report.svg new file mode 100644 index 000000000..7b347994f --- /dev/null +++ b/assets/img/monitoring-and-insights/api-insights/insights-download-report.svg @@ -0,0 +1,17 @@ + + + E744DD54-4AD4-4DBF-A596-84B6FB4EC06D + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/img/monitoring-and-insights/api-insights/latency-by-category.png b/assets/img/monitoring-and-insights/api-insights/latency-by-category.png new file mode 100644 index 000000000..9b50b8c9c Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/latency-by-category.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/latency-page-full.png b/assets/img/monitoring-and-insights/api-insights/latency-page-full.png new file mode 100644 index 000000000..e057ad9e6 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/latency-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview-page-error-rate.png b/assets/img/monitoring-and-insights/api-insights/overview-page-error-rate.png new file mode 100644 index 000000000..f7ddb2e85 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview-page-error-rate.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview-page-error-request-count.png b/assets/img/monitoring-and-insights/api-insights/overview-page-error-request-count.png new file mode 100644 index 000000000..22c0c06e9 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview-page-error-request-count.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview-page-latency.png b/assets/img/monitoring-and-insights/api-insights/overview-page-latency.png new file mode 100644 index 000000000..8f16f6993 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview-page-latency.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview-page-timeline.png b/assets/img/monitoring-and-insights/api-insights/overview-page-timeline.png new file mode 100644 index 000000000..c600085b7 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview-page-timeline.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview-page-total-traffic.png b/assets/img/monitoring-and-insights/api-insights/overview-page-total-traffic.png new file mode 100644 index 000000000..e35fd56b2 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview-page-total-traffic.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/overview.png b/assets/img/monitoring-and-insights/api-insights/overview.png new file mode 100644 index 000000000..cfac3fd8a Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/overview.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/report-page-full.png b/assets/img/monitoring-and-insights/api-insights/report-page-full.png new file mode 100644 index 000000000..3c357f12f Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/report-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/request-access.png b/assets/img/monitoring-and-insights/api-insights/request-access.png new file mode 100644 index 000000000..63e7829d7 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/request-access.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/resource-usage.png b/assets/img/monitoring-and-insights/api-insights/resource-usage.png new file mode 100644 index 000000000..be5e93fdb Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/resource-usage.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/slowest-apis.png b/assets/img/monitoring-and-insights/api-insights/slowest-apis.png new file mode 100644 index 000000000..2a67f2c2f Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/slowest-apis.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/subscribe-api.png b/assets/img/monitoring-and-insights/api-insights/subscribe-api.png new file mode 100644 index 000000000..30a691595 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/subscribe-api.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/target-error-by-status-code.png b/assets/img/monitoring-and-insights/api-insights/target-error-by-status-code.png new file mode 100644 index 000000000..32eb0e2fe Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/target-error-by-status-code.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/target-error-heatmap.png b/assets/img/monitoring-and-insights/api-insights/target-error-heatmap.png new file mode 100644 index 000000000..b4bd5318f Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/target-error-heatmap.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/top-apis-by-alert-count.png b/assets/img/monitoring-and-insights/api-insights/top-apis-by-alert-count.png new file mode 100644 index 000000000..249925df2 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/top-apis-by-alert-count.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/top-platforms.png b/assets/img/monitoring-and-insights/api-insights/top-platforms.png new file mode 100644 index 000000000..aa48cef6b Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/top-platforms.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/top-user-agents.png b/assets/img/monitoring-and-insights/api-insights/top-user-agents.png new file mode 100644 index 000000000..58a6aff0c Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/top-user-agents.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/traffic-page-full.png b/assets/img/monitoring-and-insights/api-insights/traffic-page-full.png new file mode 100644 index 000000000..5e84f62e3 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/traffic-page-full.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/update-token-expirary-time.png b/assets/img/monitoring-and-insights/api-insights/update-token-expirary-time.png new file mode 100644 index 000000000..3e223b749 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/update-token-expirary-time.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/usage-by-application.png b/assets/img/monitoring-and-insights/api-insights/usage-by-application.png new file mode 100644 index 000000000..44871e311 Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/usage-by-application.png differ diff --git a/assets/img/monitoring-and-insights/api-insights/usage-by-target.png b/assets/img/monitoring-and-insights/api-insights/usage-by-target.png new file mode 100644 index 000000000..a573cec2a Binary files /dev/null and b/assets/img/monitoring-and-insights/api-insights/usage-by-target.png differ diff --git a/assets/img/monitoring-and-insights/data_recieved_moesif_notification.png b/assets/img/monitoring-and-insights/data_recieved_moesif_notification.png new file mode 100644 index 000000000..66ad4ab95 Binary files /dev/null and b/assets/img/monitoring-and-insights/data_recieved_moesif_notification.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/add-integration-cio-dashboard.png b/assets/img/monitoring-and-insights/engineering-insights/add-integration-cio-dashboard.png new file mode 100644 index 000000000..4dea8947e Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/add-integration-cio-dashboard.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/add-integration-configure.png b/assets/img/monitoring-and-insights/engineering-insights/add-integration-configure.png new file mode 100644 index 000000000..d0bd6e503 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/add-integration-configure.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-chart.png b/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-chart.png new file mode 100644 index 000000000..96f576baf Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-chart.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-summary.png b/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-summary.png new file mode 100644 index 000000000..e4934ddde Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/change-failure-rate-summary.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/cio-dashboard.png b/assets/img/monitoring-and-insights/engineering-insights/cio-dashboard.png new file mode 100644 index 000000000..50a5ac8f7 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/cio-dashboard.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/deployment-copy-to-clipboard.png b/assets/img/monitoring-and-insights/engineering-insights/deployment-copy-to-clipboard.png new file mode 100644 index 000000000..a9716bd2f Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/deployment-copy-to-clipboard.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-snapshot.png b/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-snapshot.png new file mode 100644 index 000000000..24c12c1d8 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-snapshot.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-time-series.png b/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-time-series.png new file mode 100644 index 000000000..0a4aab1f5 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/deployment-frequency-time-series.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/deployment-history.png b/assets/img/monitoring-and-insights/engineering-insights/deployment-history.png new file mode 100644 index 000000000..c4b341813 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/deployment-history.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/dora-matrix.png b/assets/img/monitoring-and-insights/engineering-insights/dora-matrix.png new file mode 100644 index 000000000..6c1132d9f Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/dora-matrix.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/dora-metrics-summary.png b/assets/img/monitoring-and-insights/engineering-insights/dora-metrics-summary.png new file mode 100644 index 000000000..91cfc965c Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/dora-metrics-summary.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/edit-configurations.png b/assets/img/monitoring-and-insights/engineering-insights/edit-configurations.png new file mode 100644 index 000000000..d51c4cc69 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/edit-configurations.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/enable-dora-metrics.png b/assets/img/monitoring-and-insights/engineering-insights/enable-dora-metrics.png new file mode 100644 index 000000000..309951474 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/enable-dora-metrics.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/filter-label.png b/assets/img/monitoring-and-insights/engineering-insights/filter-label.png new file mode 100644 index 000000000..557377bcd Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/filter-label.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-chart.png b/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-chart.png new file mode 100644 index 000000000..c80f82d44 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-chart.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-summary.png b/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-summary.png new file mode 100644 index 000000000..658c6bc28 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/lead-time-for-a-change-summary.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-chart.png b/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-chart.png new file mode 100644 index 000000000..b74204ad8 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-chart.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-summary.png b/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-summary.png new file mode 100644 index 000000000..ecc0c88c0 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/mean-time-to-recovery-summary.png differ diff --git a/assets/img/monitoring-and-insights/engineering-insights/time-series-view.jpg b/assets/img/monitoring-and-insights/engineering-insights/time-series-view.jpg new file mode 100644 index 000000000..73280c517 Binary files /dev/null and b/assets/img/monitoring-and-insights/engineering-insights/time-series-view.jpg differ diff --git a/assets/img/monitoring-and-insights/first_time_key_moesif.png b/assets/img/monitoring-and-insights/first_time_key_moesif.png new file mode 100644 index 000000000..dbf662926 Binary files /dev/null and b/assets/img/monitoring-and-insights/first_time_key_moesif.png differ diff --git a/assets/img/monitoring-and-insights/observability/diagnostic-view.png b/assets/img/monitoring-and-insights/observability/diagnostic-view.png new file mode 100644 index 000000000..645f947ed Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/diagnostic-view.png differ diff --git a/assets/img/monitoring-and-insights/observability/logs-panel.png b/assets/img/monitoring-and-insights/observability/logs-panel.png new file mode 100644 index 000000000..b5e740d94 Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/logs-panel.png differ diff --git a/assets/img/monitoring-and-insights/observability/logs.png b/assets/img/monitoring-and-insights/observability/logs.png new file mode 100644 index 000000000..6748c5ad7 Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/logs.png differ diff --git a/assets/img/monitoring-and-insights/observability/overview-overall.png b/assets/img/monitoring-and-insights/observability/overview-overall.png new file mode 100644 index 000000000..c620926d8 Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/overview-overall.png differ diff --git a/assets/img/monitoring-and-insights/observability/throughput-and-latency.png b/assets/img/monitoring-and-insights/observability/throughput-and-latency.png new file mode 100644 index 000000000..0a4c35b72 Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/throughput-and-latency.png differ diff --git a/assets/img/monitoring-and-insights/observability/view-application-logs.png b/assets/img/monitoring-and-insights/observability/view-application-logs.png new file mode 100644 index 000000000..9912e2c56 Binary files /dev/null and b/assets/img/monitoring-and-insights/observability/view-application-logs.png differ diff --git a/assets/img/monitoring-and-insights/view-logs/audit-logs.png b/assets/img/monitoring-and-insights/view-logs/audit-logs.png new file mode 100644 index 000000000..da5aa54b8 Binary files /dev/null and b/assets/img/monitoring-and-insights/view-logs/audit-logs.png differ diff --git a/assets/img/monitoring-and-insights/view-logs/create-role-to-view-audit-logs.png b/assets/img/monitoring-and-insights/view-logs/create-role-to-view-audit-logs.png new file mode 100644 index 000000000..7b76d00dd Binary files /dev/null and b/assets/img/monitoring-and-insights/view-logs/create-role-to-view-audit-logs.png differ diff --git a/assets/img/monitoring-and-insights/view-logs/log-management-permission.png b/assets/img/monitoring-and-insights/view-logs/log-management-permission.png new file mode 100644 index 000000000..bf4e86ba8 Binary files /dev/null and b/assets/img/monitoring-and-insights/view-logs/log-management-permission.png differ diff --git a/assets/img/monitoring-and-insights/view-logs/runtime-logs.png b/assets/img/monitoring-and-insights/view-logs/runtime-logs.png new file mode 100644 index 000000000..34bdedbe1 Binary files /dev/null and b/assets/img/monitoring-and-insights/view-logs/runtime-logs.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-an-application.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-an-application.png new file mode 100644 index 000000000..906e6fb5e Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-an-application.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-application.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-application.png new file mode 100644 index 000000000..3de0697c4 Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/create-application.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/endpoints.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/endpoints.png new file mode 100644 index 000000000..50a29bb6c Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/endpoints.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/generate-credentials.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/generate-credentials.png new file mode 100644 index 000000000..9aef7a814 Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/generate-credentials.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/request-access.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/request-access.png new file mode 100644 index 000000000..60e91f46b Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/request-access.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/subscribe-to-insights-api.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/subscribe-to-insights-api.png new file mode 100644 index 000000000..5c0782b80 Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/subscribe-to-insights-api.png differ diff --git a/assets/img/monitoring-and-insights/work-with-choreo-insights-api/update-token-expirary-time.png b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/update-token-expirary-time.png new file mode 100644 index 000000000..4bb49df28 Binary files /dev/null and b/assets/img/monitoring-and-insights/work-with-choreo-insights-api/update-token-expirary-time.png differ diff --git a/assets/img/platform-services/kafka-service-overview.png b/assets/img/platform-services/kafka-service-overview.png new file mode 100644 index 000000000..11e178b6e Binary files /dev/null and b/assets/img/platform-services/kafka-service-overview.png differ diff --git a/assets/img/platform-services/set-ca-certificate.png b/assets/img/platform-services/set-ca-certificate.png new file mode 100644 index 000000000..1fd3be8dd Binary files /dev/null and b/assets/img/platform-services/set-ca-certificate.png differ diff --git a/assets/img/platform-services/set-environment-variables.png b/assets/img/platform-services/set-environment-variables.png new file mode 100644 index 000000000..91ce81f3d Binary files /dev/null and b/assets/img/platform-services/set-environment-variables.png differ diff --git a/assets/img/quick-start-guides/api-proxy-response.png b/assets/img/quick-start-guides/api-proxy-response.png new file mode 100644 index 000000000..ef4ae816d Binary files /dev/null and b/assets/img/quick-start-guides/api-proxy-response.png differ diff --git a/assets/img/quick-start-guides/create-choreo-organization.png b/assets/img/quick-start-guides/create-choreo-organization.png new file mode 100644 index 000000000..76b35c93b Binary files /dev/null and b/assets/img/quick-start-guides/create-choreo-organization.png differ diff --git a/assets/img/quick-start-guides/front-end-application.png b/assets/img/quick-start-guides/front-end-application.png new file mode 100644 index 000000000..b07faf40e Binary files /dev/null and b/assets/img/quick-start-guides/front-end-application.png differ diff --git a/assets/img/quick-start-guides/web-application.png b/assets/img/quick-start-guides/web-application.png new file mode 100644 index 000000000..1ef5e321e Binary files /dev/null and b/assets/img/quick-start-guides/web-application.png differ diff --git a/assets/img/testing/graphql-console-org.png b/assets/img/testing/graphql-console-org.png new file mode 100644 index 000000000..405329441 Binary files /dev/null and b/assets/img/testing/graphql-console-org.png differ diff --git a/assets/img/testing/graphql-console.png b/assets/img/testing/graphql-console.png new file mode 100644 index 000000000..88482631c Binary files /dev/null and b/assets/img/testing/graphql-console.png differ diff --git a/assets/img/testing/openapi-console-org.png b/assets/img/testing/openapi-console-org.png new file mode 100644 index 000000000..759e4e74d Binary files /dev/null and b/assets/img/testing/openapi-console-org.png differ diff --git a/assets/img/testing/openapi-console.png b/assets/img/testing/openapi-console.png new file mode 100644 index 000000000..9f49fc199 Binary files /dev/null and b/assets/img/testing/openapi-console.png differ diff --git a/assets/img/testing/websocket-console.png b/assets/img/testing/websocket-console.png new file mode 100644 index 000000000..c7814c1d9 Binary files /dev/null and b/assets/img/testing/websocket-console.png differ diff --git a/assets/img/tutorials/api-proxy-response.png b/assets/img/tutorials/api-proxy-response.png new file mode 100644 index 000000000..dbbeadbf9 Binary files /dev/null and b/assets/img/tutorials/api-proxy-response.png differ diff --git a/assets/img/tutorials/role-based-auth/access-token.png b/assets/img/tutorials/role-based-auth/access-token.png new file mode 100644 index 000000000..bc9412019 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/access-token.png differ diff --git a/assets/img/tutorials/role-based-auth/api-resources.png b/assets/img/tutorials/role-based-auth/api-resources.png new file mode 100644 index 000000000..ed24e1a67 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/api-resources.png differ diff --git a/assets/img/tutorials/role-based-auth/authorize-endpoint.png b/assets/img/tutorials/role-based-auth/authorize-endpoint.png new file mode 100644 index 000000000..11314c698 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/authorize-endpoint.png differ diff --git a/assets/img/tutorials/role-based-auth/callback-url.png b/assets/img/tutorials/role-based-auth/callback-url.png new file mode 100644 index 000000000..a2addc487 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/callback-url.png differ diff --git a/assets/img/tutorials/role-based-auth/code.png b/assets/img/tutorials/role-based-auth/code.png new file mode 100644 index 000000000..5aba5097a Binary files /dev/null and b/assets/img/tutorials/role-based-auth/code.png differ diff --git a/assets/img/tutorials/role-based-auth/consent.png b/assets/img/tutorials/role-based-auth/consent.png new file mode 100644 index 000000000..624d3abfe Binary files /dev/null and b/assets/img/tutorials/role-based-auth/consent.png differ diff --git a/assets/img/tutorials/role-based-auth/consumer-key.png b/assets/img/tutorials/role-based-auth/consumer-key.png new file mode 100644 index 000000000..6391c49aa Binary files /dev/null and b/assets/img/tutorials/role-based-auth/consumer-key.png differ diff --git a/assets/img/tutorials/role-based-auth/enable-asgardeo-key-manager.png b/assets/img/tutorials/role-based-auth/enable-asgardeo-key-manager.png new file mode 100644 index 000000000..092ce84db Binary files /dev/null and b/assets/img/tutorials/role-based-auth/enable-asgardeo-key-manager.png differ diff --git a/assets/img/tutorials/role-based-auth/manage-permission.png b/assets/img/tutorials/role-based-auth/manage-permission.png new file mode 100644 index 000000000..9ee60d14c Binary files /dev/null and b/assets/img/tutorials/role-based-auth/manage-permission.png differ diff --git a/assets/img/tutorials/role-based-auth/permission-values.png b/assets/img/tutorials/role-based-auth/permission-values.png new file mode 100644 index 000000000..33edf4072 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/permission-values.png differ diff --git a/assets/img/tutorials/role-based-auth/resource-permission.png b/assets/img/tutorials/role-based-auth/resource-permission.png new file mode 100644 index 000000000..c475ce4a1 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/resource-permission.png differ diff --git a/assets/img/tutorials/role-based-auth/scope-validation-failed.png b/assets/img/tutorials/role-based-auth/scope-validation-failed.png new file mode 100644 index 000000000..44f94bf8b Binary files /dev/null and b/assets/img/tutorials/role-based-auth/scope-validation-failed.png differ diff --git a/assets/img/tutorials/role-based-auth/scopes.png b/assets/img/tutorials/role-based-auth/scopes.png new file mode 100644 index 000000000..5e9e39577 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/scopes.png differ diff --git a/assets/img/tutorials/role-based-auth/sign-in-kim.png b/assets/img/tutorials/role-based-auth/sign-in-kim.png new file mode 100644 index 000000000..2f211f974 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/sign-in-kim.png differ diff --git a/assets/img/tutorials/role-based-auth/sign-in.png b/assets/img/tutorials/role-based-auth/sign-in.png new file mode 100644 index 000000000..0987f0227 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/sign-in.png differ diff --git a/assets/img/tutorials/role-based-auth/token-endpoint.png b/assets/img/tutorials/role-based-auth/token-endpoint.png new file mode 100644 index 000000000..38ca3d138 Binary files /dev/null and b/assets/img/tutorials/role-based-auth/token-endpoint.png differ diff --git a/assets/javascripts/application.js b/assets/javascripts/application.js new file mode 100644 index 000000000..54acf4fe9 --- /dev/null +++ b/assets/javascripts/application.js @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2016-2017 Martin Donath + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +import Clipboard from "clipboard" +import FastClick from "fastclick" + +import Material from "./components/Material" + +/* ---------------------------------------------------------------------------- + * Application + * ------------------------------------------------------------------------- */ + +/** + * Initialize Material for MkDocs + * + * @param {Object} config - Configuration + */ +function initialize(config) { // eslint-disable-line func-style + + /* Initialize Modernizr and FastClick */ + new Material.Event.Listener(document, "DOMContentLoaded", () => { + if (!(document.body instanceof HTMLElement)) + throw new ReferenceError + + /* Attach FastClick to mitigate 300ms delay on touch devices */ + FastClick.attach(document.body) + + /* Test for iOS */ + Modernizr.addTest("ios", () => { + return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g) + }) + + /* Wrap all data tables for better overflow scrolling */ + const tables = document.querySelectorAll("table:not([class])") // TODO: this is JSX, we should rename the file + Array.prototype.forEach.call(tables, table => { + const wrap = ( +
+
+
+ ) + if (table.nextSibling) { + table.parentNode.insertBefore(wrap, table.nextSibling) + } else { + table.parentNode.appendChild(wrap) + } + wrap.children[0].appendChild(table) + }) + + /* Clipboard integration */ + if (Clipboard.isSupported()) { + const blocks = document.querySelectorAll("div > pre, pre > code") + Array.prototype.forEach.call(blocks, (block, index) => { + const id = `__code_${index}` + + /* Create button with message container */ + const button = ( + + ) + + /* Link to block and insert button */ + const parent = block.parentNode + parent.id = id + parent.insertBefore(button, block) + }) + + /* Initialize Clipboard listener */ + const copy = new Clipboard(".md-clipboard") + + /* Success handler */ + copy.on("success", action => { + const message = action.trigger.querySelector(".md-clipboard__message") + if (!(message instanceof HTMLElement)) + throw new ReferenceError + + /* Clear selection and reset debounce logic */ + action.clearSelection() + if (message.dataset.mdTimer) + clearTimeout(parseInt(message.dataset.mdTimer, 10)) + + /* Set message indicating success and show it */ + message.classList.add("md-clipboard__message--active") + message.innerHTML = "Copied to clipboard" + + /* Hide message after two seconds */ + message.dataset.mdTimer = setTimeout(() => { + message.classList.remove("md-clipboard__message--active") + message.dataset.mdTimer = "" + }, 2000).toString() + }) + } + + /* Polyfill details/summary functionality */ + if (!Modernizr.details) { + const blocks = document.querySelectorAll("details > summary") + Array.prototype.forEach.call(blocks, summary => { + summary.addEventListener("click", ev => { + const details = ev.target.parentNode + if (details.hasAttribute("open")) { + details.removeAttribute("open") + } else { + details.setAttribute("open", "") + } + }) + }) + } + + /* Force 1px scroll offset to trigger overflow scrolling */ + if (Modernizr.ios) { + const scrollable = document.querySelectorAll("[data-md-scrollfix]") + Array.prototype.forEach.call(scrollable, item => { + item.addEventListener("touchstart", () => { + const top = item.scrollTop + + /* We're at the top of the container */ + if (top === 0) { + item.scrollTop = 1 + + /* We're at the bottom of the container */ + } else if (top + item.offsetHeight === item.scrollHeight) { + item.scrollTop = top - 1 + } + }) + }) + } + }).listen() + + /* Component: header shadow toggle */ + new Material.Event.MatchMedia("(min-width: 1220px)", + new Material.Event.Listener(window, [ + "scroll", "resize", "orientationchange" + ], new Material.Header.Shadow( + "[data-md-component=container]", + "[data-md-component=header]"))) + + /* Component: tabs visibility toggle */ + if (document.querySelector("[data-md-component=tabs]")) + new Material.Event.Listener(window, [ + "scroll", "resize", "orientationchange" + ], new Material.Tabs.Toggle("[data-md-component=tabs]")).listen() + + /* Component: sidebar with navigation */ + new Material.Event.MatchMedia("(min-width: 1220px)", + new Material.Event.Listener(window, [ + "scroll", "resize", "orientationchange" + ], new Material.Sidebar.Position( + "[data-md-component=navigation]", + "[data-md-component=header]"))) + + /* Component: sidebar with table of contents (missing on 404 page) */ + if (document.querySelector("[data-md-component=toc]")) + new Material.Event.MatchMedia("(min-width: 960px)", + new Material.Event.Listener(window, [ + "scroll", "resize", "orientationchange" + ], new Material.Sidebar.Position( + "[data-md-component=toc]", + "[data-md-component=header]"))) + + /* Component: link blurring for table of contents */ + new Material.Event.MatchMedia("(min-width: 960px)", + new Material.Event.Listener(window, "scroll", + new Material.Nav.Blur("[data-md-component=toc] [href]"))) + + /* Component: collapsible elements for navigation */ + const collapsibles = + document.querySelectorAll("[data-md-component=collapsible]") + Array.prototype.forEach.call(collapsibles, collapse => { + new Material.Event.MatchMedia("(min-width: 1220px)", + new Material.Event.Listener(collapse.previousElementSibling, "click", + new Material.Nav.Collapse(collapse))) + }) + + /* Component: active pane monitor for iOS scrolling fixes */ + new Material.Event.MatchMedia("(max-width: 1219px)", + new Material.Event.Listener( + "[data-md-component=navigation] [data-md-toggle]", "change", + new Material.Nav.Scrolling("[data-md-component=navigation] nav"))) + + /* Component: search body lock for mobile */ + new Material.Event.MatchMedia("(max-width: 959px)", + new Material.Event.Listener("[data-md-toggle=search]", "change", + new Material.Search.Lock("[data-md-toggle=search]"))) + + /* Component: search results */ + new Material.Event.Listener("[data-md-component=query]", [ + "focus", "keyup", "change" + ], new Material.Search.Result("[data-md-component=result]", () => { + return fetch(`${config.url.base}/${ + config.version < "0.17" ? "mkdocs" : "search" + }/search_index.json`, { + credentials: "same-origin" + }).then(response => response.json()) + .then(data => { + return data.docs.map(doc => { + doc.location = config.url.base + doc.location + return doc + }) + }) + })).listen() + + /* Listener: close drawer when anchor links are clicked */ + new Material.Event.MatchMedia("(max-width: 959px)", + new Material.Event.Listener("[data-md-component=navigation] [href^='#']", + "click", () => { + const toggle = document.querySelector("[data-md-toggle=drawer]") + if (!(toggle instanceof HTMLInputElement)) + throw new ReferenceError + if (toggle.checked) { + toggle.checked = false + toggle.dispatchEvent(new CustomEvent("change")) + } + })) + + /* Listener: focus input after form reset */ + new Material.Event.Listener("[data-md-component=reset]", "click", () => { + setTimeout(() => { + const query = document.querySelector("[data-md-component=query]") + if (!(query instanceof HTMLInputElement)) + throw new ReferenceError + query.focus() + }, 10) + }).listen() + + /* Listener: focus input after opening search */ + new Material.Event.Listener("[data-md-toggle=search]", "change", ev => { + alert("change"); + setTimeout(toggle => { + if (!(toggle instanceof HTMLInputElement)) + throw new ReferenceError + if (toggle.checked) { + const query = document.querySelector("[data-md-component=query]") + if (!(query instanceof HTMLInputElement)) + throw new ReferenceError + query.focus() + } + }, 400, ev.target) + }).listen() + + /* Listener: open search on focus */ + new Material.Event.MatchMedia("(min-width: 960px)", + new Material.Event.Listener("[data-md-component=query]", "focus", () => { + const toggle = document.querySelector("[data-md-toggle=search]") + if (!(toggle instanceof HTMLInputElement)) + throw new ReferenceError + if (!toggle.checked) { + toggle.checked = true + toggle.dispatchEvent(new CustomEvent("change")) + } + })) + + /* Listener: keyboard handlers */ // eslint-disable-next-line complexity + new Material.Event.Listener(window, "keydown", ev => { + alert("found"); + // TODO: split up into component to reduce complexity + const toggle = document.querySelector("[data-md-toggle=search]") + if (!(toggle instanceof HTMLInputElement)) + throw new ReferenceError + const query = document.querySelector("[data-md-component=query]") + if (!(query instanceof HTMLInputElement)) + throw new ReferenceError + + /* Abort if meta key (macOS) or ctrl key (Windows) is pressed */ + if (ev.metaKey || ev.ctrlKey) + return + + /* Search is open */ + if (toggle.checked) { + + /* Enter: prevent form submission */ + if (ev.keyCode === 13) { + if (query === document.activeElement) { + ev.preventDefault() + + /* Go to current active/focused link */ + const focus = document.querySelector( + "[data-md-component=search] [href][data-md-state=active]") + if (focus instanceof HTMLLinkElement) { + window.location = focus.getAttribute("href") + + /* Close search */ + toggle.checked = false + toggle.dispatchEvent(new CustomEvent("change")) + query.blur() + } + } + + /* Escape: close search */ + } else if (ev.keyCode === 27) { + toggle.checked = false + toggle.dispatchEvent(new CustomEvent("change")) + query.blur() + + /* Horizontal arrows and backspace: focus input */ + } else if ([8, 37, 39].indexOf(ev.keyCode) !== -1) { + if (query !== document.activeElement) + query.focus() + + /* Vertical arrows and tab: select previous or next search result */ + } else if ([9, 38, 40].indexOf(ev.keyCode) !== -1) { + const map = ev.shiftKey ? 38 : 40 + const key = ev.keyCode === 9 ? map : ev.keyCode + + /* Retrieve all results */ + const links = Array.prototype.slice.call( + document.querySelectorAll( + "[data-md-component=query], [data-md-component=search] [href]")) + + /* Retrieve current active/focused result */ + const focus = links.find(link => { + if (!(link instanceof HTMLElement)) + throw new ReferenceError + return link.dataset.mdState === "active" + }) + if (focus) + focus.dataset.mdState = "" + + /* Calculate index depending on direction, add length to form ring */ + const index = Math.max(0, ( + links.indexOf(focus) + links.length + (key === 38 ? -1 : +1) + ) % links.length) + + /* Set active state and focus */ + if (links[index]) { + links[index].dataset.mdState = "active" + links[index].focus() + } + + /* Prevent scrolling of page */ + ev.preventDefault() + ev.stopPropagation() + + /* Return false prevents the cursor position from changing */ + return false + } + + /* Search is closed and we're not inside a form */ + } else if (document.activeElement && !document.activeElement.form) { + + /* F/S: Open search if not in input field */ + // if (ev.keyCode === 70 || ev.keyCode === 83) { + // query.focus() + // ev.preventDefault() + // } + } + }).listen() + + /* Listener: focus query if in search is open and character is typed */ + new Material.Event.Listener(window, "keypress", () => { + const toggle = document.querySelector("[data-md-toggle=search]") + if (!(toggle instanceof HTMLInputElement)) + throw new ReferenceError + if (toggle.checked) { + const query = document.querySelector("[data-md-component=query]") + if (!(query instanceof HTMLInputElement)) + throw new ReferenceError + if (query !== document.activeElement) + query.focus() + } + }).listen() + + /* Retrieve facts for the given repository type */ + ;(() => { + const el = document.querySelector("[data-md-source]") + if (!el) + return Promise.resolve([]) + else if (!(el instanceof HTMLAnchorElement)) + throw new ReferenceError + switch (el.dataset.mdSource) { + case "github": return new Material.Source.Adapter.GitHub(el).fetch() + default: return Promise.resolve([]) + } + + /* Render repository information */ + })().then(facts => { + const sources = document.querySelectorAll("[data-md-source]") + Array.prototype.forEach.call(sources, source => { + new Material.Source.Repository(source) + .initialize(facts) + }) + }) +} + +/* ---------------------------------------------------------------------------- + * Exports + * ------------------------------------------------------------------------- */ + +export { + initialize +} diff --git a/assets/javascripts/bundle.fc8c2696.min.js b/assets/javascripts/bundle.fc8c2696.min.js new file mode 100644 index 000000000..359c24cd8 --- /dev/null +++ b/assets/javascripts/bundle.fc8c2696.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Ri=Object.create;var gr=Object.defineProperty;var ki=Object.getOwnPropertyDescriptor;var Hi=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Pi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,on=Object.prototype.propertyIsEnumerable;var nn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&nn(e,r,t[r]);if(kt)for(var r of kt(t))on.call(t,r)&&nn(e,r,t[r]);return e};var an=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&on.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var $i=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Hi(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=ki(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ri(Pi(e)):{},$i(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var cn=Ht((xr,sn)=>{(function(e,t){typeof xr=="object"&&typeof sn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function c(T){var Qe=T.type,De=T.tagName;return!!(De==="INPUT"&&s[Qe]&&!T.readOnly||De==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function f(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(a(r.activeElement)&&f(r.activeElement),n=!0)}function m(T){n=!1}function d(T){a(T.target)&&(n||c(T.target))&&f(T.target)}function h(T){a(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),G())}function G(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function oe(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,oe())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),G(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var fn=Ht(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(f){return!1}},r=t(),n=function(f){var u={next:function(){var p=f.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(f){return encodeURIComponent(f).replace(/%20/g,"+")},i=function(f){return decodeURIComponent(String(f).replace(/\+/g," "))},s=function(){var f=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof f){var d=this;p.forEach(function(oe,N){d.append(N,oe)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),f._entries&&(f._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(c,f){typeof c!="string"&&(c=String(c)),f&&typeof f!="string"&&(f=String(f));var u=document,p;if(f&&(e.location===void 0||f!==e.location.href)){f=f.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=f,u.head.appendChild(p);try{if(p.href.indexOf(f)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+f+" due to "+T)}}var m=u.createElement("a");m.href=c,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=c,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!f)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,G=!0,oe=this;["append","delete","set"].forEach(function(T){var Qe=h[T];h[T]=function(){Qe.apply(h,arguments),v&&(G=!1,oe.search=h.toString(),G=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,G&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(c){Object.defineProperty(s,c,{get:function(){return this._anchorElement[c]},set:function(f){this._anchorElement[c]=f},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(c){a(c)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(c){this._anchorElement.search=c,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var c=this;return function(){return c.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(c){this._anchorElement.href=c,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(c){this._anchorElement.pathname=c},enumerable:!0},origin:{get:function(){var c={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],f=this._anchorElement.port!=c&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(f?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(c){},enumerable:!0},username:{get:function(){return""},set:function(c){},enumerable:!0}}),i.createObjectURL=function(c){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(c){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var Kr=Ht((Mt,qr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Mt=="object"&&typeof qr=="object"?qr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ci}});var s=i(279),a=i.n(s),c=i(370),f=i.n(c),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var E=p()(O);return m("cut"),E},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[O?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var G=function(O,E){var H=v(O);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},oe=function(O){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof O=="string"?H=G(O,E):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?H=G(O.value,E):(H=p()(O),m("copy")),H},N=oe;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(E){return typeof E}:T=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},T(j)}var Qe=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=O.action,H=E===void 0?"copy":E,I=O.container,q=O.target,Me=O.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function wi(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function rn(j,O){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=f()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",Rt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Me,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(Rt){Me=Me&&!!document.queryCommandSupported(Rt)}),Me}}]),E}(a()),Ci=Ai},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=f.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function c(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function f(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=c},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function c(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return f(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function f(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=c},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),f=document.createRange();f.selectNodeContents(i),c.removeAllRanges(),c.addRange(f),s=c.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function f(){c.off(i,f),s.apply(a,arguments)}return f._=s,this.on(i,f,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,f=a.length;for(c;c{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var ns=/["'&<>]/;Go.exports=os;function os(e){var t=""+e,r=ns.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(f[0]===6||f[0]===2)){r=0;continue}if(f[0]===3&&(!i||f[1]>i[0]&&f[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{c(n[m](d))}catch(h){p(i[0][3],h)}}function c(m){m.value instanceof et?Promise.resolve(m.value.v).then(f,u):p(i[0][2],m)}function f(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function ln(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,c){s=e[i](s),o(a,c,s.done,s.value)})}}function o(i,s,a,c){Promise.resolve(c).then(function(f){i({value:f,done:a})},s)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),c=a.next();!c.done;c=a.next()){var f=c.value;f.remove(this)}}catch(v){t={error:v}}finally{try{c&&!c.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{mn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)mn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function It(e){return e instanceof Ie||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function mn(e){A(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new En(r,n)},t}(F);var En=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,c=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),c=0;c0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var Tn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var Te=new Tn(Sn);var _=new F(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return A(Cr(e))?e.pop():void 0}function Oe(e){return Dt(Cr(e))?e.pop():void 0}function Vt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ni(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ni();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return pn(this,arguments,function(){var r,n,o,i;return Pt(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(Nt(e))return qi(e);if(pt(e))return Ki(e);if(zt(e))return Qi(e);if(qt(e))return On(e);if(Yt(e))return Yi(e);if(Bt(e))return Gi(e)}throw Kt(e)}function qi(e){return new F(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Ki(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?L(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Vn(function(){return new Xt}))}}function zn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(f){var u,p,m,d=0,h=!1,v=!1,G=function(){p==null||p.unsubscribe(),p=void 0},oe=function(){G(),u=m=void 0,h=v=!1},N=function(){var T=u;oe(),T==null||T.unsubscribe()};return y(function(T,Qe){d++,!v&&!h&&G();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,c))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,G(),p=$r(oe,o,$e),De.error($e)},complete:function(){h=!0,G(),p=$r(oe,s),De.complete()}}),U(T).subscribe(u))})(f)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function er(e){return C(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),B())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Qn(e){return C(b(window,"load"),b(window,"resize")).pipe(Ce(0,Te),l(()=>Xe(e)),V(Xe(e)))}function tr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return C(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Te),l(()=>tr(e)),V(tr(e)))}var Gn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Dr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),ga?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Dr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=va.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Bn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Xn=typeof WeakMap!="undefined"?new WeakMap:new Gn,Zn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ya.getInstance(),n=new Aa(t,r,this);Xn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Zn.prototype[e]=function(){var t;return(t=Xn.get(this))[e].apply(t,arguments)}});var Ca=function(){return typeof rr.ResizeObserver!="undefined"?rr.ResizeObserver:Zn}(),eo=Ca;var to=new x,Ra=$(()=>k(new eo(e=>{for(let t of e)to.next(t)}))).pipe(g(e=>C(ze,k(e)).pipe(R(()=>e.disconnect()))),J(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(L(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ir(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var ro=new x,ka=$(()=>k(new IntersectionObserver(e=>{for(let t of e)ro.next(t)},{threshold:0}))).pipe(g(e=>C(ze,k(e)).pipe(R(()=>e.disconnect()))),J(1));function ar(e){return ka.pipe(S(t=>t.observe(e)),g(t=>ro.pipe(L(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function no(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),B())}var sr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function oo(e){return sr[e].checked}function Ke(e,t){sr[e].checked!==t&&sr[e].click()}function Ue(e){let t=sr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function Ha(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Pa(){return C(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function io(){let e=b(window,"keydown").pipe(L(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:oo("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),L(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!Ha(n,r)}return!0}),pe());return Pa().pipe(g(t=>t?_:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function ao(){return new x}function so(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)so(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)so(n,o);return n}function cr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function co(){return location.hash.substring(1)}function Vr(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function $a(){return b(window,"hashchange").pipe(l(co),V(co()),L(e=>e.length>0),J(1))}function fo(){return $a().pipe(l(e=>ce(`[id="${e}"]`)),L(e=>typeof e!="undefined"))}function zr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function uo(){let e=matchMedia("print");return C(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function Nr(e,t){return e.pipe(g(r=>r?t():_))}function fr(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>_),g(r=>r.status!==200?Tt(()=>new Error(r.statusText)):k(r)))}function We(e,t){return fr(e,t).pipe(g(r=>r.json()),J(1))}function po(e,t){let r=new DOMParser;return fr(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function ur(e){let t=M("script",{src:e});return $(()=>(document.head.appendChild(t),C(b(t,"load"),b(t,"error").pipe(g(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function lo(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function mo(){return C(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(lo),V(lo()))}function ho(){return{width:innerWidth,height:innerHeight}}function bo(){return b(window,"resize",{passive:!0}).pipe(l(ho),V(ho()))}function vo(){return Q([mo(),bo()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function pr(e,{viewport$:t,header$:r}){let n=t.pipe(Z("size")),o=Q([n,r]).pipe(l(()=>Xe(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:c,y:f}])=>({offset:{x:s.x-c,y:s.y-f+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,c,f)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:c,error:f});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` + + + +Redirecting... + + diff --git a/authentication-and-authorization/configure-mutual-tls-between-components/index.html b/authentication-and-authorization/configure-mutual-tls-between-components/index.html new file mode 100644 index 000000000..313e58f72 --- /dev/null +++ b/authentication-and-authorization/configure-mutual-tls-between-components/index.html @@ -0,0 +1,3547 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Mutual TLS Between Components - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Mutual TLS Between Components

+

Mutual transport layer security (mutual TLS) is a protocol that ensures privacy, integrity, and authentication of the data transmitted between two endpoints. In mutual TLS, the client and the server authenticate each other using digital certificates, establishing trust and verifying identities. Upon successful authentication, mutual TLS encrypts the data exchanged between the client and the server, preventing unauthorized access.

+

In Choreo, you can use mutual TLS to establish secure connections between components within a project.

+
+

Note

+

If mutual TLS is not required, you can configure TLS instead. TLS provides a secure communication channel between a client and server but does not require the client to present a certificate to the server. This results in the absence of mutual authentication between the client and the server. While TLS ensures the confidentiality of data transmitted between the client and server, preventing unauthorized tampering, mutual TLS enhances TLS by introducing client-side authentication and facilitating mutual verification of identities between the client and server.

+

To configure TLS, you can follow the same steps as for mutual TLS as mentioned below, without having to generate a client certificate. The client only needs the root certificate to verify the server's identity.

+
+

Generate certificates to establish mutual TLS

+
    +
  • +

    Root certificate: Trusted by both the client and the server, this certificate is used to verify the authenticity of other certificates presented during the mutual TLS handshake process and to issue certificates for clients and servers. For a specific project, you can generate a single root certificate using a tool like OpenSSL.

    +
  • +
  • +

    Client certificate: Contains the client’s identity for authentication. The common name (CN) in the certificate identifies the client. The generated client certificate must be signed by the root certificate.

    +
  • +
  • +

    Server certificate: Clients use the server certificate to verify the trustworthiness of the server and establish a secure and authenticated connection. Similar to the client certificates, the server certificate must also be signed by the root certificate. When generating the server certificate, you must specify the server's hostname for the subject alternative name (SAN). You can obtain the hostname for the specific version of a service component from any project endpoint on the Overview page.

    +
  • +
+

For example, if your project endpoint is http://my-service-3781140846:7080/todos, the hostname will be my-service-3781140846.

+

Read mutual TLS certificates from your component

+

The approach to read mutual TLS certificates from a component can vary depending on its implementation. Typically, a component can read the certificate data from the file system or via an environment variable. For detailed instructions on adding environment variables and file mounts to your application, see Manage Configurations and Secrets.

+
+

Info

+

When you specify a private key, ensure you save it as a secret.

+
+

Sample for mutual TLS communication

+

For a sample that demonstrates how you can deploy services that communicate using mutual TLS, see service-to-service-mtls.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/pass-end-user-attributes-to-upstream-services/index.html b/authentication-and-authorization/pass-end-user-attributes-to-upstream-services/index.html new file mode 100644 index 000000000..0a2abbe46 --- /dev/null +++ b/authentication-and-authorization/pass-end-user-attributes-to-upstream-services/index.html @@ -0,0 +1,3800 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pass End-User Attributes to Upstream Services - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Pass End-User Attributes to Upstream Services

+

There are scenarios where a backend service needs to apply specific logic or make decisions depending on the user consuming an API. In such scenarios, you must pass end-user attributes to the backend during an API call.

+

Choreo provides a method to send user information to a backend service through a JSON Web Token (JWT) in an HTTP header of an API request.

+

How it works

+

The backend JWT contains claims transferred between the parties, such as the user and the backend. A claim can be metadata of the request or data about the user. A set of claims is called a dialect, for example, http://wso2.org/claims.

+

For each API request, a digitally signed JWT is carried to the backend service in the following format to ensure that the authenticity of the claims list is verified:

+

{token header}.{claims list}.{signature}

+

When a request goes through Choreo, the backend JWT is appended as the X-JWT-Assertion header in the outgoing message. The backend service fetches the JWT and retrieves the required information about the user, application, or token.

+

Claims

+

Claims are fragments of information included in the JWT.

+

The following is a sample claim set added to the end-user token for an access token generated via the authorization code:

+
+

Tip

+

This access token is generated via Asgardeo using the authorization code grant type. Here, the Asgardeo application is configured to include the email claim in the token.

+
+
{
+  "sub": "11f53c32-f8ac-4810-bb79-615b2184baf5",
+  "http://wso2.org/claims/apiname": "JWT Test - Endpoint 9090 803",
+  "http://wso2.org/claims/applicationtier": "Unlimited",
+  "http://wso2.org/claims/version": "1.0.0",
+  "http://wso2.org/claims/keytype": "PRODUCTION",
+  "iss": "wso2.org/products/am",
+  "http://wso2.org/claims/applicationname": "jwtTest2",
+  "http://wso2.org/claims/enduserTenantId": "0",
+  "http://wso2.org/claims/applicationUUId": "45101ccb-865f-4f48-b7ac-18e43b07edd3",
+  "client_id": "IMJB5ZiR1dHQYBdiMIRAGis1WToa",
+  "http://wso2.org/claims/subscriber": "5f4a7105-a889-4f92-9612-eef5bafe4eec",
+  "azp": "IMJB5ZiR1dHQYBdiMIRAGis1WToa",
+  "org_id": "b554e001-761c-4d3a-a7a6-a61d73d34221",
+  "http://wso2.org/claims/tier": "Unlimited",
+  "scope": "email openid profile",
+  "exp": 1690537362,
+  "http://wso2.org/claims/applicationid": "45101ccb-865f-4f48-b7ac-18e43b07edd3",
+  "http://wso2.org/claims/usertype": "Application_User",
+  "org_name": "test",
+  "iat": 1690533762,
+  "email": "testmail@gmail.com",
+  "jti": "69558555-d386-4a81-9ca0-0a23f809cd3c",
+  "http://wso2.org/claims/apicontext": "/b554e001-761c-4d3a-a7a6-a61d73d34221/swog/jwt-test/endpoint-9090-803/1.0.0"
+}
+
+ +

The following table describes the information contained in the sample JWT claims set given above:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Claim NameDescriptionMandatory/Optional
iatThe time the token was issued.Mandatory
jtiThe unique token identifier.Mandatory
expThe token expiry time.Mandatory
issThe issuer of the token.Mandatory
http://wso2.org/claims/apinameThe name of the API in Choreo.Optional
http://wso2.org/claims/versionThe API version.Optional
http://wso2.org/claims/keytypeThe environment in Choreo that the API is in (Development or production).Optional
http://wso2.org/claims/apicontextThe API context in Choreo.Optional
http://wso2.org/claims/subscriberThe subscriber to the API, usually the app developer.Optional
http://wso2.org/claims/applicationnameThe application through which the API invocation is done.Optional
http://wso2.org/claims/applicationidThe ID of the application through which the API invocation is done.Optional
http://wso2.org/claims/applicationUUIdThe UUID of the application.Optional
client_idThe client identifier. This is copied from the original token.Optional
azpThe authorized party (the party to which the ID token was issued). This is copied from the original token.Optional
org_idThe organization ID. This is copied from the original token.Optional
org_nameThe organization name. This is copied from the original token.Optional
http://wso2.org/claims/tierThe tier/price band for the subscription.Optional
scopeThe scope of the token. This is copied from the original token.Optional
http://wso2.org/claims/usertypeThe type of application user whose action invoked the API.Optional
emailThe email address of the user. This is copied from the original token.Optional
+
+

Note

+

The claims that get added to the end-user token can vary depending on the grant type used when generating the access token. For example, if you use the client-credentials grant type to generate the access token, the generated backend JWT would contain the following information:

+
{ 
+  "http://wso2.org/claims/apiname": "DefaultAPI", 
+  "http://wso2.org/claims/version": "1.0.0", 
+  "http://wso2.org/claims/keytype": "PRODUCTION", 
+  "iss": "wso2.org/products/am", 
+  "http://wso2.org/claims/enduserTenantId": "0", 
+  "exp": 1673245727, 
+  "http://wso2.org/claims/usertype": "Application_User", 
+  "iat": 1673242127, 
+  "jti": "6e3f4392-8bd9-4900-9d08-eaab7429c510", 
+  "http://wso2.org/claims/apicontext": "/9e71ab5e-6df5-4727-92d2-80ecf1a6218d/qbky/default/1.0.0" 
+}
+
+ +
+

To verify the authenticity of claims in a JWT, the claims must be validated using the public key corresponding to the private key used to sign the JWT.

+

JSON web key set (JWKS) is a set of keys to validate a JWT. It contains a collection of JSON web keys, which are public keys used to verify the signature of a JWT.

+

Typically, when a third party (such as an identity provider)issues a JWT and the recipient needs to verify its signature, they can use a JWKS. +JWKS allows the issuer to rotate keys dynamically rather than hard-coding the public key in the application. The recipient can obtain the public key by accessing the JWKS endpoint.

+

JWKS support in Choreo to validate the JWT

+

Choreo provides an endpoint to specify the public keys for backend JWT validation. Here are the endpoint URLs for the US East and EU regions:

+ +
+

Note

+

For private data planes (PDPs), use the following JWKS endpoint URL template:

+

https://<PDP_GATEWAY_DOMAIN>/.wellknown/jwks

+

Be sure to replace <PDP-GATEWAY-DOMAIN> with the default domain configured to access the PDP APIs.

+
+

The endpoint provides one or more signing keys to validate the JWT. +The JSON web keys have a kid identifier that can be matched with the same property on the JWT to decide which key to use when validating.

+

The following is a sample JWKS response:

+
{
+   "keys": [
+       {
+           "kty": "RSA",
+           "e": "AQAB",
+           "use": "sig",
+           "kid": "ZjcwNmI2ZDJmNWQ0M2I5YzZiYzJmZmM4YjMwMDFlOTA4MGE3ZWZjZTMzNjU3YWU1MzViYjZkOTkzZjYzOGYyNg",
+           "alg": "RS256",
+           "n": "8vjeHzRhvpfMystncPnLBWy_t5F3eCxbcLbdugWnzfnIgaV6TWnqPBUagJBKpzRZs4A9Qja_ZrSVJjYsbARzCS_qiWp0Cdwkqn6ZCXpmbpfjYnKORq8N8M-zWaSZYbNvWJ5oSO4kH-LKWzODaFebwTJBpsR1vChHH95doxFuUjiZaisVaQgUJ6drRdlDtImp9r9EAX36YROuYFPoEJcvsH4_uuAR6ClJ12RE3M-YN4NTi1waVNvGbz43oNrpPy7SXgpizingxSGMqI6WU2ysRmk_f9ALgiPIpFDpufiCTYaIcRT-YcUyp9nMDlTRskMuD-dQ1sdJOa11P_yMs-glfQ"
+       }
+   ]
+}
+
+ +

The following table describes the information contained in the JWKS response:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
ktyThe cryptographic family to which the key belongs.
Choreo only supports RSA.
eThe exponent value of the public key.
useThe purpose of the key. For example, whether it is for signing or encryption.
kidThe identification parameter to match a specific key.
algThe algorithm to use with the key.
nThe modulus value of the public key.
+

Enable passing end-user attributes to the backend

+

To enable passing end-user attributes to the backend through API calls via Choreo, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Components Listing pane, click on the component for which you want to pass end-user attributes to the backend.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. +

    Go to the Set Up card and click Endpoint Configurations. This opens the Endpoint Configurations pane.

    +
    +

    Note

    +

    If the component is an API Proxy, go to the Build Area card and click Security Settings. This opens the Security Settings pane.

    +
    +
  8. +
  9. +

    Select the Pass Security Context To Backend checkbox.

    +
  10. +
  11. +

    Optionally, specify appropriate audience values in the End User Token Audiences field. Specifying values restricts the JWT to the respective audiences, enabling the backend service to validate and confirm the intended recipients, including itself.

    +
    +

    Note

    +

    The backend JWT does not include the audience field (aud) by default.

    +
    +
  12. +
  13. +

    Click Apply.

    +
  14. +
  15. To redeploy the component with the applied setting, go to the Set Up card and click Deploy.
  16. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/secure-api-access-with-asgardeo/index.html b/authentication-and-authorization/secure-api-access-with-asgardeo/index.html new file mode 100644 index 000000000..2c6ac9830 --- /dev/null +++ b/authentication-and-authorization/secure-api-access-with-asgardeo/index.html @@ -0,0 +1,3654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Secure API Access with Asgardeo - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Secure API Access with Asgardeo

+

API security refers to the measures and practices used to protect Application Programming Interfaces (APIs) from potential threats and vulnerabilities. APIs are essential for enabling communication and data exchange between different software applications and services, making them a critical component in modern software development. However, their openness and accessibility can also make them targets for various security risks. Authentication and authorization are key aspects of API security. Authentication is ensuring that only authorized users or applications can access the API. This can involve using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization is controlling what authenticated users or applications are allowed to do within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

+

Organizations using Asgardeo for identity and access management (IAM) can seamlessly integrate it with Choreo as an external Identity Provider (IdP). This guide will walk you through setting up Choreo to authenticate API invocations through Asgardeo which is configured as an external IdP.

+

This guide walks you through the following steps:

+
    +
  • Assign scopes to an API in Choreo.
  • +
  • Create an API in Asgardeo.
  • +
  • Create an application in Asgardeo and consume the Asgardeo API.
  • +
  • Create an application in Choreo and enable external IdP authentication.
  • +
  • Invoke the API with scopes.
  • +
+

Prerequisites

+

To follow this guide, you need to satisfy the following prerequisites:

+ +

Step 1: Assign scopes to an API in Choreo

+

You can provide fine-grained access control to your API resources with scopes. Follow the steps below to assign a scope to the resources in the API:

+
    +
  1. In the Component Listing pane, click on the component you want to attach scopes to.
  2. +
  3. In the left navigation menu, click Manage and then Permissions.
  4. +
  5. Click + Add Permission (Scope).
  6. +
  7. In the Permission List pane, enter the permission value and click + Add New.
  8. +
  9. Click the copy icon in front of the added scope to copy the fully qualified name of the scope. Save this value for future reference.
  10. +
  11. To attach a scope to a resource, click the Select Permissions list under the respective resource, and select the scopes you wish to attach.
  12. +
  13. Click Save and Deploy.
  14. +
  15. In the left navigation, click Manage and then Lifecycle.
  16. +
  17. Click Publish and continue to publish your API to the Choreo Developer Portal.
  18. +
+

Step 2: Create an API and an application in Asgardeo

+

Follow the Asgardeo API Authorization guide to create an application and an API in Asgardeo and to enable API authorization.

+
+

Note

+
    +
  • Use the fully qualified name of the scope when adding scopes.
  • +
  • Do the following under the protocol tab:
      +
    • Select JWT as the Access Token.
    • +
    • Select the appropriate grant types.
    • +
    • Copy the client ID and client secret of the application for future reference.
    • +
    +
  • +
+
+

Step 3: Create an application in Choreo and enable external IdP authentication

+

Follow the steps below to consume the Choreo API and use an external IdP for authentication:

+
    +
  1. Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.
  2. +
  3. Click Applications. and then click +Create.
  4. +
  5. Enter a name and description for the application.
  6. +
  7. Click Create.
  8. +
  9. In the left navigation, under Credentials and click Production.
  10. +
  11. Select the Identity Provider as Asgardeo.
  12. +
  13. Enter the Client ID you copied in step 2.
  14. +
  15. +

    Click +Add.

    +
    +

    Note

    +
      +
    • You can only use the Client ID in one application.
    • +
    • The Identity Provider dropdown is visible only to organizations where you have configured external IdPs.
    • +
    +
    +
  16. +
  17. +

    In the left navigation menu, click Subscriptions.

    +
  18. +
  19. In the Subscription Management pane that opens, click + Add APIs.
  20. +
  21. Select the API you assigned scopes to in step 1 and click Add.
  22. +
+

Step 4: Invoke the Choreo API with scopes

+
    +
  1. On the Choreo Developer Portal, go to your application.
  2. +
  3. In the left navigation menu, under Credentials and click Production.
  4. +
  5. Under Endpoints, copy the Token Endpoint URL.
  6. +
  7. +

    Obtain an access token by invoking the token endpoint as follows:

    +
    +

    Note

    +
      +
    • If you are using the production credentials, you need to deploy your component(endpoint) to the production environment by promoting it from the development environment.
    • +
    • If you are using the sandbox credentials, you can use the endpoints deployed in the development environment.
    • +
    +
    +
    +
    +
    +
    curl -X POST '<TOKEN_ENDPOINT>?grant_type=password&scope=<REQUIRED_SCOPES>&username=<USER_NAME>&password=<USER_PASSWORD>' \
    + --header 'Content-Type: application/x-www-form-urlencoded' \
    + --header 'Authorization: Basic <BASE64-ENCODED ASGARDEO_APP_CLIENT_ID:ASGARDEO_APP_CLIENT_SECRET>'
    +
    + +
    +
    +
    curl -X POST 'https://dev.api.asgardeo.io/t/orgHandle/oauth2/token?grant_type=password&scope=<REQUIRED_SCOPES>&username=<USER_NAME>&password=<USER_PASSWORD>' \
    +--header 'Content-Type: application/x-www-form-urlencoded' \
    +--header 'Authorization: Basic <BASE64-ENCODED CLIENT_ID:CLIENT_SECRET>'
    +
    + +
    +
    +
    +
  8. +
  9. +

    Once you receive the access token, you can test invoking the resource using the OpenAPI console in Choreo by specifying the scope.

    +
  10. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/secure-api-access-with-azure-ad/index.html b/authentication-and-authorization/secure-api-access-with-azure-ad/index.html new file mode 100644 index 000000000..ee8491e4a --- /dev/null +++ b/authentication-and-authorization/secure-api-access-with-azure-ad/index.html @@ -0,0 +1,3828 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Secure API Access with Azure - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Secure API Access with Microsoft Azure Active Directory (Azure AD)

+

API security refers to the measures and practices used to protect Application Programming Interfaces (APIs) from potential threats and vulnerabilities. Authentication and authorization are key aspects of API security. Authentication is ensuring that only authorized users or applications can access the API. This can involve using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization is controlling what authenticated users or applications are allowed to do within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

+

Organizations using Microsoft Azure AD for identity and access management (IAM) can seamlessly integrate it with Choreo as an external Identity Provider (IdP). This guide will walk you through setting up Choreo to authenticate API invocations through Azure AD which is configured as an external IdP.

+

This guide walks you through the following steps:

+
    +
  • Assign scopes to an API in Choreo.
  • +
  • Create an API in Azure AD.
  • +
  • Create an application in Azure AD and consume the Azure API.
  • +
  • Create an application in Choreo and enable external IdP authentication.
  • +
  • Invoke the API with scopes.
  • +
+

Prerequisites

+

To follow this guide, you need to satisfy the following prerequisites:

+ +

Step 1: Assign scopes to an API in Choreo

+

You can provide fine-grained access control to your API resources with scopes. Follow the steps below to assign a scope to the resources in the API:

+
    +
  1. In the Component Listing pane, click on the component you want to attach scopes to.
  2. +
  3. In the left navigation menu, click Manage and then Permissions.
  4. +
  5. Click + Add Permission (Scope).
  6. +
  7. In the Permission List pane, enter the permission value and click + Add New.
  8. +
  9. Click the copy icon in front of the added scope to copy the fully qualified name of the scope. Save this value for future reference.
  10. +
  11. To attach a scope to a resource, click the Select Permissions list under the respective resource, and select the scopes you wish to attach.
  12. +
  13. Click Save and Deploy.
  14. +
  15. In the left navigation menu, click Manage and then Lifecycle.
  16. +
  17. Click Publish and continue to publish your API to the Choreo Developer Portal.
  18. +
+

Step 2: Create a web API on Azure AD

+

To enable external IdP authentication for APIs, create an API on Azure AD that represents the API on Choreo. Follow the steps below:

+
    +
  1. Sign in to the Azure console.
  2. +
  3. Follow the Azure guide to create a Web API that represents your API on Choreo.
  4. +
  5. In the left navigation menu, under Manage, select Expose an API.
  6. +
  7. Add the default Application ID URI and click Save and Continue.
  8. +
  9. Under Scopes defined by this API, select Add a scope.
  10. +
  11. Enter the fully qualified name as the scope name.
  12. +
  13. Define who can consent. You can alternatively add a scope requiring admin consent.
  14. +
  15. Enter appropriate values and click Add Scope.
  16. +
+

For more information, refer to the Azure documentation:

+ +

Step 2.1: Assign users to the web API

+

You can restrict users to the API as follows:

+
    +
  1. Go to your Azure AD main menu.
  2. +
  3. Under Manage, click on Enterprise Applications. Alternatively, on Microsoft Entra, under Applications, click Enterprise Applications.
  4. +
  5. Select your API.
  6. +
  7. Under Manage, select the Users and groups then select + Add user/group.
  8. +
  9. Select the users and groups and click Select.
  10. +
+

For more information, refer to the Azure documentation: Assign the app to users and groups to restrict access

+

Step 3: Create a client application on Azure AD and invoke the Azure web API

+

To expose the API to application developers, create an application in Azure AD. This application provides you with a client-id and client-secret that your application needs to use to invoke the API.

+

Step 3.1: Create a client application

+

Follow the steps below to create the application:

+
    +
  1. Follow the steps in Register an application on Azure to create an application.
  2. +
  3. +

    Configure the platform settings. Enter your client application's redirect URI in the process.

    +
    +

    Note

    +

    OAuth2 Authorization Grant flow applies to Web Applications.

    +
    +
  4. +
+

Step 3.2: Consume the Azure AD web API from the Azure AD application

+

Once you create the application, select the API and the scopes you want the application to consume. Follow the steps below:

+
    +
  1. Go to Azure Active Directory and then click App registrations.
  2. +
  3. Select your client application (not your web API).
  4. +
  5. In the left navigation menu, click API permissions.
  6. +
  7. Click + Add a permission and select My APIs.
  8. +
  9. Select the API and the required scopes and click Add Permissions.
  10. +
  11. Once you add the scope, click on the scope and copy the scope name and keep it for future reference. Use this as the scope when you invoke the authorize and token endpoint in step 5.
  12. +
+

For more information, refer to the Azure documentation: Add permissions to access your web API

+

Step 3.3: Create secrets for the Azure web application

+

To invoke the application, provide client secrets to the consuming application. Follow the steps below to generate the credentials:

+
    +
  1. In the left navigation menu, click Certificates & Secrets.
  2. +
  3. Click + New client secret.
  4. +
  5. Provide a meaningful description and the required expiration.
  6. +
  7. Click Add.
  8. +
  9. Copy the created Secret ID and Value for future reference.
  10. +
  11. In the left navigation menu, click Overview and open the overview page of the API.
  12. +
  13. Copy the Application (client) ID and save it for future reference.
  14. +
+

For more information, refer to the Azure documentation: Add a Client Secret

+

Step 4: Create an application in Choreo and enable external IdP authentication.

+

Follow the steps below to consume the Choreo API and use an external IdP for authentication:

+
    +
  1. Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.
  2. +
  3. Click Applications. and then click +Create.
  4. +
  5. Enter a name and description for the application.
  6. +
  7. Click Create.
  8. +
  9. In the left navigation menu, under Credentials and click Production.
  10. +
  11. Select your AzureAD (Microsoft) configuration as the Identity Provider.
  12. +
  13. Enter the Application (client) ID you copied in at Step 3.2 as the Client ID.
  14. +
  15. +

    Click +Add.

    +
    +

    Note

    +
      +
    • You can only use the Client ID in one application.
    • +
    • The Identity Provider dropdown is visible only to organizations where you have configured external IdPs.
    • +
    +
    +
  16. +
  17. +

    In the left navigation menu, click Subscriptions.

    +
  18. +
  19. In the Subscription Management pane that opens, click + Add APIs.
  20. +
  21. Select the API you assigned scopes to in step 1 and click Add.
  22. +
+

Step 5: Invoke the API with scopes

+

You can now invoke the Choreo API using the authorization code grant. Choreo will authenticate the user with Azure AD and provide access to the resource.

+
    +
  1. On the Choreo Developer Portal, go to your application.
  2. +
  3. In the left navigation menu, under Credentials and click Production.
  4. +
  5. Under Endpoints, copy the Authorize Endpoint URL.
  6. +
  7. +

    Invoke the authorization endpoint as follows:

    +
    +
    +
    +
    {authorize_url}?client_id={client_id}&redirect_uri={redirect_url}&scope={scopes}&response_mode=query&response_type=code
    +
    + +
    +
    +
    https://login.microsoftonline.com/dd912d48-b0be-401f-b18c-8ca89e9c0b6c/oauth2/authorize?client_id=5eb1de74-e449-4973-a620-52c4dc9157a9&redirect_uri=https://localhost:9000&scope=api://580b40b7-5513-4714-a4e0-8d4e784f7dc6/urn:taylordean:books:books_addt&response_mode=query&response_type=code
    +
    + +
    +
    +
    +
      +
    1. Review the consent in the login screens that prompt and continue.
    2. +
    3. After you log in, you will receive an authorization code in the URL. Copy the authorization code and use it to get an access token from Azure AD by following the next steps.
    4. +
    5. On the Choreo Developer Portal, go to your application.
    6. +
    7. In the left navigation menu, under Credentials and click Production.
    8. +
    9. Under Endpoints, copy the Token Endpoint URL.
    10. +
    11. Invoke the token endpoint as follows:
    12. +
    +
    +
    +
    +
    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
    +{token_endpoint} \
    +-d 'client_id={client_id}' \
    +-d 'scope={scopes}' \
    +-d 'code={authorization_code}' \
    +-d 'redirect_uri={redirect_url}' \
    +-d 'client_secret={The client_secret value you copied from the Azure Application}'
    +-d 'grant_type=authorization_code' \    
    +
    + +
    +
    +
    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
    +https://login.microsoftonline.com/dd912d48-b0be-401f-b18c-8ca89e9c0b6c/oauth2/v2.0/token \
    +-d 'client_id=5eb1de74-e449-4973-a620-52c4dc9157a9' \
    +-d 'scope=api://580b40b7-5513-4714-a4e0-8d4e784f7dc6/urn:taylordean:books:books_add' \
    +-d 'code=0.AXAASC…zZUzKYm18yM_5-SXz1uvRbbGYF7F32hE9zIQFRQY35haD' \
    +-d 'redirect_uri=https://localhost:9000' \
    +-d 'grant_type=authorization_code' \
    +-d 'state=111' \
    +-d 'client_secret=l4Q8Q~4WKiRXYSQZly5E6Ess.fKf__U1yJR3IaMd'
    +
    + +
    +
    +
    +
  8. +
  9. +

    Once you receive the access token, you can test invoking the resource using the OpenAPI console in Choreo by specifying the scope.

    +
  10. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/index.html b/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/index.html new file mode 100644 index 000000000..ede9bc6d7 --- /dev/null +++ b/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/index.html @@ -0,0 +1,3691 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Secure Communication Between the Choreo Gateway and Your Backend with Mutual TLS - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Secure Communication Between the Choreo Gateway and Your Backend with Mutual TLS

+

To establish secure communication between the Choreo Gateway and your backend, you can configure mutual TLS.

+

Mutual TLS authentication involves both the client and server validating each other’s certificates before establishing a connection. The following diagram depicts this scenario:

+

Mutual TLS authentication

+

Configure mutual TLS to establish secure connectivity

+

To establish secure connectivity between the Choreo Gateway and your backend using mutual TLS, you must add the certificate of the backend (server certificate) to Choreo and add the certificate of Choreo (client certificate) as a trusted certificate in the backend.

+

Step 1: Configure the backend certificate

+

Prerequisites

+
    +
  • The endpoint must be protected with TLS.
  • +
  • The public certificate of the backend server should be extracted in PEM format and saved on the disk with the .pem extension.
  • +
+

To configure the backend certificate, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the API proxy for which you want to configure TLS. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  4. +
  5. In the left navigation menu, click Develop and then click Endpoints.
  6. +
  7. On the Endpoints page, click Configure corresponding to the endpoint.
  8. +
  9. Click Upload Endpoint Certificate, and select the certificate file that you extracted in the prerequisites section to add it. This adds the certificate to all the environments as the default certificate for the endpoint. You can override this certificate if necessary when you deploy or promote the API.
  10. +
+

Step 2: Configure mutual TLS with the backend service

+

There are two approaches you can take to configure mutual TLS.

+
    +
  • Generate a key pair with a self-signed certificate from Choreo, download the public certificate, and subsequently add and configure it in the backend.
  • +
  • Upload your own public or private certificate pair to Choreo. Subsequently, add and configure the public certificate of this key pair in your backend.
  • +
+

Follow the step-by-step instructions below depending on how you want to establish mutual TLS with the backend service:

+
+
+
+

When you follow these steps, Choreo generates a key pair with a self-signed certificate. You can attach this key pair to any API proxy created within the same project.

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the API proxy for which you want to generate a key pair. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  4. +
  5. In the left navigation menu, click Develop and then click Endpoints.
  6. +
  7. On the Endpoints page, click Configure corresponding to the endpoint.
  8. +
  9. If your backend does not use a CA-signed certificate and you have not already added the backend certificate, click Upload Endpoint Certificate and add the backend certificate.
  10. +
  11. To enable mutual SSL, turn on the Mutual SSL toggle.
  12. +
  13. Click Add Client Certificate.
  14. +
  15. +

    In the Add Client Certificate Pair dialog, select Generate new key pair and specify a value as the common name for the certificate pair. This value will be used to identify the certificate.

    +

    Generate new key pair

    +
  16. +
  17. +

    Optionally, click Show advanced options to expand the section and specify appropriate values for each of the fields.

    +
  18. +
  19. Click Generate. This generates the certificate and lists it under Existing Certificates.
  20. +
  21. +

    Click the more options icon corresponding to the certificate and then click View and Download.

    +

    View and download certificate

    +

    This opens the certificate for you to view and download.

    +

    Certificate details

    +
  22. +
  23. +

    To download the certificate in PEM format, click Download. You can add this certificate as a trusted certificate in the API backend server.

    +
  24. +
+

Now you can associate the certificate with the API and deploy the API.

+
+
+

Here, you can use your own public certificate and private certificate as client certificates.

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the API proxy for which you want to generate a key pair. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  4. +
  5. In the left navigation menu, click Develop and then click Endpoints.
  6. +
  7. On the Endpoints page, click Configure corresponding to the endpoint.
  8. +
  9. If your backend does not use a CA-signed certificate and you have not already added the backend certificate, click Upload Endpoint Certificate and add the backend certificate.
  10. +
  11. To enable mutual SSL, turn on the Mutual SSL toggle.
  12. +
  13. Click Add Client Certificate.
  14. +
  15. +

    In the Add Client Certificate Pair dialog, select Use my own key pair.

    +

    Use own key pair

    +
  16. +
  17. +

    Upload the private key and public certificate in PEM format or copy and paste the content of the private key and public certificate.

    +
  18. +
  19. Click Add. This generates the certificate and lists it under Existing Certificates.
  20. +
  21. +

    Click the more options icon corresponding to the certificate and then click View and Download.

    +

    View and download certificate

    +

    This opens the certificate for you to view and download.

    +

    Certificate details

    +
  22. +
  23. +

    To download the certificate in PEM format, click Download. You can add this certificate as a trusted certificate in the API backend server.

    +
  24. +
+

Now you can associate the certificate with the API and deploy the API.

+
+
+
+

Step 3: Associate the certificate with the API

+

To associate a certificate with the API, follow the steps given below:

+
    +
  1. On the Endpoints page, go to the Existing Certificates section.
  2. +
  3. +

    Select the certificate you want to associate with the API.

    +

    Associate certificate

    +
  4. +
  5. +

    Click Save.

    +
  6. +
+

Step 4: Deploy the API

+

To deploy the API, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Configure & Deploy.
  4. +
  5. Once the mediation application generation phase is complete, verify the endpoint URL populated for the environment and then click Save & Deploy.
  6. +
+

Once the deployment is complete, you can test the API.

+

Change the certificate for the production environment

+

If the API backend changes depending on the environment, the respective certificate must be updated for each environment.

+

Here, let's take a look at the steps to update the certificate for the production environment:

+
    +
  1. On the Deploy page, go to the Development card and click Promote.
  2. +
  3. In the Configurations pane that opens, click Endpoint Configuration. You will see all applicable certificates listed in the Mutual TLS list.
  4. +
  5. Select the certificate applicable to the production environment and click Promote. This promotes the component to the production environment with the selected certificate.
  6. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend/index.html b/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend/index.html new file mode 100644 index 000000000..321ae8df2 --- /dev/null +++ b/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/authentication-and-authorization/secure-web-applications-with-managed-authentication/index.html b/authentication-and-authorization/secure-web-applications-with-managed-authentication/index.html new file mode 100644 index 000000000..9ac8ab9ef --- /dev/null +++ b/authentication-and-authorization/secure-web-applications-with-managed-authentication/index.html @@ -0,0 +1,3929 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Secure Web Applications with Managed Authentication - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Secure Web Applications with Managed Authentication

+

The managed authentication capability of Choreo simplifies adding authentication and authorization to a single-page web application.

+

As a developer, you can easily set up Choreo's managed authentication to seamlessly integrate authentication into your web application. You just need to enable Choreo’s managed authentication, configure the built-in identity provider, and connect to Choreo without having to deal with the complexities of underlying OIDC/OAuth2.0 protocols.

+

Choreo's managed authentication follows the backend for frontend (BFF) architecture, which is a secure pattern recommended for browser-based applications that utilize OIDC/OAuth2.0 for authentication and authorization. This architecture ensures that OAuth tokens remain secure from browser-side code, making them immune to potential attacks like cross-site scripting (XSS).

+
+

Note

+

Choreo's managed authentication is currently available only for web applications created with React, Angular, or Vue.js buildpacks.

+
+
+

Warning

+

Managed authentication uses the 'SAMESITE' cookie attribute to prevent CSRF attacks. Therefore, it is recommended to use managed authentication with modern browsers that support the 'SAMESITE' attribute.

+
+

Step 1: Set up managed authentication for your web application

+

To secure your web application, you must implement authentication and authorization for it.

+

To easily set up authentication for your web application with Choreo's managed authentication, follow the steps given below. Before you move on to the next section, see Develop Web Applications Locally with Choreo’s Managed Authentication to ensure a seamless authentication experience when developing your web application on your local machine. You can also refer to the sample React app with managed authentication.

+

Step 1.1: Implement the sign-in functionality

+

To allow Choreo to manage the sign-in functionality for your web application, you must implement a sign-in button that redirects users to the /auth/login path on click. You can use the following code snippet or any custom button component from a preferred UI component library:

+
<button onClick={() => {window.location.href="/auth/login"}}>Login</button>
+
+ +

This code snippet works as follows:

+

When a user clicks sign in on your web application, Choreo will redirect the user to the configured identity provider and handle the authentication process, conforming to the OICD/OAuth2.0 protocols. On successful sign-in, Choreo will set the relevant session cookies and redirect the user to the post-sign-in path (default is /). The user can then invoke any Choreo-deployed APIs depending on the permission granted.

+
+

Note

+

Refer to configure the identity provider section for details on configuring an identity provider for the web application.

+
+

Optional: Pass additional query parameters to the identity provider

+

If you want to pass additional query parameters to the identity provider, include them in the /auth/login request. Choreo appends these parameters to the authorize request sent to the identity provider.

+

For example,

+
<button onClick={() => {window.location.href="/auth/login?fidp=myfederatedidp"}}>Login</button>
+
+ +

Step 1.2: Obtain user information claims

+

Choreo's managed authentication allows you to access user information claims that the identity provider returns post-sign-in, either via a cookie or by invoking a GET resource.

+

Obtain user information via the userinfo cookie

+

Upon successful sign-in, Choreo's managed authentication establishes a userinfo cookie that is accessible from the post-sign-in path you configured (by default, set to /). This userinfo cookie, provided by the identity provider, contains encoded user information claims.

+
+

Note

+
    +
  • The userinfo cookie is intentionally set to have a short lifespan of only 2 minutes.
  • +
  • As a developer, you can decide how to utilize the user information that you retrieve. You must securely store the user information because the stored information can also serve as a means to verify the logged-in state of a user.
  • +
  • The following example uses the js-cookie library for cookie parsing. You can use any cookie-parsing library of your choice. 
  • +
+
+

The recommended approach is to retrieve user information from the cookie and subsequently clear the cookie. The following is a sample code snippet that you can include in your post-sign-in path to retrieve user information from the cookie and subsequently clear the cookie:

+
    import Cookies from 'js-cookie';
+
+    // Read userinfo cookie value.
+    const encodedUserInfo = Cookies.get('userinfo')
+
+    // Decode the value. 
+    const userInfo = JSON.parse(atob(encodedUserInfo))
+
+    // Store the value in a preferred browser-based storage if needed.
+
+    // Clear the cookie.
+    Cookies.remove('userinfo', { path: <post-login-path> })
+
+ +

Obtain user information via a GET endpoint

+

Choreo's managed authentication provides the GET endpoint /auth/userinfo in addition to the userinfo cookie that it sets after successful sign-in. You can use this endpoint to query information about users who have signed in. It also serves as a mechanism to check the state of a user who has signed in.

+

The following is an example of a request to this endpoint:

+
const response = await fetch('/auth/userinfo')
+
+ +

If a user has signed in, the server sends a 200 OK response with the user information in JSON format in the response body. However, if the user is not signed in, the server sends a 401 Unauthorized response.

+

Step 1.3: Implement the sign-out functionality

+

To allow Choreo to manage the sign-out functionality of your web application, you can implement a sign-out button to redirect users to the /auth/logout path along with the session_hint cookie value on click. You can use the following code snippet or any custom button component from a preferred UI component library:

+
+

Note

+
    +
  • It is recommended to clear any user information (if stored) at the time of sign-out.
  • +
  • The following example uses the js-cookie library for cookie parsing. You can use any cookie-parsing library of your choice. 
  • +
+
+
<button onClick={async () => {
+    window.location.href = `/auth/logout?session_hint=${Cookies.get('session_hint')}`;
+}}>Logout</button>`
+
+ +

When a user clicks the sign-out button, Choreo will clear the session cookies and redirect the users to the OIDC logout endpoint of the configured identity provider (if available).  

+

Step 1.4: Invoke APIs

+

To invoke Choreo APIs within the same organization as your web application, you can use the relative path /choreo-apis/<api-suffix>, regardless of whether managed authentication is enabled for the web application or not.

+
+

Note

+

To invoke a Choreo API from a web application, you need to create a Connection from the web application to the Choreo API.

+
+

For example, if the API URL is https://2d9ec1f6-2f04-4127-974f-0a3b20e97af5-dev.e1-us-east-azure.choreoapis.dev/rbln/item-service/api-e04/1.0.0, the <api-suffix> would be /rbln/item-service/api-e04/1.0.0. You can invoke the API using the /choreo-apis/rbln/item-service/api-e04/1.0.0 relative path from your single-page application.

+
+

Info

+

To copy the exact service URL of a Connection, you can follow the steps given below: + 1. In the Choreo Console, go to the appropriate web application component. + 2. In the left navigation menu, click Connections under Dependencies. + 3. Click on the required Connection and copy the service URL.

+
+

If you enable Choreo's managed authentication, you don't have to manually add any logic to attach an access token to the API call because Choreo APIs accept the cookies set by Choreo's managed authentication. You can directly invoke the API as follows:

+
    const response = await fetch('/choreo-apis/<api-suffix>')
+
+ +

If Choreo's managed authentication is disabled, you must ensure that your web application attaches a valid access token to the API call.

+

Step 1.5: Handle session expiry

+

When a user session exceeds the configured session expiry time, it automatically expires. A 401 Unauthorized response status code for a Choreo API request from a logged-in user indicates that the session may have expired, requiring the user to re-login.

+

To programmatically handle session expiry and automatically re-login upon receiving a 401 Unauthorized response from a Choreo API, you can encapsulate the request with re-login logic. The following sample code snippet shows how to wrap GET requests:

+
    export const performGet = async (url) => {
+        try {
+            // API call
+            return await fetch('/choreo-apis/<api-suffix>');
+        } catch (error) {
+            if (error instanceof HttpError && error.status === 401) {
+                // Re-login
+                window.location.href = "/auth/login";
+            } else {
+                throw error;
+            }
+        }
+    };
+
+ +

Step 1.6: Set up a custom error page

+

You can set up Choreo's managed authentication to redirect to a customized error page within your web application by defining the error path in the configuration. In the event of an error during a redirection-based process, such as sign in or sign out, Choreo will automatically redirect the user to the designated custom error page.

+
+

Note

+

If you have not configured an error path, Choreo's managed authentication will use its default error page whenever an error occurs.

+
+

Choreo's managed authentication will include the following query parameters in the URL when redirecting to the custom error page:

+ + + + + + + + + + + + + + + + + +
ParameterDescription
codeA short textual error code indicating the error
messageThe description of the error
+

Now have successfully implemented Choreo's managed authentication for your web application. The next step is to enable managed authentication for the component, and subsequently deploy it.

+

Step 2: Enable managed authentication and configure the paths

+

To ensure that your web application functions seamlessly with managed authentication, it is essential to enable managed authentication for your web application component within Choreo.

+

You can enable managed authentication for your web application component at the time you deploy the component.

+
+

Tip

+

Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks.

+
+
    +
  1. Sign in to the Choreo Console. This opens the project home page.
  2. +
  3. In the Component Listing pane, click on the web application for which you want to enable managed authentication.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. In the Set Up card, click Configure & Deploy.
  8. +
  9. Add the necessary configurations for your component if applicable and click Next.
  10. +
  11. Make sure Managed Authentication with Choreo toggle is enabled.
  12. +
  13. +

    Specify appropriate values for the following fields:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescriptionDefault value
    Post Login PathThe relative path that the application will be redirected to on successful sign-in. In your code, you must implement the necessary logic to obtain signed-in user's information from the userinfo cookie set by managed authentication. See Obtain user information via the userinfo cookie section in Obtain user information claims./
    Post Logout PathThe relative path to which Choreo redirects you on successful sign-out./
    Error PathThe relative path to which Choreo redirects you when an error occurs during a redirection-based flow (i.e., sign in or sign out). See Set up a custom error page.Built-in error page
    Session Expiry TimeThe time in minutes after which the user session expires. For a seamless experience, the session expiry value should match the refresh token expiry time of the OIDC application in your identity provider.10080 Minutes (7 Days)
    Additional ScopesAll additional scopes required by the web application. The openid, profile, and email scopes are added by default together with the scopes required to invoke subscribed APIs.none
    +
    +

    Note

    +

    If you need to change these configurations after you deploy the component, you can click Authentication Settings on the Set Up card, make the necessary changes, and deploy the component once again.

    +
    +
  14. +
+

Step 3: Configure the identity provider for the web application

+

You can configure your web application to work with the Choreo built-in identity provider, Asgardeo, or any external identity provider which supports OIDC/OAuth2.0 .

+
+

Note

+

The identity provider configured in this step should contain the users for the web application.

+
+

Click the respective tab for details depending on which identity provider you need to configure:

+
+
+
+

Follow the steps given below to configure the built-in identity provider by generating authentication keys:

+
+

Note

+

Choreo built-in identity provider is configured by default. Therefore, this step is optional.

+
+
    +
  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  6. +
  7. In the Identity Provider list, select Choreo Built-In Identity Provider.
  8. +
  9. +

    Click Generate Secret.

    +
    +

    Note

    +

    If the Regenerate Secret button is shown instead of the Generate Secret button, it indicates that OAuth keys are already generated for the component for the selected environment.

    +
    +
  10. +
+
+

Tip

+

Refer to Configure a User Store with the Built-In Identity Provider for details on adding test users in Choreo built-in identity provider.

+
+
+

Tip

+

If you need to invoke APIs secured with role-based access control, you can test this within Choreo by creating roles for the application and mapping those roles to relevant permissions (scope) and user groups. For more information, see create roles and assign permissions and assign roles to user groups sections in Test Secure API Access with Choreo Built-In Security Token Service.

+
+
+
+

Step 3.1: Create and configure an OIDC/OAuth2.0 application in Asgardeo

+
    +
  1. Sign in to Asgardeo.
  2. +
  3. In the top navigation menu, click the Organization list and select your organization.
  4. +
  5. In the Asgardeo Console left navigation menu, click Applications.
  6. +
  7. Click + New Application.
  8. +
  9. Click Standard-Based Application.
  10. +
  11. Specify a name for the application and select OAuth2.0 OpenID Connect as the protocol.
  12. +
  13. Click Register.
  14. +
  15. +

    Click the Protocol tab and follow these steps:

    +
      +
    1. Select Code and Refresh Token as the Allowed grant types.
    2. +
    3. Specify the following as Authorized redirect URLs:
        +
      • [your-web-application-url]/auth/login/callback
      • +
      • [your-web-application-url]/auth/logout/callback
      • +
      +
    4. +
    5. Specify your web application URL under Allowed origins.
    6. +
    7. In the Access Token section, select JWT as the Token type.
    8. +
    9. +

      Click Update.

      +
      +

      Tip

      +

      If you need to invoke APIs secured with role-based access control, you must create roles in the application and map those roles to relevant permissions (scope). Then those roles should be assigned to user groups. For more information, see the Asgardeo API authorization guide.

      +
      +
    10. +
    11. +

      Copy the Client ID and Client Secret of the application. You will need to use these values in the next step to link the OIDC/OAuth2.0 application to your Choreo component.

      +
    12. +
    +
  16. +
+

Step 3.2: Link the OIDC/OAuth2.0 application to the Choreo web application component

+
    +
  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  6. +
  7. In the Identity Provider list, select Asgardeo - [your-org-name].
  8. +
  9. Paste the Client ID and Client Secret of the OIDC/OAuth2.0 application you created in Asgardeo.
  10. +
  11. Click Add Keys.
  12. +
+
+
+

Step 3.1: Create and configure an OIDC/OAuth2.0 application in the external identity provider

+
    +
  1. Create an OIDC/OAuth2.0 application in your external identity provider.
  2. +
  3. +

    Configure the OIDC/OAuth2.0 application as follows:

    +
      +
    1. Set Code and Refresh Token as allowed grant types.
    2. +
    3. Add the following as authorized redirect URL.
    4. +
    5. Specify the following as authorized redirect URLs:
    6. +
    7. +

      Specify the access token type as JWT.

      +
      +

      Tip

      +

      If you want to invoke APIs secured with role-based access control, you must ensure that users are assigned a role mapping that grants the necessary permission for API invocation. The approach of mapping application roles to users can vary depending on the identity provider.

      +
      +
    8. +
    +
  4. +
+

Step 3.2: Link the OIDC/OAuth2.0 application to the Choreo component

+
    +
  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  6. +
  7. In the Identity Provider list, select your identity provider.
  8. +
  9. Paste the Client ID and Client Secret of the OIDC/OAuth2.0 application you created in your external identity provider.
  10. +
  11. Click Add Keys.
  12. +
+
+
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/index.html b/authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/index.html new file mode 100644 index 000000000..e203a23aa --- /dev/null +++ b/authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/index.html @@ -0,0 +1,3705 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test Secure API Access with Choreo Built-In Security Token Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Test Secure API Access with Choreo Built-In Security Token Service

+

API security can protect APIs from potential threats and vulnerabilities, with authentication and authorization playing key roles. Authentication ensures that only authorized users or applications can access the API. This involves using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization governs the actions permitted for authenticated users or applications within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

+

Choreo simplifies security testing for developers, allowing them to easily test APIs with permissions in non-critical environments. With its integrated security token service, Choreo provides authorization features that generate scopes based on the correlation between scopes, roles, and user groups. Developers can create roles, assign permissions, and set up user-group mappings using Choreo's built-in identity provider (IdP).

+

This guide walks you through the following steps to test the invocation of secured APIs with permissions using Choreo's built-in authorization capability:

+
    +
  • Assign scopes to an API in Choreo.
  • +
  • Create roles and assign permissions in Choreo.
  • +
  • Assign roles to user groups.
  • +
  • Test the API invocation.
      +
    • When Choreo manages the authentication (i.e., managed authentication enabled).
    • +
    • When the application independently handles the authentication (i.e., managed authentication disabled).
    • +
    +
  • +
+

Prerequisites

+

Before you try out this guide, ensure you have set up the following:

+
    +
  • Configure the Choreo built-in identity provider with users. For step-by-step instructions, see Configure a User Store with the Built-In Identity Provider.
  • +
  • Deploy and publish an API via Choreo. If you don't have an existing service in Choreo, you can either develop a service or an API Proxy.
  • +
  • A web application for API subscription. If you don't have an application in Choreo, you must create a web application
  • +
  • Administrator rights in your Choreo organization. You need this access to configure role-group and role-permission mappings.
  • +
+

Step 1: Assign permissions to an API in Choreo

+

You can provide fine-grained access control to your API resources with permissions. Follow the steps below to assign permissions to the resources in the API:

+
    +
  1. Go to https://console.choreo.dev/ and sign in.
  2. +
  3. In the Choreo Console top navigation menu, click the Project list and select the project that contains your component.
  4. +
  5. In the Component Listing pane, click on the component for which you want to attach permissions.
  6. +
  7. In the left navigation menu, click Deploy.
  8. +
  9. On the Deploy page, go to the Set Up card and click Endpoint Configurations. This opens the Endpoint Configurations pane.
  10. +
  11. Go to the Permissions List section and click + Add Permission(Scope).
  12. +
  13. In the Permissions List section, enter a permission value and click + Add New.
  14. +
  15. Click the copy icon in front of the added permission to copy the fully qualified name of it. Save this value for future reference.
  16. +
  17. To attach permissions to a resource, click the Select Permissions list under the respective resource and select the permissions you want to attach.
  18. +
  19. Click Apply.
  20. +
  21. +

    To apply the latest permissions to the deployed component, you must redeploy it. Follow the steps below to redeploy:

    +
      +
    1. Go to the Set Up card and click Configure & Deploy.
    2. +
    3. In the Configurations pane that opens, click Next. This opens the Endpoint Details pane.
    4. +
    5. Click Deploy.
    6. +
    +
  22. +
  23. +

    To publish your API to the Choreo Developer Portal, follow the steps given below:

    +
      +
    1. In the left navigation menu, click Manage and then click Lifecycle.
    2. +
    3. Click Publish.
    4. +
    +
  24. +
+

Step 2: Create roles and assign permissions

+

The permissions assigned to your API need to be associated with roles. Follow the steps below to create roles and assign permissions to the roles.

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the project that contains your component.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. Click the Application Security tab.
  6. +
  7. Click + Role.
  8. +
  9. Specify an appropriate Role Name and Role description.
  10. +
  11. +

    Select the permissions you want to assign to the role, and then click Create.

    +
    +

    Tip

    The permissions(scopes) defined for APIs exposed via components in the project and the permissions(scopes) required by connections created for components in the project are listed here.

    +

    +
    +
  12. +
+

Step 3: Assign roles to user groups

+

You must assign roles to the user groups defined in your Choreo built-in IdP to ensure that authenticated users can obtain access tokens with the required permissions.

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your component.
  2. +
  3. +

    Click the Application Security tab and then click Role Management.

    +
    +

    Tip

    The roles defined within different projects in the organization are listed here.

    +

    +
    +
  4. +
  5. +

    Click Map Groups corresponding to a role that you want to assign to a group.

    +
  6. +
  7. Specify a group name and enter to add it. You can add multiple groups if necessary.
  8. +
  9. Click Save.
  10. +
+

Step 4: Test the API invocation

+

To test an API invocation, you must first create a connection to your API. To do this, you must have a web application created. You can use the web application you created while setting up the prerequisites.

+

To create a connection to the web application, follow the steps given below:

+
    +
  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the project where you created the web application.
  2. +
  3. On the project home page, click the web application listed under Component Listing.
  4. +
  5. In the left navigation menu, click Dependencies and then click Connections.
  6. +
  7. Create a connection to the API you deployed in Step 1.
  8. +
+

Now you can proceed to deploy the web application.

+

When deploying, if your web application is a single-page application (SPA), you have the option to allow Choreo to handle authentication on behalf of the application. This approach eliminates the need to incorporate OAuth protocol-specific logic into your application.

+

Test the invocation when Choreo-managed authentication is enabled

+

If managed authentication is enabled for your web application, Choreo automatically handles obtaining the necessary permission for API invocation. This occurs during the request for access tokens, allowing you to seamlessly invoke the subscribed APIs through your web application without additional intervention.

+
+

Note

+

If you change the permissions of an existing connection or create a new connection with permissions, you must redeploy your web application to ensure proper API invocation with managed authentication.

+
+

Test the invocation when the application manages the authentication

+

If your application manages authentication independently, follow the steps below to generate the necessary OAuth credentials to obtain access tokens:

+
    +
  1. In the left navigation menu, click Settings. This opens the settings of the web application component.
  2. +
  3. Click the Authentication Keys tab.
  4. +
  5. Click on an environment tab depending on the environment for which you want to generate credentials.
  6. +
  7. Select Choreo Built-In Identity Provider as the identity provider.
  8. +
  9. Click to expand Advanced Configurations and make sure the code and refresh grant types are selected. This is required to obtain access tokens with an authorization code grant.
  10. +
  11. Configure the callback URL of the web application to receive the authorization code.
  12. +
  13. Click Update Configurations.
  14. +
  15. Click Regenerate Secret and make a note of the client ID and secret that is generated.
  16. +
  17. Retrieve an access token using the authorization code grant, specifying the necessary OAuth scopes (You can see the endpoint details on the right side).
      +
    • When prompted for authentication, enter the credentials of a user within the built-in identity provider (IdP) who possesses the required assigned groups.
    • +
    • Navigate through the OAuth flow to obtain the JWT access token.
    • +
    +
  18. +
  19. Invoke the subscribed API using the access token.
  20. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-cli/choreo-cli-overview/index.html b/choreo-cli/choreo-cli-overview/index.html new file mode 100644 index 000000000..567ef14a2 --- /dev/null +++ b/choreo-cli/choreo-cli-overview/index.html @@ -0,0 +1,3525 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo CLI Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Command Line Interface (CLI) Overview

+

The Choreo Command Line Interface (CLI) is a command-line tool that helps you easily work with Choreo using commands. By utilizing commands, it significantly improves the development experience for Choreo users. This versatile tool simplifies different stages of the development process, making interactions more efficient and user-friendly.

+

Choreo serves as a comprehensive internal platform-as-a-service. The Choreo CLI serves as a pivotal tool aimed at enhancing its capabilities. With the Choreo CLI, you can leverage the following benefits:

+
    +
  • +

    Streamline Deployment Processes: Choreo CLI simplifies the entire process from creating a component in Choreo, building it, to deploying, testing, and monitoring independent of the language and framework used to implement the component.

    +
  • +
  • +

    Versatile workflow across frameworks: Regardless of your chosen framework, Choreo CLI offers a uniform end-to-end process. Choreo seamlessly integrates with different web application types (SPA, SSR, SSG, or simple static files), services (REST, GraphQL, gRPC), scheduled jobs, manual triggers, API proxies, and more. This versatility enables you to orchestrate a wide range of cloud-native components seamlessly.

    +
  • +
+

Key features of the Choreo CLI

+
    +
  • +

    Create and Manage Resources: Simplify project and component management. You can easily initiate and organize projects in Choreo through simple commands.

    +
  • +
  • +

    Create Builds and Deployments: Simplifies the process of creating builds and deploying components. You can build and promote components to environments easily with simple commands, ensuring a seamless transition from development to deployment.

    +
    +

    Note

    +

    The Choreo CLI currently supports the following component types:

    +
      +
    • Service
    • +
    • Web Application
    • +
    • Webhook
    • +
    • Scheduled Task
    • +
    • Manual Task
    • +
    +
    +
  • +
  • +

    Monitor with Logs : The integrated log functionality in the Choreo CLI allows you to effectively monitor your components. You can access valuable insights into your components behavior and performance directly from the command line.

    +
  • +
+

For troubleshooting tips and answers to frequently asked questions, see the Choreo CLI FAQ.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-cli/get-started-with-the-choreo-cli/index.html b/choreo-cli/get-started-with-the-choreo-cli/index.html new file mode 100644 index 000000000..9ee01a3f5 --- /dev/null +++ b/choreo-cli/get-started-with-the-choreo-cli/index.html @@ -0,0 +1,3884 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get Started with the Choreo CLI - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Get Started with the Choreo CLI

+

This guide walks you through the following sample use case:

+
    +
  • Create a web application
  • +
  • Build the web application
  • +
  • Deploy the web application in the development environment
  • +
  • Promote the web application to the production environment
  • +
+

This guide utilized a simple to-do app built with Next.js and two basic environments: Development and Production.

+

Prerequisites

+

Follow the steps below to install the CLI:

+
    +
  1. +

    Install the Choreo CLI by running the command specific to your operating system:

    +
      +
    • +

      For Linux and Mac OS +

      curl -o- https://cli.choreo.dev/install.sh | bash
      +

      +
    • +
    • +

      For Windows (via PowerShell) +

      iwr https://cli.choreo.dev/install.ps1 -useb | iex
      +

      +
    • +
    +
  2. +
  3. +

    Verify the installation by running the following command:

    +
    choreo --version
    +
    + +
  4. +
+

Step 1: Login to Choreo

+

Run the following command to login to Choreo:

+
choreo login
+
+ +

Follow the instructions on the console to open the link in the browser and login to Choreo.

+

Step 2: Create a project

+

A project in Choreo is a logical group of related components that typically represent a single cloud-native application. A project consists of one or more components.

+

Create a multi-repository project named ‘web-app-project’ by running the following command:

+
choreo create project web-app-project --type=multi-repository
+
+ +

Step 3: Create a Web Application component

+

In Choreo, a component within your project represents a singular unit of work in a cloud-native application. It can be a microservice, API, web application, or job/task. Each component is associated with a directory path in a Git repository containing the source code for the program.

+
+

Note

The Choreo CLI currently supports the following component types:

+
    +
  • Service
  • +
  • Web Application
  • +
  • Webhook
  • +
  • Scheduled Task
  • +
  • Manual Task
  • +
+

+
+
    +
  1. +

    Fork the repository https://github.com/wso2/choreo-sample-todo-list-app. This contains a sample web application that you can use for this guide.

    +
  2. +
  3. +

    To initiate the creation of a Web Application component within your project, use the following command: +This triggers a wizard prompting you to provide details for your Git repository and other configurations for your component.

    +
    choreo create component my-web-app --project=web-app-project --type=webApp
    +
    + +
  4. +
  5. +

    Select the option Enter remote repository URL manually.

    +
  6. +
  7. +

    Enter the following values for the prompts.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Promptvalue
    Configure source repositoryEnter remote repository URL manually
    Remote repository URLYour forked repository
    Branchmain
    Directory.
    Build-packnodejs
    Language Version20.x.x
    Port8080
    +
    +

    Note

    +

    The prompts may vary based on the type of component and the chosen build pack.

    +
    +
  8. +
+

Step 4: View component details

+

To view comprehensive information about the component, including basic details and service endpoint URLs once the services are deployed, you can use the following command:

+
choreo describe component "my-web-app" --project="web-app-project"
+
+ +

Step 5: Build the component

+

You must build the components before deploying them to a specific environment. Execute the following command to trigger the build:

+
choreo create build "my-web-app" --project="web-app-project"
+
+ +

Step 5.1: View build status

+

To check the status of a specific build, run the following command, replacing with the actual build ID obtained from the previous command:

+
+

Note

+

Typically, a build takes approximately 2 to 5 minutes to complete.

+
+
choreo describe build <build-id> --project="web-app-project" --component="my-web-app"
+
+ +

Step 5.2: View build logs

+

Once the build is complete, you can view the build logs for verification or debugging purposes. In the unlikely case, the build encounters any issues, the logs will help you troubleshoot.

+
choreo logs --type=build --project="web-app-project" --component="my-web-app" --deployment-track="main" --build-id=<build_id>
+
+ +

Step 6: Deploy to the Development environment

+

Once the build status indicates successful you can deploy the component in the Development environment by running the following command:

+
choreo create deployment "my-web-app" --env=Development --project="web-app-project" --build-id=<build-id>
+
+ +

Step 6.1: Verify the deployment in the Development environment

+

After deploying the component, you can retrieve the URL of the deployed web application and open the publicly available web page to verify its behavior. Use the following command to retrieve the URL:

+
choreo describe component "my-web-app" --project="web-app-project"
+
+ +

Step 6.2: View runtime logs

+

To observe runtime application logs of the web application in the Development environment, execute the following command:

+
choreo logs --type component-application --component my-web-app --project web-app-project --env Development --follow
+
+ +

Step 7: Deploy to the Production environment

+

Once you verify your application in the Development environment, you can proceed to deploy it to the Production environment with the following command:

+
    +
  • Be sure to substitute with the id obtained after triggering the build.
  • +
+
choreo create deployment "my-web-app" --env=Production --project="web-app-project" --build-id=<build-id>
+
+ +

Step 7.1: Verify the deployment in the Production environment

+

To ensure a successful deployment to the Production environment, retrieve the URL of the deployed web application using the following command:

+
choreo describe component "my-web-app" --project="web-app-project"
+
+ +

Congratulations! You successfully deployed your web application in Choreo using the Choreo CLI.

+

View all CLI functions

+

Discover other functionalities of Choreo by running the following command.

+
choreo --help
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/choreo-marketplace/index.html b/choreo-concepts/choreo-marketplace/index.html new file mode 100644 index 000000000..44d62ac2e --- /dev/null +++ b/choreo-concepts/choreo-marketplace/index.html @@ -0,0 +1,3699 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo Marketplace - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Marketplace

+

The Choreo Marketplace promotes and facilitates reusing and sharing services. It allows you to share all the services deployed in Choreo. +You can easily browse and search available services within the Marketplace and refer to the service definitions, documentation, instructions on how you can use it, etc.

+

Internal Marketplace

+

Discover services

+

The Marketplace includes all services deployed in your organization. This may be a large number of services. Therefore, effective discoverability is desirable.

+

You can use the search or apply various filter criteria to explore the services available.

+ +

The top search bar provides universal searching to find the services. It allows you to search for a text in the following search attributes:

+
    +
  • Name: The service name.
  • +
  • Label: The service labels.
  • +
  • Content: The service content: overview, summary, and documentation.
  • +
  • All: All of the above criteria.
  • +
+

Filter

+

The Choreo Marketplace provides a filtering capability through the left-hand side filter panel. It allows you to filter with the following filter attributes:

+
    +
  • +

    Type: This filter enables you to categorize services based on their type, with two available options: "Internal" and "Third-party". "Internal" refers to services deployed within Choreo, while "Third-party" refers to services running externally to Choreo, independently added to the Marketplace.

    +
  • +
  • +

    Network Visibility: This filter enables you to categorize services based on their network visibility level, with three choices: "Public," "Organization," and "Project". "Public" filters services exposed publicly, "Organization" represents services exposed across the entire organization, and "Project" represents services exposed at the project level.

    +
  • +
+

Explore a service

+

You can click on the service card to open the detailed view of the service. The detailed service page features the service name, summary, version, labels, and service icon as the header.

+

Choreo organizes the service content into four tabs. The four tabs contain information as follows:

+
    +
  • +

    Overview: Choreo displays the service overview provided by the service developer. If the service developer has not provided any content at service creation, this section will be disabled. The service developer can provide the overview content via the Manage → Marketplace section of the component.

    +
  • +
  • +

    API definition: Includes the API definition for the service, extracted from the component.yaml file in the user repository. If an API definition is not provided, this tab will be empty.

    +
    +

    Note

    +

    If you are are currently using the component-config.yaml or endpoints.yaml configuration files, see the respective migration guide for instructions on migrating to the recommended component.yaml configuration file.

    +
    +
  • +
  • +

    How to use: Includes instructions on how to use the selected service. This includes instructions on creating a connection.

    +
  • +
  • +

    Related documents: Includes any additional content the user has provided as documents through the Manage -> Marketplace section of the component.

    +
  • +
+

Add a service to the Choreo Marketplace

+

You can add services to the Marketplace as Choreo services as follows:

+

Add a Choreo service

+

In Choreo, a service exposed through the platform is termed a Choreo service, with each service being identifiable by an endpoint within a Choreo service component. The Marketplace showcases a service for each endpoint within a service component.

+

Upon deployment to the initial environment, services get automatically added to the Marketplace. Choreo effortlessly collects essential details such as component name, endpoint name, description, and service definitions during this deployment, utilizing them to generate the corresponding service entries in the Marketplace.

+

The service name follows the convention of component name - endpoint name, while all other details remain unchanged.

+

Service versioning in the Choreo Marketplace

+

In the Choreo Marketplace, service versions are displayed in their major version format. Each service in the Choreo Marketplace represents the latest version of the service within its major version, following semantic versioning principles.

+

For example, if a Choreo service has versions v1.0, v1.1, v1.2, and v2.0, the Choreo Marketplace displays services with versions v1 and v2 representing the latest versions v1.2 and v2.0 respectively.

+

When you deploy a new minor version of a service already deployed in Choreo, the corresponding service in the marketplace automatically updates to reflect the latest version within the same major version.

+

Semantic-version-based intelligent routing in the Choreo Marketplace

+

When you use a service from the Choreo marketplace as a dependency, the dependent service's traffic automatically routes to the latest version of the corresponding service within the same major version. This ensures that your dependencies remain up-to-date without requiring manual updates within a major version.

+

For example, if you create a connection to connect your Choreo component named Foo to a Choreo service named Bar, which is currently available in the Choreo Marketplace as version v1, and if the latest version of the service Bar within the v1 range is v1.2, the component Foo will automatically connect to Bar v1.2. Subsequently, when Bar releases version v1.3, traffic from Foo will automatically route to Bar v1.3.

+

Edit services in the Choreo Marketplace

+

You can edit services in the Choreo Marketplace. During redeployment to any environment, Choreo automatically updates service definitions, visibility, and descriptions.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/ci-cd/index.html b/choreo-concepts/ci-cd/index.html new file mode 100644 index 000000000..5b169f41c --- /dev/null +++ b/choreo-concepts/ci-cd/index.html @@ -0,0 +1,3771 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + CI/CD - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

CI/CD

+

Choreo provides a streamlined continuous integration and continuous deployment(CI/CD) experience to deploy applications and services efficiently across multiple environments.

+

Choreo creates environments for each project, where all components within the project share the environments. An environment is an isolated deployment area with restricted network and resource access. Services deployed in one environment cannot communicate with services deployed in another.

+

The Choreo cloud data plane provides two default environments (i.e., development and production). However, if you are in a private data plane organization, you can customize and create multiple environments based on your requirements.

+

Choreo adopts a build once, deploy many strategy to manage components across multiple environments. An application is built only once (i.e., per commit if automatic build on commit is enabled or based on the selected commit during a manual build). Then it is promoted to subsequent environments. This allows testing changes in lower, non-production environments like development before promoting the build to production.

+

Choreo injects configurations and secrets that you maintain at the environment level into components at runtime. This ensures a strict separation of environment-specific configurations from source code. Although configurations can vary across environments, the code and the built container remain unchanged. Configurations and secrets include:

+
    +
  • Resource credentials to a database, cache, or other backing services.
  • +
  • Credentials to external cloud services such as Amazon S3 or external APIs.
  • +
+

All configurations and secrets are encrypted at rest and in transit and stored in a secure vault. In a private data plane organization, you can store configurations and secrets in your infrastructure.

+

Build

+

Choreo auto-generates build pipelines that may slightly differ depending on the component type you create. Generally, all build pipelines work as follows:

+
    +
  • Builds a container image either from the provided source code or from a given Dockerfile for a specific commit.
  • +
  • Runs security and vulnerability scans if applicable, depending on the component type.
  • +
  • Pushes the container image to a container registry. In the cloud data plane, Choreo pushes the image to a Choreo-managed registry. If it is a private data plane organization, Choreo pushes the image to a registry that you own.
  • +
  • Updates service endpoints and API specifications from the provided repository if applicable.
  • +
+

Repeatable builds

+

Choreo can replicate builds from an identical code version (Git commit). This means that multiple builds initiated from the same Git commit will generate Docker images with the same behavior.

+
+

Note

+

In the event of multiple builds from the same code version, Choreo preserves only the most recent version of the Docker image created from the particular code version.

+
+

Trigger a build

+

On the Build page, click Build Latest. If necessary you have the option to select a particular commit and build an image.

+

If you want to automatically trigger a build with each commit, you can enable Auto Build on Commit.

+

Build logs

+

You can view build logs for specific builds on the Build page.

+

To view details of a specific build, click View Details corresponding to the build.

+

Deployment

+

Once you build an image in Choreo, you can deploy it via the Deploy page. To deploy an image, you can follow one of the approaches given below:

+
    +
  • +

    Manually deploy: In the Deploy page, go to the Set Up card and click Deploy.

    +
  • +
  • +

    Automatically deploy on build: In the Deploy page, go to Set Up card and enable Auto Deploy on Build. This automatically initiates deployment upon the completion of an automatic build.

    +
  • +
+
+

Info

+

To enable Auto Deploy on Build, you must enable Auto Build on Commit. This is because automatic deployment is not necessary or useful in scenarios where automatic build is not enabled.

+
+
+

Note

+
    +
  • You must trigger the first build in a Ballerina component manually to ensure that Choreo applies the required configurations to the development environment. You can enable automatic builds subsequently.
  • +
  • Choreo automatically checks the configurable defined in your source code against the configurable values applied in an environment. Choreo requests the configurable values on deployment and promotion. If you have changed the configurables in your Ballerina component, auto-build pipelines can fail as a precaution to avoid a component crash at runtime due to missing configurables.
  • +
  • The configurable verifying capability is only available for Ballerina components. For Dockerfile-based components, ensure to manage and update the configurations and secrets in environments ahead of time. You must also ensure backward compatibility between at least one release if you change the configurations.
  • +
+
+

Set up area and initial deployment

+

In the deploy phase, Choreo uses a setup area to merge the Docker image with its environment-independent configurations. Choreo then deploys this composite to the environment. This is known as the initial deployment.

+

Immutable deployments

+

Once Choreo deploys a component with configurations, the configurations become immutable. Any subsequent change results in a new deployment.

+

Promote a component to a higher environment

+

Choreo builds a container once per GitHub commit and then promotes it to subsequent higher environments.

+

You can go to the Deploy page of a component and promote it manually across environments.

+

Configurations

+

Choreo allows you to define both environment-independent configurations and environment-specific configurations.

+

Environment-independent configurations

+

These configurations apply to all environments.

+

To change environment-independent configurations, go to the Deploy page of the component, make the necessary configuration changes via the Set Up card, and then trigger a new deployment to the initial environment. From there, you can proceed to promote the component to higher environments.

+

Environment-specific configurations

+

These configurations apply to a particular environment.

+

To change environment-specific configurations, go to the Deploy page of the component, make the necessary configuration changes via the specific environment card, and trigger a new deployment.

+

To learn more about managing these configurations, see Configuration Management.

+

Task execution

+

The information on the Execute page is only applicable to scheduled and manual task components.

+

To track and monitor executions associated with a deployed scheduled task or manual task, go to the left navigation menu and click Execute.

+

You can view current and historic execution details along with a quick snapshot of recent activity via the total count of executions within the last 30 days. For each execution, you can view vital details such as the unique execution ID, the time it was triggered, and relevant revision information. Furthermore, you can dive deeper into the details by clicking on a specific execution to access its associated logs. This information enhances transparency, troubleshooting capabilities, and overall execution management, allowing you to easily monitor and analyze workflows.

+

Zero-downtime deployments

+

Choreo performs rolling updates to ensure zero downtime between deployments and promotions.

+

A new build undergoes a health check before traffic is switched to it from the current build.

+

If you configure the necessary health checks for a component, it can prevent deploying and promoting unhealthy versions of a component.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/component/index.html b/choreo-concepts/component/index.html new file mode 100644 index 000000000..a660fbfd3 --- /dev/null +++ b/choreo-concepts/component/index.html @@ -0,0 +1,3447 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Component - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Component

+

A component within a project represents a single unit of work in a cloud native application. A component is usually a single microservice, API, or job/task. Each component in Choreo is attached to a given directory path in a Git repository which either contains program source code or a Dockerfile with build instructions. A component is Choreo’s unit of deployment. Each component maps to a single pod in the Kubernetes cluster (data plane) at deployment time. Therefore, you can deploy, manage, and scale each component in Choreo independently.

+

Choreo supports different component types for various use cases. These include component types such as services, API proxies, integrations, web applications, and so on. Each component type hosts unique features based on its characteristics. For example, a scheduled integration component can accept a cron expression as a configuration to schedule an integration job/task.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/configuration-management/index.html b/choreo-concepts/configuration-management/index.html new file mode 100644 index 000000000..7d2e23452 --- /dev/null +++ b/choreo-concepts/configuration-management/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/choreo-concepts/connections/index.html b/choreo-concepts/connections/index.html new file mode 100644 index 000000000..c5710fd03 --- /dev/null +++ b/choreo-concepts/connections/index.html @@ -0,0 +1,3518 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Connections - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Connections

+

Services can exist in two main forms: standalone and integrated. Connecting services is an integral part in creating integrated solutions. Choreo allows you to connect services using Connections.

+

Using Connections, you can integrate the service you intend to deploy on Choreo with other services on Choreo or external resources. Upon creating a connection to a service on Choreo, Choreo provides you a Connection ID along with a set of connection parameters. Thereafter, you have the capability to configure your service to establish a connection using this Connection ID and map connection parameters to environment variable names in your Choreo component. You can read these environment variable names in your service implementation to retrieve the values, to create a programmatic connection to the service you want to consume.

+

At runtime, Choreo dynamically injects values into the environment variables based on the configured mapping. This approach ensures that the connection parameter values and the service connection creation remain loosely coupled, providing developers with flexibility and ease of maintenance.

+

You can add Connections in different visibility levels: Project and Component. The visibility levels are described below:

+

Project Connections

+

Project Connections are Connections you create to connect to services within a particular project. The Connections can be used by any component within the project.

+

For example, if you want to share a third-party service like Twilio across the project for all the components within that project to reuse, you can create a project connection. Components can refer to Project Connections using the connection ID. +Project connections created to consume Choreo services under the OAuth security scheme will share the same OAuth application across the project. Any component reusing such a connection will use the same client ID and client secret.

+

Component Connections

+

Component Connections are Connections you define at the component level and used by only that component.

+

For example, create a component connection if you want to connect a legacy service to a given component. Components can refer to the Component Connection using the connection ID. +If your component consumes more than one Choreo service, the Component connections created to consume those Choreo services under the OAuth security scheme can share the same OAuth application by sharing the same client ID and secret between all such connections.

+

Learn how you can share and reuse services using connections in Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/data-planes/index.html b/choreo-concepts/data-planes/index.html new file mode 100644 index 000000000..7f552c2cc --- /dev/null +++ b/choreo-concepts/data-planes/index.html @@ -0,0 +1,3715 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Data Planes - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Data Planes

+

Choreo's architecture comprises two key components: the control plane and the data plane. The control plane handles essential tasks such as administering organizations, users, and projects. In addition, it also governs the entire journey of application development, from the initial stages of creation, progressing to deployment, including measures to enforce governance and the provision for observability. The Choreo control plane is a SaaS that manages all cloud data planes and private data planes. It caters to diverse user personas, including CIOs, architects, and developers, as well as DevOps, site reliability engineers, and platform engineers.

+

The data plane is the environment where user applications are deployed based on configurations set in the control plane. These applications can range from services and web applications to APIs, integrations, and scheduled tasks. The applications can be written in various programming languages, allowing for a polyglot approach. Importantly, all traffic related to the runtime of user applications is restricted to the Choreo data plane, ensuring strict containment of user data within its boundaries.

+

Choreo's architecture features two distinct data plane types: cloud data planes and private data planes. A cloud data plane utilizes a multi-tenanted infrastructure model for deploying user applications, creating a shared yet secure environment for application runtime. In contrast, a private data plane(PDP) provides dedicated infrastructure for a single organization to run its user applications. This ensures an added layer of privacy and control for organizations with specific requirements.

+

Choreo high-level view

+

Private data planes

+

Infrastructure

+

Choreo private data planes can be deployed with almost all major cloud providers, such as Azure, AWS, and GCP, and are also compatible with on-premises infrastructure.

+

The essential requirements for a private data plane include upstream-compatible Kubernetes clusters, a container registry, a key vault (secret store), and a logging service or log storage.

+

Private data plane architecture

+

System components

+

Setting up the Choreo PDP system involves using a Helm installation on the Kubernetes infrastructure. +The following software components are installed during the helm execution:

+
    +
  • Cilium CNI and service mesh.
  • +
  • Choreo API Gateways and related components.
  • +
  • Choreo PDP agent.
  • +
  • Observability and logging APIs, along with observability agents.
  • +
  • Flux controller.
  • +
+

All of these software components receive automatic updates, including security patches and bug fixes through the flux controller connected to the Choreo Update Management System.

+

Connectivity with the control plane

+

The private data plane requires communication with the Choreo control plane to manage various activities. All these communications are outbound from the private data plane, ensuring that there is no need to open any specific IP:Port from its perspective for these interactions. However, if an organization's network restricts all outbound traffic, it is necessary to permit outbound traffic to the public IP range of the Choreo control plane.

+

The following table outlines the inbound and outbound connections from a private data plane:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Data plane componentEndpointDirectionProtocol
Choreo PDP agentChoreo control plane (CP) (mizzen server)OutboundWSS
Kubernetes API serverOutbound (cluster internal)HTTPS, WS
APIM/local adaptorGlobal adaptorOutboundHTTPS
Azure Service Bus (CP)OutboundAMQP
APIM/EnforcerEvent hub (CP)OutboundAMQP
Choreo secret resolverCloud secret storeOutbound (VPC internal)HTTPS
Container registryContainer registry (public)InboundHTTPS
Container registryOutbound (VPC internal)HTTPS
Certificate managerAzure DNS serviceOutboundHTTPS
LetsEncryptOutboundHTTPS
Flux source controllerGitHubOutboundHTTPS
Flux Helm controllerChoreo container registryOutboundHTTPS
+ +

All communication between the control plane and the private data plane is secured using TLS.

+

Observability architecture

+

The following diagram depicts the architecture overview of Choreo's in-data-plane log and observability in Azure PDP:

+

Observability architecture

+

The private data plane observability architecture is centered around a strong commitment to data privacy and compliance. This is achieved through a strategic decision to retain logs and observability data within the data planes itself. Key aspects of this architecture include:

+
    +
  • Data storage at source: Logs and observability data are stored within the data plane itself, enhancing security, simplifying access, and ensuring compliance.
  • +
  • Direct browser-to-data-plane interaction: The Choreo Console in the user's browser directly interacts with APIs in the data plane, reducing potential data routing complexities and ensuring a more secure, direct flow of information.
  • +
  • Reduced data exposure points: Fetching data directly from the data plane's APIs minimizes the number of data transfer points, effectively decreasing the chances of data exposure or interception.
  • +
  • Compliance with regulatory standards: The architecture supports data locality, aligning with global regulatory standards like GDPR and CCPA by keeping data in its original environment.
  • +
  • Improved performance and real-time insights: Direct interaction between the browser and data plane results in faster data retrieval, providing users with immediate insights.
  • +
  • User transparency and control: Users have a clear view of their data's location and access methods, alongside granular control over data access.
  • +
+

Security

+

The Choreo private data plane ensures extensive, production-grade security, ranging from infrastructure and architecture to zero-trust network security. All incoming traffic is protected by a firewall and must undergo authentication and authorization via the API Gateway. It also provides end-to-end network traffic encryption using Cilium transparent encryption, ensuring efficient data path encryption.

+

For details on the private data plane security levels supported in Choreo pricing plans, see Private Data Plane Security Levels.

+

Management models

+

Choreo supports the following management models for private data planes (PDPs), fostering collaboration between WSO2 and customers across diverse scenarios:

+
    +
  • WSO2 fully managed (infrastructure and PDP in WSO2 subscription) model
  • +
  • WSO2 fully managed (infrastructure and PDP in customer subscription) model
  • +
  • Customer self-managed (WSO2 provides installation script and updates) model
  • +
+

To explore each management model in detail so that you can make informed decisions depending on the supported cloud-based operations and security, see Private Data Plane Management Models.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/deployment-tracks/index.html b/choreo-concepts/deployment-tracks/index.html new file mode 100644 index 000000000..67b8c7d41 --- /dev/null +++ b/choreo-concepts/deployment-tracks/index.html @@ -0,0 +1,3594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deployment Tracks - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deployment Tracks

+

Deployment Tracks in Choreo are structured pathways for simplified software component deployment. They act like advanced CI/CD pipelines, ensuring your components reach their destinations seamlessly, whether from source code or prebuilt images. They establish an organized and structured approach that minimizes the chances of errors and challenges that are typically associated with deployment workflows.

+

The significance of Deployment Tracks

+

Deployment Tracks offer practical solutions to enhance the API consumer experience by addressing two critical challenges:

+
    +
  • +

    Streamlined deployment: Deployment Tracks serve as well-designed routes for your software components, enhancing the organization and reliability of the deployment process, similar to a well-structured express route.

    +
  • +
  • +

    Efficient API versioning: Especially beneficial for managed APIs, Deployment Tracks provide a straightforward method for creating API versions that seamlessly interact with previous iterations. This simplified version management benefits both API creators and consumers alike.

    +
  • +
+

Streamlined deployments

+

For streamlined deployments, Choreo dissects two integral approaches that leverage Deployment Tracks: the comprehensive CI/CD integration and the focused CD-Only strategy.

+

CI/CD with Deployment Tracks

+

A deployment track is linked to a particular branch within a GitHub repository. This connection is useful for handling deployments to various environments. On Choreo's Deploy page, you can easily visualize the deployments to specific environments associated with your selected deployment track. Moreover, the deployment track has a functionality that initiates automatic deployments for the linked branch. When activated, merging a pull request (PR) triggers a deployment to the development environment.

+

Deployment tracks - source repo

+

CD-Only strategy with Deployment Tracks

+

If you're inclined to use your own Continuous Integration (CI) systems and want to harness the deployment track as a Continuous Deployment (CD) pipeline, you can seamlessly link deployment tracks to a container registry repository. This configuration empowers users to effortlessly deploy images sourced directly from the linked container registry repository.

+

Deployment tracks - container registry

+

Efficient API versioning

+

This section applies to only service components. When working with service components in Choreo, it is important to have an effective API versioning mechanism. Choreo follows a versioning mechanism based on Semantic Versioning (SemVer) but only includes the major version and minor version with the prefix v.

+

For example, v1.2.

+

You can follow the approach given below when you version APIs in Choreo:

+
    +
  • Increment the major version when you make incompatible API changes.
  • +
  • Increment the minor version when you add functionality in a backward-compatible manner.
  • +
+
+

What is Semantic Versioning?

+

Semantic Versioning (SemVer) is a specification that defines how to assign and increment version numbers for software products, including APIs. For more information, see Semantic Versioning specification.

+
+

One of the primary concerns when dealing with SaaS APIs is to minimize disruption for API consumers while continuously developing and deploying updates.

+

In compliance with SemVer, changes that don't introduce breaking or additive modifications to the API are categorized as patch updates. Hover, from the perspective of API consumers, these changes should ideally not disrupt their API clients. Typically, API consumers are most concerned with major API version alterations, but there might be instances where minor version changes are communicated to them.

+

Therefore, in the context of deployment tracks, API developers only need to specify the major and minor versions being delivered from a particular deployment track. This information is treated as the API version attribute of a deployment track. If the publisher requires versioning for internal tracking purposes, this can be accomplished in Git through the use of Git tags, on GitHub with GitHub releases, and so forth.

+

Deployment tracks - api versioning

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/endpoint/index.html b/choreo-concepts/endpoint/index.html new file mode 100644 index 000000000..46c0ab92b --- /dev/null +++ b/choreo-concepts/endpoint/index.html @@ -0,0 +1,3448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Endpoint - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Endpoint

+

An Endpoint is a network-exposed function that resides within a component. In Choreo, service and integration components expose one or more endpoints. Each endpoint in a component can have a service contract (OpenAPI, GraphQL SDL) associated with it. This contract is used to expose the endpoint to consumers. In the absence of a contract, Choreo uses /* exposed on all HTTP verbs as the default contract to expose the service or the integration.

+

Each endpoint exposed in a component is considered a single API. Therefore, Choreo allows you to do API management per endpoint for a given component. For example, you can perform lifecycle management and configure security settings per endpoint in a given component.

+

See Configure Endpoints to learn how to configure endpoints when developing components in Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/environments/index.html b/choreo-concepts/environments/index.html new file mode 100644 index 000000000..78752b421 --- /dev/null +++ b/choreo-concepts/environments/index.html @@ -0,0 +1,3449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Environments - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Environments

+

Choreo offers developers one or more environments to run their applications within a given data plane. By default, the Choreo cloud data plane provides two environments (i.e., development and production). Each project in Choreo is associated with one or more environments available in the organization. For example, project A may choose to utilize dev, staging, and production environments, while project B may only use development and production environments.

+

You can promote components within a project across available environments. When you promote a component, its configuration values can be overridden with environment-specific values.

+

The following diagram illustrates how a component is promoted across environments.

+

Choreo environments

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/organization/index.html b/choreo-concepts/organization/index.html new file mode 100644 index 000000000..17b0c43ec --- /dev/null +++ b/choreo-concepts/organization/index.html @@ -0,0 +1,3636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Organization - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Organization

+

An organization in Choreo is a logical grouping of users and user resources. A first-time user must create an organization and be a member of it when signing in to Choreo. Users and resources in an organization cannot access resources in another organization unless an admin of the other organization invites them and adds them as a member of that organization. A user cannot create more than one organization.

+

Switch organizations

+

If you are a member of more than one organization, you can switch from one organization to another when necessary. To do this, select the required organization from the Organization list in the Choreo Console header.

+

Inviting users

+

An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

+

Manage user permission

+

Choreo manages user permissions with groups and roles.

+

Groups

+

A group in Choreo is a collection of users, each with one or more roles assigned to them. Users within a group inherit the permissions associated with the roles assigned to that group. For instance, if a user is added to the API Publisher group, they will automatically receive the API Publisher role.

+

Choreo comes with predefined groups already configured with specific roles, as follows:

+
    +
  • API Publisher: A collection of users who have the API Publisher role.
  • +
  • API Subscriber: A collection of users who have the API Subscriber role.
  • +
  • Admin : A collection of users who have the Admin role.
  • +
  • Billing Admin : A collection of users who have the Billing Admin role.
  • +
  • Choreo DevOps : A collection of users who have the Choreo DevOps role.
  • +
  • Developer : Users who develop, deploy, and manage cloud native applications at scale.
  • +
  • External API Subscriber: A collection of users who have the External API Subscriber role.
  • +
+

When creating a new group to invite members, be sure to assign a role to the group to ensure users have the required permissions.

+

Roles

+

Choreo roles are defined as follows:

+
    +
  • API Publisher: An API publisher can discover, create, publish, delete, test, and manage an API.
  • +
  • API Subscriber: An API subscriber is a developer in a particular organization. An API subscriber can subscribe to an application, manage subscriptions, manage applications, generate API keys, and manage API keys.
  • +
  • Admin: An administrator is responsible for all administration tasks, including user management, customizing the Developer Portal, managing projects, enabling analytics, managing domains, etc.
  • +
  • Billing Admin: Is responsible for billing administration that includes viewing tiers, creating and viewing organizations, managing invoices, viewing and creating subscriptions, and viewing and creating payment methods.
  • +
  • Choreo DevOps: A Choreo DevOps user is a user with access to the Choreo DevOps portal, enabling them to actively manage, ensure dependable deployment, and monitor components.
  • +
  • Developer : A user who can develop, deploy, and manage cloud native applications at scale.
  • +
  • External API subscriber: External API subscribers are API consumers who have access only to the API Developer Portal. They can join an organization with the sole purpose of consuming APIs.
  • +
  • Environment Manager (Deprecated): Manages deployment environments.
  • +
+

Organization ID

+

The Organization ID serves as a unique identifier for each organization. To get the organization ID, follow the steps below:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. Click on the Organization list on the header and select your organization.
  4. +
  5. In the left navigation, click Settings.
  6. +
  7. In the header, click the Organization list. This will open the organization level settings page.
  8. +
  9. Under Organization click Copy ID.
  10. +
+

Organization Handle

+

The organization handle is a unique string that directly corresponds to your organization's name. To get the organization handle, follow the steps below:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. Click on the Organization list on the header and select your organization.
  4. +
  5. In the left navigation, click Settings.
  6. +
  7. Under Organization click Copy Handle.
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/project/index.html b/choreo-concepts/project/index.html new file mode 100644 index 000000000..08f7a84c9 --- /dev/null +++ b/choreo-concepts/project/index.html @@ -0,0 +1,3448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Project - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Project

+

A project in Choreo is a logical group of related components that typically represent a single cloud native application. A project consists of one or more components. All components within a project can ideally be (but is not restricted to) in a single GitHub repository under different paths. This is also known as the monorepo architecture.

+

At deployment time, all components within a given project are deployed into a single namespace of the Kubernetes cluster. Components within a project can be exposed to the public internet, internally to the rest of the organization, or privately within the project only. A project in Choreo is represented as a cell with regard to the Cell-based architecture. The following diagram illustrates a project and how the components within a project are laid out at runtime:

+

Project

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/choreo-concepts/resource-hierarchy/index.html b/choreo-concepts/resource-hierarchy/index.html new file mode 100644 index 000000000..06b954982 --- /dev/null +++ b/choreo-concepts/resource-hierarchy/index.html @@ -0,0 +1,3534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Resource Hierarchy - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Resource Hierarchy

+

The following diagram depicts the high-level resources and their relationships in Choreo.

+

Resource hierarchy

+

Organizations and data planes

+

Data planes are connected to the organization and are available for all the projects in the organization. When you create an environment in a project, the data plane connected to the organization is linked with an automatically generated Kubernetes namespace.

+

Environments and data planes

+

Choreo allows multiple Kubernetes clusters to be associated with an environment.

+

This allows you to build highly resilient and resource-efficient solutions that utilize multiple clusters. Choreo synchronizes your applications and workloads between associated clusters in an environment. This allows you to perform multi-cluster deployment with a single click.

+

The following diagram depicts how multiple clusters associate with different environments:

+

Environments and dataplanes

+
+

Note

+

It is not necessary to use a different cluster per environment. You can create multiple environments on the same cluster. The above diagram is only an example of a specific solution. Your application architecture may require an entirely different configuration than what is depicted in the diagram.

+
+

Components and environments

+

Components belong to a project in Choreo and environments are provisioned per project as well. When a component is deployed, it is deployed as a container to the specified environment. Once deployed, you can promote the container image across the environments available in the project.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consume/developer-portal/index.html b/consume/developer-portal/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/consume/developer-portal/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/consume/manage-application/index.html b/consume/manage-application/index.html new file mode 100644 index 000000000..c0c68be13 --- /dev/null +++ b/consume/manage-application/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/consume/manage-subscription/index.html b/consume/manage-subscription/index.html new file mode 100644 index 000000000..9b12fc49f --- /dev/null +++ b/consume/manage-subscription/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/consume/test-api/index.html b/consume/test-api/index.html new file mode 100644 index 000000000..5c4fb5a46 --- /dev/null +++ b/consume/test-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/consuming-services/consuming-a-sevice/index.html b/consuming-services/consuming-a-sevice/index.html new file mode 100644 index 000000000..e4ede367f --- /dev/null +++ b/consuming-services/consuming-a-sevice/index.html @@ -0,0 +1,3984 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Consume a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Consume a Service

+

Choreo is a platform that allows you to create, deploy, and consume services seamlessly. The Choreo Developer Portal simplifies discovering and using APIs for API consumers.

+

Typically, an application developer who may be internal or external to your organization would want to consume the APIs published in the Developer Portal to develop their applications. In this guide, you will learn how to discover, generate credentials, and test the consumption of a service published in the Choreo Developer Portal. You will also learn how to invoke the service via a web application.

+

This guide walks you through the following steps:

+
    +
  • Create an application in the Developer Portal and generate credentials for the application.
  • +
  • Subscribe the API to the application.
  • +
  • Consume a published REST API via your web application.
  • +
+

Prerequisites

+

Before you try out this guide, if you do not have a published service that you would want to consume via the Developer Portal, follow Develop a Service documentation to publish and deploy a sample REST API.

+

Discover APIs

+

In the Choreo Developer Portal, developers can use the search option to find APIs by name. The APIs and services that are created and published through the Choreo Console become visible in the Developer Portal depending on the API's visibility as follows:

+
    +
  • +

    Public: The API is visible to all in the developer portal.

    +
  • +
  • +

    Private: The API is visible to the users who only sign in to the Developer Portal.

    +
  • +
  • +

    Restricted: The API is visible to only the user that has the roles that you specify. This option helps developers to enforce fine-grained access control to the API.

    +
  • +
+

To learn more about API visibility, see Control API Visibility.

+

The Choreo Developer Portal lists APIs based on their major version.

+

Developer Portal APIs

+

The overview page of an API displays the subscribed versions of the API along with the respective subscription details such as the subscribed application and the application creation date.

+

API overview

+
+

Tip

+

If you want to use an API, the recommended approach is to use the latest version of it. You can copy the major version pattern provided as the value of Endpoints(s) on the API overview page and use it in your client application. This ensures that your application always invokes the latest API version.

+
+

Create an application

+

An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

+

This section walks you through the steps to create an application in Choreo.

+

Let's get started!

+

Step 1: Create an application

+

To create an application in the Choreo Developer Portal, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. Click Applications. and then click +Create.
  4. +
  5. Enter a name and description for the application.
  6. +
  7. Click Create.
  8. +
+

This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

+

Step 2: Generate keys

+

Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

+

Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

+

The following section walks you through the steps to generate an API access token in Choreo.

+

Generate environment-specific keys and tokens

+

You can generate keys and tokens to invoke production and non-production endpoints separately.

+
+

Note

+

The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

+
+
    +
  1. In the Choreo Developer Portal header, click Applications.
  2. +
  3. On the My Applications page, click on the application for which you want to generate keys and tokens.
  4. +
  5. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
  6. +
  7. +

    Click to expand Advanced Configurations and review the options.

    +
      +
    • Grant Types: Select the grant types to use when generating the access token.
    • +
    • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
    • +
    • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
    • +
    • Application access token expiry time: Specify the access token expiry time in seconds.
    • +
    • Refresh token expiry time: Specify the refresh token expiry time in seconds.
    • +
    • ID token expiry time: Specify the ID token expiry time in seconds.
    • +
    +
  8. +
  9. +

    Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    +
  10. +
+

You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

+

To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

+
+

Warning

Make sure you do not use the test token in your production environment.

+

+
+

Subscribe to an API

+

You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API’s major version.

+

The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

+

To subscribe to an API via an application, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. In the Developer Portal header, click Applications.
  4. +
  5. On the My Applications page, click on the application with which you want to subscribe to an API.
  6. +
  7. In the left navigation menu, click Subscriptions.
  8. +
  9. In the Subscription Management pane that opens, click + Add APIs.
  10. +
  11. +

    Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

    +
    +

    Tip

    +

    When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

    +
    +

    Add APIs

    +

    Once you subscribe to an API, you can invoke the API using the application keys.

    +
  12. +
+

Consume the API via your web application

+

You can invoke the API/service using the credentials you created above. Since Choreo services are secured, you need to invoke the services securely with the help of your IdP. To invoke the API/service you created securely, you need to follow the steps below:

+
    +
  1. Create a web application in Choreo.
  2. +
  3. Create an OAuth application in the IdP.
  4. +
  5. Configure the web application to authenticate the API/service invocations from the IdP, and securely invoke the service/API in Choreo.
  6. +
  7. Deploy the web application.
  8. +
+

In this guide, you will be using the following products and examples:

+ +

Step 1: Create a web application component

+
+

Info

+

You can use your own web application implementation in place of the sample web application. For this exercise, let's use the choreo-samples/reading-list-app/reading-list-front-end as the web application.

+
+

To host the front-end application in Choreo, you must create a web application component. To create a web application component, follow the steps given below.

+
    +
  1. In the Choreo console, select the project of the reading list application that you created in the previous steps, from the project list located on the header.
  2. +
  3. Click Create under the Component Listing section to create a new component.
  4. +
  5. On the Web Application card, click Create.
  6. +
  7. +

    Enter a unique name and a description for the web application. You can enter the name and description given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameReading List Web App
    DescriptionFrontend application for the reading list service
    +
  8. +
  9. +

    Click Next.

    +
  10. +
  11. To allow Choreo to connect to your GitHub account, click Authorize with GitHub.
  12. +
  13. +

    In the Connect Repository pane, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    GitHub AccountYour account
    GitHub Repositorychoreo-samples
    Branchmain
    BuildpackClick React since the frontend is a React application built with Vite
    Build Context Pathreading-list-app/reading-list-front-end
    Build Commandnpm install && npm run build
    Build Outputdist
    Node Version18
    +
  14. +
  15. +

    Click Create. This initializes the service with the implementation from your GitHub repository and takes you to the Overview page of the component.

    +
  16. +
+

Let's consume the service through the web app. Choreo services are by default secured. To consume a service in Choreo you need an access token. Let's configure the web application to connect to an IdP (For this guide, let's use Asgardeo) to generate an access token for a user.

+

Step 2: Create an OAuth application in the IdP

+

To invoke the service/API in Choreo you require a token. To obtain a token you need to create an OAuth application in the IdP. If you use any other IdP other than Asgardeo, create an OAuth application and set the following:

+
    +
  • Allowed grant types: Code
  • +
  • Public client: Mark as a public client in an application.
  • +
  • Authorized redirect URLs: Enter the web app URL you copied earlier.
  • +
  • Allowed origins field: Add the same URLs that you added as authorized redirect URLs.
  • +
  • Access Token: Set JWT as the Token type.
  • +
+

Choreo uses Asgardeo as the default identity provider for Choreo applications. When you create an application in the Choreo Developer Portal, it automatically creates a corresponding application in Asgardeo. You can go to the Asgardeo application to specify the configurations required for end users to sign in to the front-end application. Follow the steps below to configure the Asgardeo OAuth application:

+
    +
  1. Access Asgardeo at https://console.asgardeo.io/ and sign in with the same credentials with which you signed in to Choreo.
  2. +
  3. Make sure you are in the same organization that you were when you created the application in the Choreo Developer Portal. You can click the Organization list in the Asgardeo Console top menu and ensure you are in the correct organization.
  4. +
  5. In the Asgardeo Console's left navigation, click Applications. You will see the readingListApp that Choreo automatically created for you.
  6. +
  7. Click on the edit icon to edit the application.
  8. +
  9. +

    Click the Protocol tab and apply the following changes:

    +
      +
    1. Under Allowed grant types, select Code.
    2. +
    3. Select the Public client checkbox.
    4. +
    5. In the Authorized redirect URLs field, enter the web app URL you copied earlier and click the + icon to add the entry.
    6. +
    7. In the Allowed origins field, add the same URLs that you added as authorized redirect URLs.
    8. +
    9. Under Access Token, select JWT as the Token type.
    10. +
    11. Click Update.
    12. +
    +
  10. +
+

Step 3: Configure the web application to connect to the IdP and invoke the service

+

In this step, you are adding the configurations needed for the web app to successfully invoke the Reading List Service REST API. These configurations need to be updated for each environment you deploy the web app. Here you will be updating the configurations for the development environment.

+
+

Note

The web application is reading the environment-specific configurations from the window object at runtime. This is done via the config.js file in the root of the web application. In this section, you will mount the config.js file for the development environment. You will need to do the same for other environments as well when you deploy your web application to multiple environments.

+

+
+

To configure the front-end application, follow the steps given below:

+
    +
  1. While on the web application component page, click DevOps in the left navigation menu and then click Configs and Secrets.
  2. +
  3. Click + Create.
  4. +
  5. +

    Select the mount configuration options as follows and click Next:

    + + + + + + + + + + + + + + + + + +
    FieldDescription
    Config TypeConfig Map
    Mount TypeFile Mount
    +
  6. +
  7. +

    Specify values as follows for the mount configuration:

    + + + + + + + + + + + + + + + + + +
    FieldDescription
    Config NameWeb App Config
    Mount Path/usr/share/nginx/html/config.js. Every config that needs to be exposed through the web server should be placed inside /usr/share/nginx/html/
    +
  8. +
  9. +

    Copy the config details as a JSON file as shown below into the text area. Fill the placeholders with the values you copied from the previous steps as mentioned in the table below:

    +
    window.config = {
    +    redirectUrl: "<web-app-url>",
    +    asgardeoClientId: "<asgardeo-client-id>",
    +    asgardeoBaseUrl: "https://api.asgardeo.io/t/<your-org-name>",
    +    choreoApiUrl: "<reading-list-service-url>"
    +};
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    redirectUrlThe web app URL you copied earlier.
    asgardeoClientIdThe Client ID of your OAuth application. In Asgardeo, you can find it on the Protocol tab of the readingListApp application
    asgardeoBaseUrlSpecify the IdP API URL (For example, Asgardeo API URL) with your organization name. i.e., https://api.asgardeo.io/t/<ORG_NAME>.
    choreoApiUrlThe reading list service URL. Copy the Public URL of the Reading List Service component from the endpoint table in the overview page for the relevant environment
    +
  10. +
  11. +

    Click Create.

    +
  12. +
+

Now you can proceed to deploy the web application.

+

Step 4: Deploy the web application

+

To deploy the web application component, follow the steps below:

+
    +
  1. In the left menu, click Deploy.
  2. +
  3. In the Build Area card, click Deploy Manually. The deployment may take a few minutes to complete.
  4. +
  5. Once the web application is deployed, copy the Web App URL from the development environment card.
  6. +
  7. Navigate to the web app URL. You can verify that the web app is successfully hosted.
  8. +
+

That's it! You can use a user created in your IdP and invoke the service through your web application.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/create-a-subscription/index.html b/consuming-services/create-a-subscription/index.html new file mode 100644 index 000000000..4ed8bc478 --- /dev/null +++ b/consuming-services/create-a-subscription/index.html @@ -0,0 +1,3408 @@ + + + + + + + + + + + + + + + + + + + + + + + + Create a subscription - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Create a subscription

+ +

You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API’s major version.

+

The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

+

To subscribe to an API via an application, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. In the Developer Portal header, click Applications.
  4. +
  5. On the My Applications page, click on the application with which you want to subscribe to an API.
  6. +
  7. In the left navigation menu, click Subscriptions.
  8. +
  9. In the Subscription Management pane that opens, click + Add APIs.
  10. +
  11. +

    Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

    +
    +

    Tip

    +

    When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

    +
    +

    Add APIs

    +

    Once you subscribe to an API, you can invoke the API using the application keys.

    +
  12. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/create-an-application/index.html b/consuming-services/create-an-application/index.html new file mode 100644 index 000000000..45677d428 --- /dev/null +++ b/consuming-services/create-an-application/index.html @@ -0,0 +1,3463 @@ + + + + + + + + + + + + + + + + + + + + + + + + Create an application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Create an application

+ +

An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

+

This section walks you through the steps to create an application in Choreo.

+

Let's get started!

+

Step 1: Create an application

+

To create an application in the Choreo Developer Portal, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. Click Applications. and then click +Create.
  4. +
  5. Enter a name and description for the application.
  6. +
  7. Click Create.
  8. +
+

This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

+

Step 2: Generate keys

+

Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

+

Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

+

The following section walks you through the steps to generate an API access token in Choreo.

+

Generate environment-specific keys and tokens

+

You can generate keys and tokens to invoke production and non-production endpoints separately.

+
+

Note

+

The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

+
+
    +
  1. In the Choreo Developer Portal header, click Applications.
  2. +
  3. On the My Applications page, click on the application for which you want to generate keys and tokens.
  4. +
  5. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
  6. +
  7. +

    Click to expand Advanced Configurations and review the options.

    +
      +
    • Grant Types: Select the grant types to use when generating the access token.
    • +
    • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
    • +
    • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
    • +
    • Application access token expiry time: Specify the access token expiry time in seconds.
    • +
    • Refresh token expiry time: Specify the refresh token expiry time in seconds.
    • +
    • ID token expiry time: Specify the ID token expiry time in seconds.
    • +
    +
  8. +
  9. +

    Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    +
  10. +
+

You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

+

To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

+
+

Warning

Make sure you do not use the test token in your production environment.

+

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/generate-an-access-token/index.html b/consuming-services/generate-an-access-token/index.html new file mode 100644 index 000000000..a90d2868a --- /dev/null +++ b/consuming-services/generate-an-access-token/index.html @@ -0,0 +1,3557 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generate an Access Token - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Generate an Access Token

+

Using access tokens for request authorization strengthens security measures, particularly in preventing certain types of denial-of-service (DoS) attacks aimed at published APIs. API consumers generate access tokens to access the API, incorporating them into their HTTP header requests as simple string values.

+

When you register an application on the Developer Portal, you can generate a consumer key and a consumer secret for it. The consumer key and the consumer secret represent the credentials of the application. Similar to a user's username, the consumer key becomes the unique identifier of the application so that you can use it to authenticate the request to the API. Choreo issues an access token for the application against the mentioned consumer key.

+

This section walks you through the steps to generate an access token for your application in Choreo.

+

Let's get started!

+

Prerequisites

+

Before you try out this guide, be sure you have the following:

+
    +
  1. An application in the Choreo Developer Portal. If you do not have an application created, create a new application
  2. +
  3. Generate keys for the application.
  4. +
  5. Subscribe APIs to the application.
  6. +
+

Generate an access token via cURL

+

You can follow the steps below to generate an access token for your application via cURL:

+
    +
  1. In the Choreo Developer Portal header, click Applications.
  2. +
  3. On the My Applications page, click on the application for which you want to generate the token.
  4. +
  5. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
  6. +
  7. Copy the Consumer Key, Consumer Secret, and Token Endpoint values.
  8. +
  9. +

    Use the following template and compile the cURL command with the values you copied in the above step.

    +
    +
    +
    +
    +
    +

    curl -k -X POST <token_endpoint> -d "grant_type=client_credentials" -H "Authorization: Basic <base64encode(consumer-key:consumer-secret)>"
    +
    +6. Execute the cURL command to generate an access token.

    +
  10. +
+

Generate an access token via the Choreo Console (for testing purposes)

+

You can follow the steps below to generate an access token for testing purposes:

+
    +
  1. In the Choreo Developer Portal header, click Applications.
  2. +
  3. On the My Applications page, click on the application for which you want to generate keys and tokens.
  4. +
  5. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
  6. +
  7. Click Generate Token.
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/manage-application/index.html b/consuming-services/manage-application/index.html new file mode 100644 index 000000000..8c2032fc8 --- /dev/null +++ b/consuming-services/manage-application/index.html @@ -0,0 +1,3690 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Applications

+

An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

+

This section walks you through the steps to create an application in Choreo.

+

Let's get started!

+

Step 1: Create an application

+

To create an application in the Choreo Developer Portal, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. Click Applications. and then click +Create.
  4. +
  5. Enter a name and description for the application.
  6. +
  7. Click Create.
  8. +
+

This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

+

Step 2: Generate keys

+

Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

+

Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

+

The following section walks you through the steps to generate an API access token in Choreo.

+

Generate environment-specific keys and tokens

+

You can generate keys and tokens to invoke production and non-production endpoints separately.

+
+

Note

+

The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

+
+
    +
  1. In the Choreo Developer Portal header, click Applications.
  2. +
  3. On the My Applications page, click on the application for which you want to generate keys and tokens.
  4. +
  5. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
  6. +
  7. +

    Click to expand Advanced Configurations and review the options.

    +
      +
    • Grant Types: Select the grant types to use when generating the access token.
    • +
    • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
    • +
    • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
    • +
    • Application access token expiry time: Specify the access token expiry time in seconds.
    • +
    • Refresh token expiry time: Specify the refresh token expiry time in seconds.
    • +
    • ID token expiry time: Specify the ID token expiry time in seconds.
    • +
    +
  8. +
  9. +

    Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    +
  10. +
+

You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

+

To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

+
+

Warning

Make sure you do not use the test token in your production environment.

+

+
+

Grant types

+

Choreo authentication is based on OAuth 2.0. In OAuth 2.0, grant types are methods that allow client applications to obtain an access token depending on the type of the resource owner, the type of the application, and the trust relationship between the authorization server and the resource owner.

+

Authorization code grant

+

The Authorization code flow provides a secure way for a client application to obtain an access token without exposing the user's credentials to the client application. The user only authenticates with the authorization server, which then issues an authorization code that can be exchanged for an access token.

+

This helps to protect user credentials and prevents credentials from being compromised by malicious client applications.

+

Refresh token grant

+

A refresh token is a token that you can use to get a new access token when your current access token is expired or when you need a new access token. You can use the refresh token grant type for this purpose. Issuing a refresh token is optional for the authorization server. If the authorization server issues a refresh token, it includes it in the response with the access token. You can use this refresh token and send it to the authorization server to obtain a new access token. Choreo's default authorization server, Asgardeo, issues refresh tokens for all grant types other than the client credentials grant type, as recommended by the OAuth 2.0 specification.

+
+

Note

+
    +
  • Keep your refresh token private, similar to the access token.
  • +
  • The process to get a new access token using the Refresh Token grant type requires no user interaction.
  • +
+
+

Client credentials grant

+

The client credentials flow provides a secure way for client applications to obtain an access token without user authentication. This is useful in scenarios where the client application needs to access its own resources, such as data storage or APIs, but does not require access to user data. However, it is important to ensure that the client credentials are kept secure because any party who has these credentials can obtain access tokens and access the client's resources.

+

Implicit grant

+

The implicit grant flow is an OAuth 2.0 grant type that enables a client application to obtain an access token directly from the authorization server without an intermediate authorization code exchange. This flow is commonly used in browser-based applications where the client application runs in a web browser.

+

However, it is important to note that the access token is exposed in the browser's URL fragment, which can make it vulnerable to certain types of attacks, such as cross-site scripting (XSS). As a result, this flow is typically not recommended for applications that require high security.

+

Password grant

+

The password grant flow is an OAuth 2.0 grant type that enables a client application to obtain an access token by presenting the user's username and password directly to the authorization server. This flow is generally considered less secure than other grant types, as it requires the client application to handle and transmit the user's credentials.

+

The password grant is primarily used in scenarios where the client application is highly trusted, and the user experience is prioritized over security concerns. It is generally not recommended for use in public-facing applications or scenarios where sensitive data is accessed.

+

Revoke access tokens

+

Revoking JWT access tokens can be challenging due to their self-validating nature. Once a token is issued, it contains all the necessary information within itself to validate its authenticity, without requiring additional server-side lookups or interactions.

+

It is recommended to use an expiry time that is not more than 900 seconds.

+

In traditional session-based authentication, the server can easily revoke a session by invalidating its associated session ID. However, in the case of JWTs, there is no central authority that maintains a list of valid or invalid tokens. As a result, revoking a JWT token requires the use of denylist or allowlist techniques, which can add additional complexity to the authentication flow and may not always be foolproof.

+

To mitigate these challenges, it is recommended to use short-lived JWT access tokens and regularly refresh them. This reduces the risk of unauthorized access if a token is stolen or leaked, as the token will expire after a short period of time. Additionally, implementing other security measures such as strong encryption and secure token storage can further enhance the security of JWT-based authentication.

+

The Choreo Developer Portal keeps the lifespan of a token to 15 minutes (900 seconds) by default. Application Developers can increase the time if necessary, but as mentioned above, it is recommended to keep it to the minimal possible value.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/manage-subscription/index.html b/consuming-services/manage-subscription/index.html new file mode 100644 index 000000000..a71aa90ca --- /dev/null +++ b/consuming-services/manage-subscription/index.html @@ -0,0 +1,3464 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Subscription - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Subscriptions

+

You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API’s major version.

+

The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

+

To subscribe to an API via an application, follow the steps given below:

+
    +
  1. Sign in to the Choreo Developer Portal.
  2. +
  3. In the Developer Portal header, click Applications.
  4. +
  5. On the My Applications page, click on the application with which you want to subscribe to an API.
  6. +
  7. In the left navigation menu, click Subscriptions.
  8. +
  9. In the Subscription Management pane that opens, click + Add APIs.
  10. +
  11. +

    Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

    +
    +

    Tip

    +

    When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

    +
    +

    Add APIs

    +

    Once you subscribe to an API, you can invoke the API using the application keys.

    +
  12. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/consuming-services/share-applications/index.html b/consuming-services/share-applications/index.html new file mode 100644 index 000000000..ab540b9bf --- /dev/null +++ b/consuming-services/share-applications/index.html @@ -0,0 +1,3463 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Share Applications - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Share Applications

+

Choreo's application-sharing feature allows you to share your applications with members within your organization. This facilitates collaborative efforts when there is a need for multiple members to work on the same application.

+

Follow the steps given below to share an application with members of your organization:

+
    +
  1. Sign in to the Choreo Developer Portal and click the Applications tab.
  2. +
  3. On the Applications page, click on the application you want to share.
  4. +
  5. On the Application Overview page that opens, click the Share button displayed on the right side.
  6. +
  7. +

    In the Share Application dialog, enter one or more email addresses depending on the members with whom you want to share the applications.

    +
    +

    Note

    +

    You must type an email address and press enter for it to get added.

    +
    +
  8. +
  9. +

    Click Confirm. This will share the application in read-only mode with the specified members.

    +
  10. +
+

To see the members with whom the application is shared, go to the Application Overview page and take a look at the email addresses in the Shared with field.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deploy/deploy-a-ballerina-application/index.html b/deploy/deploy-a-ballerina-application/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/deploy/deploy-a-ballerina-application/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/deploy-a-containerized-application/index.html b/deploy/deploy-a-containerized-application/index.html new file mode 100644 index 000000000..71782578a --- /dev/null +++ b/deploy/deploy-a-containerized-application/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/configs-and-secrets/index.html b/deploy/devops/configs-and-secrets/index.html new file mode 100644 index 000000000..7d2e23452 --- /dev/null +++ b/deploy/devops/configs-and-secrets/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/containers/index.html b/deploy/devops/containers/index.html new file mode 100644 index 000000000..285bc5f10 --- /dev/null +++ b/deploy/devops/containers/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/health-checks/index.html b/deploy/devops/health-checks/index.html new file mode 100644 index 000000000..5bf5a2814 --- /dev/null +++ b/deploy/devops/health-checks/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/runtime/index.html b/deploy/devops/runtime/index.html new file mode 100644 index 000000000..a97ad5a0a --- /dev/null +++ b/deploy/devops/runtime/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/scaling/index.html b/deploy/devops/scaling/index.html new file mode 100644 index 000000000..1be5bf027 --- /dev/null +++ b/deploy/devops/scaling/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/deploy/devops/storage/index.html b/deploy/devops/storage/index.html new file mode 100644 index 000000000..abb2b9867 --- /dev/null +++ b/deploy/devops/storage/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/bring-your-own-image/index.html b/develop-components/bring-your-own-image/index.html new file mode 100644 index 000000000..449c12630 --- /dev/null +++ b/develop-components/bring-your-own-image/index.html @@ -0,0 +1,3836 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bring Your Own Image - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Bring Your Own Image (BYOI)

+

Choreo allows you to deploy and manage prebuilt container images from external container registries as Choreo components. This enables you to deploy and effectively manage your container images within the Choreo environment.

+
+

Info

+

This feature is currently only available on private data planes (PDPs) for the following component types:

+
    +
  • Service
  • +
  • Web Application
  • +
  • Scheduled Task
  • +
  • Manual Task
  • +
+
+

Prerequisites

+

Before you try out this guide, ensure you have the following:

+
    +
  • +

    A container registry: Ensure you have a container registry containing the images you want to deploy. Choreo is compatible with various container registries, including but not limited to GCR (Google Container Registry), ACR (Azure Container Registry), GitHub Container Registry, and Docker Hub.

    +
  • +
  • +

    An image in the registry: You need an image ready for deployment.

    +
  • +
  • +

    (Optional) An external build/CI pipeline: This is to initiate automatic deployments during the build process outside of Choreo.

    +
  • +
+

When using a container registry to deploy a component, Choreo cannot create an image from the source code (Git) or initiate a new deployment when a new image is ready. However, you can use your existing build process to trigger a deployment on Choreo by sending an HTTP POST request to a webhook with the new image details.

+

This feature is currently only available on private data planes (PDPs). You can find this option under Deploy an image from a container registry in the Select Source step during component creation for service components, web applications, scheduled tasks, and manual tasks.

+

Step 1: Register a container registry

+

To get started, establish a connection between your container registry and Choreo.

+
+

Info

+

When you use your Choreo credentials, Choreo does not pull your images into its control plane. Instead, it functions as an orchestrator, facilitating your data plane's ability to retrieve images from an external container registry. Choreo passes on these credentials to the data plane for authentication and access.

+
+

To register your container registry, follow these steps:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, go to the Organization list and select your organization.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization settings page.
  6. +
  7. Click the Credentials tab and then click the Container Registries tab.
  8. +
  9. Click +Add Registry to configure the Git repository connection.
  10. +
  11. Specify a Registry Display Name.
  12. +
  13. Select the Authentication Type. Fill in the required information depending on your authentication type. For details on each authentication type, see Authentication types.
  14. +
  15. Click Save.
  16. +
+

Authentication types

+

Choreo provides the following authentication options:

+

Public (anonymous) access

+

You can use this option to establish a connection with a container registry that permits unrestricted public or anonymous access (for example, Public Docker Hub). In this case, only the registry host information is necessary.

+

For example, the following are the Docker Hub registry hosts for reference:

+ + + + + + + + + + + + + + + + + +
VendorRegistry host
Docker Hub (public repositories)registry.hub.docker.com
Docker Hub (private repositories)registry.docker.com
+

* If necessary, you can use other mirrors instead of the above.

+

Basic authentication

+

To use basic authentication to authenticate to the container registry, you must provide the username and password.

+

Docker config

+

You can provide a Docker config in JSON format to authenticate to the container registry. This option only allows you to register one container registry. That is, it only allows a single registry under auths.

+

You must provide the credentials directly within the configuration. Choreo cannot utilize references to executable authentication plugins.

+

Sample Docker config format:

+
    {
+    "auths": {
+        "index.docker.io/v1/": {
+        "auth": "c3R...zE2"
+        }
+    }
+    }
+
+ +

Vendor-specific authentication

+

This option is specifically for private data planes, where your cloud provider manages authentication at the Kubernetes level. Choreo requires knowledge of the registry host because the data plane already possesses implicit (preconfigured) access to the registry.

+

Follow the guidelines below based on your container registry:

+
+
+
+

Azure Container Registry

+

Recommended authentication options:

+
    +
  • +

    Service principal-based basic authentication

    +
  • +
  • +

    Vendor-specific authentication on Azure private data planes

    +

    Contact Choreo support to enable infrastructure-level private access to your registry from your Azure private data plane on AKS. If you are on a self-managed PDP on Azure, follow this guide.

    +
  • +
+
+
+

Google Artifact Registry

+

Recommended authentication options:

+ +
+
+

Elastic Container Registry

+

ECR does not allow the creation of static access passwords for basic authentication. The passwords (that is, access tokens) provided by AWS are only valid for 10 hours and must be manually regenerated. However, when an ECR is attached to an EKS cluster at an infrastructure level, this limitation does not apply because the authentication is handled by AWS internally. For details, see https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html.

+

Choreo recommends using ECR when you are exclusively on an AWS private data plane using the vendor-specific authentication option. Contact Choreo support to enable a private connection between your ECR and the underlying EKS clusters on your data plane. If you are on a self-managed PDP, you can follow this guide.

+
+
+

Recommended authentication options:

+
    +
  • +

    Basic authentication

    +

    Use your Docker Hub username/password or an access token. You can generate an access token from your Docker Hub account settings and use it in place of the password. For details, see https://docs.docker.com/docker-hub/access-tokens/.

    +
  • +
  • +

    Docker config

    +

    Sign in to the Docker CLI and copy the contents of the docker config JSON. Note that external credential stores and multiple repositories within the same config object are not supported. For more information, see https://docs.docker.com/engine/reference/commandline/login/.

    +
  • +
+
+
+

GitHub Container Registry

+

Recommended authentication option:

+
    +
  • +

    Basic authentication using a PAT token

    +

    Create a personal access token (PAT) and use it in place of the password. You cannot use your own GitHub password. You must provide a PAT token.

    +
  • +
+
+
+
+

Step 2: Create a component in Choreo

+
    +
  1. In the left navigation, click Overview and select your project. Alternatively, select your project from the Project list in the Choreo Console header.
  2. +
  3. Under Component Listing click + Create.
  4. +
  5. Select your component type (BYOI is only available for Service, Web Application, Scheduled Task, or Manual Task components).
  6. +
  7. +

    Enter a display name, a unique name, and a description for the component.

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    +
  8. +
  9. +

    Click either the Docker Hub tab or the Container Registry tab depending on your vendor.

    +
  10. +
  11. Under Deploy an image from Container Registry/Docker Hub, select the container registry you have registered in Step 1.
  12. +
  13. +

    Enter the full image URL. The image URL format in general is as follows: + [container-registry-host]/[repository-name]/[image-name]:[tag]

    +
    +

    Tip

    +

    When a public image from Docker Hub lacks a specified repository name, it typically defaults to /library/. For example, you can access the public Nginx image https://hub.docker.com/_/nginx as registry.hub.docker.com/library/nginx:1.25.

    +
    +
  14. +
+

Step 3: Deploy the component in Choreo

+

To deploy the component and bring your image to Choreo, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Update Image & Deploy.
  4. +
  5. In the Endpoint pane that opens, you can see the endpoint ready to be deployed. Click the edit icon next to the endpoint name. Optionally, you can define the endpoints for your service when you manually deploy the service. For more information, see Expose service endpoints.
  6. +
  7. Change the Network Visibility to Public. This setting securely exposes the endpoint for consumption.
  8. +
  9. +

    Click Update.

    +
    +

    Info

    +

    In this example, you deploy a Ballerina service as a REST endpoint. Therefore, Choreo generated the REST endpoint automatically. If you deploy a non-Ballerina service, you must manually add the REST endpoint and set the network visibility to Public.

    +
    +
  10. +
  11. +

    Select your update image option. Refer to the update options listed below.

    +

    You have the capability of updating the image when you are deploying the component in Choreo in one of the following three ways:

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    Update Image TagThis option allows you to update the tag of the image.
    Update Image URLWith this option, you can change the image name, tag, and the image repository of the image URL.
    Previous ImagesThis option allows you to select a previous image and redeploy the image.
    +
  12. +
  13. +

    Click Deploy. This deploys the service to the development environment.

    +
  14. +
+

Step 4: Expose service endpoints

+
+

Info

+

This section only applies to service components.

+
+

After creating a service component in Choreo, you have the option to define the endpoints for your service when manually deploying a new image.

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Update Image & Deploy.
  4. +
  5. In the Endpoint pane that opens, optionally, you can define the endpoints for your service when you manually deploy the service.
  6. +
  7. Click Create/Update Endpoints.
  8. +
  9. Under the Edit endpoints.yaml section, you can edit the endpoints YAML file in the provided editor. + Alternatively, you can upload the associated API specification/schema files (OpenAPI/GraphQL schemas). Instead of specifying the file path, you can also reference this file in the endpoints.yaml file by its file name, similar to the Git-based Choreo components. The endpoints template follows the standard definitions for defining endpoints in Choreo. For more details, see Configure Endpoints.
  10. +
+

Auto-deploy images in Choreo with an external CI/build pipeline

+

Choreo does not have automatic detection and deployment for newly added images or tags in the linked container registry. To overcome this limitation, Choreo allows you to integrate your own CI pipelines and initiate deployments manually. This approach enables you to use your existing CI setup or build a pipeline for image creation and pushing. You can then trigger automatic deployments using a webhook.

+

Follow the steps below to configure your CI/build pipeline:

+
    +
  1. Build and push the container image associated with a Choreo component to your container registry.
  2. +
  3. In the left navigation menu, click DevOps and then click External CI.
  4. +
  5. +

    Generate a token for your CI pipeline from the Manage Tokens section.

    +
    +

    Note

    +
      +
    • The tokens are bound to a specific component.
    • +
    • It is recommended to reference the token from a secure location available to your CI pipeline. For example, use a GitHub secret if you are using GitHub Actions.
    • +
    +
    +
  6. +
  7. +

    To trigger an automatic deployment to your development environment, you can initiate an HTTP POST request to the Choreo webhook endpoint with the updated image details. Alternatively, you can use the provided Webhook snippets. This action will seamlessly deploy the image to the development environment.

    +
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/configure-endpoints-body/index.html b/develop-components/configure-endpoints-body/index.html new file mode 100644 index 000000000..e0ed0eb3a --- /dev/null +++ b/develop-components/configure-endpoints-body/index.html @@ -0,0 +1,3544 @@ + + + + + + + + + + + + + + + + + + + + + + + + Configure endpoints body - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure endpoints body

+ +

Services and integrations are exposed to other services, integrations, or applications through endpoints. A service or an integration can expose multiple endpoints, each representing a unique entry point into the service. For example, a service may expose a REST API endpoint and a GraphQL endpoint, each providing different ways to interact with the service. Endpoints provide specific details for how the service or the integration can be consumed. For instance, the port number, protocol, and the schema such as open API specification (OAS) or GraphQL schema. By defining these details, endpoints make it possible for other services, integrations, and applications to discover and interact with the service in a standardized way.

+

Choreo defines endpoints by combining port binding, protocol, endpoint name, network visibility, endpoint schema, and additional protocol-related fields. The following table describes each attribute of an endpoint.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
NameA unique identifier for the endpoint within the service component.
PortThe network port on which the endpoint is accessible.
TypeThe endpoint protocol. Supported protocols: REST, GraphQL, gRPC, WS, UDP, and TCP.
Network VisibilityDetermines the level of visibility of an endpoint. Possible values are:
  • Project: Allows components within the same project to access the endpoint.
  • Organization: Allows any component within the same organization to access the endpoint but restricts access to components outside the organization.
  • Public: Allows any client to access the endpoint, regardless of location or organization.
SchemaSpecifies the structure and format of the data exchanged through the endpoint.
Context (HTTP and GraphQL only)A context path that you add to the endpoint's URL for routing purposes.
+

Configure endpoints

+

The method of defining endpoints depends on the buildpack. For buildpacks other than Ballerina and WSO2 MI, it is required to have an component.yaml file in project root directory to create the Service component.

+

Configure endpoints with buildpacks (except Ballerina)

+

When you build a service component using any other buildpacks(Java, Python, NodeJS, Ruby, PHP, Go, Dockerfile, etc) other than Ballerina and WSO2 MI, you can configure the endpoint details with the component.yaml source configuration file. You must place this file inside the .choreo directory at the build context path and commit it to the source repository.

+

To learn about the component.yaml file, see Overview of the component.yaml file.

+

Configure endpoints with the Ballerina buildpack

+

When you create a service component with the Ballerina buildpack, Choreo automatically detects the endpoint details for REST APIs. You can override the auto-generated endpoint configuration by providing the component.yaml file in the source directory.

+
+

Note

+

Automatic endpoint generation is not supported for dynamic endpoint parameters such as variable ports. Therefore, you must use an component.yaml file to define dynamic endpoint parameters.

+
+

To learn about the component.yaml file, see Overview of the component.yaml file.

+

Expose endpoints as managed APIs

+

Exposing endpoints as managed APIs is crucial to ensure secure and controlled access to the services being exposed. When a user wants to expose their written service to the outside world or to the organization at large, there is an inherent security risk involved. To mitigate this risk, the Choreo platform is built with an internal (access within the organization only) or external (publicly accessible) gateway that is protected with Choreo API management making the services secure by design.

+
+

Note

+

This feature is not available for gRPC, UDP, and TCP endpoints.

+
+

If you want to expose an endpoint as a managed API in Choreo, you need to set the network visibility to either Organization or Public. This allows the endpoint to be exposed through the Choreo API Gateway, which provides a number of benefits, including:

+
    +
  • Expose APIs to external and internal consumers
  • +
  • Full lifecycle API Management
  • +
  • API throttling
  • +
  • Secure APIs with industry-standard authorization flows
  • +
  • API analytics and monitoring
  • +
+

Once you deploy the service component, Choreo will expose the endpoint as a managed API through the Choreo API Gateway. You can then use the full lifecycle API management features provided by Choreo to test, deploy, maintain, monitor, and manage your API using the API management features.

+

Understand the default component URL

+

The default URL of a component corresponds to the default endpoint of the component and is structured as follows:

+

<domain>/<project-name>/<component-name>

+

This URL does not include the default endpoint name. For all other endpoints, the URL structure includes the endpoint name, as follows:

+

<domain>/<project-name>/<component-name>/<endpoint-name>

+

If a component has multiple endpoints, Choreo allows you to change the endpoint corresponding to the default component URL. For a component with a single endpoint, the default URL automatically corresponds to that endpoint.

+

Change the default endpoint of a component

+

To change the default endpoint of a component, follow the steps given below:

+
+

Note

+
    +
  • You cannot change the default endpoint if it has associated published APIs. You must go to the Lifecycle page and unpublish the relevant APIs before updating the default endpoint. For instructions on unpublishing an API, see Lifecycle Management.
  • +
  • Choreo does not allow you to change the default endpoint of a component if you create multiple deployment tracks within its current major version, or promote the component beyond its initial environment.
  • +
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to change the default endpoint.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. On the Deploy page, go to the Set Up card and click Configure & Deploy.
  8. +
  9. In the Environment Configurations pane that opens, click Next.
  10. +
  11. In the File Mount pane that opens, click Next.
  12. +
  13. In the Endpoint Details pane that opens, click the Default Endpoint list, select the endpoint you want to set as the default endpoint, and then click Update.
  14. +
  15. Click Deploy. This deploys the component with the selected endpoint as the default, and the default URL will now correspond to this endpoint.
  16. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/configure-endpoints/index.html b/develop-components/configure-endpoints/index.html new file mode 100644 index 000000000..4b5c88021 --- /dev/null +++ b/develop-components/configure-endpoints/index.html @@ -0,0 +1,3673 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Endpoints - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Endpoints

+

Services and integrations are exposed to other services, integrations, or applications through endpoints. A service or an integration can expose multiple endpoints, each representing a unique entry point into the service. For example, a service may expose a REST API endpoint and a GraphQL endpoint, each providing different ways to interact with the service. Endpoints provide specific details for how the service or the integration can be consumed. For instance, the port number, protocol, and the schema such as open API specification (OAS) or GraphQL schema. By defining these details, endpoints make it possible for other services, integrations, and applications to discover and interact with the service in a standardized way.

+

Choreo defines endpoints by combining port binding, protocol, endpoint name, network visibility, endpoint schema, and additional protocol-related fields. The following table describes each attribute of an endpoint.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
NameA unique identifier for the endpoint within the service component.
PortThe network port on which the endpoint is accessible.
TypeThe endpoint protocol. Supported protocols: REST, GraphQL, gRPC, WS, UDP, and TCP.
Network VisibilityDetermines the level of visibility of an endpoint. Possible values are:
  • Project: Allows components within the same project to access the endpoint.
  • Organization: Allows any component within the same organization to access the endpoint but restricts access to components outside the organization.
  • Public: Allows any client to access the endpoint, regardless of location or organization.
SchemaSpecifies the structure and format of the data exchanged through the endpoint.
Context (HTTP and GraphQL only)A context path that you add to the endpoint's URL for routing purposes.
+

Configure endpoints

+

The method of defining endpoints depends on the buildpack. For buildpacks other than Ballerina and WSO2 MI, it is required to have an component.yaml file in project root directory to create the Service component.

+

Configure endpoints with buildpacks (except Ballerina)

+

When you build a service component using any other buildpacks(Java, Python, NodeJS, Ruby, PHP, Go, Dockerfile, etc) other than Ballerina and WSO2 MI, you can configure the endpoint details with the component.yaml source configuration file. You must place this file inside the .choreo directory at the build context path and commit it to the source repository.

+

To learn about the component.yaml file, see Overview of the component.yaml file.

+

Configure endpoints with the Ballerina buildpack

+

When you create a service component with the Ballerina buildpack, Choreo automatically detects the endpoint details for REST APIs. You can override the auto-generated endpoint configuration by providing the component.yaml file in the source directory.

+
+

Note

+

Automatic endpoint generation is not supported for dynamic endpoint parameters such as variable ports. Therefore, you must use an component.yaml file to define dynamic endpoint parameters.

+
+

To learn about the component.yaml file, see Overview of the component.yaml file.

+

Expose endpoints as managed APIs

+

Exposing endpoints as managed APIs is crucial to ensure secure and controlled access to the services being exposed. When a user wants to expose their written service to the outside world or to the organization at large, there is an inherent security risk involved. To mitigate this risk, the Choreo platform is built with an internal (access within the organization only) or external (publicly accessible) gateway that is protected with Choreo API management making the services secure by design.

+
+

Note

+

This feature is not available for gRPC, UDP, and TCP endpoints.

+
+

If you want to expose an endpoint as a managed API in Choreo, you need to set the network visibility to either Organization or Public. This allows the endpoint to be exposed through the Choreo API Gateway, which provides a number of benefits, including:

+
    +
  • Expose APIs to external and internal consumers
  • +
  • Full lifecycle API Management
  • +
  • API throttling
  • +
  • Secure APIs with industry-standard authorization flows
  • +
  • API analytics and monitoring
  • +
+

Once you deploy the service component, Choreo will expose the endpoint as a managed API through the Choreo API Gateway. You can then use the full lifecycle API management features provided by Choreo to test, deploy, maintain, monitor, and manage your API using the API management features.

+

Understand the default component URL

+

The default URL of a component corresponds to the default endpoint of the component and is structured as follows:

+

<domain>/<project-name>/<component-name>

+

This URL does not include the default endpoint name. For all other endpoints, the URL structure includes the endpoint name, as follows:

+

<domain>/<project-name>/<component-name>/<endpoint-name>

+

If a component has multiple endpoints, Choreo allows you to change the endpoint corresponding to the default component URL. For a component with a single endpoint, the default URL automatically corresponds to that endpoint.

+

Change the default endpoint of a component

+

To change the default endpoint of a component, follow the steps given below:

+
+

Note

+
    +
  • You cannot change the default endpoint if it has associated published APIs. You must go to the Lifecycle page and unpublish the relevant APIs before updating the default endpoint. For instructions on unpublishing an API, see Lifecycle Management.
  • +
  • Choreo does not allow you to change the default endpoint of a component if you create multiple deployment tracks within its current major version, or promote the component beyond its initial environment.
  • +
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to change the default endpoint.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. On the Deploy page, go to the Set Up card and click Configure & Deploy.
  8. +
  9. In the Environment Configurations pane that opens, click Next.
  10. +
  11. In the File Mount pane that opens, click Next.
  12. +
  13. In the Endpoint Details pane that opens, click the Default Endpoint list, select the endpoint you want to set as the default endpoint, and then click Update.
  14. +
  15. Click Deploy. This deploys the component with the selected endpoint as the default, and the default URL will now correspond to this endpoint.
  16. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/configure-mutual-tls-between-components/index.html b/develop-components/configure-mutual-tls-between-components/index.html new file mode 100644 index 000000000..829b17d73 --- /dev/null +++ b/develop-components/configure-mutual-tls-between-components/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/deploy-a-containerized-application/index.html b/develop-components/deploy-a-containerized-application/index.html new file mode 100644 index 000000000..7aa293ac0 --- /dev/null +++ b/develop-components/deploy-a-containerized-application/index.html @@ -0,0 +1,3730 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy a Containerized Application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deploy a Containerized Application

+

Using Choreo, you can easily deploy applications written in different language frameworks (such as Java, Go, NodeJS, Python, etc.) on shared or private data planes using containers.

+

Choreo supports deploying containerized applications for the following component types:

+
    +
  • Service
  • +
  • Web Application
  • +
  • Scheduled Task
  • +
  • Manual Task
  • +
  • Event Handler
  • +
  • Test Runner
  • +
+

Connect your repository to Choreo

+

To connect your GitHub repository to Choreo, you should authorize the Choreo Apps GitHub application to access your account or organization. When you attempt to connect your GitHub repository via the Component creation page, the Choreo Apps authorization prompt will appear.

+
    +
  • +

    Connect GitHub Repository

    +

    Connect GitHub Repository

    +
  • +
  • +

    Authorize GitHub Application

    +

    Authorize GitHub Application

    +
  • +
  • +

    Grant Repository Access

    +

    Grant Repository Access

    +

    The Choreo Apps requires the following permission:

    +
      +
    • Read access to issues and metadata
    • +
    • Read and write access to code, pull requests, and repository hooks
    • +
    +
  • +
+
+

Note

+

You can revoke access if you do not want Choreo to have access to your GitHub account. Choreo needs write access only to send pull requests to a user repository. Choreo does not directly push any changes to a repository.

+
+

Alternatively, you can connect a public repository without requiring authorization from the Choreo Apps GitHub application. You can paste a public repository URL in the Provide Repository URL field at the time of component creation.

+
+

Tip

+

Authorizing the repository with the Choreo Apps GitHub application becomes essential if you want to enable Auto Deploy for the component. If you own the repository, you can subsequently authorize it with the Choreo Apps GitHub application to enable Auto Deploy.

+
+

After granting access to the required repositories, you can choose a repository and an associated branch to connect to the Choreo component. +For the containerized application deployments, you should select the Dockerfile as the Buildpack and provide Dockerfile Path and Docker Context Path for the Docker build.

+

Connected Dockerfile Repository

+

The following table describes the individual fields in the Create Component pane.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
GitHub AccountYour GitHub account or organization. If you want to add another GitHub account, you can expand the list and click + Add.
GitHub RepositoryDepending on the repository access you provided, the list will show available repositories to be connected.
BranchThe branch of the repository.
BuildpackDetermines the implementation of the component: Any language or other language as a Docker container.
Dockerfile PathThe path to your Dockerfile. This path is defined relative to the repository root.
For example, if the Dockerfile is at the repository root, the value for this field is /Dockerfile.
Docker Context PathThe Docker build context path. To include the repository root, leave the default / value.
Port*The port at which your service is running.
OpenAPI Filepath*The path to an OpenAPI specification (in YAML/JSON) relative to the repository root. If you don't provide a path, the system automatically generates a default allow-all specification.
+
+

Note

+
    +
  • +

    Fields marked with * are not visible for all component types.

    +
  • +
  • +

    To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. You can refer to the sample Dockerfile for guidance.

    +
  • +
  • +

    To ensure that the defined USER instruction is valid, it must conform to the following conditions:

    +
      +
    • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
    • +
    • Usernames are not considered valid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
    • +
    +
  • +
+
+

Deploy the containerized component

+

Choreo will automatically apply deployment configurations and settings based on the component type you select during creation. +For example, if you select the Service component type, Choreo will deploy it as a Kubernetes deployment with appropriate scaling configurations.

+

You can run unit tests in the build pipeline by adding the relevant command to the Dockerfile. For example:

+ +

Application configurations

+

You must provide any required configurations for running the application in the Configs & Secrets section of the component's DevOps page. Alternatively, you can also review the configurations when you manually deploy via the Deploy page.

+

After clicking the Create button, you can select the confidentiality of the configuration and specify how to mount it to the container.

+

Application Configuration Page

+

Create Configuration Mount Page

+

Configuration types

+
    +
  • ConfigMap: Stores non-confidential data as key-value pairs.
  • +
  • Secret: Stores and manages sensitive information, such as passwords, OAuth tokens, and ssh keys as key-value pairs.
  • +
+

Mount types

+
    +
  • Environment Variables: Mounts the selected ConfigMap or Secret as an environment variable in the container.
  • +
  • File Mount: Mounts the selected ConfigMap or Secret as a file in the container. Here, the key is the file name, and the value is the file content.
  • +
+

The following image shows adding a ConfigMap with File Mount mount type to be read by the application.

+

Configuration File Mount Page

+
+

Note

+

The JSON file includes ${DB_PASS} as an environment variable defined in a Secret. The application reads the JSON file and substitutes the placeholders with the corresponding environment variables.

+
+

Deployment configurations

+

Choreo lets you configure deployment settings such as scaling, resource limits, and health checks based on your selected component type.

+

For more information about these configurations, see Choreo's DevOps capabilities.

+

You can configure the Endpoints to expose your service using the Service Component in Choreo. See Service Component Overview for more information.

+

Build, deploy, and promote

+

After adding the application configuration, you can build and deploy it by clicking the Deploy Manually button. Choreo will start the build process with the selected commit in the Build Area.

+
+

Note

+

The Auto Deploy on Commit feature, which automatically builds and deploys the application upon pushing a code change to the repository, is enabled by default. To turn off this feature, navigate to the Build Area of the Deploy page.

+
+

Choreo scans your Dockerfile for security vulnerabilities during the build phase, and if there are no issues found, it proceeds with the build process. After building the image, it scans it again for vulnerabilities before deployment to the environment. You can view the build logs from the right-side panel, as shown in the image below.

+

Build Logs Panel

+

Once the build process is complete, Choreo will deploy the application automatically to the Development environment. To promote the build to higher environments, you can click the Promote button. The number of environment cards visible on the page may vary depending on your environment configurations.

+

Troubleshoot security vulnerability scan failures (Trivy)

+

By default, Choreo utilizes the Aqua Trivy (OSS) image vulnerability scanner to detect security vulnerabilities in all Dockerfile-based build pipelines. The scanner will fail the pipeline if any CRITICAL CVEs (Common Vulnerabilities and Exposures) are detected. CVEs of other severity levels are recorded but does not fail the pipeline.

+

If you cannot fix a critical CVE immediately, you can opt to ignore it. To ignore a critical CVE, add a trivyignore (<docker-build-context-path>/.trivyignore) file to your build context path. In the file, add the CVEs you need the pipeline to ignore, one entry per line as follows:

+
CVE-2023-xxxx
+CVE-2023-yyyy
+
+ +

You can add comments in the file by using # in front of the comment as follows:

+
# comments can be added like this
+CVE-2023-xxxx
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/deploy-an-application-with-buildpacks/index.html b/develop-components/deploy-an-application-with-buildpacks/index.html new file mode 100644 index 000000000..75968b1b6 --- /dev/null +++ b/develop-components/deploy-an-application-with-buildpacks/index.html @@ -0,0 +1,3876 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy an Application with Buildpacks - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deploy an Application with Buildpacks

+

Using Choreo, you can easily deploy applications written in different language frameworks (such as Java, Go, NodeJS, Python, Ruby, PHP, etc.) on shared or private data planes.

+

Choreo supports deploying applications with buildpacks for the following component types:

+
    +
  • Service
  • +
  • Web Application
  • +
  • Scheduled Task
  • +
  • Manual Task
  • +
  • Webhook
  • +
  • Event Handler
  • +
  • Test Runner
  • +
+

Buildpacks

+

Buildpacks are a fundamental building block in modern application development. They convert your source code into a secure, efficient, production-ready container image without a Dockerfile. With Choreo, developers can take advantage of this powerful tool to effortlessly deploy their applications without the hassle of manual configuration.

+

Choreo uses Google Buildpacks as default buildpacks for Java, Go, NodeJS, Python, PHP, and Ruby. Choreo uses its own buildpacks for Ballerina and WSO2 MI.

+

Develop a component

+

To develop a service component that exposes a Service in Go, you can follow the Develop a Service guide.

+

Follow the guidelines below based on your language:

+
+
+
+

Supported Versions - 3.10.x, 3.11.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceReading Books List Service
Manual TaskHello World Task
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers.

+
+

Info

+

In Python projects, it is mandatory to have a Procfile with the web process type in the project root directory.

+
+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web: python main.py
+web: gunicorn --bind :8080 --workers 1 --threads 8 --timeout 0 main:app
+web: flask run --host=0.0.0.0

+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 2201.3.5, 2201.4.1, 2201.5.0, 2201.5.1, 201.6.0, 2201.7.0

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceEcho Service
Manual TaskCovid19 Statistics To Email
WebhookSalesforce New Case To Google Sheet
Scheduled TaskShopify New Customers to HubSpot Create/Update Contact
+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 1.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceGreeting Service
Manual TaskHello World Task
Web ApplicationHello World Web Application
+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 6.x, 7.x, 8.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + +
Component TypeExample
ServiceGreeting Service
+

For more examples, see Choreo samples.

+
+
+

Supported Versions + - 8, 11, 17, 18 (OpenJDK Runtime Environment Temurin)

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceProduct Management Service
Manual TaskHello World Task
+
+

Info

+

When working on Java projects:

+
    +
  • The Main class should be defined in the manifest file.
  • +
  • If Maven files such as mvn.cmd exist in the project without the .mvn directory, the build will fail. To ensure a successful build, you must either commit the .mvn directory along with any Maven files or not include any Maven files in the project if you choose not to commit the .mvn directory.
  • +
+
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers. +If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. +In Java projects, it is optional to include a Procfile.

+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web: java -jar target/sample.jar

+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 12.x.x, 14.x.x, 16.x.x, 18.x.x, 20.x.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceReading Books List Service
Manual TaskHello World Task
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers. +If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. +In NodeJS projects, it is optional to include a Procfile.

+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web: node app.js

+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 8.1.x, 8.2.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceHello World Service
Manual TaskHello World Task
Web ApplicationHello World Web Application
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers. +If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. +In PHP projects, it is optional to include a Procfile.

+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web:php -S 0.0.0.0:8000 index.php

+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 3.1.x, 3.2.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + + + + + + + + + +
Component TypeExample
ServiceHello World Service
Manual TaskHello World Task
Web ApplicationHello World Web Application
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers. +If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. +In Ruby projects, it is optional to include a Procfile.

+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web: ruby app.rb
+web:bundle exec ruby app.rb -p 8080

+

For more examples, see Choreo samples.

+
+
+

Supported Versions - 4.1.0.x, 4.2.0.x

+

Refer below examples for different component types. Follow the readme.md inside the example.

+ + + + + + + + + + + + + +
Component TypeExample
ServiceHello World Service
+

For more examples, see Choreo samples.

+
+
+

Supported Java Versions + - 8, 11, 17, 18 (OpenJDK Runtime Environment Temurin)

+
+

Info

+

You can use this buildpack only with web applications. For other component types, use the Java buildpack. Additionally, if the generated artifact is a WAR file, it is necessary to include a Procfile.

+
+

Procfile

+

A Procfile is a configuration file used to declare the commands that are run by your application's containers. +If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. +In Java projects, it is optional to include a Procfile.

+

Here's an example Procfile for an application:

+
web: <command to start your application>
+
+ +

e.g.,

+

web: java -jar target/sample.war

+
+
+
+

Configure build-time environment variables

+

You can configure the environment variables necessary to build the component using the Build Configurations Editor on the component Build page.

+
+

Info

+

The capability to configure build-time environment variables is not available for components created using Ballerina or WSO2 MI buildpacks.

+
+

During the build process, the build-time environment variables and their values are passed to the buildpack. Therefore, you can configure both buildpack-specific environment variables and those required for the component build.

+

For example, if you want to override the Maven command of the Java buildpack, you can use GOOGLE_MAVEN_BUILD_ARGS as the environment key and clean install as the value.

+

For more examples, see Google Cloud's buildpacks documentation.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-a-rest-api-proxy/index.html b/develop-components/develop-a-rest-api-proxy/index.html new file mode 100644 index 000000000..0382539cc --- /dev/null +++ b/develop-components/develop-a-rest-api-proxy/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-a-web-application/index.html b/develop-components/develop-a-web-application/index.html new file mode 100644 index 000000000..0a05f6185 --- /dev/null +++ b/develop-components/develop-a-web-application/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-a-webhook/index.html b/develop-components/develop-a-webhook/index.html new file mode 100644 index 000000000..bd83dd29f --- /dev/null +++ b/develop-components/develop-a-webhook/index.html @@ -0,0 +1,3778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a Webhook - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Webhook

+

Choreo allows developers to design high-quality webhooks. To explore this capability, let's consider a scenario where a team of software engineers in an organization should be notified via email whenever someone creates a GitHub issue with the bug label in a specific repository.

+

In this tutorial, you will address the requirement by doing the following:

+
    +
  • Create a webhook by connecting to a forked GitHub repository where you have the webhook implementation that addresses the described requirement.
  • +
  • Deploy the webhook to the development environment.
  • +
  • Modify the webhook implementation to connect the webhook to GitHub, enabling it to act in response to selected GitHub-related events.
  • +
  • Test the webhook.
  • +
  • Promote the webhook to the production environment.
  • +
+

Prerequisites

+

Before you try out the steps in this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
    8. +
    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample integration for this guide.

    +
  • +
+

Step 1: Create a Webhook component

+

To create a project, add a Webhook component to it, design the webhook, test it, and then commit it to make it available in the Choreo Console, follow these sub-steps:

+

First, let's create a Webhook component as follows:

+
    +
  1. Go to https://console.choreo.dev/, and sign in using your preferred method.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Go to the Webhook card and click Create.
  6. +
  7. This opens the Create a Webhook pane, where you can specify a name and description for the component. Enter a unique name and description.
  8. +
  9. Go to the GitHub tab.
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Select the Access Mode depending on your requirement.

    +
  14. +
  15. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    GitHub AccountYour account
    GitHub Repositorychoreo-samples
    Branchmain
    BuildpackBallerina
    Project Pathgithub-event-to-email-webhook
    +
  16. +
  17. +

    Click Create.

    +
  18. +
+

Choreo creates the Webhook component with the sample implementation and opens the component Overview page.

+

Step 2: Deploy

+

Let's deploy the webhook to the development environment to make it invokable:

+
    +
  1. In the Choreo Console left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Configure & Deploy.
  4. +
  5. +

    In the Configurations pane, enter the following information:

    +
      +
    1. +

      In the webhookSecret field, enter any value.

      +
      +

      Note

      +

      You must save this value for later use.

      +
      +
    2. +
    3. +

      In the toEmail field, enter the email address to send notification emails.

      +
    4. +
    5. Click Deploy.
    6. +
    +

    You can monitor the deployment progress in the Console pane that opens on the right of the page.

    +
  6. +
+

Once Choreo completes the deployment, the Development card indicates the Deployment Status as Active.

+
+

Notes

+

In the deployment card, you can click the icon corresponding to configurables to open the Configurations pane and edit configurations:

+
+

Step 3: Connect the webhook to the GitHub repository

+

To allow the webhook to read the labels of issues in a specific GitHub repository, you must connect the webhook to the GitHub repository. To do this, follow these steps:

+
    +
  1. +

    In the Choreo Console left navigation menu, click Overview.

    +
  2. +
  3. +

    On the Overview page, copy the invoke URL. You can click the copy icon within the URL field.

    +
  4. +
  5. +

    Go to your GitHub account and open the repository for which you want to generate notification emails.

    +
  6. +
  7. +

    In the top menu, click the Settings tab.

    +
  8. +
  9. +

    In the left navigation menu, click Webhooks.

    +
  10. +
  11. +

    Click Add webhook and enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Payload URLThe invoke URL you copied in Step 3, sub-step 1.
    Content TypeSelect application/json
    SecretThe last webhook secret you configured in Step 2.
    +
    +

    Tip

    +
      +
    • +

      Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      +
    • +
    • +

      Project Path specifies the location of the project to build the component.

      +
    • +
    +
    +
  12. +
  13. +

    Under Which events would you like to trigger this webhook?, select Let me select individual events.

    +
  14. +
  15. +

    Select the Issues checkbox in the list of events displayed.

    +

    By doing so, you select GitHub issues as events that need to trigger this webhook.

    +
  16. +
  17. +

    In the same list of events, clear the Pushes checkbox to ensure that GitHub does not trigger your webhook when the team pushes changes to the selected GitHub repository.

    +
  18. +
  19. +

    Click Add webhook to save the configuration.

    +
  20. +
+

Now you have integrated Choreo with GitHub via the webhook you created and deployed. You can proceed to test the webhook.

+

Step 4: Test

+

To test your webhook, create a GitHub issue with the Bug label in the repository that you connected to the webhook.

+

You will receive a mail similar to the following to the email address you provided in Step 2.

+

Step 5: Promote

+

To promote the webhook to the Production environment, follow these steps:

+
    +
  1. +

    On the Deploy page, go to the Development card and click Promote.

    +
  2. +
  3. +

    In the Configuration Types pane, leave the default selection (i.e., Use default configuration values) unchanged.

    +

    If you have configured any default values for the configurable variables, selecting Use default configuration values allows you to proceed with those values.

    +

    If you have not configured any default values for configurable variables, follow the steps given below to specify values.

    +
  4. +
  5. +

    Click Next.

    +
  6. +
  7. +

    In the webhookSecret field, enter any value.

    +
    +

    Note

    +

    You must save this value for later use.

    +
    +
  8. +
  9. +

    In the toEmail field, enter the email address to send notification emails.

    +
  10. +
  11. Click Promote.
  12. +
+

Once the component is promoted to production, the Production card displays the deployment status as Active.

+

Now you have successfully created, deployed, and tested a Webhook component and promoted it to production.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-an-api-proxy/index.html b/develop-components/develop-an-api-proxy/index.html new file mode 100644 index 000000000..4b445dcbe --- /dev/null +++ b/develop-components/develop-an-api-proxy/index.html @@ -0,0 +1,3832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop an API Proxy - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop an API Proxy

+

An API proxy acts as an intermediary between an existing API and Choreo, intercepting all requests made to the API. It also functions as a managed API, which allows you to apply essential API management features such as security policies and rate limiting.

+

In this guide, you will:

+
    +
  • Create an API proxy component to expose an existing API.
  • +
  • Deploy the API proxy.
  • +
  • Test the API proxy to verify its functionality.
  • +
  • Manage the API.
  • +
  • Consume the API.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
+

Step 1: Create an API proxy

+

To create an API proxy, you can either upload an OpenAPI specification or provide an OpenAPI specification URL. In this guide, you will specify a URL to an OpenAPI definition of a sample API.

+

Follow the steps given below:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the API Proxy card. + This opens the Create an API Proxy pane, where you can upload an OpenAPI definition or provide the URL of an OpenAPI. In this guide, you will define resources manually. Therefore, click Skip Source to proceed.
  6. +
  7. +

    Specify the values given in the following table as API proxy details:

    +
    +

    Info

    +

    In the Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Display NameHR API
    Namehr-api
    Contextabc-hr
    Version1.0
    Targethttps://samples.choreoapps.dev/company/hr
    Access ModeExternal
    +
  8. +
  9. +

    Click Create.

    +
  10. +
+

This creates the API proxy component and takes you to the Overview page. Now you can proceed to define resources for the API proxy.

+

Step 2: Define resources for the API proxy

+

To add a new resource that can retrieve a department by the department ID, follow the steps given below:

+
    +
  1. In the left navigation menu, click Develop and then click Resources.
  2. +
  3. Select GET as the HTTP Verb and enter /department/{departmentId} as the URI Pattern.
  4. +
  5. Click + to add the resource.
  6. +
  7. +

    Click to expand the added resource and specify appropriate values for the Operation ID and Description fields. You can specify the values given in the following table:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Operation IDfindDepartment
    DescriptionFind a department by department ID
    +
  8. +
  9. +

    To remove the five default resources that start with /*, click the delete icon corresponding to each resource. This marks the resources for deletion.

    +
  10. +
  11. Click Save.
  12. +
+

Step 3: Deploy the API proxy

+

To deploy the API proxy to the development environment, follow the steps given below:

+
    +
  1. +

    In the left navigation menu, click Deploy.

    +
  2. +
  3. +

    In the Build Area card, click Configure & Deploy. This opens the Configure & Deploy pane, where you can select the API access mode depending on how you want the API to be accessible. Here, you can select External.

    +
  4. +
  5. +

    Click Deploy. The Development card indicates the Deployment Status as Active when the API proxy is successfully deployed.

    +
  6. +
+

Now you are ready to test the API proxy.

+

Step 3: Test the API proxy

+

Choreo allows you to test your API proxy using either the integrated OpenAPI Console or cURL.

+

In this guide, you will use the OpenAPI Console to test the API proxy.

+

Follow the steps given below:

+
+

Tip

Choreo enables OAuth 2.0 to secure APIs by default. Therefore, you need an access token to invoke an API.

+
    +
  • Choreo automatically generates a key to test the API via the OpenAPI Console. To view the key, click the show key icon in the Security Header field.
  • +
  • Choreo allows you to disable security for an entire API or a specific API resource for testing purposes. If you want to disable security, follow these steps:
      +
    1. In the left navigation menu, click Deploy.
    2. +
    3. Go to the Build Area card and click Security Settings.
    4. +
    5. In the Security Settings pane, perform one of the following actions depending on your requirement:
        +
      • To disable security for the entire API, clear the OAuth2 checkbox.
      • +
      • To disable security for a specific API resource, go to the Permissions section, click to expand the relevant resource and then turn off the Security toggle.
      • +
      +
    6. +
    7. Click Apply.
    8. +
    +
  • +
+

+
+
    +
  1. +

    In the left navigation menu, click Test and then click OpenAPI Console.

    +
  2. +
  3. +

    Select Development from the environment drop-down list.

    +
  4. +
  5. +

    Expand the GET /department/{departmentId} resource and click Try it Out to test it.

    +
  6. +
  7. +

    Enter 1 as the departmentId and click Execute. You will see a response similar to the following:

    +

    API proxy response

    +
  8. +
+

This indicates that your API proxy is working as expected.

+

Step 4: Manage the API proxy

+

Now that you have a tested API proxy, you can publish it and make it available for application developers to consume. Depending on your requirement, you can apply security, throttling, and other settings to the API before you publish it.

+

In this guide, you will apply rate limiting to the API and publish it.

+

Step 4.1: Apply a rate limiting level to the API proxy

+

To apply a rate limiting level to the API, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. Go to the required environment card and click the setting icon corresponding to API Configuration.
  4. +
  5. In the API Configuration pane that opens, click Rate Limiting to expand the section.
  6. +
  7. Select API Level as the Rate Limiting Level.
  8. +
  9. Specify appropriate values for the Request Limit and Time Unit fields. In this guide, you can proceed with the default values. + This applies a rate-limiting policy to the entire API. If necessary, you can also apply rate limits at the operation level. For more information, see API Rate Limiting.
  10. +
  11. Click Apply. This applies the rate limiting level to the API proxy and redeploys it.
  12. +
+

Step 4.2: Publish the API proxy

+

To publish the API proxy to the Choreo Developer Portal, follow the steps given below:

+
    +
  1. In the left navigation menu, click Lifecycle under Manage. This takes you to the Lifecycle page where you can see the different lifecycle stages the API can be in. You can see that the current lifecycle stage is Created.
  2. +
  3. Click Publish.
  4. +
  5. In the Publish API dialog that opens, click Confirm to proceed publishing the API with the specified display name. If you want to change the display name, make the necessary changes and then click Confirm. This changes the API lifecycle state to Published.
  6. +
+

Step 5: Invoke the API

+

To generate credentials for the published API and to invoke it via the Choreo Developer Portal, follow the steps below:

+
    +
  1. +

    To open the published API in the Choreo Developer Portal via the Lifecycle page, click Go to Devportal. This takes you to the HR API in the Choreo Developer Portal.

    +
  2. +
  3. +

    To generate credentials to test the API, follow the steps given below:

    +
      +
    1. In the Developer Portal left navigation menu, click Production under Credentials.
    2. +
    3. +

      Click Generate Credentials. Choreo generates new tokens and populates the Consumer Key and Consumer Secret fields.

      +
      +

      Tip

      +

      If you want to test the API via an API test tool or through code, click Generate Access Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client. You do not need to generate an access token if you are testing the API via the Try Out capability in the Choreo Developer Portal.

      +
      +
    4. +
    +
  4. +
  5. +

    To invoke a resource via the Try Out capability in the Choreo Developer Portal, follow the steps given below:

    +
      +
    1. In the Developer Portal left navigation menu, click Try Out.
    2. +
    3. In the Endpoint list, select Development as the environment to try out the API.
    4. +
    5. To generate an access token to try out the API, click Get Test Key. This populates the Access Token field with a test key.
    6. +
    7. Expand the GET /department/{departmentId} resource and click Try it out.
    8. +
    9. +

      Enter 1 as the departmentId and click Execute. You will see a response similar to the following:

      +

      Try out response

      +
    10. +
    +
  6. +
+

Now, you have gained hands-on experience creating, deploying, testing, and publishing an API proxy using Choreo API Manager.

+

To learn more about the API management capabilities supported by Choreo API Manager, see API Management.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-components-using-vs-code/index.html b/develop-components/develop-components-using-vs-code/index.html new file mode 100644 index 000000000..bc125e9b5 --- /dev/null +++ b/develop-components/develop-components-using-vs-code/index.html @@ -0,0 +1,3662 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop Components Using VS Code - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop Components Using VS Code

+

The Choreo VS Code extension provides comprehensive component management capabilities to streamline local development within Choreo.

+

Prerequisites

+

To ensure a smooth development experience with the Choreo extension, make sure you have the following:

+
    +
  1. +

    Visual Studio Code installed with the Choreo extension version 2.0.0 or later.

    +
  2. +
  3. +

    A locally cloned GitHub repository to create new components or link to existing Choreo components.

    +
  4. +
  5. +

    Git version 2.0.0 or later.

    +
  6. +
+

Get started

+

To use the capabilities of the Choreo extension in the VS Code editor, you need an active Choreo account. If you already have an account, follow these steps to set up the extension:

+
    +
  1. Install the Choreo VS Code extension and wait for activation. On successful activation, the Choreo extension opens in the VS Code editor.
  2. +
  3. +

    Sign in to Choreo using one of the following methods:

    +
      +
    • In the Choreo activity pane, click Sign In. + Sign in
    • +
    • Use the Sign In command provided by the Choreo extension.
    • +
    +

    This redirects you to an external URI to complete the authentication process. On successful sign-in, the Choreo activity pane displays your account details along with any components detected within the VS Code workspace.

    +
  4. +
+

Create a new component

+
    +
  1. Open the source code directory where you want to build, deploy, and manage components using Choreo.
  2. +
  3. +

    Create a new component using one of the following methods:

    +
      +
    • In the Choreo activity pane, click Create Component. + Create Component Button
    • +
    • Use the Create New Component command provided by the Choreo extension.
    • +
    +
  4. +
  5. +

    If the Choreo extension cannot determine the project context of the opened workspace, it prompts you to select the organization and the project to which the new component belongs.

    +
  6. +
  7. +

    Specify component details such as the name, type, buildpack, etc.

    +

    Component Form

    +

    On successful creation, the component details view opens, and the Choreo activity pane displays the new component.

    +

    Component Details

    +
    +

    Tip

    +

    Once the component is created, a .choreo/context.yaml file is generated in the root of the Git repository. For more details, see Understand the project context.

    +
    +
  8. +
+

The component details view allows you to manage your component by performing various actions such as the following:

+
    +
  • Triggering builds for selected commits.
  • +
  • Viewing lists of builds and statuses.
  • +
  • Diagnosing build failures with build logs.
  • +
  • Deploying builds in available environments.
  • +
  • Accessing runtime logs and deployed component URLs.
  • +
  • Invoking deployed service endpoints.
  • +
+

Understand the project context

+

Context files contain metadata related to the project, allowing the extension to establish an association between local directories and Choreo projects. These files, such as the context.yamlfile, resides in the /.choreo directory within the root of the Git repository.

+

The Choreo extension scans the root of the opened Git repository to find the context.yaml file and lists the components of the associated project. This allows you to easily open and manage the components they are developing within the VS Code workspace.

+

A context.yaml file can contain multiple projects, whereas, a workspace opened via VS Code can have multiple context.yaml files with different project associations. In such cases, VS Code allows you to switch between these projects, add new project associations, or remove existing ones, allowing you as a developer to focus on components of a particular project at a time.

+

You can decide whether to commit the context.yaml file to the Git repository. Committing this file enables other team members working on the same repository to have a seamless developer experience with Choreo.

+

If the context.yaml file for a particular project is not committed to the Git repository or is unavailable for other reasons, you can easily regenerate it using one of the following methods:

+
    +
  • In the Choreo activity pane, click Link Directory. + Link Directory
  • +
  • Use the Link Directory command provided by the Choreo extension.
  • +
+

Discover additional features

+

To access a range of functionalities provided by the Choreo extension, open the VS Code command palette and type Choreo.

+

Troubleshoot issues

+

To troubleshoot Choreo extension issues, follow these steps:

+
    +
  1. +

    To open the OUTPUT pane, go to the VS Code editor main menu, click View, and then click Output.

    +
  2. +
  3. +

    Select Choreo from the drop-down menu on the right-hand side to view the Choreo output for troubleshooting.

    +
  4. +
+

Get help

+

For assistance with the Choreo VS Code extension, create GitHub issues.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-components-with-git/index.html b/develop-components/develop-components-with-git/index.html new file mode 100644 index 000000000..52eda8300 --- /dev/null +++ b/develop-components/develop-components-with-git/index.html @@ -0,0 +1,3717 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop Components With Git - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop Components With Git

+

Choreo enables you to develop components by connecting your GitHub, Bitbucket, or GitLab repository. You have the flexibility to either connect an existing repository or start with an empty repository and commit the source code later. By integrating your repositories with Choreo, you can automate tasks and optimize workflows across multiple systems, all within the Choreo platform. Choreo currently supports GitHub, Bitbucket, and GitLab as Git providers.

+
+

Tip

+

Choreo supports both Bitbucket Server and Bitbucket Cloud. The currently supported Bitbucket Server version is 8.9.2.

+
+

In Choreo, you can connect a Git repository that contains Ballerina source code or a Docker project. To connect a Git repository to Choreo as a Docker project, your Git repository must include the following:

+
    +
  • A Dockerfile: Specifies the instructions to build the Docker image.
  • +
  • A build context: A set of files in the specified path used to build the image.
  • +
+

Once you connect your Git repository to Choreo, you can build, deploy, and manage your application easily.

+

Connect a Git repository to Choreo

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Choreo Console header, go to the Organization list and select your organization.
  4. +
  5. In the left navigation menu, click Settings. This opens the organization-level settings page.
  6. +
  7. Click the Credentials tab.
  8. +
  9. Click +Add Credentials to configure the Git repository connection.
  10. +
  11. Enter a Credential Name, select the Git provider, and enter the Personal Access Token you obtained from the Git provider.
  12. +
  13. Click Save.
  14. +
+

Authorize GitHub with Choreo

+

Authorizing Choreo as a GitHub application grants Choreo the following permissions to perform the respective actions on your behalf within the repository:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PermissionReadWriteDescription
IssuesYNRead component ID label to filter the pull requests
MetadataYNList repositories
ContentsYYList branches and create a branch to commit sample code
Pull RequestYYCreate a pull request if you start with a Choreo sample
WebhooksYYTrigger automatic deployment and configuration generation
+

Add Git submodules to a project

+

Choreo provides Git submodule support when you connect your GitHub repository to Choreo. This allows you to manage and include external repositories effectively within Choreo build pipelines. Key benefits of this capability include:

+
    +
  • Code sharing without duplication: Use submodules to maintain shared libraries across multiple projects, ensuring a single source of truth.
  • +
  • Efficient third-party library management: Manage third-party libraries as submodules to update them independently and track changes easily, avoiding direct code integration.
  • +
+

For example, when you work with the Micro Integrator (MI) runtime in Choreo, you can use Git submodules to reuse MI templates and sequences across components without duplication.

+
+

Tip

+

If you encounter an error stating that you cannot clone a submodule due to insufficient permissions, follow the instructions below to grant the necessary permissions:

+
    +
  • +

    For a personal account:

    +
      +
    1. Sign in to your personal GitHub account.
    2. +
    3. In the upper-right corner, click your profile picture, and then click Settings.
    4. +
    5. In the left navigation menu, go to the Integrations section and click Applications.
    6. +
    7. Under the Installed GitHub Apps tab, click Configure corresponding to choreo.dev.
    8. +
    9. Under Repository Access, grant access to the necessary repositories.
    10. +
    +
  • +
  • +

    For an organization account:

    +
      +
    1. Sign in to your organization's GitHub account.
    2. +
    3. In the upper-right corner, click your profile picture, and then click Settings.
    4. +
    5. In the left navigation menu, go to the Third-Party Access section and click GitHub Apps.
    6. +
    7. Click Configure corresponding to choreo.dev.
    8. +
    9. +

      Under Repository Access, grant access to the necessary repositories.

      +
      +

      Note

      +

      Choreo currently does not support accessing private repositories in other organizations.

      +
      +
    10. +
    +
  • +
+
+

Authorize Bitbucket with Choreo

+

Authorizing using a personal access token (PAT) from Bitbucket grants Choreo the following permissions to perform the respective actions on your behalf within the repository.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PermissionReadWriteDescription
AccountYNGet user information and workspace details
RepositoriesYYList branches and create a branch to commit sample code
Pull RequestsYYCreate a pull request if you start with a Choreo sample
WebhooksYYTrigger automatic deployment and configuration generation
+

Authorize self-managed GitLab with Choreo

+

Authorizing using a personal access token (PAT) obtained from your GitLab self-managed server grants Choreo the following permissions to perform the respective actions on your behalf within the repository.

+ + + + + + + + + + + + + +
PermissionDescription
APIGrants full read/write access to the API, covering all groups and projects, as well as read/write access to the repository.
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-integrations/develop-a-manual-task/index.html b/develop-components/develop-integrations/develop-a-manual-task/index.html new file mode 100644 index 000000000..c080cc084 --- /dev/null +++ b/develop-components/develop-integrations/develop-a-manual-task/index.html @@ -0,0 +1,3914 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a Manual Task - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Manual Task

+

This guide walks you through the steps to develop, deploy, test, and observe a manual task using Choreo.

+

In this guide, you will:

+
    +
  • Develop a manual task to fetch the weather forecast for a specified location for the next 24 hours from the OpenWeatherMap API.
  • +
  • Process the weather data to a specific format.
  • +
  • Send the formatted data to a specified email address.
  • +
+

Prerequisites

+

Before you try out the steps in this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
    8. +
    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample integration for this guide.

    +
    +

    Repository file structure

    +

    To work with the sample repository, it is important to familiarize yourself with the repository file structure. The sample code for this guide is in the <sample-repository-dir>/weather-to-email-integration directory. To understand how the functionality is implemented, you must read the code comments. The following table describes what you will find in each file in the repository:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    File pathFile content
    Ballerina.tomlContains metadata about the project
    Dependencies.tomlLists the dependencies required for the project
    main.balContains the entry point of the project, including the main function
    types.balContains custom data types used in the project
    utils.balContains utility functions and helper functions used in the project
    +
    +
  • +
  • +

    Go to OpenWeatherMap and sign up to obtain an API key. For details on how to obtain an API key, see the OpenWeatherMap documentation.

    +
  • +
+

Step 1: Create a manual task component

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Manual Task card.
  6. +
  7. +

    Enter a unique name and a description for the component. You can use the name and description given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Component NameWeatherToEmail
    DescriptionMy first manual task
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    BuildpackBallerina
    Project Directoryweather-to-email-integration
    +
    +

    Tip

    +
      +
    • +

      Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      +
    • +
    • +

      Project Directory specifies the location of the project to build the component.

      +
    • +
    +
    +
  14. +
  15. +

    Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    +
  16. +
+

Step 2: Build the manual task

+

To build the manual task, follow the steps given below:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. In the Builds pane, click Build. This opens the Commits pane where you can see all the commits related to the component.
  4. +
  5. +

    Select the latest commit and click Build. This triggers the build process and displays the build progress in the Build Logs pane.

    +
    +

    Info

    +

    The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with the build status.

    +
    +
  6. +
+

Here, you will see the build status as Success.

+

Step 3: Deploy the manual task

+

To deploy the manual task, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. +

    In the Configurations pane, specify values as follows for the configurable variables:

    +
    +

    Tip

    +

    The configurable variables populated here are defined in the sample Ballerina project used in this guide. To learn how to declare configurable variables in Ballerina, see the Ballerina documentation on declaring configurable variables. If configurable variables are detected in a connected Ballerina project, Choreo prompts for the respective values during component deployment.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    apiKeyThe API key you obtained in the prerequisites section
    latitudeLatitude of the location to get the weather forecast
    longitudeLongitude of the location to get the weather forecast
    emailThe email address to receive the formatted weather forecast information
    +
    +

    Note

    +

    If you use Ballerina as the buildpack and you want to set a configurable variable as a secret, click the lock icon corresponding to the configurable variable. This marks it as a secret and conceals the input value.

    +

    For example, if you consider the configurable variables in this guide and set the apiKey as a secret, its input value will be concealed as follows:

    +

    Configurable variable as a secret

    +

    If you want to update the input value at a later time, you can click Update Secret Content and specify a new value.

    +

    Update secret

    +
    +
  6. +
  7. +

    Click Deploy.

    +
  8. +
+

Step 4: Execute the manual task

+

To execute the manual task, follow the steps given below:

+
    +
  1. In the left navigation menu, click Execute.
  2. +
  3. +

    Click Run Now. This triggers the task.

    +
    +

    Inject dynamic values into your application as command-line arguments

    +

    If you want to inject dynamic values into your application as command-line arguments when you run a manual task, follow the steps given below:

    +
      +
    1. Click the drop-down icon next to Run Now and then click Run with Arguments.
    2. +
    3. In the Runtime Arguments pane that opens, enter the arguments you want to pass to your application.
    4. +
    5. Click Execute. This triggers the task with the specified arguments.
    6. +
    +

    The capability to run a manual task with arguments is supported for the following buildpacks:

    +
    +
    +
    +

    To explore a Dockerfile-based manual task with arguments, try out the Hello World Task sample. For instructions, see the readme.md file in the sample repository.

    +
    +

    Info

    +

    When you work on Docker projects, the Run with Arguments capability is not supported if the Dockerfile contains CMD. In such scenarios, you must use ENTRYPOINT to define your default commands.

    +
    +
    +
    +

    To explore a Go-based manual task with arguments, try out the Hello World Go Task sample. For instructions, see the readme.md file in the sample repository.

    +
    +
    +

    To explore a Java-based manual task with arguments, try out the Hello World Java Task sample. For instructions, see the readme.md file in the sample repository.

    +
    +

    Info

    +

    When you work on Java projects:

    +
      +
    • The Run with Arguments capability is not supported if Procfile is available in the project.
    • +
    • The Main class should be defined in the manifest file.
    • +
    • If Maven files such as mvn.cmd exist in the project without the .mvn directory, the build will fail. To ensure a successful build, you must either commit the .mvn directory along with any Maven files or not include any Maven files in the project if you choose not to commit the .mvn directory.
    • +
    +
    +
    +
    +

    To explore a NodeJS-based manual task with arguments, try out the Hello World NodeJS Task sample. For instructions, see the readme.md file in the sample repository.

    +
    +

    Info

    +

    When you work on NodeJS projects:

    +
      +
    • The Run with Arguments capability is not supported if Procfile is available in the project.
    • +
    • The project root must contain the package.json file with the main attribute defined.
    • +
    +
    +
    +
    +

    To explore a WSO2 MI-based manual task with arguments, try out the Weather to Logs Task sample. For instructions, see the readme.md file in the sample repository.

    +
    +

    Info

    +

    When you work on WSO2 MI projects and you want to deploy a WSO2 MI integration as a manual task in Choroeo, you must use the WSO2 MI automation mode. For details, see Running the Micro Integrator in Automation Mode.

    +
    +
    +
    +

    To explore a Ballerina manual task with arguments, try out the Weather to Email Task sample. For instructions, see the README.md file in the sample repository.

    +
    +

    Info

    +

    If you want to pass arguments to Ballerina main functions, you can use the Run with Arguments capability. For details on the arguments you can pass, see the Ballerina documentation. You can also override configurable values in the same manner. For more information, see Provide values to configurable variables.

    +
    +
    +
    +
    +
    +
  4. +
+

Step 5: Test the manual task

+

Once the task is triggered, an email with the subject [WSO2 Choreo Demo] Next 24H Weather Forecast is sent from choreo.demo@gmail.com to the email address specified as the email configurable variable value in Step 3.

+

If the manual task ran successfully, you should receive an email similar to the following to the email address you specified:

+

Received email

+

Step 6: Observe the manual task

+

The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

+

To visualize and monitor the performance of the manual task you deployed, click Observability in the left navigation menu. You can observe the following:

+
    +
  • The throughput and latencies of requests served over a given period.
  • +
  • The logs that are generated over a given period.
  • +
  • The flame graph (Diagnostics View) that is generated over a given period.
  • +
  • The low-code diagram.
  • +
+

To learn more about the observability details you can view via Choreo observability, see Observability Overview.

+

Step 7: Monitor executions

+

To track and monitor executions associated with the deployed scheduled task, go to the left navigation menu and click Execute.

+
+

Tip

+

The Execute view is applicable to both scheduled and manual tasks.

+
+

You can view the following information:

+
    +
  • +

    The total number of executions within the past 30 days.

    +

    Total Execution

    +
  • +
  • +

    The currently active executions and those that are already complete.

    +

    Here, you can view information such as the execution ID, the revision of the execution, and the time it was triggered.

    +

    Execution History

    +
  • +
  • +

    Detailed execution logs for a specific execution.

    +

    You can click on an execution to view detailed logs related to it.

    +
    +

    Info

    +

    It may take a few minutes for the logs to appear. You may need to manually refresh to view the latest logs.

    +
    +

    Execution History

    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-integrations/develop-a-scheduled-task/index.html b/develop-components/develop-integrations/develop-a-scheduled-task/index.html new file mode 100644 index 000000000..b294d82c7 --- /dev/null +++ b/develop-components/develop-integrations/develop-a-scheduled-task/index.html @@ -0,0 +1,3869 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a Scheduled Task - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Scheduled Task

+

Choreo is a versatile integration platform that allows you to create various types of integrations depending on your requirement.

+

If you have a requirement to automatically run a specific integration at regular intervals, you can use Choreo to develop a scheduled task. This type of integration can automate the synchronization of data between different systems at specified intervals, reducing errors and improving productivity by eliminating the need for manual intervention.

+

This guide walks you through the steps to develop, deploy, test, and observe a scheduled task using Choreo.

+

In this guide, you will:

+
    +
  • Develop a scheduled task to fetch the weather forecast for a specified location for the next 24 hours from the OpenWeatherMap API.
  • +
  • Process the weather data to a specific format.
  • +
  • Send the formatted data to a specified email address at a specific time every day.
  • +
+

Prerequisites

+

Before you try out the steps in this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
    8. +
    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample integration for this guide.

    +
    +

    Repository file structure

    +

    To work with the sample repository, it is important to familiarize yourself with the repository file structure. The sample code for this guide is in the <sample-repository-dir>/weather-to-email-scheduled-task directory. To understand how the functionality is implemented, you must read the code comments. The following table describes what you will find in each file in the repository:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    File pathFile content
    Ballerina.tomlContains metadata about the project
    Dependencies.tomlLists the dependencies required for the project
    main.balContains the entry point of the project, including the main function
    types.balContains custom data types used in the project
    utils.balContains utility functions and helper functions used in the project
    +
    +
  • +
  • +

    Go to OpenWeatherMap and sign up to obtain an API key. For details on how to obtain an API key, see the OpenWeatherMap documentation.

    +
  • +
+

Step 1: Create a scheduled task component

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Scheduled Task card.
  6. +
  7. +

    Enter a unique name and a description for the component. You can use the name and description given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Component NameWeatherToEmail
    DescriptionMy first scheduled task
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    BuildpackBallerina
    Project Directoryweather-to-email-scheduled-task
    +
    +

    Tip

      +
    • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.
    • +
    +

    +
      +
    • Project Directory specifies the location of the project to build the component.
    • +
    +
    +
  14. +
  15. +

    Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    +
  16. +
+

Now you can proceed to build and deploy the scheduled task.

+

Step 2: Build the scheduled task

+

To build the scheduled task, follow the steps given below:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. In the Builds pane, click Build. This opens the Commits pane where you can see all the commits related to the component.
  4. +
  5. +

    Select the latest commit and click Build. This triggers the build process and displays the build progress in the Build Logs pane.

    +
    +

    Info

    +

    The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with the build status.

    +
    +
  6. +
+

Here, you will see the build status as Success.

+

Step 3: Deploy the scheduled task

+

To deploy the scheduled task, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. +

    In the Configurations pane, specify values as follows for the configurable variables:

    +
    +

    Tip

    +

    The configurable variables populated here are defined in the sample Ballerina project used in this guide. To learn how to declare configurable variables in Ballerina, see the Ballerina documentation on declaring configurable variables. If configurable variables are detected in a connected Ballerina project, Choreo prompts for the respective values during component deployment.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    apiKeyThe API key you obtained in the prerequisites section
    latitudeLatitude of the location to get the weather forecast
    longitudeLongitude of the location to get the weather forecast
    emailThe email address to receive the formatted weather forecast information
    +
    +

    Note

    +

    If you use Ballerina as the buildpack and you want to set a configurable variable as a secret, click the lock icon corresponding to the configurable variable. This marks it as a secret and conceals the input value.

    +

    For example, if you consider the configurable variables in this guide and set the apiKey as a secret, its input value will be concealed as follows:

    +

    Configurable variable as a secret

    +

    If you want to update the input value at a later time, you can click Update Secret Content and specify a new value.

    +

    Update secret

    +
    +
  6. +
  7. +

    Click Next.

    +
  8. +
  9. +

    In this step, you must define a schedule to run the task. In this guide, you set the schedule to receive the weather information daily at 8.00 AM UTC. Enter values as follows to configure the schedule:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Select Time ZoneSelect a time zone to schedule the task
    Select RangeDay
    Every1
    At08:00
    +
    +

    Tip

    +

    When you develop a scheduled task, you can define a schedule depending on your requirement. If you want to test and verify the immediately, you can schedule the deployment to run in just a few minutes after you create it. However, to avoid unnecessary expenses, make sure you reschedule or stop the deployment once you test and verify.

    +
    +
  10. +
  11. +

    Click Deploy. This deploys the scheduled task to the development environment and indicates the Scheduled Status as Active in the Development card.

    +
  12. +
+

You can test the scheduled task when it runs at the configured time.

+

Step 4: Test the scheduled task

+

When the scheduled task runs at the configured time, an email with the subject [WSO2 Choreo Demo] Next 24H Weather Forecast is sent from choreo.demo@gmail.com to the email address specified as the email configurable variable value in Step 3.

+

If the scheduled task ran successfully, you should receive an email similar to the following to the email address you specified:

+

Received email

+

Step 5: Observe the scheduled task

+

The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

+

To visualize and monitor the performance of the scheduled task you deployed, click Observability in the left navigation menu. You can observe the following:

+
    +
  • The throughput and latencies of requests served over a given period.
  • +
  • The logs that are generated over a given period.
  • +
  • The flame graph (Diagnostics View) that is generated over a given period.
  • +
  • The low-code diagram.
  • +
+

To learn more about the observability details you can view via Choreo observability, see Observability Overview.

+

Step 6: Monitor executions

+

To track and monitor executions associated with the deployed scheduled task, go to the left navigation menu and click Execute.

+
+

Tip

+

The Execute view is applicable to both scheduled and manual tasks.

+
+

You can view the following information:

+
    +
  • +

    The total number of executions within the past 30 days.

    +

    Total Execution

    +
  • +
  • +

    The currently active executions and those that are already complete.

    +

    Here, you can view information such as the execution ID, the revision of the execution, and the time it was triggered.

    +

    Execution History

    +
  • +
  • +

    Detailed execution logs for a specific execution.

    +

    You can click on an execution to view detailed logs related to it.

    +
    +

    Info

    +

    It may take a few minutes for the logs to appear. You may need to manually refresh to view the latest logs.

    +
    +

    Execution History

    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-integrations/develop-an-event-handler/index.html b/develop-components/develop-integrations/develop-an-event-handler/index.html new file mode 100644 index 000000000..c7a2b62b9 --- /dev/null +++ b/develop-components/develop-integrations/develop-an-event-handler/index.html @@ -0,0 +1,3707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop an Event Handler - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop an Event Handler

+

An Event Handler executes predefined actions in response to specific events. Choreo simplifies the process of creating and deploying such integrations.

+

This guide walks you through the steps to create and deploy an Event Handler using WSO2 MI and Choreo.

+

In this guide, you will build a simple event handler that monitors RabbitMQ for new messages and displays them once they become available.

+

Prerequisites

+

Before you try out the steps in this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
    8. +
    +
  • +
  • +

    Use an existing RabbitMQ instance or start a new RabbitMQ instance on a server that can be accessed via the internet. Obtain the username, hostname, password, and vhost from the RabbitMQ instance to use later as environment variables.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample integration for this guide.

    +
  • +
+

Step 1: Create an event handler component

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Event Handler card.
  6. +
  7. +

    Enter a unique name and a description for the component. You can use the name and description given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Component NameSalesOrderListener
    DescriptionRabbitMQ integration
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    BuildpackWSO2 MI because you are creating the REST API from a WSO2 Integration Studio project
    Project Directorymi-rabbitmq-listener
    +
    +

    Tip

      +
    • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.
    • +
    +

    +
      +
    • Project Directory specifies the location of the project to build the component.
    • +
    +
    +
  14. +
  15. +

    Click Create.

    +
  16. +
+

Step 2: Deploy the integration

+

To deploy the integration, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Configure & Deploy.
  4. +
  5. +

    In the Configurations pane, click + Add corresponding to Environment Variables and add the following environment variables:

    +
    +

    Tip

    Use the values from your RabbitMQ instance as per the Prerequisites section, for the environment variables.

    +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameValue
    HOSTNAMEHostname of your RabbitMQ server
    VHOSTVirtual hostname of your RabbitMQ server
    USERNAMEUsername for connecting to RabbitMQ
    PASSWORDPassword associated with the RabbitMQ username
    +
  6. +
  7. +

    Click Deploy. This deploys the event handler to the development environment and indicates the Deployment Status as Active in the Development card.

    +
  8. +
+

Step 3: Test the integration

+

To test the integration, follow the steps given below:

+
    +
  1. Send a sales order message to the SalesOrderQueue on the RabbitMQ server.
      +
    • You can send a sample sales order message similar to the following: +
      {
      +    "order_id": "12345",
      +    "customer_name": "John Doe",
      +    "product": "Widget",
      +    "quantity": 10,
      +    "total_amount": 100.00
      +}
      +
    • +
    +
  2. +
  3. Observe the logs:
      +
    • In the left navigation menu, click Logs and then click Runtime Logs. You will see the order message in the logs.
    • +
    +
  4. +
+

Now you have gained hands-on experience in creating, configuring, and deploying an event handler.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-integrations/develop-an-integration-with-integration-studio/index.html b/develop-components/develop-integrations/develop-an-integration-with-integration-studio/index.html new file mode 100644 index 000000000..0d488d105 --- /dev/null +++ b/develop-components/develop-integrations/develop-an-integration-with-integration-studio/index.html @@ -0,0 +1,3721 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop an Integration with Integration Studio - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop an Integration with Integration Studio

+

The seamless integration of APIs, microservices, applications, and data across different languages and formats requires the ability to expose integrations as APIs. Choreo simplifies building, deploying, and managing integration components, making it easy for you to quickly expose integrations as APIs.

+
+

Note

+
    +
  • To develop integrations that you need to use in Manual Task and Schedule Task components in Choreo, you need to use the automation mode in the WSO2 Micro Integrator. See Running MI in Automation Mode.
  • +
  • To develop integrations for any other component types (Service, webhook, event-handler, etc) you need to use the server mode.
  • +
+
+

This guide walks you through the steps to expose an integration you created in WSO2 Integration Studio as an API in Choreo.

+

In this guide, you will:

+
    +
  • Create a component to expose the sample integration in the Choreo samples repository as an API.
  • +
  • Deploy, test, and observe the integration component.
  • +
  • Publish the integration component as an API to the Choreo Developer Portal.
  • +
+

Prerequisites

+

Before you try out the steps in this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
    8. +
    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample integration for this guide.

    +
  • +
+

Step 1: Create the integration component

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a unique name and a description for the component. You can enter the name and description given below:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Component NameHello World
    DescriptionHello World REST API
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    BuildpackWSO2 MI because you are creating the REST API from a WSO2 Integration Studio project
    Project Directoryhello-world-mi
    +
  14. +
  15. +

    Click Create. Choreo initializes the component with the sample integration.

    +
  16. +
+

Step 2: Deploy the integration component

+

To deploy the integration component to the development environment, follow the steps given below:

+
    +
  1. In the Choreo Console left navigation menu, click Deploy.
  2. +
  3. In the Build Area card, click Configure & Deploy.
  4. +
  5. In the Configurations pane, click Next. This displays details of the endpoint ready to be deployed.
  6. +
  7. +

    Click Deploy. This deploys the integration component to the development environment. +The Development card indicates the Deployment Status as Active when the integration is successfully deployed.

    +
    +

    Tip

    +

    Choreo uses endpoints to expose Service component to the network. You can read more about configuring endpoints in Configure Endoints.

    +
    +
    +

    Tip

    +

    Automatic deployment is enabled for the component by default. Therefore, you are required to perform only the first deployment manually.

    +
    +
  8. +
+

Now you can test the integration.

+

Step 3: Test the integration

+

To test the integration using the OpenAPI Console. Follow the steps given below:

+
    +
  1. In the Choreo Console left navigation menu, click Test and then click Console.
  2. +
  3. In the OpenAPI Console that opens, select Development from the environment drop-down list.
  4. +
  5. Click to expand the GET /integration operation.
  6. +
  7. Click Try it out and then click Execute. This sends a request to your deployed integration.
  8. +
  9. +

    Go to the Response body section and observe the response returned by the integration. If the integration works as expected, you should see a response similar to the following:

    +

    {"Hello" : "Integration"}

    +
  10. +
+

Step 4: Observe the integration

+

The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

+

To visualize and monitor the performance of the integration component you deployed, click Observability in the left navigation menu. You can observe the following:

+
    +
  • The throughput and latencies of requests served over a given period.
  • +
  • The logs that are generated over a given period.
  • +
  • The flame graph (Diagnostics View) that is generated over a given period.
  • +
+

To learn more about the observability details you can view via Choreo observability, see Observability Overview.

+

Step 5: Publish the integration component

+

To publish the integration component, follow the steps given below:

+
    +
  1. In the Choreo Console left navigation menu, click Manage and then click Lifecycle. This opens the Lifecycle Management pane, where you can see the different lifecycle stages that an API can be in. You can see that the current lifecycle stage is Created.
  2. +
  3. In the Lifecycle Management pane, click Publish. This changes the API lifecycle stage to Published and exposes the integration as an API in the Choreo Developer Portal.
  4. +
+

To open the published API in the Developer Portal via the Lifecycle Management pane, click Go to Devportal. In the Choreo Developer Portal, you can view the published API, manage subscriptions for it, and generate access tokens for testing purposes.

+

Now, you have gained hands-on experience in exposing an integration designed using WSO2 Integration Studio as a REST API in Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/develop-a-ballerina-graphql-api/index.html b/develop-components/develop-services/develop-a-ballerina-graphql-api/index.html new file mode 100644 index 000000000..973aa5be2 --- /dev/null +++ b/develop-components/develop-services/develop-a-ballerina-graphql-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-ballerina-rest-api/index.html b/develop-components/develop-services/develop-a-ballerina-rest-api/index.html new file mode 100644 index 000000000..04ce966b6 --- /dev/null +++ b/develop-components/develop-services/develop-a-ballerina-rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-ballerina-service/index.html b/develop-components/develop-services/develop-a-ballerina-service/index.html new file mode 100644 index 000000000..29442ef0b --- /dev/null +++ b/develop-components/develop-services/develop-a-ballerina-service/index.html @@ -0,0 +1,3791 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a Ballerina Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Ballerina Service

+

Choreo allows you to develop and deploy applications using your preferred programming language. This guide demonstrates how to deploy a service component that exposes a REST API using the Ballerina language. No prior knowledge of the Ballerina language is required to follow this guide.

+

A REST API is a web service adhering to Representational State Transfer (REST) principles, using HTTP methods to access and manage resources. This guide walks you through building a Ballerina service component, deploying it on Choreo, and using it with an HTTP client application.

+

In this guide, you will:

+
    +
  • +

    Build a simple greeting service using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.

    +
      +
    • +

      Request:

      +

      $ curl GET http://localhost:9090/greeter/greet?name=Ballerina

      +
    • +
    • +

      Response:

      +

      $ hello Ballerina!

      +
    • +
    +
  • +
  • +

    Deploy the service in Choreo. The service will run on port 9090.

    +
  • +
  • Test the service.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample greetings service implementation in Ballerina.

    +
  • +
+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

+
+

Note

+

The specified file paths are relative to <sample-repository-dir>/greeting-service.

+
+ + + + + + + + + + + + + + + + + + + + + +
FilepathDescription
service.balThe greetings service code written in the Ballerina language.
tests/service_test.balTest files related to the service.bal file.
Ballerina.tomlThe Ballerina configuration file.
+

Let's get started!

+

Step 1: Create a service component

+

To create a Ballerina service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameBallerina Greetings
    Component Nameballerina-greetings
    DescriptionSend greetings
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Ballerina as the buildpack.

    +
  16. +
  17. In the Ballerina Project Directory, specify /greeting-service.
  18. +
  19. Click Create. This creates the component and takes you to the Overview page of the component.
  20. +
+

You have successfully created a service that exposes a REST API written in the Ballerina language. Next, let's build and deploy the service.

+

Step 2: Build and deploy

+

Now that you have connected the source repository and configured the endpoint details, it's time to build and deploy the service.

+
+

Note

+

If you are rebuilding the Ballerina service component after changing the Ballerina version, ensure that before building the code, the version of the Ballerina distribution mentioned in the Ballerina.toml file matches the distribution version specified in the Dependencies.toml file.

+
+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +

    To build and deploy the service, follow the steps below:

    +
  8. +
+

Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

+

For detailed instructions, see the following sections:

+ +

Manage the deployment

+

If you want to view Kubernetes-level insights to perform a more detailed diagnosis of this Ballerina REST API, see Choreo's DevOps capabilities.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/develop-a-go-rest-api/index.html b/develop-components/develop-services/develop-a-go-rest-api/index.html new file mode 100644 index 000000000..135917fcf --- /dev/null +++ b/develop-components/develop-services/develop-a-go-rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-grpc-service/index.html b/develop-components/develop-services/develop-a-grpc-service/index.html new file mode 100644 index 000000000..2ee3b646c --- /dev/null +++ b/develop-components/develop-services/develop-a-grpc-service/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-rest-api/index.html b/develop-components/develop-services/develop-a-rest-api/index.html new file mode 100644 index 000000000..d832de08e --- /dev/null +++ b/develop-components/develop-services/develop-a-rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-service-with-docker/index.html b/develop-components/develop-services/develop-a-service-with-docker/index.html new file mode 100644 index 000000000..1739ccabb --- /dev/null +++ b/develop-components/develop-services/develop-a-service-with-docker/index.html @@ -0,0 +1,3826 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a service with Docker - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Service with Docker

+

Choreo is a platform that allows you to create and deploy applications in any language.

+

In this guide, you will:

+
    +
  • create a containerized service component using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.
  • +
  • Deploy it in Choreo using a Dockerfile. The service will run on port 9090.
  • +
  • Test the service.
  • +
+

If you want to create a service component that exposes a Ballerina service, see Develop a Ballerina Service .

+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample greetings service implementation with the Dockerfile.

    +
  • +
+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

+
+

Note

+

The specified file paths are relative to <sample-repository-dir>/greeting-service-go

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FilepathDescription
main.goThe Go-based greeter service code.
DockerfileThe Dockerfile to build the container image of the application.
.choreo/component.yaml  Choreo-specific configuration that provides information about how Choreo exposes the service.
openapi.yamlThe OpenAPI contract of the greeter service. This is required to publish the service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml file.
+

Let's get started!

+

Configure the service port with endpoints

+

In Choreo, you can expose your services via endpoints.

+

You are going to run the greeter service on port 9090. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

+

To configure the endpoint details of a containerized component, Choreo looks for an component.yaml file inside the .choreo directory. Be sure to place the .choreo directory at the root of the Docker build context path.

+

In the greeter sample, the component.yaml file is in the greeting-service-go/.choreo/ directory.

+

Step 1: Create a service component from a Dockerfile

+

To create a containerized service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGreetings
    Component Namegreetings
    DescriptionSend greetings
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Context/greeting-service-go
    Dockerfile/greeting-service-go/Dockerfile
    +
    +

    Info

    +
      +
    1. +

      To successfully build your container with Choreo, it is essential to explicitly define a user ID (UID) under the USER instruction in your Dockerfile. For reference, see sample Dockerfile. +To ensure that the defined USER instruction is valid, it must conform to the following conditions:

      +
        +
      • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
      • +
      • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      • +
      +
    2. +
    3. +

      The Dockerfile used in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

      +
    4. +
    +
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

+

Step 2: Build and deploy

+

Now that we have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then we can deploy that image test the greeter service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +

    You can access the following scans under Build.

    +
      +
    • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
    • +
    • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
    • +
    • +

      Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

      +
      +

      Info

      +

      If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

      +
      +
    • +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane, click Next to skip the configuration.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  10. +
+

Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

+

To perform a more detailed diagnosis of this Dockerfile-based REST API by viewing Kubernetes-level insights, see Choreo's DevOps capabilities.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/develop-a-service/index.html b/develop-components/develop-services/develop-a-service/index.html new file mode 100644 index 000000000..94dc2e334 --- /dev/null +++ b/develop-components/develop-services/develop-a-service/index.html @@ -0,0 +1,3793 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop a Service

+

Choreo allows you to create and deploy applications in your preferred programming language.

+

In this guide, you will:

+
    +
  • Build a simple greeting service using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.
  • +
  • Deploy the service in Choreo using a Go buildpack. The service will run on port 9090.
  • +
  • Test the service.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample greetings service implementation in Go.

    +
  • +
+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

+
+

Note

+

The specified file paths are relative to <sample-repository-dir>/greeting-service-go

+
+ + + + + + + + + + + + + + + + + + + + + +
FilepathDescription
main.goThe Go-based greeter service code.
.choreo/component.yaml  Choreo-specific configuration that provides information about how Choreo exposes the service.
openapi.yamlThe OpenAPI contract of the greeter service. This is required to publish the service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml file.
+

Let's get started!

+

Configure the service port with endpoints

+

In Choreo, you can expose your services via endpoints.

+

You are going to run the greeter service on port 9090. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

+

To configure the endpoint details of a containerized component, Choreo looks for an component.yaml file inside the .choreo directory. Be sure to place the .choreo directory at the root of the Docker build context path.

+

In the greeter sample, the component.yaml file is in the greeting-service-go/.choreo/ directory.

+

Step 1: Create a service component

+

To create a containerized service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGreetings
    Component Namegreetings
    DescriptionSend greetings
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Go as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Go Project Directory/greeting-service-go
    Language Version1.x
    +
  18. +
  19. +

    Click Create. This creates the component and lists it under Component Listing on the project home page.

    +
  20. +
+

You have successfully created the service. The next step is to build and deploy it.

+

Step 2: Build and deploy

+

Now that you have connected the source repository and configured the endpoint details, it's time to build and deploy the greeter service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. On the project home page, click on the Greetings component you created. This takes you to the component overview page.
  2. +
  3. In the left navigation menu, click Build.
  4. +
  5. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  6. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane, click Next to skip the configuration.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  10. +
+

Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/develop-a-tcp-service/index.html b/develop-components/develop-services/develop-a-tcp-service/index.html new file mode 100644 index 000000000..91f68706d --- /dev/null +++ b/develop-components/develop-services/develop-a-tcp-service/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/develop-a-udp-service/index.html b/develop-components/develop-services/develop-a-udp-service/index.html new file mode 100644 index 000000000..35acff85f --- /dev/null +++ b/develop-components/develop-services/develop-a-udp-service/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/index.html b/develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/index.html new file mode 100644 index 000000000..66cf6235b --- /dev/null +++ b/develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/index.html @@ -0,0 +1,3880 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a Ballerina GraphQL Endpoint via a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a Ballerina GraphQL Endpoint via a Service

+

Choreo offers the flexibility to develop and deploy applications in a language of your preference. This guide shows you how to deploy a service component that exposes a GraphQL API using the Ballerina language in Choreo. No prior knowledge of the Ballerina language is required to follow this guide.

+

GraphQL API is a query language and runtime that provides a single endpoint for retrieving flexible and efficient data in a strongly-typed and self-documenting way. By following this guide, you will build a service component in Ballerina and deploy it on Choreo for any GraphQL client application to utilize it.

+

This guide shows how to build a simple reading list service and deploy it in Choreo using Ballerina. The GraphQL endpoint you create in this guide has two operations: Query and Mutation. The Query type operations read the data in the data source, and the Mutation operations update the data in the data source. The reading list service has two queries and three mutations as follows:

+

Queries

+

Retrieve the reading list

+

This resource accepts an optional filter, status, which filters the reading list by reading status. Accepted values for status are reading, read, and to_read.

+

Sample request: +

$ curl -X POST -H "Content-Type: application/json" -d '{"query": "query {allBooks (status: \"reading\") { id title author status }}"}' http://localhost:8090
+

+

Sample response +

$ {
+  "data": {
+    "allBooks": [
+      {
+        "id": 1,
+        "title": "Sample Book",
+        "author": "Test Author",
+        "status": "to_read"
+      }
+    ]
+  }
+}
+

+

Retrieve a book item from the reading list

+

This resource accepts a filter, id, which will select the book item from the reading list by book id. The id is an Integer value.

+

Sample request +

$ curl -X POST -H "Content-Type: application/json" -d '{"query": "query {book (id: 1) { id title author status }}"}' http://localhost:8090
+

+

Sample response +

$ {
+  "data": {
+    "book": {
+      "id": 1,
+      "title": "Sample Book",
+      "author": "Test Author",
+      "status": "to_read"
+    }
+  }
+}
+

+

Mutations

+

Add a book item to the reading list

+

This remote function accepts a book record as the input and consists of the title and the author. When you add a new book to the reading list, the method updates the reading status of the newly added book to to_read. This method returns the added book item upon successful execution.

+

Sample request

+
$ curl -X POST -H "Content-type: application/json" -d '{ "query": "mutation { addBook(book: {title: \"Sample Book\", author: \"Test Author\"}) { id title author status } }" }' 'http://localhost:8090'
+
+ +

Sample response

+
$ {
+  "data": {
+    "addBook": {
+      "id": 1,
+      "title": "Sample Book",
+      "author": "Test Author",
+      "status": "to_read"
+    }
+  }
+}
+
+ +

Update the reading status of a book

+

This remote function requires id and status as inputs to update the reading status of the selected book. The id refers to the id of the book. It is an integer. The status refers to the reading status that needs to be updated. This method returns the updated book item upon successful execution.

+

Sample request

+
$ curl -X POST -H "Content-type: application/json" -d '{ "query": "mutation { setStatus(id: 1, status: \"reading\") { id title author status } }" }' 'http://localhost:8090'
+
+ +

Sample response

+
$ {
+  "data": {
+    "setStatus": {
+      "id": 1,
+      "title": "Sample Book",
+      "author": "Test Author",
+      "status": "reading"
+    }
+  }
+}
+
+ +

Delete a book item from the reading list

+

This remote function requires the id as the input to delete the book item from the reading list. This method returns the removed book item upon successful execution.

+

Sample request

+
$ curl -X POST -H "Content-type: application/json" -d '{ "query": "mutation { deleteBook(id: 1) { id title author status } }" }' 'http://localhost:8090'
+
+ +

Sample response +

$ {
+  "data": {
+    "deleteBook": {
+      "id": 1,
+      "title": "Sample Book",
+      "author": "Test Author",
+      "status": "reading"
+    }
+  }
+}
+

+

Our next step is to set up the resources that you will require to follow the guide, including the sample reading list application and the Choreo GitHub app.

+

Prerequisites

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample GraphQL service implementation for this guide.

    +
  • +
+

Let's get started!

+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the reading list service.

+
+

Note

+

The following file paths are relative to the path <sample-repository-dir>/reading-list-graphql.

+
+ + + + + + + + + + + + + + + + + + + + + +
FilepathDescription
service.balThe reading list service code written in the Ballerina language.
Ballerina.tomlThe Ballerina configuration file.
.choreo/component.yamlThe configuration file with endpoint details.
+

Step 1: Create a service component

+

To create a Ballerina service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameBallerina Reading List
    Component Nameballerina-reading-list
    DescriptionManage a reading list
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Ballerina as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + +
    FieldValue
    Ballerina Project Directoryreading-list-graphql
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service component that exposes a GraphQL API written in the Ballerina language. Next, let's build and deploy the service.

+

Step 2: Build and deploy

+

Now that we have connected the source repository, it's time to build and deploy the reading list service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +

    To build and deploy the service, follow the steps below:

    +
  8. +
+

Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

+

For detailed instructions, see the following sections:

+ + + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/index.html b/develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/index.html new file mode 100644 index 000000000..6a3794c65 --- /dev/null +++ b/develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/index.html @@ -0,0 +1,4100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a gRPC Endpoint via a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a gRPC Endpoint via a Service

+

Choreo allows you to create and deploy applications in your preferred programming language. One powerful option is gRPC, a high-performance and language-agnostic remote procedure call (RPC) framework. It utilizes Protocol Buffers to define services and generate client/server code.

+

In this guide, you will learn to use Choreo to create a service component that exposes a gRPC server implemented in Go, enabling efficient and scalable communication with any gRPC client application. No prior knowledge of the Go language is necessary to follow this guide.

+

By following this guide, you will:

+
    +
  • Create a simple gRPC server using a Service component.
  • +
  • +

    Link the containerized gRPC service to the Choreo component using the Dockerfile. + The greeter service has a single RPC method named sayHello. Following is the proto file the server and the client application are using:

    +
    syntax = "proto3";
    +option go_package = "github.com/wso2/choreo-samples/go-grpc/pkg";
    +
    +service greeter {
    +  rpc SayHello (HelloRequest) returns (HelloReply) {}
    +}
    +
    +message HelloRequest {
    +  string name = 1;
    +}
    +
    +message HelloReply {
    +  string message = 1;
    +}
    +
    + +
  • +
  • +

    Deploy the gRPC server component in Choreo.

    +
  • +
  • Create a gRPC client using a Manual Trigger component.
  • +
  • Deploy the gRPC client.
  • +
  • Invoke the gRPC server using a gRPC client and check the response through the Choreo log view.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    +
  • +
+

Let's get started!

+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service.

+
+

Note

+

The following file paths are relative to the path <sample-repository-dir>/go-grpc.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File PathDescription
main.goThe greeter service code written in the Go language.
greeter_client/main.goThe greeter client application written in the Go language.
Dockerfile.serverThe Dockerfile to build the container image of the server application.
Dockerfile.clientThe Dockerfile to build the container image of the client application.
.choreo/component.yamlThe Choreo-specific configuration that provides information about how Choreo exposes the service.
pkg/greeter.protoThe interface definition of the gRPC service. This is used to generate the server and client stubs for the Go application.
+

Configure the service port with endpoints

+

In Choreo, you can expose your services via endpoints.

+

Let's run the gRPC server service component on port 8080. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

+

Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of the containerized component. Ensure the .choreo directory is at the root of the Docker build context path.

+

In the gRPC server sample, the component.yaml file is at go-grpc/.choreo/component.yaml, where the build context path is go-grpc.

+

Step 1: Create a service component with a gRPC endpoint

+

To create a containerized service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo gRPC Server
    Component Namego-grpc-server
    DescriptionSend greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextgo-grpc
    Dockerfilego-grpc/Dockerfile.server
    +
    +

    Info

    +
      +
    1. +

      To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. +To ensure that the defined USER instruction is valid, it must conform to the following conditions:

      +
        +
      • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
      • +
      • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      • +
      +
    2. +
    3. +

      The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

      +
    4. +
    +
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

+

Step 2: Build and deploy

+

Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the greeter service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +

    You can access the following scans under Build.

    +
      +
    • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
    • +
    • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
    • +
    • +

      Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

      +
      +

      Info

      +

      If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

      +
      +
    • +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane, click Next to skip the configuration.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  10. +
  11. +

    Once you have successfully deployed your service, navigate to the component overview page and copy the gRPC service URL. You need to provide that URL when setting up the client application later in this guide.

    +
  12. +
+

You have successfully deployed the gRPC server. Currently, the gRPC service is only accessible by the components deployed within the same project.

+

Step 3: Invoke the gRPC service

+

Let's invoke the gRPC service that you created above, using a gRPC client.

+

Step 3.1: Create a manual task for the gRPC client

+

To create a manual task component, follow these steps:

+
    +
  1. On the Choreo Console header, click the Project list and select the project where you created the gRPC service component. This opens the project home page.
  2. +
  3. Go to the Component Listing section and click + Create.
  4. +
  5. Click the Manual Task card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo gRPC Client
    Component Namego-grpc-client
    DescriptionReceive greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextgo/grpc
    Dockerfilego/grpc/Dockerfile.client
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

Step 3.2: Build the gRPC client component

+

To build the component, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 3.3: Setup environment variables and deploy the gRPC client

+

The client application, in this case, the gRPC client, requires the server URL of the gRPC server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

+
    +
  1. On the Choreo Console left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click + Add.
  6. +
  7. +

    Specify the following name and value to configure the environment variable for the client application:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameGREETER_SERVICE
    ValuePaste the URL value copied after deploying the gRPC service via step 2.2 above. Make sure to drop the http:// or grpc:// part and the trailing / from the URL when copying. For example, if the URL is http://go-grpc-server-3192360657:8080/, add only go-grpc-server-3192360657:8080.
    +
  8. +
  9. +

    Click Add and then click Next.

    +
  10. +
  11. Click Deploy.
  12. +
+

Step 3.4: Execute the gRPC client component

+

To execute the gRPC client, follow these steps:

+
    +
  1. In the left navigation menu, click Execute.
  2. +
  3. Click Run Now. This triggers the gRPC client and generates logs. + You can trigger multiple runs to generate multiple logs.
  4. +
+

For details on what you can monitor via the execute page, see Monitor executions.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/index.html b/develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/index.html new file mode 100644 index 000000000..08522b561 --- /dev/null +++ b/develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/index.html @@ -0,0 +1,3683 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a Prism-Based Mock Server Using an OpenAPI Specification - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a Prism-Based Mock Server Using an OpenAPI Specification

+

Choreo supports deploying Prism-based mock servers using OpenAPI specifications. With the Choreo Prism mock service component, you can serve multiple mock servers, each based on a different OpenAPI specification, as separate endpoints.

+

By default, these mock servers serve static content generated from the examples in the configured OpenAPI Specification (OAS).

+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the Prism mock service artifacts for this guide.

    +
  • +
+

Step 1: Create a Prism mock service component

+

To create a Prism mock service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component.

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Prism Mock as the buildpack.

    +
  16. +
  17. Select prism-mock-service as the Project Directory.
  18. +
  19. Click Create. This creates the component and takes you to the Overview page of the component.
  20. +
+

Step 2: Build and deploy the component

+

Now that you have successfully created the Prism mock service, it's time to build and deploy it.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest. This builds the service from the latest commit.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  6. +
+

Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

+

Serve dynamic content

+

The Prism mock service can serve dynamic content according to the schema definitions in the OpenAPI specification. To use the Prism mock service with dynamic content, clients must add the prefer:dynamic=true header in the request.

+

To generate meaningful dynamic responses, you can use the x-faker attribute in schema definitions of the OpenAPI specification. For more information on dynamically generated responses with the x-faker attribute, see the Prism documentation.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/expose-a-tcp-server-via-a-service/index.html b/develop-components/develop-services/expose-a-tcp-server-via-a-service/index.html new file mode 100644 index 000000000..4800a22b8 --- /dev/null +++ b/develop-components/develop-services/expose-a-tcp-server-via-a-service/index.html @@ -0,0 +1,4082 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a TCP Server via a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a TCP Server via a Service

+

Choreo offers the flexibility to design and deploy applications in the programming language of your choice. One viable choice for specific network communication needs is TCP (Transmission Control Protocol). TCP provides a reliable, stream-oriented communication mechanism that ensures data integrity and orderliness during transmission. It's the go-to option for scenarios where guaranteed data delivery and error recovery are paramount.

+

In this guide, you will learn to use Choreo to create a service component that exposes a TCP server implemented in Go, enabling efficient and scalable communication with any TCP client application. No prior knowledge of the Go language is necessary to follow this guide.

+

By following this guide, you will:

+
    +
  • Setup a TCP server
      +
    • Create a simple TCP server using a service component.
    • +
    • Link the containerized TCP service to the Choreo component using a Dockerfile.
    • +
    • Deploy the TCP server component in Choreo.
    • +
    +
  • +
  • Setup a TCP client
      +
    • Create a TCP client using a manual task component.
    • +
    • Link the containerized TCP client to the Choreo component using a Dockerfile.
    • +
    • Deploy the TCP client component in Choreo.
    • +
    +
  • +
  • Invoke the TCP server using a TCP client and observe the response through the Choreo log view.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    +
  • +
+

Let's get started!

+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the sample service.

+
+

Note

+

The following file paths are relative to the path <sample-repository-dir>/docker-tcp-service.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File PathDescription
server/main.goThe greeter service code written in the Go language.
client/main.goThe greeter client application written in the Go language.
Dockerfile.serverThe Dockerfile to build the container image of the server application.
Dockerfile.clientThe Dockerfile to build the container image of the client application.
.choreo/component.yamlThe Choreo-specific configuration provides information about how Choreo exposes the service.
+

Configure the service port with endpoints

+

In Choreo, you can expose your services via endpoints.

+

Let's run the TCP server service component on port 5050. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

+

Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of a containerized component. Place the .choreo directory at the root of the Docker build context path.

+

In our TCP server sample, the component.yaml file is at docker-tcp-service/.choreo/component.yaml, where the build context path is docker-tcp-service.

+

Step 1: Create a service component with a TCP endpoint

+

To create a containerized service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo TCP Server
    Component Namego-tcp-server
    DescriptionSend greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextdocker-tcp-service
    Dockerfiledocker-tcp-service/Dockerfile.server
    +
    +

    Info

    +
      +
    1. +

      To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. +To ensure that the defined USER instruction is valid, it must conform to the following conditions:

      +
        +
      • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
      • +
      • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      • +
      +
    2. +
    3. +

      The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

      +
    4. +
    +
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

+

Step 2: Build and deploy

+

Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +

    You can access the following scans under Build.

    +
      +
    • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
    • +
    • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
    • +
    • +

      Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

      +
      +

      Info

      +

      If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

      +
      +
    • +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane, click Next to skip the configuration.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  10. +
  11. +

    Once you have successfully deployed your service, navigate to the component overview page and copy the TCP service address. You need to provide that address when setting up the client application later in this guide.

    +
  12. +
+

You have successfully deployed the TCP server. Currently, the TCP service is only accessible by the components deployed within the same project.

+

Step 3: Invoke the TCP service

+

Now let's use a TCP client to invoke the TCP service that you created above. To do this, you can create a manual trigger component as the TCP client. This is the recommended approach because, in this example, it's more efficient to have a client that connects to the server, sends a request, and then stops. Here, a continuously executing task isn't required. Furthermore, if you use a manual trigger component, you won't need to expose an endpoint in the client for invocation, unlike with an API.

+

Step 3.1: Create a manual trigger for the TCP client

+

To create a manual task component, follow these steps:

+
    +
  1. On the Choreo Console header, click the Project list and select the project where you created the TCP service component. This opens the project home page.
  2. +
  3. Go to the Component Listing section and click + Create.
  4. +
  5. Click the Manual Task card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo TCP Client
    Component Namego-tcp-client
    DescriptionReceive greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextdocker-tcp-service
    Dockerfiledocker-tcp-service/Dockerfile.client
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

Step 3.2: Build the TCP client component

+

To build the component, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 3.3: Setup environment variables and deploy the TCP client

+

The client application, in this case, the TCP client, requires the server URL of the TCP server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

+
    +
  1. On the Choreo Console left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click + Add.
  6. +
  7. +

    Specify the following name and value to configure the environment variable for the client application:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameSERVER_ADDRESS
    ValuePaste the URL value copied after deploying the TCP service via step 2.2 above. Make sure to drop the tcp:// part and the trailing / from the URL when copying. For example, add only go-tcp-server-1097922445:8080.
    +
  8. +
  9. +

    Click Add and then click Next.

    +
  10. +
  11. Click Deploy.
  12. +
+

Step 3.4: Execute the TCP client component

+

To execute the TCP client, follow these steps:

+
    +
  1. In the left navigation menu, click Execute.
  2. +
  3. Click Run Now. This triggers the TCP client and generates logs. + You can trigger multiple runs to generate multiple logs.
  4. +
+

For details on what you can monitor via the execute page, see Monitor executions.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/expose-a-udp-server-via-a-service/index.html b/develop-components/develop-services/expose-a-udp-server-via-a-service/index.html new file mode 100644 index 000000000..c91e55610 --- /dev/null +++ b/develop-components/develop-services/expose-a-udp-server-via-a-service/index.html @@ -0,0 +1,4082 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a UDP Server via a Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a UDP Server via a Service

+

Choreo offers the flexibility to design and deploy applications in the programming language of your choice. One compelling choice for certain network communication needs is UDP (User Datagram Protocol). UDP is a high-speed, connectionless protocol ideal for scenarios where lightweight, real-time data transmission is essential.

+

In this guide, you will learn to use Choreo to create a Service component that exposes a UDP server implemented in Go, enabling efficient and scalable communication with any UDP client application. No prior knowledge of the Go language is necessary to follow this guide.

+

By following this guide, you will:

+
    +
  • Setup a UDP server
      +
    • Create a simple UDP server using a Service component.
    • +
    • Link the containerized UDP service to the Choreo component using the Dockerfile.
    • +
    • Deploy the UDP server component in Choreo.
    • +
    +
  • +
  • Setup a UDP client
      +
    • Create a UDP client using a manual task component.
    • +
    • Link the containerized UDP client to the Choreo component using the Dockerfile.
    • +
    • Deploy the UDP client component in Choreo.
    • +
    +
  • +
  • Invoke the UDP server using a UDP client and check the response through the Choreo log view.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    +
  • +
+

Let's get started!

+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the sample service.

+
+

Note

+

The following file paths are relative to the path <sample-repository-dir>/docker-udp-service.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File PathDescription
server/main.goThe greeter service code written in the Go language.
client/main.goThe greeter client application written in the Go language.
Dockerfile.serverThe Dockerfile to build the container image of the server application.
Dockerfile.clientThe Dockerfile to build the container image of the client application.
.choreo/component.yamlThe Choreo-specific configuration provides information about how Choreo exposes the service.
+

Configure the service port with endpoints

+

In Choreo, you can expose your services via endpoints.

+

Let's run the UDP server service component on port 5050. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

+

Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of a containerized component. Place the .choreo directory at the root of the Docker build context path.

+

In our gRPC server sample, the component.yaml file is at docker-udp-service/.choreo/component.yaml, where the build context path is docker-udp-service.

+

Step 1: Create a service component with a UDP endpoint

+

To create a containerized service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo UDP Server
    Component Namego-udp-server
    DescriptionSend greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextdocker-udp-service
    Dockerfiledocker-udp-service/Dockerfile.server
    +
    +

    Info

    +
      +
    1. +

      To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. +To ensure that the defined USER instruction is valid, it must conform to the following conditions:

      +
        +
      • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
      • +
      • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      • +
      +
    2. +
    3. +

      The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

      +
    4. +
    +
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

+

Step 2: Build and deploy

+

Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +

    You can access the following scans under Build.

    +
      +
    • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
    • +
    • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
    • +
    • +

      Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

      +
      +

      Info

      +

      If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

      +
      +
    • +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane, click Next to skip the configuration.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  10. +
  11. +

    Once you have successfully deployed your service, navigate to the component overview page and copy the UDP service address. You must provide that address when setting up the client application later in this guide.

    +
  12. +
+

You have successfully deployed the UDP server. Currently, the UDP service is only accessible by the components deployed within the same project.

+

Step 3: Invoke the UDP service

+

Now let's use a UDP client to invoke the UDP service that you created above. To do this, you can create a manual trigger component as the UDP client. This is the recommended approach because, in this example, it's more efficient to have a client that connects to the server, sends a request, and then stops. Here, a continuously executing task isn't required. Furthermore, if you use a manual trigger component, you won't need to expose an endpoint in the client for invocation, unlike with an API.

+

Step 3.1: Create a manual trigger for the UDP client

+

To create a manual task component, follow these steps:

+
    +
  1. On the Choreo Console header, click the Project list and select the project where you created the UDP service component. This opens the project home page.
  2. +
  3. Go to the Component Listing section and click + Create.
  4. +
  5. Click the Manual Task card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameGo UDP Client
    Component Namego-udp-client
    DescriptionReceive greetings
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select Docker as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Docker Contextdocker-udp-service
    Dockerfiledocker-udp-service/Dockerfile.client
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

Step 3.2: Build the UDP client component

+

To build the component, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 3.3: Setup environment variables and deploy the UDP client

+

The client application, in this case, the UDP client, requires the server URL of the UDP server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

+
    +
  1. On the Choreo Console left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click + Add.
  6. +
  7. +

    Specify the following name and value to configure the environment variable for the client application:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameSERVER_ADDRESS
    ValuePaste the URL value copied after deploying the UDP service via step 2.2 above. Make sure to drop the udp:// part and the trailing / from the URL when copying. For example, add only go-udp-server-1097922445:8080.
    +
  8. +
  9. +

    Click Add and then click Next.

    +
  10. +
  11. Click Deploy.
  12. +
+

Step 3.4: Execute the UDP client component

+

To execute the UDP client, follow these steps:

+
    +
  1. In the left navigation menu, click Execute.
  2. +
  3. Click Run Now. This triggers the UDP client and generates logs. + You can trigger multiple runs to generate multiple logs.
  4. +
+

For details on what you can monitor via the execute page, see Monitor executions.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/index.html b/develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/index.html new file mode 100644 index 000000000..212db32e0 --- /dev/null +++ b/develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/index.html @@ -0,0 +1,3758 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a WebSocket Endpoint via a NodeJS Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Expose a WebSocket Endpoint via a NodeJS Service

+

Choreo allows you to create and deploy applications in your preferred programming language, offering a seamless platform for building dynamic and scalable solutions. This guide walks you through the steps to deploy a WebSocket service using the NodeJS buildpack.

+

WebSockets provide real-time, two-way communication between a client and server over a persistent TCP connection. This makes WebSocket APIs ideal for applications that require real-time updates.

+

In this guide, you will:

+
    +
  • Build a simple WebSocket service using a sample implementation in NodeJS.
  • +
  • Deploy the service in Choreo, allowing any WebSocket client application to establish a connection and exchange real-time messages with your service.
  • +
+

Prerequisites

+
    +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the Project Home page of the default project created for you.

    +
  • +
  • +

    Fork the Choreo samples repository, which contains the sample WebSocket service implementation for this guide.

    +
  • +
+

Let's get started!

+

Learn the repository file structure

+

It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the NodeJS chat Application.

+
+

Note

+

The following file paths are relative to the path <sample-repository-dir>/websocket-chat-app/websocket-chat-service-nodejs.

+
+ + + + + + + + + + + + + + + + + +
FilepathDescription
server.jsThe NodeJS chat service.
.choreo/component-config.yamlThe configuration file with endpoint details.
+

Step 1: Create a service component

+

To create a NodeJS service component, follow these steps:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Service card.
  6. +
  7. +

    Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameNodeJS Chat Service
    Component Namenodejs-chat-service
    DescriptionManage a chat service
    +
  8. +
  9. +

    Click the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Under Connect Your Repository, enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select NodeJS as the buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + +
    FieldValue
    NodeJS Project Directorywebsocket-chat-app/websocket-chat-service-nodejs
    +
  18. +
  19. +

    Click Create. This creates the component and takes you to the Overview page of the component.

    +
  20. +
+

You have successfully created a service component that provides a WebSocket API built with NodeJS. The next step is to proceed with building and deploying the service.

+

Step 2: Build and deploy

+

Now that you have connected the source repository, it's time to build and deploy the chat service.

+

Step 2.1: Build

+

To build the service, follow these steps:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    On the Build page, click Build Latest.

    +
    +

    Note

    +

    Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Step 2.2: Deploy

+

To deploy the service, follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    +
    +
  8. +
+

Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

+

During testing, once the WebSocket connection is established, you can send {"type": "Connect", "username": "user1"} to the WebSocket endpoint to connect to the chat service. You can then send chat messages by using {"type": "Data", "message": "Hello, World!"}.

+
+

Note

+

Some clients, such as certain browsers, may not support adding headers to the WebSocket handshake. In these cases, you can include the access token or Test key required for WebSocket API invocation within the sec-websocket-protocol header, along with any specified subprotocols.

+

For example: sec-websocket-protocol: choreo-oauth2-token, {access token}, subprotocols

+

If you are using a Test Key, replace choreo-oauth2-token with choreo-test-key.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-services/service-component-overview/index.html b/develop-components/develop-services/service-component-overview/index.html new file mode 100644 index 000000000..e5b3a0f31 --- /dev/null +++ b/develop-components/develop-services/service-component-overview/index.html @@ -0,0 +1,3497 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Service Component Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Service Component Overview

+

Explore how to create, deploy, manage, and observe service components in Choreo.

+

What is a service component?

+

A service component in Choreo lets you deploy and expose REST, GraphQL, gRPC, UDP, WS or TCP services. It is a fundamental building block for creating cloud-native applications in Choreo. They provide a simple and effective way to expose functionality as a service to other components within Choreo or to the outside world.

+

Service components encapsulate business logic and provide standardized interfaces, called endpoints, for communicating with other components or systems. You can deploy and scale services independently, which makes them highly flexible and adaptable to changing workloads.

+

With the help of the service component, developers can quickly create APIs and microservices, making it easier to implement and manage complex software systems. Service components can also be integrated with other Choreo components, that acts as message processors, connectors, and data sources, etc to create powerful end-to-end solutions.

+

You can expose a service to other components through endpoints. For details on configuring endpoints, see Configure Endpoints.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/index.html b/develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/index.html new file mode 100644 index 000000000..9a8b603f8 --- /dev/null +++ b/develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/index.html @@ -0,0 +1,3854 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Build and Deploy a Single-Page Web Application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Build and Deploy a Single-Page Web Application

+

A web application is an application program hosted on a server and serves ingress traffic through a browser. In Choreo, you can deploy a web application by creating a Web Application component and connecting it to a Git repository that contains the implementation of the web application. Web applications can fall into one of the following categories:

+
    +
  • Single page applications (SPAs): Examples include React, Angular, Vue, Svelte, etc.
  • +
  • Web servers: These serve static content or provide server-side rendering/static site generation (SSR/SSG).
  • +
  • Static content: Examples include websites and other static resources that do not require a backend, usually comprising static HTML/JS/CSS files.
  • +
+

Prerequisites

+
    +
  • To deploy a Web Application component, you must have a GitHub account with a repository containing the web application's implementation. For this guide, fork the https://github.com/wso2/choreo-samples repository, which contains the sample web application implementation.
  • +
+

Create a web application

+

You can create a web application in Choreo as follows:

+
    +
  • +

    Build and deploy a SPA from the source code.

    +
      +
    • Create a Web Application component by connecting a repository that includes the web application source code.
    • +
    • Select the relevant buildpack. Default buildpacks include React, Angular, and Vue.js. If you are using a different SPA framework, you can try one of these buildpacks because the configurations can be overridden to support most Javascript-based SPAs.
    • +
    • Enter the build command based on your package manager. + NPM, yarn, and pnpm are supported and the relevant package manager is run based on the dependency lock file in your repository (defaults to NPM if no lock file is present).
    • +
    • Specify the build output directory.
    • +
    • Specify the NodeJS version. Choreo does not pick the Nodejs version from the package.json engine property. The required Node version must be explicitly set in the build configuration.
    • +
    +

    Once you create the Web Application component, Choreo automatically generates a build pipeline for your single-page application and deploys it.

    +
  • +
  • +

    Bring your Dockerfile.

    +
      +
    • Create a Web Application component by connecting a repository that contains the Dockerfile for your containerized web application.
    • +
    • Commit a Dockerfile to your connected git repository to have full control over your build process.
    • +
    +

    This approach is recommended if you are deploying a web server and not just a single-page application (or a single-page application with a complex build process).

    +
  • +
  • +

    Host static websites.

    +
      +
    • To host static web content, you can create a Web Application component and connect it to the GitHub repository that contains the required static assets.
    • +
    • Select the Static Websites buildpack. This buildpack does not trigger a build process. It only fetches the files from the path specified in the repository and serves as it is.
    • +
    +
  • +
+

Now let's take a look at how you can build and deploy a SPA from source code:

+

Follow the steps below to create a sample Web Application component and deploy it in Choreo:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/login/. This opens the Project Home page.
  2. +
  3. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
  4. +
  5. Click the Web Application card.
  6. +
  7. This opens the Create a Web Application pane, where you can specify a name and description for the component. Enter a unique name and description.
  8. +
  9. Go to the GitHub tab.
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    GitHub AccountYour account
    GitHub Repositorychoreo-samples
    Branchmain
    +
  14. +
  15. +

    Select React as the Buildpack.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    Project Directory/react-single-page-app
    Build Commandnpm run build
    Build Pathbuild
    Node Version18
    +
    +

    Tip

    +

    Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks. To learn how to set up authentication for your web application with Choreo's managed authentication, see Secure Web Applications with Managed Authentication.

    +
    +
  18. +
  19. +

    Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    +
  20. +
+

You have successfully created a Web Application component from the source code. Now let's build and deploy the web application.

+

Build your web application

+

To build the web application, follow the steps given below:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. In the Builds pane, click Build. This opens the Commits pane, where you can see all the commits related to the component.
  4. +
  5. +

    Select the latest commit and click Build. This triggers the build process and displays the progress in the Build Logs pane.

    +

    You can access the following scans in the Build Logs pane:

    +
      +
    • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
    • +
    • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
    • +
    • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.
    • +
    +
    +

    Info

    +

    If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

    +
    +
    +

    Note

    +

    The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with its status.

    +
    +
  6. +
+

Here, you will see the build status as Success.

+

Deploy and access your web application

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can add a file mount if necessary. In this guide, you will not add a file mount.
  4. +
  5. Click Next. This takes you to the Authentication Settings pane.
  6. +
  7. +

    Keep the default settings and click Deploy.

    +
    +

    Note

    +
      +
    • The deployment process can take a few minutes to complete. On successful deployment, you will see the Deployment Status as Active in the Development card.
    • +
    +
    +
  8. +
  9. +

    To verify that you have successfully hosted the web application, click the Web App URL in the Development card. This takes you to the web application.

    +
  10. +
+

Create a short URL for your web application in production

+
+

Info

+

This feature is only available on the Choreo cloud data plane.

+
+

When you promote your component to the Production environment, you have the option to create a personalized short URL for your web application. The URL follows the https://{your-short-prefix}.choreoapps.dev structure, where you can select a name of your preference for {your-short-prefix}.

+

To create a short URL for your web application, follow the steps given below:

+
    +
  1. Click Promote in the Development card and promote your web application to production.
  2. +
  3. In the Production card, click Create a short URL.
  4. +
  5. +

    Specify a Short URL prefix of your choice and click Save.

    +
    +

    Note

    +

    Short URL names/prefixes are subject to availability, provided on a first-come-first-serve basis.

    +
    +
  6. +
+

Manage runtime configurations for web applications

+

For web applications with a backend server, Choreo allows you to mount runtime configurations and secrets as environment variables and/or file mounts for a specific environment. Alternatively, you can also inject them into the client application during server-side rendering or when serving static content.

+

However, in the case of SPAs that run completely on the browser, Choreo does not support baking-in environment variables or other configurations. This is because Choreo follows a multi-environment deployment model, where configuration should be kept separate from the build and injected at runtime. For example, in most React SPA frameworks, the process.env stub is available during build time. However, it does not actually read in variables from the runtime. Instead, it is baked into the final JavaScript output during the build process.

+

To manage runtime configurations, Choreo recommends the following approach (although this is a React example, the approach is generally applicable to other SPA frameworks as well).

+
+

Note

+
    +
  • With SPAs, anything you mount as a runtime config will be available to your users in the browser.
  • +
  • Do not include sensitive secrets that are not browser-safe.
  • +
+
+

Follow the steps given below to manage runtime configurations for the React application you created above:

+
    +
  1. Go to your forked Choreo samples repository.
  2. +
  3. Open the public directory.
  4. +
  5. +

    Create and commit a new file named config.js in the public directory of your React application. This file should contain the runtime configuration variables you want to expose to your application, such as API endpoints or feature flags. Let's expose the API URL and a feature flag as follows:

    +

    window.config = {
    +apiUrl: 'https://api.example.com',
    +    featureFlags: {
    +        enableNewFeature: true,
    +        enableExperimentalFeature: false,
    +    },
    +};
    +
    +4. In your index.html file inside the public directory, add a script tag as follows to include the config.js file inside the tag. The config.js file will be accessible via JavaScript at runtime.

    +

    <!DOCTYPE html>
    +<html lang="en">
    +<head>
    +    <meta charset="utf-8" />
    +    <title>My React App</title>
    +</head>
    +<body>
    +    <div id="root"></div>
    +    <script src="%PUBLIC_URL%/config.js"></script>
    +</body>
    +</html>
    +
    +This makes the window.config object available to your app at runtime.

    +
  6. +
  7. +

    In your React component, you can access the configuration variables by referencing the window.config object as follows:

    +

    import React from 'react';
    +
    +function MyComponent() {
    +const apiUrl = window.config.apiUrl;
    +const enableNewFeature = window.config.featureFlags.enableNewFeature;
    +const enableExperimentalFeature = window.config.featureFlags.enableExperimentalFeature;
    +
    +// ...
    +}
    +
    +Now you can deploy your component.

    +
  8. +
  9. +

    When you deploy your component to Choreo, create a config file mount in the specified path for each environment (where your index.html expects the config.js file as in this example). +https://wso2.com/choreo/docs/devops-and-ci-cd/manage-configurations-and-secrets/#apply-a-file-mount-to-your-container.

    +
  10. +
+

Limitations

+

The following limitations are specific to the Choreo cloud data plane:

+
    +
  • Request size limit, including headers, cookies, and payloads: 256KB
  • +
  • Response body size limit: 20MB
  • +
  • Only one open port is permitted per web application. While you can have multiple ports open for project-level communication within a data plane, incoming traffic from the internet can only be directed to one port. This differs from the Service type components, which support multiple endpoints.
  • +
+

Troubleshoot a web application

+
    +
  • +

    I’m seeing a blank page or a 502 error after I deploy my web application

    +

    If you encounter a blank page or a 502 error after deploying your web application, it typically indicates that the wrong directory is being served. To resolve this issue, follow these steps:

    +
      +
    • Double-check the build output directory, especially if you are using a Dockerfile-less buildpack. Ensure that the specified output directory matches the actual output directory generated during the build process. For example, if you have erroneously entered public/ as the output directory when it should have been build/.
    • +
    +

    By verifying and correcting the output directory alignment, you should be able to address the issue of encountering a blank page or experiencing a 502 error on deploying your web application.

    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/index.html b/develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/index.html new file mode 100644 index 000000000..65ef340d1 --- /dev/null +++ b/develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/index.html @@ -0,0 +1,3678 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop Web Applications Locally with Choreo’s Managed Authentication - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Develop Web Applications Locally with Choreo’s Managed Authentication

+

Choreo’s managed authentication capability exposes a set of backend for frontend (BFF) endpoints, facilitating authentication and authorization for web applications. These endpoints are readily available for single-page web applications deployed on Choreo.

+

As a web application developer, there may be instances where it becomes necessary to run the application on your personal workstation. In such situations, the expectation is for authentication and authorization during local development to work in the same manner as it would when the application is deployed to Choreo, eliminating the need to modify the source code.

+

Choreo's local development capability ensures a seamless local application development experience where the authentication and authorization process aligns with Choreo’s deployment environment. This facilitates a smoother transition from development to deployment, improving workflow efficiency.

+

How local development works in Choreo

+

Local development uses a proxy that sits in front of the locally running web application. This proxy intercepts all incoming requests. The requests to /choreo-apis/* and /auth/* are then forwarded to Choreo, while all other requests are forwarded to the locally running web application. The proxy runs on HTTPS using a self-signed certificate, crucial for secure, HTTP-only cookie-based managed authentication. Upon running the proxy, you can access the web application using the proxy's URL and start developing the application locally. You will observe that the behavior of the web application, in terms of the managed authentication functionality, is similar to how it would be after deploying to Choreo.

+

Configure local development

+

Prerequisites

+
    +
  • Create a single-page application (SPA) with managed authentication enabled. For details on how to set up managed authentication for your web application, see Secure Web Applications with Managed Authentication.
  • +
  • +

    Promote and deploy the application to the environment where you want to enable local development.

    +
    +

    Note

    +
      +
    • The web application that you run locally will use the same managed authentication configuration as the environment where you are configuring local development.
    • +
    • Local development is only allowed in non-critical environments.
    • +
    +
    +
  • +
+

Apply configurations

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
  8. +
  9. In the Local Development pane that opens, click the Local Development toggle to enable it.
  10. +
  11. If you want to update the port on which the local development proxy server runs, click to expand Advanced Configurations and specify a value for Proxy Port.
  12. +
  13. Click Apply.
  14. +
+

Now you have done the necessary configurations to set up local development. The next section walks you through the steps to access your web application so that you can develop it locally.

+

Access your web application to develop it locally

+

Prerequisites

+
    +
  • Ensure that local development is enabled in the environment where you want to proceed with local development.
  • +
  • Ensure that your web application is running locally on http://localhost on a specific port.
  • +
+

Access your web application locally

+

You can either use the Choreo built-in identity provider or external identity provider to access your web application locally.

+
+
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
  8. +
  9. In the Local Development pane that opens, copy the command given under Step 1.
  10. +
  11. Paste the command in a terminal, ensure you replace [APP_PORT] with the port on which your application is running locally, and run the command.
  12. +
  13. +

    To access the application and proceed to develop it, go to the URL given under Step 2 in the Local Development pane.

    +
    +

    Note

    +

    The local development proxy runs on HTTPS using a self-signed certificate. Your browser may warn that the certificate is not valid. Accept the risk and proceed.

    +
    +
  14. +
+
+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
  8. +
  9. In the Local Development pane that opens, copy the redirect URLs given under Step 1.
  10. +
  11. Go to the settings in the OAuth application in your identity provider and specify the copied URLs as allowed redirect URLs.
  12. +
  13. Go to the Local Development pane in the Choreo Console and copy the command given under Step 2.
  14. +
  15. Paste the command in a terminal, ensure you replace [APP_PORT] with the port on which your application is running locally, and run the command.
  16. +
  17. +

    To access the application and proceed to develop it, go to the URL given under Step 3 in the Local Development pane.

    +
    +

    Note

    +

    The local development proxy runs on HTTPS using a self-signed certificate. Your browser may warn that the certificate is not valid. Accept the risk and proceed.

    +
    +
  18. +
+
+
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/manage-component-source-configurations/index.html b/develop-components/manage-component-source-configurations/index.html new file mode 100644 index 000000000..87d3556ff --- /dev/null +++ b/develop-components/manage-component-source-configurations/index.html @@ -0,0 +1,4202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Component Source Configurations - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Component Source Configurations

+

In Choreo, you can configure service endpoints and connections via the component.yaml source configuration file. This file ensures that the configurations required to initialize endpoints and connections are defined, as they cannot be inferred from the source code. This guide provides an overview of how to configure and manage these settings effectively.

+

The source configuration file must be committed to your repository within the .choreo directory at the root of the project directory. This ensures the ability to version the configuration files alongside repository commits, enabling better tracking and management of configurations.

+
+

Note

+
    +
  • The component-config.yaml and endpoints.yaml files will eventually be deprecated and replaced by the component.yaml file. +
  • +
  • Choreo prioritizes configuration files in the following order: component.yaml takes the highest precedence, followed by component-config.yaml, and then endpoints.yaml.
  • +
+
+

Overview of the component.yaml file

+

File location:

+
<build-context-path>/.choreo/component.yaml
+
+ +
+

Note

+
    +
  • For components built using Buildpacks, replace build-context-path with the <project-directory>. +For example, <project-directory>/.choreo/component.yaml.
  • +
  • For components built using Docker, replace build-context-path with the <docker-context-path>. +For example, <docker-context-path>/.choreo/component.yaml.
  • +
+
+

Sample component.yaml file content:

+

Click the respective tab to view the structure for your current configuration file version:

+
+
+
+
# +required The configuration file schema version
+schemaVersion: 1.1
+
+# +optional Incoming connection details for the component
+endpoints:
+  # +required Unique name for the endpoint.
+  # This name will be used when generating the managed API
+  - name: greeter-sample
+    # +optional Display name for the endpoint.
+    displayName: Go Greeter Sample
+    # +required Service section has the user service endpoint details
+    service:
+      # +optional Context (base path) of the API that gets exposed via the endpoint.
+      basePath: /greeting-service
+      # +required Numeric port value that gets exposed via the endpoint
+      port: 9090
+    # +required Type of traffic that the endpoint is accepting.
+    # Allowed values: REST, GraphQL, WS, GRPC, TCP, UDP.
+    type: REST
+    # +optional Network level visibilities of the endpoint.
+    # Accepted values: Project|Organization|Public(Default).
+    networkVisibilities: 
+      - Public
+      - Organization
+    # +optional Path to the schema definition file. Defaults to wild card route if not provided
+    # This is only applicable to REST or WS endpoint types.
+    # The path should be relative to the docker context.
+    schemaFilePath: openapi.yaml
+
+  # +optional Outgoing connection details for the component.
+  dependencies:
+    # +optional Defines the connection references from the Internal Marketplace.
+    connectionReferences:
+      # +required Name of the connection.
+      - name: hr-connection
+        # +required Name of the connection instance.
+        resourceRef: service:/HRProject/UserComponent/v1/ad088/PUBLIC
+
+ +

The descriptor-based approach of the component.yaml file simplifies and streamlines endpoint and connection configuration management. The use of versioned schemas ensures backward compatibility, providing a seamless transition with future updates.

+

You can define the following root-level configurations via the component.yaml file:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
schemaVersionRequiredThe version of the component.yaml file. Defaults to the latest version.
endpointsOptionalThe list of endpoint configurations.
dependenciesOptionalThe list of dependency configurations.
+

Endpoint configurations

+

In the endpoints section of the component.yaml file, you can define multiple service endpoint configurations. Each endpoint must have a unique name and the required fields specified in the schema overview.

+
+

Why have a unique name?

+

When you define multiple endpoints, the endpoint.name is appended to the Choreo-generated URL. A unique name ensures the endpoint is easily recognizable and readable within the URL.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
nameRequiredA unique identifier for the endpoint within the service component. Avoid using excessively long names.
displayNameOptionalA display name for the endpoint.
serviceRequiredService details for the endpoint.
      .basePathRequiredThe base path of the API exposed via this endpoint.
      .portRequiredThe numeric port value exposed via this endpoint.
typeRequiredThe type of traffic the endpoint accepts. For example, REST, GraphQL, gRPC, UDP, or TCP.
networkVisibilitiesRequiredThe network-level visibility of the endpoint. For example, project, organization, or public.
schemaFilePathRequiredThe file path to the swagger definition file. Defaults to the wildcard route if not specified. This field should be a relative path to the project path when using Java, Python, NodeJS, Go, PHP, Ruby, or WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, the path should be relative to the component root or Docker context.
+

Dependency configurations

+

In the dependencies section of the component.yaml file, you can define multiple connection configurations under dependencies.connectionReferences. You can use the connection reference generated in the in-line developer guide when creating a connection. For instructions on copying connection configurations, see the in-line developer guide displayed during connection creation.

+

You must include the following configurations in the dependencies.connectionReferences schema:

+ + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
nameRequiredThe name given to the connection.
resourceRefRequiredA unique, human-readable identifier for the service you are connecting.
+
+

Note

+

Choreo automatically generates connection configurations when you create a connection. The properties such as name and resourceRef are automatically generated. The configurations required to establish the connection will be injected into Choreo-defined environment variables.

+
+
+
+
# +required The configuration file schema version
+schemaVersion: 1.0
+
+# +optional Incoming connection details for the component
+endpoints:
+  # +required Unique name for the endpoint.
+  # This name will be used when generating the managed API
+  - name: greeter-sample
+    # +optional Display name for the endpoint.
+    displayName: Go Greeter Sample
+    # +required Service section has the user service endpoint details
+    service:
+      # +optional Context (base path) of the API that gets exposed via the endpoint.
+      basePath: /greeting-service
+      # +required Numeric port value that gets exposed via the endpoint
+      port: 9090
+    # +required Type of traffic that the endpoint is accepting.
+    # Allowed values: REST, GraphQL, WS, GRPC, TCP, UDP.
+    type: REST
+    # +optional Network level visibilities of the endpoint.
+    # Accepted values: Project|Organization|Public(Default).
+    networkVisibilities: 
+      - Public
+      - Organization
+    # +optional Path to the schema definition file. Defaults to wild card route if not provided
+    # This is only applicable to REST or WS endpoint types.
+    # The path should be relative to the docker context.
+    schemaFilePath: openapi.yaml
+
+  # +optional Outgoing connection details for the component.
+  dependencies:
+    # +optional Defines the service references from the Internal Marketplace.
+    serviceReferences:
+      # +required Name of the service reference.
+      - name: choreo:///apifirst/mttm/mmvhxd/ad088/v1.0/PUBLIC
+        # +required Name of the connection instance.
+        connectionConfig: 19d2648b-d29c-4452-afdd-1b9311e81412
+        # +required Environment variables injected into the component for connection configuration.
+        env:
+          # +required Key name of the connection configuration.
+          - from: ServiceURL
+            # +required Environment variable injected into the container.
+            to: SERVICE_URL
+
+ +

The descriptor-based approach of the component.yaml file simplifies and streamlines endpoint and connection configuration management. The use of versioned schemas ensures backward compatibility, providing a seamless transition with future updates.

+

You can define the following root-level configurations via the component.yaml file:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
schemaVersionRequiredThe version of the component.yaml file. Defaults to the latest version.
endpointsOptionalThe list of endpoint configurations.
dependenciesOptionalThe list of dependency configurations.
+

Endpoint configurations

+In the endpoints section of the component.yaml file, you can define multiple service endpoint configurations. Each endpoint must have a unique name and the required fields specified in the schema overview.

+
+

Why have a unique name?

+

When you define multiple endpoints, the endpoint.name is appended to the Choreo-generated URL. A unique name ensures the endpoint is easily recognizable and readable within the URL.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
nameRequiredA unique identifier for the endpoint within the service component. Avoid using excessively long names.
displayNameOptionalA display name for the endpoint.
serviceRequiredService details for the endpoint.
      .basePathRequiredThe base path of the API exposed via this endpoint.
      .portRequiredThe numeric port value exposed via this endpoint.
typeRequiredThe type of traffic the endpoint accepts. For example, REST, GraphQL, gRPC, UDP, or TCP.
networkVisibilitiesRequiredThe network-level visibility of the endpoint. For example, project, organization, or public.
schemaFilePathRequiredThe file path to the swagger definition file. Defaults to the wildcard route if not specified. This field should be a relative path to the project path when using Java, Python, NodeJS, Go, PHP, Ruby, or WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, the path should be relative to the component root or Docker context.
+

Dependency configurations

+

In the dependencies section of the component.yaml file, you can define multiple service connection configurations under dependencies.serviceReferences. You can use the service references generated in the in-line developer guide when creating a service connection. For instructions on copying connection configurations, see the in-line developer guide displayed during connection creation.

+

You must include the following configurations in the dependencies.serviceReferences schema:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
nameRequiredA unique name for the service reference.
connectionConfigRequiredA unique name for the connection instance.
envRequiredThe list of environment variable mappings to inject into the container.
      .fromRequiredThe key name of the connection configuration.
      .toRequiredThe environment variable to inject into the container.
+
+

Note

+

Choreo automatically generates connection configurations when you create a connection. The properties such as name, connectionConfig, and env.from are automatically generated. However, you must manually set the env.to value.

+
+
+
+
+

Overview of the component-config.yaml file

+

File location:

+
<build-context-path>/.choreo/component-config.yaml
+
+ +

Sample component-config.yaml file content:

+
apiVersion: core.choreo.dev/v1beta1
+kind: ComponentConfig
+spec:
+  # +optional Incoming connection details for the component (AKA endpoints).
+  inbound:
+    # +required Unique name for the endpoint.
+    # This name will be used when generating the managed API
+    - name: Greeting Service
+      # +required Numeric port value that gets exposed via the endpoint
+      port: 9090
+      # +required Type of traffic that the endpoint is accepting.
+      # Allowed values: REST, GraphQL, GRPC, TCP, UDP, WS.
+      type: REST
+      # +optional Network level visibility of the endpoint. Defaults to Public
+      # Accepted values: Project|Organization|Public.
+      networkVisibility: Public
+      # +optional Context (base path) of the API that gets exposed via the endpoint.
+      # This is mandatory if the endpoint type is set to REST, GraphQL or WS.
+      context: /greeting
+      # +optional The path to the schema definition file. Defaults to wildcard route if not specified.
+      # This is only applicable to REST and WS endpoint types.
+      # The path should be relative to the Docker context.
+      schemaFilePath: greeting_openapi.yaml
+  # +optional Outgoing connection details for the component.
+  outbound:
+    # +optional Defines the service references from the Internal Marketplace.
+    serviceReferences:
+      # +required Name of the service reference.
+      - name: choreo:///apifirst/mttm/mmvhxd/ad088/v1.0/PUBLIC
+        # +required Name of the connection instance.
+        connectionConfig: 19d2648b-d29c-4452-afdd-1b9311e81412
+        # +required Environment variables injected to the component for connection configuration.
+        env:
+          # +required Key name of the connection configuration.
+          - from: ServiceURL
+            # +required Environment variable injected to the container.
+            to: SERVICE_URL
+
+ +

The component-config.yaml file complements and enhances the existing endpoint configuration process. It allows you to define how the endpoints (inbound connections) in your service are exposed and how your service connects to external services or components (outbound connections).

+

You can define the following root-level configurations via the component-config.yaml file:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
apiVersionRequiredThe version of the component-config.yaml file defaults to core.choreo.dev/v1beta1.
kindRequiredThe resource type of the file defaults to ComponentConfig.
spec.inboundOptionalThe list of inbound connection configurations.
spec.outboundOptionalThe list of outbound connection configurations.
+

Inbound connection configurations (spec.inbound)

+

In the spec.inbound configuration section, you can specify endpoints to set up inbound connections. To specify endpoints, you can follow the existing endpoints schema structure. For details on the endpoints schema structure, see the endpoints schema documentation.

+

Outbound connection configurations (spec.outbound)

+

In the spec.outbound section, you can define serviceReferences. To define serviceReferences, you can use the service references generated in the Internal Marketplace when creating a service connection. To copy the outbound connection configurations, see the inline developer guide displayed when you create a connection.

+

You must include the following configurations in the serviceReferences schema:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
nameRequiredA unique name for the service reference.
connectionConfigRequiredA unique name for the connection instance.
envOptionalThe list of environment variable mappings to inject into the container.
env.fromRequiredThe key name of the connection configuration.
env.toRequiredThe environment variable to inject into the container.
+

Overview of the endpoints.yaml file

+

File location:

+
<build-context-path>/.choreo/endpoints.yaml
+
+ +

Sample endpoints.yaml file content:

+
# +required Version of the endpoint configuration YAML
+version: 0.1
+
+# +required List of endpoints to create
+endpoints:
+  # +required Unique name for the endpoint.
+  # This name will be used when generating the managed API
+- name: Greeting Service
+  # +required Numeric port value that gets exposed via this endpoint
+  port: 9090
+  # +required Type of the traffic this endpoint is accepting.
+  # Allowed values: REST, GraphQL, GRPC, UDP, TCP, WS.
+  type: REST
+  # +optional Network level visibility of this endpoint. Defaults to Public
+  # Accepted values: Project|Organization|Public.
+  networkVisibility: Project
+  # +optional Context (base path) of the API that is exposed via this endpoint.
+  # This is mandatory if the endpoint type is set to REST, GraphQL or WS.
+  context: /greeting
+  # +optional Path to the schema definition file. Defaults to wild card route if not provided
+  # This is only applicable to REST and WS endpoint types.
+  # The path should be relative to the docker context.
+  schemaFilePath: greeting_openapi.yaml
+
+ +

The endpoints.yaml configuration file allows you to define configurations for multiple endpoints necessary for Choreo service components. This schema is essential to identify the context, port binding, network exposure level, and other attributes required to generate a Choreo endpoint.

+

You can define the following root-level configurations via the endpoints.yaml file:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConfigurationRequiredDescription
versionRequiredThe version of the endpoints.yaml file.
nameRequiredA unique name for the endpoint, which Choreo will use to generate the managed API.
portRequiredThe numeric port value that gets exposed via this endpoint.
typeRequiredThe type of traffic this endpoint accepts, such as REST, GraphQL, gRPC, WS, UDP, or TCP. Currently, the MI preset supports only the REST type.
networkVisibilityRequiredThe network level visibility of this endpoint, which defaults to Public if not specified. Accepted values are Project, Organization, or Public.
contextRequiredThe context (base path) of the API that Choreo exposes via this endpoint.
schemaFilePathRequiredThe swagger definition file path. Defaults to the wildcard route if not provided. This field should be a relative path to the project path when using the Java, Python, NodeJS, Go, PHP, Ruby, and WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, this field should be a relative path to the component root or Docker context.
+

Migration guide

+

With the upcoming deprecation of the component-config.yaml file and the endpoints.yaml file, Choreo provides a seamless migration path to the component.yaml file. See the following guidelines for details depending on the configuration you want to migrate from:

+

Migrate from the component-config.yaml file

+

To migrate from the component-config.yaml file to the component.yaml file, do the following:

+
    +
  • Add the schemaVersion in the component.yaml and omit apiVersion and kind.
  • +
  • +

    Move endpoint configurations from the spec.inbound section to the endpoints section in the component.yaml file.

    +
      +
    • Copy the value of spec.inbound.context to endpoints.service.basePath.
    • +
    • Copy the value of spec.inbound.port to endpoints.service.port.
    • +
    • Copy the value of spec.inbound.networkVisibility to endpoints.networkVisibilities.
    • +
    +
  • +
  • +

    Move dependency configurations from the spec.outbound section to the dependencies section in the component.yaml file.

    +
  • +
+

Migrate from the endpoints.yaml file

+

To migrate from the endpoints.yaml file to the component.yaml file, do the following:

+
    +
  • Add the schemaVersion in the component.yaml and omit version.
  • +
  • Move endpoint configurations from the endpoints.yaml file to the endpoints section in the component.yaml file.
      +
    • Copy the value of context to endpoints.service.basePath.
    • +
    • Copy the value of port to endpoints.service.port.
    • +
    • Copy the value of networkVisibility to endpoints.networkVisibilities.
    • +
    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/manage-deployment-tracks-for-choreo-components/index.html b/develop-components/manage-deployment-tracks-for-choreo-components/index.html new file mode 100644 index 000000000..8dd159c95 --- /dev/null +++ b/develop-components/manage-deployment-tracks-for-choreo-components/index.html @@ -0,0 +1,3681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Deployment Tracks for Choreo Components - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Deployment Tracks for Choreo Components

+

Choreo allows you to create and manage dedicated deployment tracks for components, facilitating independent version control and deployment. This capability also allows you to unlink deployment tracks from associated branches or relink them to different branches so that you can align with your preferred Git workflows, such as the feature branch workflow or GitFlow workflow.

+
+

Info

+

Deployment track creation and management does not apply to API Proxy and BYOI components.

+
+

Create a deployment track

+

Prerequisites:

+
    +
  • Create a component in Choreo.
  • +
+

Follow the steps below to create a deployment track for a component:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you want to create a deployment track for.
  4. +
  5. On the header of the component overview page, click the Deployment Track drop-down list.
  6. +
  7. Click + Create New to open the Create Deployment Track dialog.
  8. +
  9. In the Create Deployment Track dialog, do the following:
      +
    1. Select a branch to associate with the deployment track.
    2. +
    3. Optionally, specify a description for the deployment track.
    4. +
    5. To create a deployment track for a service component, specify a unique API version indicating the major and minor version numbers.
    6. +
    +
  10. +
  11. Click Create.
  12. +
+ +

If you want to detach a branch reference from a deployment track, you must unlink the branch.

+
+

Info

+

When you unlink the branch of a deployment track, the active deployments are unaffected. However, while you can redeploy the existing deployment, you cannot perform a new deployment.

+
+

Follow the steps below to unlink a deployment track of a component:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to unlink a deployment track.
  4. +
  5. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
  6. +
  7. Click the edit icon corresponding to the deployment track you want to unlink.
  8. +
  9. In the Edit Branch dialog that opens, click the Branch Name list and select None.
  10. +
  11. Click Save.
  12. +
+ +

To associate a branch reference to an unlinked deployment track, you must link a branch.

+
+

Info

+

To build and deploy the contents of the linked branch, you must perform a manual build and deploy.

+
+

Prerequisites:

+
    +
  • A minimum of two branches in your GitHub repository.
  • +
+

Follow the steps below to link a branch to an unlinked deployment track:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you want to associate a branch reference for.
  4. +
  5. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
  6. +
  7. Click + Link Branch corresponding to the unlinked deployment track for which you want to associate a branch.
  8. +
  9. In the Link Branch dialog that opens, click the Branch Name list and select the branch you want to relink.
  10. +
  11. Click Save.
  12. +
+ +

To switch the branch reference of a linked deployment track, you must relink to an appropriate branch.

+
+

Info

+

If you unlink the existing branch of a deployment track and link a different branch, you must perform a manual build and deploy to build and deploy the contents of the recently linked branch.

+
+

Prerequisites:

+
    +
  • A minimum of two branches in your GitHub repository.
  • +
+

Follow the steps below to switch the branch reference of a linked deployment track:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you want to relink a deployment track for.
  4. +
  5. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
  6. +
  7. Click the Edit Branch icon corresponding to the deployment track you want to relink.
  8. +
  9. In the Edit Branch dialog that opens, click the Branch Name list and select the branch you want to relink.
  10. +
  11. Click Save.
  12. +
+

Now that you understand how to create and manage deployment tracks for components, let’s explore a sample scenario to see how a developer can use deployment tracks to manage version releases in Choreo.

+

Sample Scenario: Manage version releases with deployment tracks

+

Let’s consider the following version release scenario:

+
    +
  • To initiate work on a new feature, a developer creates a new branch, named feature-x from either the main or dev branch.
  • +
  • Once development is complete, the developer proceeds to merge the feature-x branch into the dev branch for testing.
  • +
  • Upon successful testing in the dev branch, the developer proceeds to merge all the changes into the main branch for production deployment.
  • +
+

Following are the actions you need to take from a deployment track perspective to manage the version release:

+
    +
  1. To prepare for the new version release, unlink the main branch from the associated deployment track (let’s consider this as the deployment track 1).
  2. +
  3. Proceed to merge the dev branch containing the tested changes into the main branch.
  4. +
  5. Unlink the dev branch from the associated deployment track (let’s consider this as deployment track 2).
  6. +
  7. Link deployment track 2 containing the latest version of the service to the main branch for deployment.
  8. +
  9. To facilitate ongoing development and testing, create another deployment track (let’s consider this as deployment track 3) and link it to the dev branch.
  10. +
+
+

Tip

+
    +
  • As a developer, you can strategically unlink and relink deployment tracks to effectively manage different versions of your services within Choreo.
  • +
  • You can create new deployment tracks for ongoing development branches like dev to ensure a continuous development and release cycle.
  • +
+
+

Delete a deployment track

+

If you no longer need a deployment track, you can delete it.

+
+

Note

+

If the component exposes an endpoint or proxy and you want to delete the last version in the major version range, the recommended approach is to retire that version first. This allows consumers to transition to the next major version and prevents a sudden break in their experience. +For example, if you have deployment tracks for v1.0 and v2.0, notify consumers to switch to v2.0 before deleting v1.0. Then, retire the APIs in v1.0 and proceed to delete the associated deployment track.

+
+

Prerequisites:

+
    +
  • At least 2 deployment tracks in a component.
  • +
+

Follow the steps below to delete a deployment track:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to delete a deployment track.
  4. +
  5. On the header of the component overview page, click the Deployment Track drop-down list.
  6. +
  7. Click + View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
  8. +
  9. Click the Delete icon corresponding to the deployment track you want to delete.
  10. +
  11. Click Delete to confirm the deletion.
  12. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/index.html b/develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/index.html new file mode 100644 index 000000000..06562ece6 --- /dev/null +++ b/develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/index.html @@ -0,0 +1,3742 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage the Micro Integrator Runtime Version in Your Integration Project - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage the Micro Integrator Runtime Version in Your Integration Project

+

Choreo allows you to use a preferred WSO2 Micro Integrator (MI) runtime version in your integration project. Currently, Choreo supports MI product versions 4.1.0 and 4.2.0. You have the flexibility to deploy WSO2 updates within these specified versions.

+

When you create an integration project, you can specify a required runtime version to gain control over the environment in which your integration runs. This version management capability empowers you to tailor your projects depending on your runtime requirements, enhancing the customization and adaptability of your integration workflows.

+

Understand the version string

+

WSO2 Micro Integrator (MI) utilizes a versioning system consisting of three-digit numbers, such as 4.1.0 and 4.2.0, following semantic versioning principles. The product remains committed to receiving updates from WSO2, including security fixes, bug resolutions, and enhancements. Within the Choreo platform, the MI runtime version is constructed by combining the product release version with its corresponding update level.

+

In Choreo, the MI runtime version is structured as a four-digit number, for example, 4.1.0.14 or 4.2.0.17. The first three digits represent the product release version, while the last digit signifies the update level of the product. The fourth digit is optional and can be omitted.

+

Version string

+

Version management in WSO2 Integration Studio

+

If you are using WSO2 Integration Studio to build and deploy integration artifacts in WSO2 Micro Integrator, you can create multiple runtime environments and execute projects on any selected environment. WSO2 Integration Studio also allows you to configure multiple Micro Integrator runtime environments, offering flexibility and customization in the execution of integration processes.

+

You can specify the Runtime version when you create an integration project in WSO2 Integration Studio. In the project creation wizard, specify the runtime version in the Runtime version field, as shown below. +Specify Runtime version

+

An integration project is structured as a Maven project with multiple sub-modules. The root pom.xml file holds crucial information about the target runtime. The runtime version you configure when you create a new project is saved within the root pom.xml file. The version information is stored in the element under the in the pom.xml file. If there is a need to update the runtime version, you have the flexibility to modify the value to a valid runtime version and ensure that the project runs in the required runtime environment.

+

project runtime version

+

You can establish multiple runtime environments by utilizing updated MI instances. With a valid WSO2 subscription, you can also access and download updates to set up an updated MI server locally. This update process allows you to select a preferred update level as the runtime version. Consequently, you can run your integration on a runtime with the latest updates, ensuring optimal performance and access to new features.

+

Configure a Micro Integrator runtime environment in Integration Studio

+

If you are using WSO2 Integration Studio, follow these steps to set up a remote server instance with a Micro Integrator runtime environment to execute your integration project:

+
+

Note

+

If you have not downloaded and installed WSO2 Integration Studio, you can follow the installation instructions in the WSO2 API Manager documentation.

+
+
    +
  1. Launch WSO2 Integration Studio and click Add Server in the Getting Started view. + Add server
  2. +
  3. In the Define a New Server dialog, click to expand the WSO2 directory and select WSO2 Remote Server. + Define a remote server instance
  4. +
  5. +

    Enter the WSO2 Micro Integrator Management API URL in the Server URL field and click Test Connection.

    +
    +

    Note

    +

    The Management API of WSO2 Micro Integrator is an internal REST API introduced to substitute MI admin services. The default HTTPS port of the Management API of WSO2 Micro Integrator is 9164. If you have not manually changed the default port, you must set the Management API URL as https://localhost:9164/management. If you have changed the default HTTPS port, you must set the port number appropriately when specifying the Server URL. For more information on the default ports of WSO2 Micro Integrator, see WSO2 Micro Integrator default ports in the WSO2 API Manager documentation.

    +
    +

    Set server URL

    +
  6. +
  7. +

    Click Finish.

    +
  8. +
  9. In the Add and Remove dialog, select the integration components to move from the left side to the right side.
  10. +
  11. Click Add >.
  12. +
  13. Click Finish.
  14. +
+

Your integration project is now running in a remote server instance with the Micro Integrator runtime environment you require. +If you need to make changes to the integration project, expand the remote server instance, right-click on the deployed exporter project, and select Redeploy to apply the changes.

+

Redeploy project

+

Convention for version interpretation in Choreo deployments

+

You can use the following convention to indicate the required MI runtime version in your integration project:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Version formatExampleDescription
Product version4.1.0, 4.2.0Deploy on the latest update level of the mentioned product version.
Product version with update level4.1.0.15, 4.2.0.17Deploy on the exact update level of the mentioned product version.
GA version4.1.0.0, 4.2.0.0Deploy on the exact GA version without any update.
Default versionEmpty valueDeploy on the latest update level of the default product version.
+

Choreo utilizes Alpine images for configuring and deploying the Micro Integrator runtime. This includes automated configuration of the JRE/JDK, customized to the compatibility of the chosen runtime version, simplifying the setup procedure.

+

Migrate between runtime versions

+

Changing the runtime version in an integration project may become necessary during product version upgrades or when you want to apply updates.

+

To change the runtime version of a MI Integration, follow the below steps.

+

Update the runtime version in the integration project

+

To change the runtime version in the integration project, follow the steps below: +1. Open the project in Integration Studio. +2. Right-click on the project and select Change Runtime MI Version. + Update Runtime version +3. Specify the new runtime version as shown below: + Update Runtime version +4. Alternatively, you can manually update the version by opening the root pom.xml file. Open pom.xml and change the required runtime version in <project.runtime.version> element under <properties> section.

+

To test the changes locally, you must download and set up the runtime environment locally. Then, you must configure the Integration Studio runtime environment by directing it to the locally installed MI runtime. Once the setup is complete, you can deploy your integrations on the MI runtime environment and proceed to the testing phase.

+

After completing the tests to ensure everything works as expected, you can follow below steps to deploy the project in Choreo:

+
    +
  1. Commit and push the changes to your repository.
  2. +
  3. Go to https://console.choreo.dev/ and sign in.
  4. +
  5. Select your project from the Project list in the header.
  6. +
  7. Select your MI integration component from the Component list in the header.
  8. +
  9. In the left navigation menu, click Build.
  10. +
  11. Select the latest commit and click Build.
  12. +
  13. In the left navigation menu, click Deploy.
  14. +
  15. Click on the Configure and Deploy and deploy the component.
  16. +
  17. Verify the Runtime version by checking the logs by selecting the Runtime Logs under the Observability section.
  18. +
+

You will see the runtime version in the logs as shown below: + Runtime version in logs

+

Next, you must conduct additional testing in the development environment on Choreo before you promote the integration to production environments.

+

Troubleshoot errors

+

The following error codes can help you troubleshoot errors that occur during the integration component build:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Error codeDescription
110 - 119Internal server error.
121Malformed runtime version.
122The specified runtime version is not available. Either the product or update level is not available.
123Trivy security vulnerabilities found in the libs directory.
124Trivy security vulnerabilities found in the dropins directory.
125Trivy security vulnerabilities found in the libs or dropins directory.
126Error building integration project.
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/sharing-and-reusing/create-a-connection/index.html b/develop-components/sharing-and-reusing/create-a-connection/index.html new file mode 100644 index 000000000..ce3b68639 --- /dev/null +++ b/develop-components/sharing-and-reusing/create-a-connection/index.html @@ -0,0 +1,3524 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create a Connection - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Create a Connection

+

Connections in Choreo provide a simple and uniform approach to seamlessly integrate components with services or resources.

+

Choreo allows you to create connections to services deployed in Choreo or registered as external services. It also allows you to create connections to any Choreo-managed database.

+

To create a connection to a service or a database, follow the step-by-step instructions in the respective tab:

+
+
+
+

Create a connection to a Choreo service

+

Follow these steps to create a connection to a service deployed in Choreo:

+
    +
  1. +

    In the Choreo Console, go to the top navigation menu and set the visibility level as project or component as follows:

    +
      +
    • Project Connection: Select an organization and a project in that organization.
    • +
    • Component Connection: Select an organization, a project in that organization, and a component in the selected project.
    • +
    +
  2. +
  3. +

    In the left navigation menu, click Dependencies and then Connections. This page lists all the existing connections.

    +
  4. +
  5. Click +Create. This opens the Marketplace view where you can browse and search for services or databases.
  6. +
  7. Click the Services tab. You can search and apply filters to efficiently find a service.
  8. +
  9. Click on the service you want to connect to.
  10. +
  11. Enter a name and a description for the connection and then click Next. This displays the Service URL for both development and production environments.
  12. +
  13. Click Create.
  14. +
+

This creates the connection and displays its details for each environment, along with an inline guide on how to use the connection in your component.

+

Create a connection to an external service

+

Follow these steps to create a connection to an external service:

+
    +
  1. Follow steps 1–5 from the previous section.
  2. +
  3. Expand the Environment to Endpoint section and verify the service endpoints assigned to the Choreo environments.
  4. +
  5. Click Create.
  6. +
+

For step-by-step instructions on using a connection in your service, see Use a Connection in Your Service.

+

For step-by-step instructions on using a connection in your web application, see Use a Connection in Your Web Application.

+
+
+

Prerequisites:

+ +

Follow these steps to create a connection to a Choreo-managed database:

+
    +
  1. +

    In the Choreo Console, go to the top navigation menu and set the visibility level as project or component as follows:

    +
      +
    • Project Connection: Select an organization and a project in that organization.
    • +
    • Component Connection: Select an organization, a project in that organization, and a component in the selected project.
    • +
    +
  2. +
  3. +

    In the left navigation menu, click Dependencies and then Connections. This page lists all the existing connections.

    +
  4. +
  5. Click +Create. This opens the Marketplace view where you can browse and search for services or databases.
  6. +
  7. Click the Databases tab. You can search and apply filters to efficiently find a database.
  8. +
  9. Click on the database you want to connect to.
  10. +
  11. +

    To create the connection, follow these steps:

    +
      +
    1. Enter a name and description.
    2. +
    3. +

      Under Environment Configuration, select credentials for each environment.

      +
      +

      Note

      +

      By default, the selected database is applied to all environments. To use different databases for specific environments, select the appropriate database and provide the corresponding credentials for each environment.

      +
      +
    4. +
    5. +

      Click Create.

      +
    6. +
    +
  12. +
+

This creates the connection and displays the database connection details for each environment, along with an inline guide on how to use the connection in your component.

+

For step-by-step instructions on using a database in your component, see Use a Database Connection in Your Component.

+
+
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/sharing-and-reusing/share-and-reuse-services/index.html b/develop-components/sharing-and-reusing/share-and-reuse-services/index.html new file mode 100644 index 000000000..093ae3442 --- /dev/null +++ b/develop-components/sharing-and-reusing/share-and-reuse-services/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/sharing-and-reusing/share-and-reuse-web-applications/index.html b/develop-components/sharing-and-reusing/share-and-reuse-web-applications/index.html new file mode 100644 index 000000000..e04a4f385 --- /dev/null +++ b/develop-components/sharing-and-reusing/share-and-reuse-web-applications/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-components/sharing-and-reusing/use-a-connection-in-your-service/index.html b/develop-components/sharing-and-reusing/use-a-connection-in-your-service/index.html new file mode 100644 index 000000000..ba8a69cef --- /dev/null +++ b/develop-components/sharing-and-reusing/use-a-connection-in-your-service/index.html @@ -0,0 +1,3946 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use a Connection in Your Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Use a Connection in Your Service

+

Choreo allows you to share and reuse your services, accelerating development and enhancing efficiency in building integrated applications through connections.

+

For step-by-step on instruction on creating a connection, see Create a Connection.

+

To learn more about Choreo Connections, see the documentation on Connections.

+

Consume a service through a connection

+

You can consume a Choreo-deployed service within another service. Consuming connections from within Choreo services is seamless and straightforward. Follow the steps below to consume a Choreo service:

+

Step 1: Add connection configurations

+

To integrate another service into your application, click the appropriate tab below based on your current configuration file and follow the step-by-step instructions:

+
+
+
+
    +
  1. +

    Copy and paste the snippet from the in-line developer guide into the component.yaml file.

    +

    The following is a sample snippet:

    +
    dependencies:
    +    connectionReferences:
    +    - name: <CONNECTION_NAME>
    +      resourceRef: <RESOURCE_IDENTIFIER>
    +
    + + + + + + + + + + + + + + + + + + +
    FieldDescription
    nameThe name given to the connection.
    resourceRefA unique, readable identifier of the service being connected to.
    +
  2. +
  3. +

    If you've previously added a connectionReferences section under dependencies, append this as another item under connectionReferences. Upon deploying the component, Choreo automatically creates a subscription if applicable and the necessary configurations to establish the connection will be injected into the Choreo-defined environment variables.

    +

    The following table details the Choreo-defined environment variables:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Configuration KeyChoreo-Defined Environment Variable Name
    ServiceURLCHOREO_<CONNECTION_NAME>_SERVICEURL
    ConsumerKeyCHOREO_<CONNECTION_NAME>_CONSUMERKEY
    ConsumerSecretCHOREO_<CONNECTION_NAME>_CONSUMERSECRET
    TokenURLCHOREO_<CONNECTION_NAME>_TOKENURL
    +

    If you'd like to use custom environment variable names instead of the Choreo-defined ones, add the dependency as a service reference under dependencies in the same file. For more details, refer to the instructions under the component.yaml file (v1.0) tab.

    +

    The following table provides details on the configuration keys associated with the connection:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescriptionOptionalSensitive
    ServiceURLstringService URL of the Choreo servicefalsefalse
    ConsumerKeystringConsumer key of the Choreo servicefalsefalse
    ConsumerSecretstringConsumer secret of the Choreo servicefalsetrue
    TokenURLstringToken URL of the STSfalsefalse
    +
  4. +
+

Step 2: Read configurations within the application

+

Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

+

The following is a sample code snippet in NodeJS:

+
const serviceURL = process.env.CHOREO_<CONNECTION_NAME>_SERVICEURL;
+
+ +
+
+
+

Note

+

This component.yaml v1.0 is a legacy configuration format. For new projects, we recommend using the latest version (v1.1) of component.yaml for improved usability and features.

+
+
    +
  1. +

    Copy and paste the snippet from the in-line developer guide into the component.yaml file.

    +

    The following is a sample snippet:

    +
    dependencies:
    +    serviceReferences:
    +    - name: <SERVICE_NAME>
    +      connectionConfig: <CONNECTION_ID>
    +      env:
    +      - from: ServiceURL
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: ConsumerKey
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: ConsumerSecret
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: TokenURL
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    nameThe name of the service you are connecting to.
    connectionConfigThe unique connection identifier for the connection.
    envThe environment variable mapping.
    fromThe key of the configuration entry.
    toThe environment variable name to which Choreo will inject the value of the key.
    +
  2. +
  3. +

    Replace <YOUR_ENV_VARIABLE_NAME_HERE> with an appropriate environment variable name of your choice. If you have previously added a service reference section under dependencies, append this as another item under serviceReferences.

    +

    Upon deploying the component, Choreo automatically creates a subscription if applicable and populates the specified environment variables with actual values.

    +

    The following table provides details on the configuration keys associated with the connection:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescriptionOptionalSensitive
    ServiceURLstringService URL of the Choreo servicefalsefalse
    ConsumerKeystringConsumer key of the Choreo servicefalsefalse
    ConsumerSecretstringConsumer secret of the Choreo servicefalsetrue
    TokenURLstringToken URL of the STSfalsefalse
    +
  4. +
+

Step 2: Read configurations within the application

+

Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

+

The following is a sample code snippet in NodeJS:

+
const serviceURL = process.env.SVC_URL;
+
+ +
+
+
+

Note

+

This component-config.yaml is a legacy configuration format. For new projects, we recommend using the latest version (v1.1) of component.yaml for improved usability and features.

+
+
    +
  1. +

    Copy and paste the snippet from the in-line developer guide into the component-config file under the spec section.

    +

    The following is a sample snippet:

    +
    outbound:
    +    serviceReferences:
    +    - name: <SERVICE_NAME>
    +      connectionConfig: <CONNECTION_ID>
    +      env:
    +      - from: ServiceURL
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: ConsumerKey
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: ConsumerSecret
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: TokenURL
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    nameThe name of the service you are connecting to.
    connectionConfigThe unique connection identifier for the connection.
    envThe environment variable mapping.
    fromThe key of the configuration entry.
    toThe environment variable name to which Choreo will inject the value of the key.
    +
  2. +
  3. +

    Replace <YOUR_ENV_VARIABLE_NAME_HERE> with an appropriate environment variable name of your choice. If you have previously added an outbound service reference, append this as another item under serviceReferences.

    +

    Upon deploying the component, Choreo automatically creates a subscription if applicable and populates the specified environment variables with actual values.

    +

    The following table provides details on the configuration keys associated with the connection:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescriptionOptionalSensitive
    ServiceURLstringService URL of the Choreo servicefalsefalse
    ConsumerKeystringConsumer key of the Choreo servicefalsefalse
    ConsumerSecretstringConsumer secret of the Choreo servicefalsetrue
    TokenURLstringToken URL of the STSfalsefalse
    +
  4. +
+

Step 2: Read configurations within the application

+

Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

+

The following is a sample code snippet in NodeJS:

+
const serviceURL = process.env.SVC_URL;
+
+ +
+
+
+

Step 3: Acquire an OAuth 2.0 access token

+

To consume a Choreo service with the visibility level set to organization or public and secured by the OAuth 2.0 security scheme, you must obtain an OAuth 2.0 token from the token endpoint. Subsequently, you can use the token to invoke the service.

+
    +
  • +

    For languages with OAuth 2.0-aware HTTP clients, you must pass the OAuth 2.0-related configurations such as client id, client secret and so on, obtained when creating the connection to your HTTP client configuration. The HTTP client autonomously manages token retrieval and refreshing.

    +
  • +
  • +

    For languages without OAuth 2.0-aware HTTP clients, you must manually initiate a call to the token endpoint. This includes fetching the token and managing token expiration and refresh directly within your application code. The following is a sample curl command to obtain a token:

    +
    CONSUMER_KEY="your_consumer_key"
    +CONSUMER_SECRET="your_consumer_secret"
    +TOKEN_URL="your_token_url"
    +
    +# Encode client credentials as Base64
    +CLIENT_CREDENTIALS=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)
    +
    +curl -X POST $TOKEN_URL \
    +  -H "Content-Type: application/x-www-form-urlencoded" \
    +  -H "Authorization: Basic $CLIENT_CREDENTIALS" \
    +  --data-urlencode "grant_type=client_credentials"
    +
    + +
  • +
+

Step 4: Invoke the Service

+

You can invoke the service as follows:

+
    +
  • +

    For languages with OAuth 2.0-aware HTTP clients, you can invoke the service in a straightforward manner. The HTTP client seamlessly manages OAuth 2.0 authentication without requiring additional intervention.

    +

    As the service URL you can use the URL that you resolved in step 2. For sample requests and responses, see the API definition provided via the Choreo marketplace for the service.

    +
  • +
  • +

    For languages without OAuth 2.0-aware HTTP clients, you can use the token obtained in step 3 to make calls to the dependent service. Subsequently, add the obtained token to the HTTP authorization header with the bearer prefix. +As the service URL you can use the URL that you resolved in step 2. For sample requests and responses, see the API definition of the service provided via the Choreo marketplace.

    +

    The following is a sample code snippet in NodeJS:

    +
    const response = await axios.get(serviceURL/{RESOURCE_PATH}, {
    +    headers: {
    +      'Authorization': `Bearer ${accessToken}`
    +    }
    +});
    +
    + +
    +

    Note

    +

    If you want to consume a Choreo service at the project visibility level, you don't need to obtain a token. You can directly invoke the service using the resolved URL.

    +
    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/sharing-and-reusing/use-a-connection-in-your-web-application/index.html b/develop-components/sharing-and-reusing/use-a-connection-in-your-web-application/index.html new file mode 100644 index 000000000..7798d486c --- /dev/null +++ b/develop-components/sharing-and-reusing/use-a-connection-in-your-web-application/index.html @@ -0,0 +1,3572 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use a Connection in Your Web Application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Use a Connection in Your Web Application

+

Choreo simplifies the process of integrating services into your web application. The approach to connect to a service can vary based on your web application.

+

To connect to a selected service, follow the step-by-step instructions given below depending on the authentication mechanism used in your web application.

+
+
+
+

Choreo-managed authentication allows you to seamlessly handle authentication for your web application. You can configure your web application to work with the built-in identity provider of Choreo or any external identity provider that supports OIDC/OAuth2.0

+
+

Note

+

Choreo's managed authentication is currently available only for web applications created with React, Angular, or Vue.js buildpacks.

+
+

Follow the steps below to use an existing connection within your web application:

+

Step 1: Add the connection configuration

+

To integrate a service into your application, you must first add the connection configuration as follows:

+
    +
  1. +

    For single page applications (SPAs), you must add the connection configuration as a file mount. You can mount a file via the Configurations pane on the Deploy page. You must mount a file (for example, config.js) and add the configuration provided in the in-line developer documentation into it.

    +

    The following is a sample configuration:

    +
         window.configs = {
    +         apiUrl: '<SERVICE_URL>',        
    +     };
    +
    + +
  2. +
  3. +

    To ensure accessibility of the config.js file via JavaScript at runtime, add a script tag as follows in the index.html file to reference the config.js file:

    +
    <!DOCTYPE html>
    +<html lang="en">
    +<head>
    +    <meta charset="utf-8" />
    +    <title>My React App</title>
    +</head>
    +<body>
    +    <div id="root"></div>
    +    <script src="%PUBLIC_URL%/config.js"></script>
    +</body>
    +</html>
    +
    + +
    +

    Note

    +

    If you use an external IdP, you must add the IdP's configuration to the same file.

    +

    For more information on working with IdPs, see Configure Asgardeo as an External Identity Provider.

    +
    +
  4. +
+

Step 2: Read the configuration

+

Once you add the connection configuration, you can proceed to read the configuration from your application. The steps to read depend on the programming language you use.

+

The following is a sample code snippet in NodeJS:

+
     const serviceURL = window?.configs?.apiUrl ? window.configs.apiUrl : "/";
+
+ +

Step 3: Invoke the service

+

If you use Choreo-managed authentication, Choreo handles the security handshaking for the application during deployment. The connected service will be accessible under the same domain as your application. Therefore, you can call the configured path directly using your preferred HTTP client.

+

The following is a sample code snippet in NodeJS:

+
     const response = await axios.get(serviceURL/{RESOURCE_PATH});
+
+ +
+

Note

+

If you are using an external IdP provider instead of Choreo-managed authentication, you must obtain an access token from your IdP and add it to the HTTP authorization header with the bearer prefix.

+
+
+
+

If you are not using Choreo-managed authentication or your web application lacks authentication, follow the steps below to connect to a service from your web application:

+

Step 1: Add the connection configuration

+

For single-page applications (SPAs), you must add the connection configuration as a file mount. You can mount a file via the Configurations pane on the Deploy page. You must mount a file (for example, config.js) and add the following configuration into it.

+

The following is a sample configuration:

+
     window.configs = {
+         apiUrl: '<SERVICE_URL>',
+         consumerKey: '<CONSUMER_KEY>',
+         consumerSecret: '<CONSUMER_SECRET>',
+         tokenUrl: '<TOKEN_URL>',
+     };
+
+ +

For other types of web applications, you must add the respective configuration into your application.

+

Step 2: Read the configuration

+

Once you have added the connection configuration, you can proceed to read the configuration from your application. The steps to read depend on the programming language you use.

+

The following is a sample code snippet in NodeJS:

+
     const serviceURL = window?.configs?.apiUrl ? window.configs.apiUrl : "/";
+
+ +

Step 3: Acquire an OAuth 2.0 access token

+
    +
  • +

    For languages with OAuth 2.0-aware HTTP clients, you must pass the OAuth 2.0-related configurations such as client id, client secret and so on, obtained when creating the connection to your HTTP client configuration. The HTTP client autonomously manages token retrieval and refreshing.

    +
  • +
  • +

    For languages without OAuth 2.0-aware HTTP clients, you must manually initiate a call to the token endpoint. This includes fetching the token and managing token expiration and refresh directly within your application code. The following is a sample curl command to obtain a token:

    +
    CONSUMER_KEY="your_consumer_key"
    +CONSUMER_SECRET="your_consumer_secret"
    +TOKEN_URL="your_token_url"
    +
    +# Encode client credentials as Base64
    +CLIENT_CREDENTIALS=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)
    +
    +curl -X POST $TOKEN_URL \
    +-H "Content-Type: application/x-www-form-urlencoded" \
    +-H "Authorization: Basic $CLIENT_CREDENTIALS" \
    +--data-urlencode "grant_type=client_credentials"
    +
    + +
  • +
+

Step 4: Invoke the service

+

You can invoke the service as follows:

+
    +
  • +

    For languages with OAuth 2.0-aware HTTP clients, you can invoke the service in a straightforward manner. The HTTP client seamlessly manages OAuth 2.0 authentication without requiring additional intervention.

    +

    As the service URL you can use the URL that you resolved in step 2 above. For sample requests and responses, see the API definition provided via the Choreo marketplace for the service.

    +
  • +
  • +

    For languages without OAuth 2.0-aware HTTP clients, you can use the token obtained in step 3 above to make calls to the dependent service. Subsequently, add the obtained token to the HTTP authorization header with the bearer prefix.

    +

    As the service URL you can use the URL that you resolved in step 2 above. For sample requests and responses, see the API definition of the service provided via the Choreo marketplace.

    +

    The following is a sample code snippet in NodeJS:

    +
        const response = await axios.get(serviceURL/{RESOURCE_PATH}, {
    +        headers: {
    +        'Authorization': `Bearer ${accessToken}`
    +        }
    +    })
    +
    + +
  • +
+
+
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/index.html b/develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/index.html new file mode 100644 index 000000000..8aec1c6a7 --- /dev/null +++ b/develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/index.html @@ -0,0 +1,3693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use a Database Connection in Your Component - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Use a Database Connection in Your Component

+

Choreo allows you to share and reuse Choreo-managed databases, accelerating development and enhancing efficiency in building integrated applications through connections.

+

For step-by-step instructions on creating a database connection, see Create a Connection.

+

To learn more about Choreo Connections, see the documentation on Connections.

+

Consume a database through a connection

+

To consume a Choreo-managed database via a connection, follow these steps:

+

Step 1: Add connection configurations

+
    +
  1. +

    Copy and paste the snippet from the inline developer guide into the component-config file under the spec section.

    +

    The following is a sample snippet:

    +
    outbound:
    +    serviceReferences:
    +    - name: database:hrdbProd
    +      connectionConfig: 01ef700c-e378-138e-a11f-6e8e5a924f54
    +      env:
    +      - from: HostName
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: Port
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: Username
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: Password
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +      - from: DatabaseName
    +        to: <YOUR_ENV_VARIABLE_NAME_HERE>
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    NameThe name of the database you are connecting to.
    ConnectionConfigThe unique connection identifier for the connection.
    envThe environment variable mapping.
    fromThe key of the configuration entry.
    toThe environment variable name to which Choreo will inject the value of the key.
    +
  2. +
  3. +

    Replace <YOUR_ENV_VARIABLE_NAME_HERE> with appropriate environment variable names. If you have already added an outbound service reference, append this as another entry under serviceReferences.

    +

    The following table provides details on the configuration keys associated with the connection:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescriptionOptionalSensitive
    HostNamestringThe hostname of the database server where the database resides.falsefalse
    PortstringThe port number on which the database server listens for connections.falsefalse
    UsernamestringThe username for database access.falsefalse
    PasswordstringThe password for database access.falsetrue
    DatabaseNamestringThe name of the database to connect.falsefalse
    +
  4. +
+

Step 2: Read configurations within the application

+

Once you add the connection configuration snippet, you can read the configurations within your application. The steps to follow depend on the programming language you are using.

+

The following is a sample code snippet in JavaScript:

+
const hostName = process.env.HOST_NAME;
+
+ +

Step 3: Initiate a database connection

+

To initiate a connection to the database, follow these steps:

+

In this example, you will connect to a MySQL database.

+

Step 3.1: Install the required packages

+

For the MySQL database, install the mysql2 package using npm:

+
// Install the mysql2 package
+npm install mysql2
+
+ +

Step 3.2: Import required packages

+
const client = require('mysql2')
+
+ +

Step 3.3: Establish a connection

+

To establish the connection, use the environment variables for hostName, username, password, databaseName, and port as follows:

+

var connection = client.createConnection({
+      host: hostName,
+      user: username,
+      password: password,
+      database: databaseName,
+      port: port
+});
+
+connection.connect((err) => {
+      if (err) {
+          return;
+      }
+      // Connection is successful
+});
+
+By following these steps, your component can interact with the Choreo-managed database seamlessly.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/submit-and-manage-workflow-approval-requests/index.html b/develop-components/submit-and-manage-workflow-approval-requests/index.html new file mode 100644 index 000000000..69d749ac4 --- /dev/null +++ b/develop-components/submit-and-manage-workflow-approval-requests/index.html @@ -0,0 +1,3445 @@ + + + + + + + + + + + + + + + + + + + + + + + + Submit and Manage Workflow Approval Requests - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Submit and Manage Workflow Approval Requests

+

In Choreo, if an administrator configures a workflow to require approval, you must submit a request to obtain approval to perform the task.

+

Upon submitting a workflow approval request, Choreo notifies all authorized assignees via email about the review request. When an authorized assignee approves or rejects the request, you will receive an email with details of the decision.

+

The approach to request approval can vary depending on the workflow.

+

Request approval for environment promotion

+

Prerequisites:

+
    +
  • Ensure you have a component created, built, and deployed to the development environment.
  • +
  • Ensure that an approval workflow is configured for environment promotion.
  • +
  • Ensure you are promoting the component to a critical environment, such as production.
  • +
+

To request approval to promote a component from the development environment to production, follow these steps:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you want to deploy. This takes you to the Overview page of the component.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Go to the Development card and click Request to Promote.
  8. +
  9. +

    In the Request Approval pane that opens, enter your request details and click Submit. This creates a request and notifies all authorized assignees via email about the request.

    +
    +

    Note

    +

    When an environment promotion request for a specific component is pending review, Choreo restricts other developers from making the same request until the pending request is either approved or rejected.

    +
    +
  10. +
+

When an authorized assignee approves the request, you will receive a confirmation email and can proceed to promote the component to production.

+

Cancel a workflow approval request

+

If you want to cancel a workflow approval request that is already submitted, you can do so before the request is approved or rejected.

+

When you submit a workflow approval request, the Request to Promote button changes to Cancel Request. To cancel an approval request, click Cancel Request. Upon confirming the cancellation, all configured approvers are notified immediately, and the request will no longer be pending.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-components/work-with-the-micro-integrator-runtime-in-choreo/index.html b/develop-components/work-with-the-micro-integrator-runtime-in-choreo/index.html new file mode 100644 index 000000000..d531b743f --- /dev/null +++ b/develop-components/work-with-the-micro-integrator-runtime-in-choreo/index.html @@ -0,0 +1,3977 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get Started with the Micro Integrator Runtime - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Work with the Micro Integrator Runtime in Choreo

+

WSO2 Micro Integrator (WSO2 MI) is a lightweight, high-performance integration runtime. It allows you to run integrations developed using WSO2 Integration Studio within Choreo.

+

The topics on this page walk you through the key aspects you need to understand to use the WSO2 MI runtime effectively in Choreo.

+

Integration types

+

Choreo supports the following WSO2 MI integrations that cater to different use cases and requirements. Each integration type serves a specific purpose. Therefore, it is essential to understand their differences to easily choose the most appropriate integration for your use case.

+
    +
  • Service: Exposes an integration as an API via HTTP, making it possible to create a RESTful interface for your integration services. This type is ideal for scenarios where you need to provide an API for external systems or clients to interact with your integration.
  • +
  • Event Handler: Triggers an integration based on external events such as messages arriving on a queue or updates in a database. This type is well-suited for implementing event-driven architectures or responding to changes in your system's environment.
  • +
  • Scheduled Task: Runs an integration automatically at predefined time intervals, ensuring that specific integration tasks occur at regular intervals. This type is ideal for batch processing, data synchronization, or periodic maintenance tasks.
  • +
  • Manual Task: Initiates an integration via user action, giving you full control over when the integration executes. This type is useful for on-demand tasks, testing, or debugging purposes.
  • +
+

Develop integrations with WSO2 Integration Studio

+

WSO2 Integration Studio is a powerful, Eclipse-based graphical development environment that enables you to build and deploy integration artifacts in WSO2 Micro Integrator. This comprehensive IDE offers a robust set of tools for designing and testing integration flows and crafting integration artifacts. By utilizing the visual, drag-and-drop capabilities of WSO2 Integration Studio, developers can significantly reduce the time and effort needed to construct and deploy integration flows.

+

In addition to streamlining the development process, Integration Studio offers features such as debugging, testing, and version control to ensure the quality and reliability of integration flows. By creating an Integration project and Composite Exporter project in WSO2 Integration Studio, developers can export their integration projects as a single deployment artifact, known as a composite application. This composite application encompasses all the components and configurations necessary for deploying the integration project to WSO2 Micro Integrator.

+

The Composite Exporter project simplifies the deployment process by allowing developers to package their integration projects as a single, self-contained artifact that can be easily deployed and managed. This approach enhances the consistency and reliability of integration projects while streamlining the overall deployment process.

+

To start developing integrations with WSO2 Integration Studio, see WSO2 API Manager Documentation - Developing Integration Solutions.

+

Integration project directory structure

+

An Integration Project in WSO2 Integration Studio is a multi-module Maven project that can contain multiple modules with WSO2 Synapse configurations and a composite application module to export all the configurations as a single deployable artifact.

+

An integration project directory structure includes the following key components:

+
    +
  • WSO2 Synapse configurations: These modules contain the essential configurations for the integration project.
  • +
  • Composite Application module: This module is responsible for exporting all the Synapse configurations as a single deployable artifact.
  • +
+

Optionally, you can include the following components in your integration project:

+
    +
  • OpenAPI definition file: You can add the OpenAPI definition file to any location within the project. When creating a component, you'll need to define the path to this file. Choreo will automatically generate an OpenAPI definition for you based on your integration project, if you don't provide one.
  • +
  • Java libraries: If your integration project requires additional Java libraries, you can add them to the libs directory located in the project root.
  • +
  • deployment.toml file: This optional configuration file allows you to customize the preconfigured settings of WSO2 MI instances running on Choreo. By including this file, you can tailor the behavior of your WSO2 MI instances to better suit your project's specific requirements.
  • +
+

Understanding the Integration Project directory structure is crucial for organizing your project and ensuring that all necessary components are included in the final deployable artifact.

+

OpenAPI support

+

OpenAPI Support plays a crucial role in enhancing the functionality of integrations exposed as APIs. By providing an OpenAPI definition for your exposed integration, you can streamline testing and management processes, ensuring a more efficient and user-friendly experience. Choreo will automatically generate an OpenAPI definition for you based on your integration project, if you don't provide one, saving you time and effort.

+

To incorporate OpenAPI support, store the OpenAPI definition file within the repository hosting your Integration Studio project. When creating the project, simply point to the file's location in the repository. If needed, you can change the location of the OpenAPI definition file later via the deploy page.

+

Open API file

+

By leveraging OpenAPI Support, you can optimize the way you test and manage your integrations, resulting in a more efficient development process and a smoother user experience.

+

Work with third-party libraries

+

The use of third-party libraries in your Micro Integrator project can offer several advantages, such as enhanced functionality, improved integration capabilities, optimized performance, and reduced development time.

+

Here are some of the benefits of adding third-party JARs to the Micro Integrator:

+
    +
  • Increased functionality: Third-party libraries can extend the core Micro Integrator distribution, allowing for greater flexibility and customization of integration solutions.
  • +
  • Enhanced integration capabilities: Third-party libraries enable the Micro Integrator to interact with existing systems such as databases or other APIs, improving overall integration capabilities.
  • +
  • Optimized performance: By offering optimized implementations of common functions, third-party libraries can improve the performance of the Micro Integrator.
  • +
  • Efficient development: Developers can avoid re-implementing commonly used functions, reducing development time and increasing efficiency.
  • +
+

To incorporate third-party libraries into your Micro Integrator project, create a new directory called libs at the +root of your project. If your project root and GitHub repository root are not the same, place the libs directory in +the project root. After adding the required JAR files to the libs directory, the Micro Integrator runtime will +automatically include them when deploying the component. This process ensures that any dependencies needed by your +integration flow are available at runtime.

+

In addition to jar libraries, you may also need to incorporate OSGi bundle JARs into your project. To do this, +create another directory called dropins at the root of your project. Similarly, if the project root and GitHub +repository root differ, place the dropins directory in the project root. Within the dropins directory, add the OSGi +bundle JAR files. The OSGI runtime will pick up these bundles during deployment, enabling you to utilize their +functionality within your Micro Integrator project.

+

Libs directory

+

Importing custom certificates to MI

+

The feature enables Choreo MI users to import certificates into the MI client-truststore.jks file. This functionality +proves valuable when users need to establish connections with servers or services utilizing SSL/TLS encryption and +possessing self-signed certificates or certificates issued by private certificate authorities (CAs) that are not +automatically trusted. Importing the certificate to the MI client-truststore.jks file enables MI clients to establish secure connections with +the server or service seamlessly, eliminating SSL/TLS errors or warnings.

+

Before importing the certificate, it is necessary to obtain the certificate file, which can be in PEM or DER format. You +can get the certificate from the server or service provider or export it from a web browser. Certificates should be +added to the /wso2mi/certs/ folder. Users need to verify that the mount path for the certificate file aligns with this +specific path.

+
    +
  1. In the Choreo console, select the component you wish to add a certificate to.
  2. +
  3. From the left navigation click Deploy.
  4. +
  5. Click on the Configs and Secrets tab.
  6. +
  7. Click Create.
  8. +
  9. Select ConfigMap as the Config Type and File Mount as the Mount Type.
  10. +
  11. Click Next.
  12. +
  13. +

    Specify the following values as mount configurations:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Config NameAn appropriate name for the certificate.
    Mount path/wso2mi/certs/<filename>. For example, /wso2mi/certs/certificate.crt
    +
  14. +
  15. +

    Click Upload File and attach the certificate.

    +
  16. +
  17. Click Create.
  18. +
+

Working with sensitive data using MI Secure Vault

+

MI Secure Vault is a feature that allows users to securely store sensitive data, such as passwords and tokens, and +provide access to that data to MI Integrations. This feature provides an added layer of security to your integrations by +reducing the risk of accidental exposure of sensitive data.

+

To use MI Secure Vault to work with sensitive data, follow these steps:

+
    +
  1. Select the component from the Choreo Console.
  2. +
  3. From the left navigation, click Deploy.
  4. +
  5. Click on the Configure and Deploy.
  6. +
  7. Click on the Add Environment Configurations
  8. +
  9. +

    Specify the following values as configurations:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameAn appropriate name for the secret/alias.
    ValueValue for the secret
    +
  10. +
  11. +

    Select Mark as a Secret.

    +
  12. +
  13. Click Add.
  14. +
  15. Click Deploy.
  16. +
  17. Once the secret has been created, you can access it in your integration code using the following syntax:
  18. +
+

<property name="secret_value_1" expression="wso2:vault-lookup('user_pass')" scope="default" type="STRING"/>
+
+This code retrieves the secret named "user_pass" from the MI Secure Vault and stores it in the property named " +secret_value_1". You can then use this property in your integration code to access the secret value.

+

You can refer to the Accessing secrets +section of MI Secure Vault documentation for more information on these features. By using MI +Secure Vault to store and access sensitive data in your integrations, you can ensure that your integrations +remain secure and protect sensitive data from unauthorized access.

+

Scan third-party libraries to identify security vulnerabilities

+

Scanning third-party libraries for security vulnerabilities is essential for identifying potential weaknesses in an application that could be exploited by attackers. Taking a proactive approach to security helps organizations detect and mitigate risks before they can be exploited, preventing data breaches, system compromises, and other security incidents.

+

Choreo incorporates a security vulnerability scanning process during deployment. It uses Trivy to scan and detect critical vulnerabilities in third-party libraries added to the integration component. If the scan uncovers any critical vulnerabilities, the deployment process is halted. The deployment pane displays the Trivy scan status and any security failures in the Library (Trivy) vulnerable scan step, which can be accessed by clicking on it. Once the vulnerability has been addressed, you can redeploy the component.

+

Customize WSO2 Micro Integrator preconfigured settings

+

Customizing WSO2 Micro Integrator Preconfigured Settings is essential for ensuring that the integration solution works optimally within the specific context of your organization. While WSO2 MI comes with preconfigured settings designed for general use, these settings may not be suitable for every organization's unique requirements. Customizing these settings can help optimize performance and ensure compatibility with your organization's systems and applications.

+

To customize the preconfigured settings of WSO2 MI instances running on Choreo, define a deployment.toml file in the GitHub repository subpath of your Micro Integrator project:

+

deployment.toml

+
+

Note

+

If you change critical configuration parameters such as port offset and hostname, it can break internal communication. +Therefore, the recommended approach is to update only the necessary configuration parameters.

+
+

Given below is a sample deployment.toml file that can be used to configure the JMS transport. For more information on WSO2 MI +configuration parameters, see the MI Config Catalog.

+
[[transport.jms.sender]]
+name = "myQueueSender"
+parameter.initial_naming_factory = "org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+parameter.provider_url = "$env{JMS_PROVIDER_URL}"
+parameter.connection_factory_name = "QueueConnectionFactory"
+parameter.connection_factory_type = "queue"
+parameter.cache_level = "producer"
+
+[[transport.jms.listener]]
+name = "myQueueListener"
+parameter.initial_naming_factory = "org.apache.activemq.jndi.ActiveMQInitialContextFactory"
+parameter.provider_url = "$env{JMS_PROVIDER_URL}"
+parameter.connection_factory_name = "QueueConnectionFactory"
+parameter.connection_factory_type = "queue"
+parameter.cache_level = "consumer"
+
+ +

Environment variables

+

Using environment variables is a recommended practice when developing integration artifacts with WSO2 Integration Studio, as it improves configuration management, security, portability, and manageability. By leveraging environment variables, organizations can streamline the management and maintenance of their integrations, ensuring that updates can be implemented quickly and efficiently.

+

The component's Deploy page provides a user-friendly interface to manage environment variables across different environments. For information on managing environment variables for complex use cases, see Configurations and secrets.

+

Environment variables

+

Environment variables offer several benefits:

+
    +
  • Configuration management: They simplify the process of managing and updating configuration settings, making it easier to maintain consistency across different environments.
  • +
  • Security: Environment variables help protect sensitive information by storing it securely and separating it from the main codebase.
  • +
  • Portability: By using environment variables, you can ensure that your integration artifacts can be easily migrated and deployed across various environments with minimal changes.
  • +
  • Manageability: Environment variables offer a centralized way to manage configuration settings, making it easier to update and maintain your integrations over time.
  • +
+

For a comprehensive list of parameters that can be configured as environment variables, see WSO2 API Manager Documentation - Injecting Parameters - Supported parameters.

+

Configure logging

+

Configuring logging is crucial when developing and maintaining a software system, as it can significantly improve efficiency during the development, testing, and maintenance phases of the software development process. Logging captures events and messages that occur during an application's execution, providing valuable insights for troubleshooting and debugging issues.

+

With Micro Integrator instances, you can configure and customize logging according to your requirements. Logging configurations can be added to each MI instance's environment, allowing you to fine-tune logging depending on the specific environment or deployment scenario.

+

To configure logging in MI instances, follow the steps given below:

+
+

Tip

+

You can use environment variables with specific naming conventions.

+
+
    +
  1. Start the variable name with logging_level_ followed by the package or class name.
  2. +
  3. Replace the dot character in the package name with an underscore.
  4. +
  5. +

    Set the variable value to the required logging level for the corresponding package or class.

    +

    For example, to enable wire logs, change the logging level of the org.apache.synapse.transport.http.wire package to debug.

    +
  6. +
+

To configure logging, set the environment variable as follows:

+
    +
  1. In the left navigation menu, click Deploy and then click Configs & Secrets.
  2. +
  3. Click + Create.
  4. +
  5. Select ConfigMap as the Config Type and Environment Variables as the Mount Type.
  6. +
  7. Click Next.
  8. +
  9. +

    Specify the following values as mount configurations:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Config NameAn appropriate name for the configuration.
    Namelogging_level_org_apache_synapse_transport_http_wire
    Valuedebug
    +
  10. +
  11. +

    Click Create.

    +
  12. +
+

Connectors

+

WSO2 Micro Integrator (MI) Connectors are prebuilt connectors designed to simplify integration between WSO2 MI and various other systems. They enable seamless connections to databases, message brokers, REST APIs, and more, allowing you to perform actions such as sending messages, executing queries, or retrieving data. These connectors are easy to use, making it straightforward to incorporate them into your WSO2 MI integration flows. Micro Integrator connectors are versatile and can be utilized in various integration scenarios, including data integration, service-oriented architecture (SOA) integration, and event-driven architecture (EDA) integration.

+

WSO2 Integration Studio is a comprehensive development environment that facilitates the creation of integration flows using WSO2 Micro Integrator Connectors. With Integration Studio, you can design and implement integration flows that connect diverse systems and execute various actions, such as sending messages, executing queries, or retrieving data. You can build integration flows using either prebuilt connectors provided by WSO2 MI or custom connectors developed using the Connector Development Toolkit. Integration Studio offers a graphical user interface that simplifies the process of building and testing integration flows while also providing a set of tools for managing and deploying these flows in a WSO2 MI runtime environment.

+

For more information, see the following topics in the WSO2 API Manager documentation.

+ +

Deploying integrations in Choreo

+

WSO2 MI buildpack is where you can deploy integrations developed with WSO2 Micro Integrator as an API. In this preset, you have three different ways to define endpoints. Choreo gives priory to the definition of endpoints in the below-mentioned order.

+
    +
  1. +

    Using component.yaml file +This is the most flexible method to define endpoints. You can configure the endpoint details with the component.yaml configuration file. Place this file in the .choreo directory in the project path of the component. +If the Micro Integrator project has inbound endpoints, you can expose them via different endpoints using the component.yamlfile.

    +

    To learn about the component.yaml file, see Overview of the component.yaml file.

    +
  2. +
  3. +

    Auto generating endpoints +If component.yaml is not provided and if the source Micro Integrator project has APIs, Choreo scans the project and generates the API endpoints. If the project has few APIs, an endpoint will be generated for each API. The visibility of this auto-generated endpoint is set to Public by default. You can change the visibility in the deployment flow.

    +
  4. +
  5. +

    Provide default endpoints +If component.yaml is not provided and if the source Micro Integrator project doesn't have APIs, Choreo generates a default endpoint which will expose the default micro integrator port (8290) with Public visibility and wildcard context.

    +
  6. +
+
+

Note

+

If you are currently using component-config.yaml or endpoints.yaml configuration files, see the respective migration guide for instructions on migrating to the recommended component.yaml configuration file.

+
+

Explore Choreo examples on GitHub

+

For a hands-on experience with MI-based integrations in Choreo, we recommend exploring our samples in Choreo Console. You can filter out the samples based on the buildpack WSO2 MI. This will point you to the samples in the Choreo samples GitHub repository

+

Choreo samples - GitHub Repository

+
    +
  • +

    Fork the Repository: Start by forking the repository to your account.

    +
  • +
  • +

    Explore & run: Navigate through the different integration scenarios. Each example has a README.md with setup and execution instructions.

    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/develop-integrations/develop-a-scheduled-integration/index.html b/develop-integrations/develop-a-scheduled-integration/index.html new file mode 100644 index 000000000..9aca84db2 --- /dev/null +++ b/develop-integrations/develop-a-scheduled-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop-integrations/develop-an-event-triggered-integration/index.html b/develop-integrations/develop-an-event-triggered-integration/index.html new file mode 100644 index 000000000..8118f0933 --- /dev/null +++ b/develop-integrations/develop-an-event-triggered-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/api-policies/attach-policies/index.html b/develop/api-policies/attach-policies/index.html new file mode 100644 index 000000000..40f377644 --- /dev/null +++ b/develop/api-policies/attach-policies/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/api-policies/create-a-policy/index.html b/develop/api-policies/create-a-policy/index.html new file mode 100644 index 000000000..40f377644 --- /dev/null +++ b/develop/api-policies/create-a-policy/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/api-policies/policies/index.html b/develop/api-policies/policies/index.html new file mode 100644 index 000000000..40f377644 --- /dev/null +++ b/develop/api-policies/policies/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/api-proxies/policies/index.html b/develop/components/api-proxies/policies/index.html new file mode 100644 index 000000000..ab7382632 --- /dev/null +++ b/develop/components/api-proxies/policies/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/api-proxy/index.html b/develop/components/api-proxy/index.html new file mode 100644 index 000000000..b6c31b837 --- /dev/null +++ b/develop/components/api-proxy/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/graphql-api/index.html b/develop/components/graphql-api/index.html new file mode 100644 index 000000000..6687d8ac7 --- /dev/null +++ b/develop/components/graphql-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/manual-trigger/index.html b/develop/components/manual-trigger/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/develop/components/manual-trigger/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/rest-api/index.html b/develop/components/rest-api/index.html new file mode 100644 index 000000000..3ae58b707 --- /dev/null +++ b/develop/components/rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/scheduled-trigger/index.html b/develop/components/scheduled-trigger/index.html new file mode 100644 index 000000000..ee4d4f84e --- /dev/null +++ b/develop/components/scheduled-trigger/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/service/index.html b/develop/components/service/index.html new file mode 100644 index 000000000..d832de08e --- /dev/null +++ b/develop/components/service/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/components/webhook/index.html b/develop/components/webhook/index.html new file mode 100644 index 000000000..8cddf1c85 --- /dev/null +++ b/develop/components/webhook/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/manage-repository/connect-your-own-github-repository-to-choreo/index.html b/develop/manage-repository/connect-your-own-github-repository-to-choreo/index.html new file mode 100644 index 000000000..67d4dfb3b --- /dev/null +++ b/develop/manage-repository/connect-your-own-github-repository-to-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/develop/run-and-test/forecast-performance-metrics/index.html b/develop/run-and-test/forecast-performance-metrics/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/develop/run-and-test/forecast-performance-metrics/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/developer-portal/developer-portal/index.html b/developer-portal/developer-portal/index.html new file mode 100644 index 000000000..be2480499 --- /dev/null +++ b/developer-portal/developer-portal/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/developer-portal/manage-application/index.html b/developer-portal/manage-application/index.html new file mode 100644 index 000000000..ba29e0924 --- /dev/null +++ b/developer-portal/manage-application/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/developer-portal/manage-subscription/index.html b/developer-portal/manage-subscription/index.html new file mode 100644 index 000000000..2ca5a5090 --- /dev/null +++ b/developer-portal/manage-subscription/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/developer-portal/test-api/index.html b/developer-portal/test-api/index.html new file mode 100644 index 000000000..ad391b29d --- /dev/null +++ b/developer-portal/test-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/devops-and-ci-cd/autoscale-component-replicas/index.html b/devops-and-ci-cd/autoscale-component-replicas/index.html new file mode 100644 index 000000000..f9cda5494 --- /dev/null +++ b/devops-and-ci-cd/autoscale-component-replicas/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/devops-and-ci-cd/autoscale/autoscale-component-replicas/index.html b/devops-and-ci-cd/autoscale/autoscale-component-replicas/index.html new file mode 100644 index 000000000..d350e0583 --- /dev/null +++ b/devops-and-ci-cd/autoscale/autoscale-component-replicas/index.html @@ -0,0 +1,3474 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Autoscale Component Replicas - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Autoscale Component Replicas

+

Choreo allows you to automatically scale your component replicas up or down in number based on resource consumption to ensure high availability.

+
+

Note

+

Autoscaling capabilities are only available in paid plans for private data plane organizations. +In the free tier, components run in a single-replica, low-availability mode.

+
+

Scale component replicas

+

The following parameters allow you to scale component replicas:

+
    +
  • Min replicas: The minimum number of replicas to run at any given time. It is recommended to keep the value at a minimum of 2.
  • +
  • Max replicas: The maximum number of replicas to scale up to. In the cloud data plane, this is restricted to a maximum of 5. There is no restriction on the value in private data planes.
  • +
  • CPU Threshold: The average CPU utilization across all running replicas. If the CPU utilization across all active instances reaches the threshold, the number of active replicas automatically scales up until the average CPU utilization falls below the threshold.
  • +
  • Memory Threshold: The average memory usage across all running replicas. Like the CPU Threshold, if all active instances reach the memory threshold, the number of active replicas automatically scales up until the average memory usage falls below the threshold.
  • +
+
+

Tip

+

If you update a scaling parameter, it may not immediately reflect in the Choreo Console because the change can take some time to propagate.

+
+
+

Run a fixed number of replicas

+

If you want to run exactly 3 replicas for a component, you must set the minimum and maximum replicas to 3.

+
+
+

Scale to zero

+
    +
  • Although it is possible to set the minimum number of replicas to 0, your component does not scale to zero automatically during low usage. It can only go down to 1 replica.
  • +
  • Setting both the minimum and maximum replicas to 0 suspends the deployment.
  • +
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/index.html b/devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/index.html new file mode 100644 index 000000000..f628e2b9d --- /dev/null +++ b/devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/index.html @@ -0,0 +1,3612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Autoscale Components with Scale-to-Zero - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Autoscale Components with Scale-to-Zero

+

Choreo provides the scale-to-zero capability for HTTP applications you deploy in the data plane. This lets you run your components in a serverless mode.

+

Scale to zero is very useful in lower environments, where you can significantly reduce infrastructure costs by scaling down idle workloads. In production environments, you can also use scale-to-zero capability if your application's behavior aligns with this feature behavior. In the paid tier, if you want to run your application with more guaranteed high availability, it is recommended to choose HPA (Horizontal Pod Autoscaler) scaling method and configure a minimum replica count of 2 or higher.

+

How Scale to Zero works in Choreo

+
+

Info

+

For service components and web-apps you create after February 23, 2024, Choreo enables the scale-to-zero feature by default.

+
+

When Scale to Zero is enabled, your apps will automatically scale down to zero unless they receive HTTP traffic. When the application receives an HTTP request, your workload quickly scales up from zero to handle the request. When a new request is received by the deployment, the deployment will scale up to one replica and serve the request. When the deployment remains idle for a set period (approximately 5 minutes), it will automatically scale back to zero until a new request is received.

+

When Scale to Zero is enabled, you can set the maximum number of replicas for deployments with this capability. Choreo dynamically scales deployments up to meet high HTTP traffic demand, up to the specified number of replicas. If the pending requests surpass the defined threshold under Number of pending requests to spawn a new pod, Choreo automatically adds a new replica to handle the increased load.

+

Free User - Scale to Zero

+

Enable scale to zero

+

For service components and web-apps you create after February 23, 2024, Choreo enables the scale-to-zero feature by default. When deploying or promoting the component, the deployment will automatically scale-to-zero. +Upon the next request to the deployed service, a replica will be created to serve the request.

+
+

Note

+
    +
  • For the services which contain at least one endpoint with the network visibility as Project, Choreo will not automatically scale-to-zero those components when you deploy or promote them.
  • +
  • HTTP services that run on a port other than the below list of ports will not automatically scale-to-zero your component when deploying or promoting: 5000, 6000, 7000, 8000, 9000, 7070 to 7079, 8080 to 8089, and 9090 to 9099 or 8290.
  • +
+
+

To enable scale-to-zero for service components created before February 23, 2024, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component you want to scale-to-zero.
  4. +
  5. Make sure the component is deployed to an environment and is ready to receive traffic.
  6. +
  7. +

    In the left navigation menu, click DevOps and then click Scaling.

    +
      +
    • +

      If you are a free user, you will see a view similar to the one below. You can click the scale-to-zero card to enable scale-to-zero for your component.

      +

      Free User - Scale to Zero

      +
    • +
    • +

      If you are a paid user or you are running your applications in your own private data plane, you will see a view similar to the one below. You can click the scale-to-zero card to enable scale-to-zero for your component.

      +

      Paid User - Scale to Zero

      +
    • +
    +
    +

    Note

    +

    The scale-to-zero service should start within 60 seconds. If it doesn’t, the gateway will timeout the request.

    +
    +
  8. +
+

You can independently scale Choreo components in both the Development and Production environments. The deployment card indicates the scaling status of each environment. To configure the scale-to-zero feature for a specific environment, click on the scale-to-zero link, which redirects to the DevopsScaling page.

+

Deploy View - Scale to Zero

+

When you turn on the scale-to-zero for your application, the minimum replicas for your app will be set to zero. However, you can still select an appropriate maximum number of replicas.

+

Limitations

+
    +
  • The scale-to-zero feature currently exclusively supports web applications and HTTP services. TCP and HTTPS services are not supported to be scaled to zero.
  • +
  • To scale to zero, your HTTP service must run on one of the specified ports: 5000, 6000, 7000, 8000, 9000, 7070 to 7079, 8080 to 8089, and 9090 to 9099 or 8290. If you have an endpoint in your component running in any other port, your component will not automatically scale-to-zero when deploying or promoting. Also, if you try to switch to the “scale-to-zero” option in the “Devops” → “Scaling” view, it will fail.
  • +
  • +

    Scheduled tasks and manually triggered components cannot connect to a service on a project scope if scale-to-zero is enabled. Attempting to do so results in the following error:

    +

    Host not found, not forwarding request.

    +

    To allow a task-type component to invoke a project-level service, set it to HPA mode if you are on a paid plan, or to no scaling if you are on the Developer plan.

    +
  • +
+

Architecture

+

When your Choreo application scales down to zero, an intermediary proxy service intercepts incoming requests. If a request is directed at your application, this service initiates a scale-up. Requests are held in the proxy's queue until your application becomes active. After scaling up, the proxy forwards the queued requests to your application.

+

If your application remains without HTTP traffic for an extended period (default idle time is 5 minutes), it will be scaled down to zero until more HTTP requests arrive. Conversely, if there's a surge in HTTP traffic to your scaled-up application, Choreo will further increase its scale to manage the demand. Choreo considers adding additional replicas if the number of queued requests surpasses the 'Target Pending Requests' threshold, which is set to 100 by default. You can adjust this threshold in the user interface.

+
+

Note

+

The initial request after a long period of inactivity experiences a delay because the application must first scale up from zero. If your API operates in a service-chain sequence (e.g., service-1 activates service-2, which in turn calls service-3), this waiting time may extend further. If your application or its chain takes a considerable time to scale up, be aware that the first request might face a timeout.

+
+

Troubleshooting

+

When Choreo enables scale-to-zero by default, it will configure the readiness probe with some default values. However, in some cases, you may observe that your first request responds with a 503 status code. To overcome these behaviors, fine-tune the readiness probe in the DevOpsHealth Checks view to match your application's needs.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/builds-and-deployments/index.html b/devops-and-ci-cd/builds-and-deployments/index.html new file mode 100644 index 000000000..3837c1e10 --- /dev/null +++ b/devops-and-ci-cd/builds-and-deployments/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/devops-and-ci-cd/configure-container-resources-commands-and-arguments/index.html b/devops-and-ci-cd/configure-container-resources-commands-and-arguments/index.html new file mode 100644 index 000000000..ab022d03d --- /dev/null +++ b/devops-and-ci-cd/configure-container-resources-commands-and-arguments/index.html @@ -0,0 +1,3616 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Container Resources, Commands, and Arguments - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Container Resources, Commands, and Arguments

+

In Choreo, you can view detailed information about the container that comprises a component, such as its image tag, the corresponding commit ID, any imposed resource usage limits, and so on.

+

Each component in Choreo is limited to a single main container.

+

Container details

+
+

Resource Limits

+

Resource limits ensure that a single component does not take up more resources than it requires, which can affect other workloads on the data plane. If a process exceeds the allocated memory limit, the corresponding container will be forcefully shut down and restarted. If the process exceeds the allocated CPU limit, it gets throttled and can result in significant latencies in compute and I/O operations.

+
+

Choreo allows you to edit the default container configuration depending on your requirement.

+

Update container configurations

+

Follow these steps to update container configurations:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to edit container configurations.
  4. +
  5. In the left navigation menu, click DevOps and then click Containers.
  6. +
  7. On the Containers page, click Edit to update the corresponding container configuration.
  8. +
  9. +

    Apply the necessary changes and click Save.

    +

    Edit container configurations

    +
  10. +
+

The following topics walk you through the container configuration changes you can apply.

+

Update resource requests and limits

+
+

Note

+

The capability to update resource requests and limits is only available in paid pricing plans.

+
+

To update resource requests and limits, move the corresponding slider to a required position. A resource request cannot be less than its corresponding limit.

+

Set the image pull policy

+

You can select one of the following options as the image pull policy.

+
    +
  • Always: The image is always pulled from the container registry, even if a matching tag is already present in the data plane.
  • +
  • +

    If Not Present - The image is pulled from the container registry only if a matching image is not present in the data plane.

    +
    +

    Tip

    +

    The recommended option is If Not Present.

    +
    +
  • +
+

Specify container ports

+

You can specify appropriate values for the Container Port and Service Port. The Service Port is the port exposed outside of the container to your project-scoped endpoint. If you do not know the value to specify as the Service Port, specify the Container Port value in both fields.

+
+

Tip

+

You do not need to configure port values manually for Ballerina components. The capability to edit port values is primarily for containerized/Dockerfile-based components.

+
+

You can also select an appropriate Protocol.

+

Define a command and arguments for the container

+

You can define a command and arguments for a container when you want to provide or override the ENTRYPOINT of a container. For example, in a scenario where you want to run legacy or third-party applications, you would want to provide or override the ENTRYPOINT of a container.

+

Container command and arguments example

+

When you define a command and arguments,

+
    +
  • It specifies the ENTRYPOINT array and it is not executed within a shell.
  • +
  • Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged.
  • +
  • $$ are reduced to $, which allows escaping the $(VAR_NAME) syntax. This means that "$$(VAR_NAME)" produces the string literal "$(VAR_NAME)".
  • +
  • Escaped references are never expanded, regardless of whether the variable exists or not.
  • +
+

The ENTRYPOINT of the container image is used if you do not define a command and arguments for the container.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/configure-storage/index.html b/devops-and-ci-cd/configure-storage/index.html new file mode 100644 index 000000000..6273325ea --- /dev/null +++ b/devops-and-ci-cd/configure-storage/index.html @@ -0,0 +1,3627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Storage - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Storage

+

All components you create in Choreo have a default read-only file system, which you cannot access or write to from your applications.

+

Volume mounts allow you to create either temporary or persisted writable file system storage locations for your applications.

+

Volume mount types

+ + + + + + + + + + + + + + + + + + + + + +
TypeDescription
Empty Directory (In-Memory)A fast, temporary in-memory (tmpfs) storage location. This volume gets erased when you restart or remove the attached container. Available on all data planes.
Empty Directory (Disk)A temporary storage location on disk. This volume gets destroyed when you restart or remove the attached container. Only available on private data planes.
Persistent VolumeA permanent storage location. This volume persists even if you restart or remove the attached container. Only available on private data planes.
+
+

Tip

+

All components have a writable location in the /tmp directory at the time of component creation. You can also configure other writable locations if required.

+
+

Create a temporary storage space for your container

+

Empty directory (in-memory or on-disk) mounts allow you to create temporary file systems that your application can read from and write to. This option provides a convenient way to create a scratch space to write files temporarily before storing them in a more permanent storage location such as a cloud-backed storage bucket. +For example, unzipping a file, temporarily writing results from a memory-intensive operation to disk, a temporary local cache, etc. +However, it is important to note that these volumes destroy when you restart or update a container because the volumes are attached to the lifetime of a container.

+

Follow these steps to create a temporary storage space for your container:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to create a temporary storage.
  4. +
  5. In the left navigation menu, click DevOps and then click Storage.
  6. +
  7. Click + Create.
  8. +
  9. In the Create a Volume Mount pane, specify a name for the volume and select Empty Directory (In-Memory).
  10. +
+

Create temporary storage

+
    +
  1. +

    Click Next.

    +
    +

    In-memory (tmpfs) storage uses up container memory

    +

    Storage capacity for this type of volume will count against the container's memory limit.
    +Uncontrolled writes to this location may starve your application process of memory and can result in the container getting killed and restarted if the memory limits exceed.

    +
    +
  2. +
  3. +

    To add a mount location, specify a Mount Path and click Add mount.

    +
    +

    Tip

    +
      +
    • You can add multiple mount locations to a volume.
    • +
    • Mount paths should be absolute file paths and will be available to your application to read/write from.
    • +
    +
    +

    Specify mount details

    +
  4. +
  5. +

    Click Create. This applies the volume mount immediately to your container and triggers a rolling restart.

    +
  6. +
+

Create a persistent storage space for your container

+

Follow these steps to create a persistent storage space for your container:

+
+

Note

+

Persistent volume options are only available in private data plane organizations.

+
+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to create a persistent storage.
  4. +
  5. In the left navigation menu, click DevOps and then click Storage.
  6. +
  7. Click + Create.
  8. +
  9. In the Create a Volume Mount pane, specify a name for the volume and select Persistent Volume.
  10. +
  11. Select a Storage Class.
  12. +
  13. Move the Storage Capacity slider to set the required capacity.
  14. +
  15. +

    Select an appropriate Access Mode.

    +
    +

    Check and specify an access mode supported by the storage class

    +
      +
    • You must check the cloud provider documentation to select an appropriate access mode that the storage class supports. Choreo does not verify whether the storage class supports the access mode you select.
    • +
    • If the storage class does not support the access mode you select, it can result in a runtime mount error.
    • +
    +
    +

    Create persistent storage

    +
  16. +
  17. +

    Click Next.

    +
  18. +
  19. +

    To add a mount location, specify a Mount Path and click Add mount.

    +
    +

    Tip

    +
      +
    • You can add multiple mount locations to a volume.
    • +
    • Mount paths should be absolute file paths and will be available to your application to read/write from.
    • +
    +
    +
  20. +
  21. +

    Click Create. This applies the volume immediately to your container.

    +
  22. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/index.html b/devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/index.html new file mode 100644 index 000000000..e71ea0885 --- /dev/null +++ b/devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/index.html @@ -0,0 +1,3969 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure VPNs on the Choreo Cloud Data Plane - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure VPNs on the Choreo Cloud Data Plane

+

Secure access to private networks from the Choreo cloud data plane is an essential use case for cloud data plane users.

+

Choreo allows this secure connection using Tailscale. For this, Choreo provides a prebuilt Tailscale image component that can act as a forward proxy, which you can deploy in your Choreo project as a service. This service allows you to forward traffic to your external networks via Tailscale’s peer-to-peer WireGuard network.

+

The following diagram illustrates the high-level deployment architecture of the Tailscale pre-installed forward proxy:

+

Deployment architecture

+

Let's take a look at the specifics of each part to understand the deployment architecture.

+
    +
  • +

    Choreo project

    +

    In Choreo, a project groups various components. For more information on what a project in Choreo is, see the documentation on Project.

    +
  • +
  • +

    Tailscale proxy

    +

    This acts as the Tailscale pre-installed forward proxy, facilitating secure peer-to-peer WireGuard connections from the Choreo cloud data plane to private networks. It includes a Tailscale Daemon, SOCKS5 proxy, and a configurable TCP forwarder.

    +
      +
    • +

      Tailscale daemon

      +

      This is the core component of Tailscale. It is a software service that provides secure network connectivity and private networking solutions. For more details see the Tailscale documentation.

      +
    • +
    • +

      SOCKS5 proxy

      +

      This uses Tailscale’s userspace networking mode, rather than the kernel mode. Therefore, the inbuilt SOCKS5 proxy handles the forwarded traffic and directs it through the Tailscale network.

      +
    • +
    • +

      TCP forwarder

      +

      Forwards inbound TCP (transmission control protocol) traffic from the Tailscale proxy container’s network interface to the SOCKS5 proxy, ensuring it reaches its destination via the secured WireGuard tunnel.

      +
    • +
    +
  • +
  • +

    User applications and the Choreo API gateway

    +

    User applications within the same namespace (project) can use the Kubernetes service created to front the Tailscale proxy, for connecting to the corresponding private endpoints. You can either expose this service within the organization via the internal API gateway or expose it to the public via the external API gateway. For more details, see the documentation on Choreo endpoints.

    +
  • +
+
+ +

Now that you understand the deployment architecture, let’s explore how you can use Tailscale to secure connections to your private networks.

+

Configure and use Tailscale to access private network endpoints

+

This section walks you through the steps to create, configure, deploy, and use the Tailscale proxy component.

+

Tailscale proxy deployment

+

Let's get started.

+

Prerequisites

+
    +
  • Understand the basics of how Tailscale works.
  • +
  • Have a Tailscale account (Tailnet). There are multiple plans available for you to set up your Tailscale network. For details, see Tailscale plans.
  • +
  • Install Tailscale and connect your private data center or server to it, so that your private services are accessible via your Tailscale network. To quickly get started with Tailscale, see the Tailscale quickstart.
  • +
  • +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the organization home page.

    +
  • +
+

Step 1: Create the Tailscale proxy

+

Step 1.1: Create a project

+

Follow the steps given below to create a project:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. +
  3. On the organization home page, click + Create Project.
  4. +
  5. +

    Enter a display name, unique name, and description for the project. You can enter the values given below:

    +
    +

    Info

    +

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Display NameTailscale Proxy Project
    Nametailscale-proxy-project
    Project DescriptionMy Tailscale project
    +
  6. +
  7. +

    Click Create. This creates the project and takes you to the project home page.

    +
  8. +
+

Step 1.2: Create the Tailscale proxy component

+
    +
  1. On the project home page, click Service under Create a Component.
  2. +
  3. +

    Enter a display name, component name, and a description for the service. For this guide, let's enter the following values:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameTailscale proxy
    Component Nametailscale-proxy
    DescriptionTailscale proxy component
    +
  4. +
  5. +

    Click the Container Registry tab.

    +
  6. +
  7. In the Container Registry list, select Choreo Samples Registry.
  8. +
  9. Click the Tailscale Proxy card.
  10. +
  11. Click Create.
  12. +
+

Now you have successfully created the Tailscale proxy. You can proceed to configure and deploy it.

+

Step 2: Configure and deploy the Tailscale proxy

+

Here, you will add the required volume mounts, set the Tailscale authentication key, configure the TCP forwarder, configure endpoints, and deploy the Tailscale proxy. Follow the steps given below:

+

Step 2.1: Add required volume mounts

+

Tailscale requires the following volume mounts for its operations:

+
    +
  • /var/run/tailscale
  • +
  • /.local
  • +
+

To create the volume mounts, follow the step-by-step instructions in Configure Storage.

+

Step 2.2: Configure and deploy the component

+

To configure and deploy the component, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Build Area card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click + Add and add the TS_AUTH_KEY environment variable as a secret. To add the environment variable, you must obtain an authentication key from your Tailscale network.
      +
    • For details on how to obtain an authentication key from your Tailscale network, see Auth keys in the Tailscale documentation.
    • +
    +
  6. +
  7. Click Next.
  8. +
  9. In the File Mount pane that opens, click + Add.
  10. +
  11. +

    To mount a configuration file to the Tailscale proxy component and specify the port mapping for the TCP forward proxy running there, do the following:

    +
      +
    1. Specify /config.yaml as the Mount Path.
    2. +
    3. +

      Specify the following in the sample configuration file: +

      portMappings:
      +    8080: "100.108.78.93:8090"
      +    8081: "100.108.78.93:1433"
      +

      +
      +

      Note

      +

      In this sample configuration, the TCP traffic arriving at port 8080 on your Tailscale proxy will be forwarded to port 8090 on the node with IP address 100.108.78.93 in your Tailscale network. Similarly, port 8081 will map to the corresponding address. You can find the IP addresses of your nodes on the Tailscale machines page in your Tailscale network's admin console or via the Tailscale clients running on your machine.

      +
      +
    4. +
    +
  12. +
  13. +

    Click Next.

    +
  14. +
  15. +

    In the Endpoints pane that opens, click + Add and edit the endpoints.yaml configuration to expose your Tailscale proxy as a service. The following is a sample endpoints.yaml configuration you can use:

    +
    +

    Note

    +

    The sample endpoints.yaml file given below defines two project-level endpoints. These endpoints can be used by other components within the same project to access the services. If you want to directly expose your private endpoint via the Choreo gateway either with the Public or Organization visibility, you can set the networkVisibility property of the endpoint to Public or Organization.

    +
    +
    version: 0.1
    +endpoints:
    +  - name: Private HTTP service
    +    port: 8080
    +    type: REST
    +    networkVisibility: Project
    +    context: /
    +  - name: Private DB service
    +    port: 8081
    +    type: TCP
    +    networkVisibility: Project
    +    context: /
    +
    + +
  16. +
  17. +

    Click Save.

    +
  18. +
  19. +

    Click Next and then click Deploy.

    +
    +

    Note

    +

    Deploying the component may take a while. You can track the progress by observing the logs. Once the deployment is complete, the build status changes to Active on the Development environment card.

    +
    +
  20. +
+

When the component is deployed, you can observe a new node connected to your Tailscale network. To view this, go to the Tailscale machines page of your Tailscale coordination server.

+

Step 3: Access private network endpoints with the Tailscale proxy

+

Now you have successfully deployed the Tailscale proxy in your project and it is connected to your Tailnet. You can proceed to use the Tailscale proxy to provision access for other components to securely access private network endpoints.

+

You can configure endpoints of the Tailscale proxy to use it for various aspects within Choreo.

+

Post-deployment actions

+

Handle node key expiry

+

Tailscale nodes have a default node key expiry time of 180 days. Nodes require re-authentication after key expiry to avoid connection losses and application downtime. There is an option to disable node key expiry if necessary. For more details, see Node key expiry documentation.

+

Handle auth key expiry

+

Auth keys are used to register new nodes into your Tailscale network. The default expiry time for auth keys is 90 days, but nodes remain connected even after auth key expiry. This becomes an issue only if the Tailscale Proxy component is redeployed or restarted.

+

Update port mapping configurations

+

If you want to add a new private endpoint to your network and access it via the same Tailscale proxy within Choreo, you must add a new port mapping entry in the port mapping configuration of your Tailscale proxy deployment.

+

Best practices

+

Configure health checks

+

Since the Tailscale proxy acts as a forward proxy, it is important to configure health checks. You can use one of the open ports of the TCP forwarder as a health endpoint. For details on how to set up health probes in Choreo, see Set up health checks.

+

Use Tailscale ACLs

+

You can use Tailscale ACLs to precisely manage permission for users and devices on your Tailnet.

+

Disable scale-to-zero for the Tailscale proxy

+

It is recommended to disable Scale-to-Zero for the Tailscale proxy because it acts as a forward proxy and should always be up and running to make consistent connections with the Tailscale VPN mesh. +If you enable Scale-to-Zero, you may experience service downtime.

+

Run multiple replicas with HPA (horizontal pod autoscaler)

+

To achieve high availability and resiliency for the Tailscale proxy, you must run multiple replicas with HPA. To configure multiple replicas for the Tailscale proxy component, go to the Scaling page under DevOps. For more details, see Autoscale component replicas

+

Security best practices

+

Before deploying the Tailscale proxy in production environments, it is recommended to follow the Tailscale production best practices and security best practices.

+
+

Note

+

Choreo blocks incoming connections from other nodes in your Tailnet to the Tailscale proxy to prevent access to your project’s namespace in the Choreo cloud data plane.

+
+

Troubleshoot issues

+

For assistance in resolving common Tailscale proxy issues, see Troubleshoot Tailscale proxy issues.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/manage-configurations-and-secrets/index.html b/devops-and-ci-cd/manage-configurations-and-secrets/index.html new file mode 100644 index 000000000..c52b68744 --- /dev/null +++ b/devops-and-ci-cd/manage-configurations-and-secrets/index.html @@ -0,0 +1,3675 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Configurations and Secrets - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Configurations and Secrets

+

Choreo allows you to easily manage and version your component's configurations and secrets as file mounts or environment variables.

+
+

Note

+

All configurations and secrets applied to a Choreo component are stored in an encrypted secret vault in the cloud data plane, which is managed by WSO2. +If you are on a private data plane, the configurations and secrets are stored in an Azure key vault or AWS secret manager attached to your data plane in your cloud environment.

+
+

The difference between configurations and secrets

+

Choreo considers all configurations and secrets to be sensitive content when storing them, but gives you the option to choose between secret or configuration when you create a file mount or an environment variable.

+
    +
  • Secrets are write-only. Once you create a secret, you cannot see or retrieve its content via the Choreo Console. However, you can overwrite the existing content at any time.
  • +
  • +

    Configurations can be read and updated via the Choreo Console after you create them.

    +
    +

    Note

    +

    If you want to include sensitive data such as database passwords, cloud credentials, service accounts, and so on, the recommended approach is to use a secret instead of a configuration.

    +
    +
  • +
+

Apply a file mount to your container

+

Follow these steps to apply a file mount to a component you have created:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to define configurations and secrets.
  4. +
  5. In the left navigation menu, click DevOps and then click Configs & Secrets.
  6. +
  7. Click + Create.
  8. +
  9. In the Create a Config or Secret pane, click File Mount.
  10. +
  11. +

    If you want to create the file mount as a secret, select Mark as a Secret. Otherwise, proceed to the next step.

    +
    +

    Note

    +

    If you create the file mount as a secret, you will not be able to read the file content after you create the file mount.

    +
    +
  12. +
  13. +

    In the Display Name field, specify a name for the file mount.

    +
    +

    Tip

    +

    The display name does not affect the file mount or its content. It is only a reference to identify the configuration or secret you create.

    +
    +
  14. +
  15. +

    In the File Mount Path field, specify where to mount the file inside the container. Use an absolute file path with the file name and extension if applicable.

    +
    +

    Tip

    +

    The file name in the mount path does not need to match the configuration name or the name of the file you upload.

    +
    +
  16. +
  17. +

    Upload a configuration file or copy and paste the configuration content into the editor.

    +
  18. +
  19. +

    Click Create.

    +
    +

    Note

    +

    Configurations and secrets are applied immediately to your environment on creation. To ensure that the container reflects the new content, your existing running replicas undergo a rolling restart.

    +
    +
  20. +
+

Apply environment variables to your container

+

Follow these steps to apply environment variables to a component you have created:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to define configurations and secrets.
  4. +
  5. In the left navigation menu, click DevOps and then click Configs & Secrets.
  6. +
  7. Click + Create.
  8. +
  9. In the Create a Config or Secret pane, click Environment Variables.
  10. +
  11. +

    If you want to create the environment variable values as secrets, select Mark as a Secret. Otherwise, proceed to the next step.

    +
    +

    Note

    +

    If you create environment variables as secrets, you will not be able to read the values you set for the environment variables after you create them.

    +
    +
  12. +
  13. +

    In the Display Name field, specify a name to identify the configuration or secret.

    +
    +

    Tip

    +

    The display name you specify does not affect the environment variables you set. It is only a reference to identify the configuration or secret you create.

    +
    +
  14. +
  15. +

    Under Add Environment Variables, specify the necessary environment variables as key-value pairs. You can click Add Item to add any number of environment variables.

    +
  16. +
  17. +

    Click Create.

    +
  18. +
+

Update an existing configuration or secret

+

Follow these steps to update a configuration or secret you have defined:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to update configurations and secrets.
  4. +
  5. In the left navigation menu, click DevOps and then click Configs & Secrets.
  6. +
  7. Click the edit icon corresponding to the configuration or secret you want to update.
  8. +
  9. Apply the necessary changes and click Save.
  10. +
+

Delete an existing configuration or secret

+

Follow these steps to delete a configuration or secret you have defined:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to delete configurations and secrets.
  4. +
  5. In the left navigation menu, click DevOps and then click Configs & Secrets.
  6. +
  7. Click the delete icon corresponding to the configuration or secret you want to delete.
  8. +
  9. Enter the name of the configuration or secret to confirm deletion.
  10. +
  11. Click Delete.
  12. +
+

Manage Ballerina configurables

+

Choreo manages the Ballerina configurables for the Ballerina components you create.

+

When you deploy or promote a Ballerina application, you can modify the Ballerina configurables via the Deploy page.

+
+

Tip

+

You can use configurables instead of environment variables to add file mounts to a Ballerina component. + Environment variables are primarily for components written in other languages.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/manage-environments/index.html b/devops-and-ci-cd/manage-environments/index.html new file mode 100644 index 000000000..e30cb7f60 --- /dev/null +++ b/devops-and-ci-cd/manage-environments/index.html @@ -0,0 +1,3609 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Manage Environments - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Manage Environments

+

By default, all projects created in the cloud data planes (irrespective of the data plane region) are provisioned with two environments (i.e., development and production).

+

The environments are listed in the order of deployment and promotion. The initial deployment takes place in the first environment and you can proceed to promote a component to subsequent environments.

+

Create a new environment

+

Prerequisites

+
    +
  • To create additional environments, you must have a Choreo subscription or a private data plane.
  • +
  • To create a new environment in a private data plane organization, you must have the ENVIRONMENT-MANAGEMENT permission. By default, ENVIRONMENT-MANAGEMENT permission is granted to Admin and Choreo DevOps roles.
  • +
+

To create a new environment, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console and switch to the organization where you want to create a new project.
  2. +
  3. In the left navigation menu, click DevOps and then click Environments (note that this is the Environments page under your organization, not your projects).
  4. +
  5. +

    On the Environments page, click Create and specify the following details to create a new environment:

    +
      +
    • Name: A display name for the new environment.
    • +
    • +

      Data Plane - The data plane to create the new environment.

      +
      +

      Tip

      +

      The Data Plane list displays all the private data planes registered under your organization.

      +
      +
    • +
    • +

      DNS Prefix: A DNS prefix to identify the exposed APIs in the environment. Here, the base domain depends on the custom domain attached to the API gateways provisioned on the selected data plane.

      +
    • +
    • +

      Mark environment as a Production environment: Select if you want this environment to be a production environment.

      +
      +

      Tip

      +

      In Choreo, you can have multiple non-production and production environments. To work in a production environment, you must have privileged permissions to access and deploy to production environments.

      +
      +
    • +
    +
  6. +
+

Change the order of promotion

+

The order in which environments are listed on the Environments page is the same order in which promotion takes place.

+

To change the order of promotion across environments in an organization, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console and switch to the organization for which you want to change the order of promotion.
  2. +
  3. In the left navigation menu, click DevOps and then click Environments.
  4. +
  5. +

    On the Environments page, click and drag environment list items to rearrange the order of listed environments.

    +
    +

    Note

    +

    Although changes to the order of promotion for environments are applied immediately, the change does not affect the components already running in environments. Only subsequent builds and promotions will follow the new order.

    +
    +
  6. +
+

To see the changes, go to the Deploy page of a component (in any project).

+

Delete an environment

+

To delete an environment, follow the steps given below:

+
+

Warning

+

Environment deletion is a permanent, non-reversible operation.

+
+
    +
  1. Sign in to the Choreo Console and switch to your organization.
  2. +
  3. In the left navigation menu, click DevOps and then click Environments.
  4. +
  5. In the Environments list, click the delete icon corresponding to the environment you want to delete. This displays a confirmation dialog with details on the impact of deletion.
  6. +
  7. Review the details, then type the environment name to confirm the deletion.
  8. +
  9. Click Delete.
  10. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/set-up-health-checks/index.html b/devops-and-ci-cd/set-up-health-checks/index.html new file mode 100644 index 000000000..5fd8a4792 --- /dev/null +++ b/devops-and-ci-cd/set-up-health-checks/index.html @@ -0,0 +1,3639 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Set Up Health Checks - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Set Up Health Checks

+

Health checks ensure that a running container is always healthy and ready to serve traffic.

+

Liveness probes

+

Liveness probes run periodically on your container and restart if the probe fails. +This allows the container to self-heal in scenarios where the application may have crashed or become unresponsive.

+

Readiness probes

+

Similar to liveness probes, readiness probes run periodically throughout the lifecycle of a container. +However, unlike liveness probes, these probes do not restart the container if the probe fails. Instead, they stop the container from receiving network traffic.

+
+

Readiness probes on single replicas

+

You must be mindful when you configure readiness probes on a single-running replica. If the readiness probe fails, your application stops receiving traffic because there is only one active replica. The application may not recover unless the liveness probe fails and restarts the container.

+
+

Probe types

+

You can configure the following probe types for both readiness and liveness probes.

+

HTTP GET request

+

This probe sends an HTTP GET request to a specified port and path on the container. A response status code in the range of 200-399 indicates that the request is a success.

+

Depending on your requirement, you can configure additional HTTP headers.

+

The recommended approach is to create a /healthz or /health endpoint in your service for this purpose.

+

HTTP GET probe

+

TCP connection probe

+

This probe attempts to open a socket to the container on the specified port. If it cannot establish a TCP connection, it becomes a failure.

+

Execute a command

+

This probe executes a given script inside the container. A non-zero return from the command is considered a failure.

+

For example, ["cat", "/tmp/healthy"] is considered healthy if the file /tmp/healthy is present. If not, it becomes a failure (non-zero exit code). +In such scenarios, the application is responsible for writing and maintaining this file in the specified location.

+

Configure liveness and readiness probes

+

Follow these steps to configure liveness and readiness probes on a container:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to configure liveness and readiness probes.
  4. +
  5. In the left navigation menu, click DevOps and then click Health Checks.
  6. +
  7. On the Health Checks page, click + Create.
  8. +
  9. +

    Configure the liveness probe depending on your requirement.

    +

    Configure probe

    +
  10. +
  11. +

    Click Save.

    +
  12. +
  13. Configure the readiness probe depending on your requirement.
  14. +
  15. +

    Click Save.

    +
    +

    Note

    +

    You can update or remove a probe at any time.

    +
    +
  16. +
+

Follow these steps to ensure that the container works as expected:

+
    +
  1. In the left navigation menu, click Runtime under DevOps.
  2. +
  3. On the Runtime page, check the details to confirm that the container works as expected. If the container does not start, check the events and conditions to see if any of the probes are causing the container to fail.
  4. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devops-and-ci-cd/view-runtime-details/index.html b/devops-and-ci-cd/view-runtime-details/index.html new file mode 100644 index 000000000..77dac040b --- /dev/null +++ b/devops-and-ci-cd/view-runtime-details/index.html @@ -0,0 +1,3596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + View Runtime Details - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

View Runtime Details

+

In Choreo, you can view details about running replicas of a component in a specific environment (i.e., Development or Production).

+

To view the runtime details of a component, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the Component Listing pane, click on the component for which you want to view runtime details.
  4. +
  5. In the left navigation menu, click DevOps and then click Runtime. This opens the Runtime page populated with data retrieved from the underlying Choreo data plane.
  6. +
+

Runtime details

+

The runtime details you can see here are analogous to a zoomed-in view of a specific environment on the Deploy page.

+

The following topics walk you through the specific details you can view and actions you can perform via the Runtime page.

+

Redeploy a release

+

On the Runtime page, you can click Redeploy Release to immediately redeploy all resources, including configurations and secrets, to a specific environment. This triggers a rolling update to sync all the latest changes to the data plane.

+
+

What is a release?

+

A release in Choreo uniquely identifies an underlying deployment of a component to an environment for a given version. For example, if you deploy a component to two environments across two versions, the component will have four active releases.

+
+

The capability to redeploy a release also allows you to quickly restart all the running replicas of a component in a specific environment.

+

View running instances

+

The running instances you see on the Runtime page provide insights into the active replicas of your component in the selected environment.

+
    +
  • You can view details of each active replica and its associated real-time CPU and memory usage, status, restarts, and the time of the last activity.
  • +
  • +

    If you want to see the real-time logs and information on conditions and events of a replica, click the menu icon of the replica and then click Real-time Logs or Conditions & Events depending on what you need to view. These options provide insights that help to diagnose issues in deployments.

    +

    Running instances

    +
    +

    Note

    +
      +
    • All metrics such as the total and replica-level CPU and memory usage displayed on the Runtime page are real-time data and are instantaneous representations of a component's current state.
    • +
    • You can take a look at the observability metrics of a component to see historical data and usage trends.
    • +
    +
    +
  • +
+

Observe real-time container logs

+

Unlike the logs available in the Observability Metrics of a component, these logs are fetched in real-time from the data plane and are not historical. Therefore, you can only see logs of active containers and the last shutdown container.

+

Real-time container logs

+
    +
  • Display Previous Logs: Enable to retrieve logs from the last shutdown/crashed/restarted container of an instance.
  • +
  • Since Seconds: Specify the duration in seconds to fetch corresponding logs.
  • +
  • Filter Logs: Enable to filter and displays matching log lines. This is a fuzzy string search.
  • +
+

View container conditions and events

+

Conditions and events provide information necessary to troubleshoot failing deployments.

+

Container conditions and events

+

If a component is not behaving as expected and you cannot detect any issues via the application logs, these events can provide necessary debugging information, such as the following:

+
    +
  • Failing health checks (liveness and readiness probes).
  • +
  • Missing or invalid configuration/secret mounts.
  • +
  • Missing or invalid storage volume mounts.
  • +
  • Scheduling issues in the underlying data plane.
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/get-started/build-your-first-cloud-native-application-with-choreo/index.html b/get-started/build-your-first-cloud-native-application-with-choreo/index.html new file mode 100644 index 000000000..1bab0eb3b --- /dev/null +++ b/get-started/build-your-first-cloud-native-application-with-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/quick-start-guide/index.html b/get-started/quick-start-guide/index.html new file mode 100644 index 000000000..d6b0fce67 --- /dev/null +++ b/get-started/quick-start-guide/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-containerized-service-component/index.html b/get-started/tutorials/create-your-first-containerized-service-component/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/get-started/tutorials/create-your-first-containerized-service-component/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-event-triggered-integration/index.html b/get-started/tutorials/create-your-first-event-triggered-integration/index.html new file mode 100644 index 000000000..661c5de8a --- /dev/null +++ b/get-started/tutorials/create-your-first-event-triggered-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-integration-as-an-api/index.html b/get-started/tutorials/create-your-first-integration-as-an-api/index.html new file mode 100644 index 000000000..615ee5353 --- /dev/null +++ b/get-started/tutorials/create-your-first-integration-as-an-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-rest-api-proxy/index.html b/get-started/tutorials/create-your-first-rest-api-proxy/index.html new file mode 100644 index 000000000..2dcb90eb6 --- /dev/null +++ b/get-started/tutorials/create-your-first-rest-api-proxy/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-rest-api/index.html b/get-started/tutorials/create-your-first-rest-api/index.html new file mode 100644 index 000000000..d6b0fce67 --- /dev/null +++ b/get-started/tutorials/create-your-first-rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/create-your-first-webhook/index.html b/get-started/tutorials/create-your-first-webhook/index.html new file mode 100644 index 000000000..8cddf1c85 --- /dev/null +++ b/get-started/tutorials/create-your-first-webhook/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/deploy-a-containerized-application-as-an-event-triggered-integration/index.html b/get-started/tutorials/deploy-a-containerized-application-as-an-event-triggered-integration/index.html new file mode 100644 index 000000000..71782578a --- /dev/null +++ b/get-started/tutorials/deploy-a-containerized-application-as-an-event-triggered-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/tutorials/secure-an-api-with-role-based-access-control/index.html b/get-started/tutorials/secure-an-api-with-role-based-access-control/index.html new file mode 100644 index 000000000..3d59ba7a9 --- /dev/null +++ b/get-started/tutorials/secure-an-api-with-role-based-access-control/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/get-started/what-is-choreo/index.html b/get-started/what-is-choreo/index.html new file mode 100644 index 000000000..bd71d2425 --- /dev/null +++ b/get-started/what-is-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/graphql-api/index.html b/graphql-api/index.html new file mode 100644 index 000000000..2028df1e0 --- /dev/null +++ b/graphql-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..a4f3d294b --- /dev/null +++ b/index.html @@ -0,0 +1,726 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + + +
+ + + + + +
+
+
+

How can we help?

+
+ +
+
+ +
+ +
+ + + + + + + + + + + + + +
+ +
+
+ +
+
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/insights/choreo-insights-api/index.html b/insights/choreo-insights-api/index.html new file mode 100644 index 000000000..20ba0d419 --- /dev/null +++ b/insights/choreo-insights-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/insights/configure-alerts/index.html b/insights/configure-alerts/index.html new file mode 100644 index 000000000..596d3c98d --- /dev/null +++ b/insights/configure-alerts/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/insights/generate-custom-reports/index.html b/insights/generate-custom-reports/index.html new file mode 100644 index 000000000..5d5d36567 --- /dev/null +++ b/insights/generate-custom-reports/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/insights/programmatic-access-choreo-insights-api/index.html b/insights/programmatic-access-choreo-insights-api/index.html new file mode 100644 index 000000000..97170bf00 --- /dev/null +++ b/insights/programmatic-access-choreo-insights-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/insights/view-api-insights/index.html b/insights/view-api-insights/index.html new file mode 100644 index 000000000..cf6928035 --- /dev/null +++ b/insights/view-api-insights/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/index.html b/integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/index.html new file mode 100644 index 000000000..e6ba56a41 --- /dev/null +++ b/integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/index.html @@ -0,0 +1,3733 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Integrate and Manage Generative AI Services - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Integrate and Manage Generative AI Services

+

Generative AI (GenAI) services leverage advanced machine learning models to create original content such as text, images, music, or code, by identifying and learning patterns from existing data. Powered by deep neural networks and other machine learning models, these services can generate human-like outputs in various formats. This versatility makes GenAI ideal for tasks such as content creation, image generation, conversation automation, etc.

+

Choreo enables seamless integration with GenAI services, allowing you to incorporate these capabilities within your applications.

+

Register a GenAI service

+

To use a GenAI service in Choreo, you need to register it. Once registered, the service becomes available in the Internal Marketplace, allowing you to consume it via a Connection.

+

You can register a GenAI service at two levels:

+
    +
  • Organization level: This makes the service accessible from any project within the organization.
  • +
  • Project level: This restricts the service to a specific project.
  • +
+

Prerequisites

+

Before registering a GenAI service, obtain the following details from the service provider: + - API key. + - Service URL. + - Other necessary parameters. For example, client credentials.

+

To register a GenAI service, follow these steps:

+
+

Note

+

Ensure that you register the service at the appropriate level depending on the usage. If the service must be shared among multiple projects, register it at the organization level. Otherwise, register it at the project level.

+
+

Step 1: Select a service provider

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. Follow one of these steps depending on your requirements:
      +
    • To register a GenAI service at the organization level, go to the Choreo Console header and select your organization from the Organization list.
    • +
    • To register a GenAI service at the project level, go to the Choreo Console header and select your project from the Project list.
    • +
    +
  4. +
  5. In the left navigation menu, click Dependencies and then click GenAI Services.
  6. +
  7. Click + Register.
  8. +
  9. Select a service provider.
  10. +
  11. Click Next.
  12. +
+

Step 2: Provide service details

+
    +
  1. +

    Under Register Service, enter the following details for the service:

    +
      +
    • A Name and Version.
    • +
    • The Service URL.
    • +
    +
  2. +
  3. +

    Click Next.

    +
  4. +
+

Step 3: Add configurations

+
    +
  1. +

    Under Add Configurations, enter details for the service. + !!! note + - The configuration details to enter vary depending on the selected service provider. + - To successfully register a service, ensure you provide all the required configurations.

    +
  2. +
  3. +

    Click Register.

    +
  4. +
+

Once registered, the GenAI service is automatically listed in the Internal Marketplace.

+

If you want to remove the service from the Internal Marketplace, see Remove a GenAI service from the Internal Marketplace.

+

Discover GenAI services

+

The GenAI services you register are discoverable via the Internal Marketplace for you to consume via a Connection.

+

For details on consuming a GenAI service via a connection, see Create a Connection.

+

Manage GenAI services

+

When you create a GenAI service, it gets listed in the GenAI Services list.

+

View or update GenAI service details

+

To view or update a GenAI service, follow these steps.

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the left navigation menu, click Dependencies and then click GenAI Services. This lists all the GenAI services you have created.
  4. +
  5. Click on a service to view or update its details.
      +
    • General Details: Displays service metadata. For example, the service name, overview, labels, etc.
    • +
    • Service Definition: Displays the service definition. To update the definition, click Upload and select the new definition file.
    • +
    +
  6. +
+

Add a GenAI service to the Internal Marketplace

+
+

Info

+

To add a GenAI service to the Internal Marketplace, you must provide all the required configurations.

+
+
    +
  1. In the Choreo Console left navigation menu, click Dependencies and then click GenAI Services.
  2. +
  3. Click on the service you want to add to the Internal Marketplace.
  4. +
  5. Click Add to Marketplace.
  6. +
+

Remove a GenAI service from the Internal Marketplace

+
    +
  1. In the Choreo Console left navigation menu, click Dependencies and then click GenAI Services.
  2. +
  3. Click on the service you want to remove from the Internal Marketplace.
  4. +
  5. Click Remove from Marketplace.
  6. +
+

This removes the service from the Internal Marketplace. Therefore, the service will not be available to consume via a Connection. However, the connections created before removal will continue to work as expected.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/integrate-and-manage-external-services/integrate-and-manage-third-party-services/index.html b/integrate-and-manage-external-services/integrate-and-manage-third-party-services/index.html new file mode 100644 index 000000000..7d3b82553 --- /dev/null +++ b/integrate-and-manage-external-services/integrate-and-manage-third-party-services/index.html @@ -0,0 +1,3752 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Integrate and Manage Third-Party Services - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Integrate and Manage Third-Party Services

+

Third-party services are external applications, platforms, or APIs you can integrate with your system to enhance its functionality, extend capabilities, or provide specialized features. These services are developed and maintained by external entities, providing expertise in specific domains outside your application's core focus.

+

The following topics walk you through the steps to seamlessly register, manage, and consume third-party services, adhering to API-first principles.

+

Register a third-party service in Choreo

+

To use a third-party service in Choreo, you need to register it. Once registered, the service becomes available in the Internal Marketplace, allowing you to consume it via a Connection.

+

You can register a third-party service at two levels:

+
    +
  • Organization level: This makes the service accessible from any project within the organization.
  • +
  • Project level: This restricts the service to a specific project.
  • +
+

Choreo allows you to register the following third-party service types:

+
    +
  • REST APIs
  • +
  • GraphQL APIs
  • +
  • Asynchronous APIs
  • +
  • SOAP
  • +
  • gRPC
  • +
+

Prerequisites

+

Before registering a third-party service, obtain the following details from the service provider:

+
    +
  • API specification. For example, OpenAPI or GraphQL schema.
  • +
  • Service URL.
  • +
  • Other necessary parameters. For example, client credentials, API keys, etc.
  • +
+

To register a third-party service, follow these steps:

+
+

Note

+

Ensure you register the service at an appropriate level depending on the service usage. If the service must be shared among multiple projects, register it at the organization level. Otherwise, register it at the project level.

+
+

Step 1: Provide basic details

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. Follow one of these steps depending on your requirement:
      +
    • To register a third-party service at the organization level, go to the Choreo Console header and select your organization from the Organization list.
    • +
    • To register a third-party service at the project level, go to the Choreo Console header and select your project from the Project list.
    • +
    +
  4. +
  5. In the left navigation menu, click Dependencies and then click Third-Party Services.
  6. +
  7. Click + Register.
  8. +
  9. Provide details for the service:
      +
    • Enter a Name and Version.
    • +
    • Upload the service definition file. This automatically detects the service type.
    • +
    • Verify the Service Type.
    • +
    +
  10. +
  11. Click Define Endpoints.
  12. +
+

Now you are ready to define endpoints for the service.

+

Step 2: Define service endpoints

+

An endpoint is a set of parameters required to connect to a service. The required parameters are service URL, API key header, etc. +These parameters provide the necessary information for a client application to interact with the service.

+

To define service endpoints, follow these steps:

+
    +
  1. +

    Under Define New Endpoint,

    +
      +
    • Enter a Name for the endpoint.
    • +
    • Enter the Endpoint URL.
    • +
    +
  2. +
  3. +

    Under Additional Parameters, add any other parameters required to connect to the service. + For example, API key, authorization token, etc.

    +
    +

    Note

    +
      +
    • If you want to keep a parameter confidential, select the Secret checkbox.
    • +
    • If there are multiple endpoints, the parameter names will be the same for all the endpoints.
    • +
    +
    +
  4. +
  5. +

    Select the environments where the endpoint should be accessible.

    +
    +

    Note

    +

    Service consumers can create connections to the endpoint only from the selected environments.

    +
    +
  6. +
  7. +

    Click OK.

    +
  8. +
  9. +

    If you want to add more endpoints, click + New Endpoint and repeat steps 1 to 4.

    +
  10. +
  11. +

    Click Register.

    +
  12. +
+

When you define all required parameter values for at least one endpoint, the service will be automatically listed in the Internal Marketplace. Otherwise, you must add the service to the Internal Marketplace after providing the endpoint values.

+

If you want to remove a third-party service from the Internal Marketplace, see Remove a third-party service from the Internal Marketplace.

+

For details on managing third-party services, see Manage third-party service.

+

Discover third-party services

+

The third-party services you register are discoverable via the Internal Marketplace to consume via a Connection.

+

For details on consuming a third-party service via a connection, see Create a Connection.

+

Manage third-party services

+

When you create a third-party service, it gets listed in the Third-Party Services list.

+

View or update third-party service details

+

To view or update a third-party service, follow these steps.

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. In the left navigation menu, click Dependencies and then click Third-Party Services. This lists all the third-party services you have created.
  4. +
  5. Click on a service to view or update its details.
      +
    • General Details: Displays service metadata. For example, the service name, overview, labels, etc.
    • +
    • Service Definition: Displays the service definition. To update the definition, click Upload and select the new definition file.
    • +
    • Endpoints: Displays service endpoint details. You can add, modify, or delete service endpoints.
    • +
    +
  6. +
+

Add a third-party service to the Internal Marketplace

+
+

Info

+

To add a third-party service to the Internal Marketplace, you must provide all required parameters for at least one endpoint.

+
+
    +
  1. In the Choreo Console left navigation menu, click Dependencies and then click Third-Party Services.
  2. +
  3. Click on the service you want to add to the Internal Marketplace.
  4. +
  5. Click Add to Marketplace.
  6. +
+

Remove a third-party service from the Internal Marketplace

+
    +
  1. In the Choreo Console left navigation menu, click Dependencies and then click Third-Party Services.
  2. +
  3. Click on the service you want to remove from the Internal Marketplace.
  4. +
  5. Click Remove from Marketplace.
  6. +
+

This removes the service from the Internal Marketplace. Therefore, the service will not be available to consume via a Connection. However, the connections created before removal will continue to work as expected.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ipaas/ballerina/create-your-first-event-triggered-integration/index.html b/ipaas/ballerina/create-your-first-event-triggered-integration/index.html new file mode 100644 index 000000000..15101c383 --- /dev/null +++ b/ipaas/ballerina/create-your-first-event-triggered-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/ipaas/ballerina/develop-integrations-with-ballerina/index.html b/ipaas/ballerina/develop-integrations-with-ballerina/index.html new file mode 100644 index 000000000..615ee5353 --- /dev/null +++ b/ipaas/ballerina/develop-integrations-with-ballerina/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/ipaas/get-started-with-choreo-ipaas/index.html b/ipaas/get-started-with-choreo-ipaas/index.html new file mode 100644 index 000000000..615ee5353 --- /dev/null +++ b/ipaas/get-started-with-choreo-ipaas/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/ipaas/micro-integrator/create-your-first-integration/index.html b/ipaas/micro-integrator/create-your-first-integration/index.html new file mode 100644 index 000000000..615ee5353 --- /dev/null +++ b/ipaas/micro-integrator/create-your-first-integration/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/ipaas/micro-integrator/develop-integrations-with-integration-studio/index.html b/ipaas/micro-integrator/develop-integrations-with-integration-studio/index.html new file mode 100644 index 000000000..9dbb1230c --- /dev/null +++ b/ipaas/micro-integrator/develop-integrations-with-integration-studio/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/js/open_in_new_tab.js b/js/open_in_new_tab.js new file mode 100644 index 000000000..964fb4c1e --- /dev/null +++ b/js/open_in_new_tab.js @@ -0,0 +1,45 @@ +// Description: Open external links in a new tab and PDF links in a new tab +// Source: https://jekyllcodex.org/without-plugin/new-window-fix/ + +//open external links in a new window +function external_new_window() { + for(let c = document.getElementsByTagName("a"), a = 0;a < c.length;a++) { + let b = c[a]; + if(b.getAttribute("href") && b.hostname !== location.hostname) { + b.target = "_blank"; + b.rel = "noopener"; + } + } +} +//open PDF links in a new window +function pdf_new_window () +{ + if (!document.getElementsByTagName) { + return false; + } + let links = document.getElementsByTagName("a"); + for (let eleLink=0; eleLink < links.length; eleLink ++) { + if ((links[eleLink].href.indexOf('.pdf') !== -1)||(links[eleLink].href.indexOf('.doc') !== -1)||(links[eleLink].href.indexOf('.docx') !== -1)) { + links[eleLink].onclick = + function() { + window.open(this.href); + return false; + } + } + } +} + +function apply_rules() { + external_new_window(); + pdf_new_window(); +} + +if (typeof document$ !== "undefined") { + // compatibility with mkdocs-material's instant loading feature + // based on code from https://github.com/timvink/mkdocs-charts-plugin + // Copyright (c) 2021 Tim Vink - MIT License + // fixes [Issue #2](https://github.com/JakubAndrysek/mkdocs-open-in-new-tab/issues/2) + document$.subscribe(function() { + apply_rules(); + }) +} \ No newline at end of file diff --git a/manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/index.html b/manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/index.html new file mode 100644 index 000000000..5ab6940e6 --- /dev/null +++ b/manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/index.html @@ -0,0 +1,3542 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add Choreo-Managed Databases and Caches to the Marketplace - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Add Choreo-Managed Databases and Caches to the Marketplace

+

When you create a Choreo-managed database or cache, you can add it to the Marketplace, making it available for consumption through a connection.

+
+

Note

+

To add a Choreo-managed database or cache to the Marketplace, you must register at least one credential for it.

+
+

Step 1: Register credentials

+

When you create a database or cache server, you get super admin credentials by default. You can use these credentials to create new user credentials. The steps to create new user credentials depend on the type of database or cache you are using.

+

You can register either the default super admin credentials or any custom credentials you create using the super admin credentials.

+

To register credentials for a database, follow these steps:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. Go to the Choreo Console header and select your organization from the Organization list.
  4. +
  5. In the left navigation menu, click Dependencies and then click Databases.
  6. +
  7. Click on a required database to view its details.
  8. +
  9. Click the Databases tab.
  10. +
  11. Click to expand the database for which you want to register credentials, then click Add Credentials.
  12. +
  13. In the Add Credentials dialog, do one of the following depending on your requirements:
      +
    • If you want to use the custom credentials you created using the super admin credentials, select Add New Credentials and specify appropriate values for each field.
    • +
    • If you want to use the default super admin credentials, select Add Super Admin Credentials and specify appropriate values for each field.
    • +
    +
  14. +
  15. Click Save.
  16. +
+
+

Tip

+

Choreo allows you to delete registered credentials to prevent their use when establishing new connections. However, deleting credentials will not affect any existing database connections that are already using them.

+
+

Step 2: Add the database or cache to the Marketplace

+
    +
  • On the Databases tab, click +Add to Marketplace corresponding to the database you want to add.
  • +
+

Once the database is added to the Marketplace, it can be consumed via a connection. For details on creating a connection to a Choreo-managed database, see Create a connection to a database.

+
+

Note

+

To remove a database or cache that you added to the Marketplace, click the corresponding Remove from Marketplace. This action prevents new connections to the removed database, but existing connections remain unaffected.

+
+

For details on using a database connection in your component, see Use a Database Connection in Your Component.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/billing-for-platform-services/index.html b/manage-databases-and-caches/billing-for-platform-services/index.html new file mode 100644 index 000000000..3426e5289 --- /dev/null +++ b/manage-databases-and-caches/billing-for-platform-services/index.html @@ -0,0 +1,3455 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Billing - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Billing for Platform Services (Databases and Caches)

+

Any platform services you create within your Choreo Organization will be included in your current Choreo subscription. The quantity included will vary depending on the service plan of the resources you create.

+

A few important considerations:

+
    +
  • Usage is billed hourly. If you create a database that you later remove within the same month, you will only be charged for the hours during which it was active.
  • +
  • Fixed pricing based on service plans. Choreo does not charge extra for network bandwidth usage.
  • +
+
+

Try out the free trial

+

Choreo provides a 7 day free trial for all database types on the 'Hobbyist' service plan (for free tier users).

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/choreo-managed-caches/index.html b/manage-databases-and-caches/choreo-managed-caches/index.html new file mode 100644 index 000000000..6a478551e --- /dev/null +++ b/manage-databases-and-caches/choreo-managed-caches/index.html @@ -0,0 +1,3763 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo-Managed Cache - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo-Managed Cache

+

Fully compatible with legacy Redis® OSS.

+

Choreo-Managed Cache provides fully-managed in-memory NoSQL databases on AWS, Azure, GCP, and Digital Ocean and can be used as a cache, database, streaming engine, or message broker.

+

Create a Choreo-Managed Cache

+

Follow the steps below to create a Choreo-Managed Cache:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then click Databases.
  6. +
  7. Click + Create and select Choreo-Managed Cache as the data store type. Provide a display name for this server and follow the instructions.
  8. +
  9. Select a preferred cloud provider (AWS, Azure, GCP, or Digital Ocean).
      +
    • The cloud provider provisions the compute and storage infrastructure for your data store.
    • +
    • The functionality remains the same across cloud providers, though service plans and costs may differ.
    • +
    +
  10. +
  11. Select a region for your data store.
      +
    • Available regions depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
    • +
    +
  12. +
  13. Select a service plan.
      +
    • Service plans vary in terms of dedicated CPU, memory (RAM), and storage space allocated for your data store, as well as high-availability configurations for production use cases.
    • +
    +
  14. +
  15. Click Create.
  16. +
+

Connect to your Choreo-Managed Cache

+

To connect to your Choreo-Managed Cache, follow these guidelines:

+
    +
  • Use any legacy Redis® OSS compatible driver (in any programming language) to connect to your Choreo-Managed Cache.
  • +
  • You can find the connection parameters in the Overview section in the Choreo Console under the relevant database. Note that Choreo-Managed Cache enforces TLS.
  • +
  • Choreo-Managed Cache instances accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
  • +
+

High availability and automatic backups

+

The high availability and the automatic backup retention periods for a Choreo-Managed Cache can vary as follows depending on the service plan you select.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Service planHigh availabilityBackup featuresBackup history
HobbyistSingle-node with limited availability.Single backup only for disaster recoveryNone
StartupSingle-node with limited availability.Single backup only for disaster recovery1 day
BusinessTwo-node (primary + standby) with higher availability (automatic failover if the primary node fails).Automatic backups3 days
PremiumThree-node (primary + standby + standby) with highest availability (automatic failover if the primary node fails).Automatic backups13 days
+

In general, service plans are recommended for production scenarios due to the following reasons:

+
    +
  • Provides another physical copy of the data in case of hardware, software, or network failures.
  • +
  • Reduces the data loss window in disaster scenarios.
  • +
  • Ensures quicker restoration with controlled failover in case of failures, as the standby is already installed and running.
  • +
+

Automatic backups

+
    +
  • Choreo runs full backups daily to automatically backup Choreo-Managed Caches and has write-ahead logs (WAL) copied at 5-minute intervals or for every new file generated.
  • +
  • Choreo encrypts all backups at rest.
  • +
  • Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the data store.
  • +
+

Failure recovery

+
    +
  • +

    Minor failures: Choreo automatically handles minor failures such as service process crashes or temporary loss of network access in all plans without requiring significant changes to the service deployment. Choreo automatically restores the service to normal operation once it automatically restarts the crashed process or when it restores the network access.

    +
  • +
  • +

    Severe failures: Failures such as losing a node entirely in case of hardware or severe software problems, require more drastic recovery measures. The monitoring infrastructure automatically detects a failing node when the node starts reporting issues in the self-diagnostics or when it stops communicating. In such cases, the monitoring infrastructure automatically schedules a new replacement node to be created.

    +
      +
    • In the event of a data store failover, the service URI of your service remains the same; only the IP address will change to point to the new primary node.
    • +
    • Hobbyist and Startup plans provide a single node, and in case of failure, a new node starts up, restores its state from the latest available backup, and resumes serving traffic.
    • +
    • As there is just a single/primary node, the caching service becomes unavailable for the duration of the restoration operation. Therefore, all write operations made since the last backup will be lost.
    • +
    +
  • +
+

Limitations

+

Connection limits

+

The number of simultaneous connections in a Choreo-Managed Cache depends on the total available memory on the server instances.

+

You can use the following to estimate:

+
max_number_of_connections = 4 x m
+
+ +

Here, m represents the memory in megabytes, where at least 10,000 connections are available, even on the smallest servers. +For example, on a server with 4GB memory (4,096 MB), the simultaneous connections are:

+
4 x 4096 = 16384 // 16k connections
+
+ +

This number is estimated by the exact available memory so it can vary between different plans and cloud providers. To see the exact maximum connections allowed, use the * redis-cli and info command as follows:

+
echo "info" | redis-cli -u REDIS_URI | grep maxclients
+
+ +

Restricted commands

+

To maintain the stability and security of a managed environment, Choreo restricts certain commands on Choreo-Managed Cache services.

+
+

Support for Lua scripts on Choreo-Managed Cache

+
    +
  • Choreo-Managed Cache has built-in support for running Lua scripts to perform various actions directly on the server. Scripting is typically controlled using the EVAL, EVALSHA, and SCRIPT LOAD commands.
  • +
  • For all newly-created cache instances, EVAL, EVALSHA, and SCRIPT LOAD commands are enabled by default.
  • +
+
+

The following commands are disabled on Choreo:

+
    +
  • bgrewriteaof: Initiates a background append-only file rewrite.
  • +
  • cluster: Manages Caching cluster commands.
  • +
  • command: Provides details about all Caching commands.
  • +
  • debug: Contains sub-commands for debugging Caching.
  • +
  • failover: Manages manual failover of a master to a replica.
  • +
  • migrate: Atomically transfers a key from one caching instance to another.
  • +
  • role: Returns the role of the instance in the context of replication.
  • +
  • slaveof: Makes the server a replica of another instance, or promotes it as master.
  • +
  • acl: Manages caching access control lists.
  • +
  • bgsave: Creates a snapshot of the data set into a dump file.
  • +
  • config: Alters the configuration of a running caching server.
  • +
  • lastsave: Returns the UNIX timestamp of the last successful save to disk.
  • +
  • monitor: Streams back every command processed by the Caching server.
  • +
  • replicaof: Makes the server a replica of another instance.
  • +
  • save: Synchronously saves the dataset to disk.
  • +
  • shutdown: Synchronously saves the dataset to disk and then shuts down the server.
  • +
+

The following eval commands are also disabled:

+
    +
  • eval: Executes a Lua script server-side.
  • +
  • eval_ro: Read-only variant of the eval command.
  • +
  • evalsha: Executes a script cached on the server side by its SHA1 digest.
  • +
  • evalsha_ro: Read-only variant of the evalsha command.
  • +
  • fcall: Calls a Caching function.
  • +
  • fcall_ro: Read-only variant of the fcall command.
  • +
  • function: Manages Caching functions.
  • +
  • script: Manages the script cache.
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/choreo-managed-databases-and-caches/index.html b/manage-databases-and-caches/choreo-managed-databases-and-caches/index.html new file mode 100644 index 000000000..f64128568 --- /dev/null +++ b/manage-databases-and-caches/choreo-managed-databases-and-caches/index.html @@ -0,0 +1,3539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo-Managed Databases, Vector Databases, and Caches

+

Choreo allows you to create PostgreSQL and MySQL databases as well as Choreo-Managed Cache instances on all major cloud providers (AWS, Azure, GCP, and DigitalOcean) as fully Choreo-managed platform services. +These databases and caches can be seamlessly provisioned to offer persistence and caching capabilities for all your Choreo components. Choreo provides various service plans for each type, ranging from smaller instances for development purposes to production-grade databases with automatic backups and high-availability multi-nodes.

+

PostgreSQL on Choreo

+

PostgreSQL (also known as Postgres), is an open-source object-relational database management system. You can create PostgreSQL databases on Choreo as fully Choreo-managed, flexible SQL databases that are ideal for both structured and unstructured data. If you want to perform an efficient vector similarity search, you can create a PostgreSQL vector database.

+ +

MySQL on Choreo

+

MySQL is a user-friendly, flexible, open-source relational database management system with a well-established history in the SQL database realm. Choreo allows you to swiftly create fully Choreo-managed MySQL databases, enabling rapid setup and utilization.

+ +

Choreo-Managed Cache

+

A fully-managed cache compatible with legacy Redis® OSS. A versatile, in-memory NoSQL database that serves as a cache, database, streaming engine, and message broker. Choreo-managed Cache allows you to have fully-managed instances that can be swiftly provisioned and integrated into your applications within minutes.

+ +

+ PostgreSQL, MySQL, and Redis® are trademarks and property of their respective owners. All product and service names used in this documentation are for identification purposes only. +

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/choreo-managed-mysql-databases/index.html b/manage-databases-and-caches/choreo-managed-mysql-databases/index.html new file mode 100644 index 000000000..af72a8a07 --- /dev/null +++ b/manage-databases-and-caches/choreo-managed-mysql-databases/index.html @@ -0,0 +1,3683 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + MySQL - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo-managed MySQL Databases

+

MySQL on Choreo offers fully managed, flexible relational databases on AWS, Azure, GCP, and Digital Ocean.

+

Create a Choreo-managed MySQL database

+

Follow the steps below to create a Choreo-managed MySQL database:

+
    +
  1. From the environment list on the header, located next to the Deployment Tracks list, select your Organization.
  2. +
  3. In the left navigation menu, click Dependencies and then Databases.
  4. +
  5. Click Create and select MySQL as the database type. Provide a display name for this server and follow the instructions.
  6. +
  7. Select your preferred cloud provider from AWS, Azure, GCP, and Digital Ocean.
  8. +
  9. Choreo uses the cloud provider to provision the compute and storage infrastructure for your database.
  10. +
  11. There is no functional difference between databases created on different cloud providers, apart from changes to service plans (and associated costs).
  12. +
  13. Choose the region for your database.
  14. +
  15. Available regions will depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
  16. +
  17. Select the service plan.
  18. +
  19. Service plans vary in the dedicated CPU, memory (RAM), storage space allocated for your database, the backup retention periods, and high-availability configurations for production use cases.
  20. +
+

Connect to your Choreo-managed MySQL database

+

To connect to your Choreo-managed MySQL database, consider the following guidelines:

+
    +
  • You can use any MySQL driver, ORM, or supported generic SQL library (may depend on the programming language) to connect to the database.
  • +
  • You can find the connection parameters in the Overview section in the Choreo Console under the relevant database.
  • +
  • MySQL databases accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
  • +
+

High Availability and Automatic Backups

+

The high availability characteristics and the automatic backup retention periods for Choreo-managed MySQL databases vary based on your service plan as explained below:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Service PlanHigh AvailabilityBackup Retention Time
HobbyistSingle-node with limited availabilityNone
StartupSingle-node with limited availability2 days
BusinessTwo-node (primary + standby) with higher availability14 days
PremiumThree-node (primary + standby + standby) with highest availability30 days
+

In general, we recommend service plans for production scenarios for multiple reasons: +- Provides another physical copy of the data in case of hardware, software, or network failures. +- Typically reduces the data loss window in disaster scenarios. +- Provides a quicker time to restore with a controlled failover in case of failures, as the standby is already installed and running.

+

Automatic Backups

+
    +
  • +

    Choreo runs full backups daily to automatically back up Choreo-managed MySQL databases and record binary logs continuously. +Choreo encrypts all backups at rest.

    +
  • +
  • +

    Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the database.

    +
  • +
+

Connection Limits

+

The maximum number of simultaneous connections to MySQL databases is fixed for each service plan and depends on how much RAM your service plan offers.

+
+

Note

+

An extra_connection with a value of 1 is added for system processes for all MySQL databases, regardless of the service plan.

+
+

For plans under 4 GiB RAM

+

For plans under 4 GiB of RAM, the number of allowed connections is 75 per GiB:

+
max_connections = 75 x RAM + extra_connection
+
+ +

For plans with over 4 GiB RAM:

+

For plans with 4 GiB or more RAM, the number of allowed connections is 100 per GiB:

+
max_connections = 100 x RAM + extra_connection
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/choreo-managed-postgresql-databases/index.html b/manage-databases-and-caches/choreo-managed-postgresql-databases/index.html new file mode 100644 index 000000000..aa820153e --- /dev/null +++ b/manage-databases-and-caches/choreo-managed-postgresql-databases/index.html @@ -0,0 +1,3711 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + PostgreSQL - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo-Managed PostgreSQL Databases and Vector Databases

+

PostgreSQL on Choreo offers fully Choreo-managed, efficient object-relational databases on AWS, Azure, GCP, and Digital Ocean. Additionally, Choreo allows you to create fully-managed PostgreSQL vector databases if you want to perform efficient vector similarity search.

+

Create a Choreo-managed PostgreSQL database

+

Follow the steps below to create a Choreo-managed PostgreSQL database:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then Databases.
  6. +
  7. Click Create and select PostgreSQL as the database type. Provide a display name for this server and follow the instructions.
  8. +
  9. Select your preferred cloud provider from AWS, Azure, GCP, or Digital Ocean.
      +
    • The cloud provider is used to provision the compute and storage infrastructure for your database.
    • +
    • There is no functional difference between databases created on different cloud providers, apart from changes to service plans (and associated costs).
    • +
    +
  10. +
  11. Choose the region for your database.
  12. +
  13. Available regions will depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
  14. +
  15. Select the service plan.
  16. +
  17. Service plans vary in the dedicated CPU, memory (RAM), storage space allocated for your database, the backup retention periods, and high-availability configurations for production use cases.
  18. +
+

Create a Choreo-managed PostgreSQL vector database

+

Follow the steps below to create a Choreo-managed PostgreSQL vector database:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then Vector Databases.
  6. +
  7. Follow steps 4 onwards in the Create a Choreo-managed PostgreSQL database section.
  8. +
+

Connecting to your Choreo-managed PostgreSQL database

+

To connect to your Choreo-managed PostgreSQL database, consider the following guidelines:

+
    +
  • You can use any PostgreSQL driver, ORM, or supported generic SQL library (may depend on the programming language) to connect to the database.
  • +
  • The connection parameters can be found in the Overview section in the Choreo Console under the relevant database.
  • +
  • PostgreSQL databases accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
  • +
+

High Availability and Automatic Backups

+

The high availability characteristics and the automatic backup retention periods for Choreo-managed PostgreSQL databases vary based on the selected service plan as shown below.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Service PlanHigh AvailabilityBackup Retention Time
HobbyistSingle-node with limited availabilityNone
StartupSingle-node with limited availability2 days
BusinessTwo-node (primary + standby) with higher availability14 days
PremiumThree-node (primary + standby + standby) with highest availability30 days
+

Service plans with standby nodes are generally recommended for production scenarios for multiple reasons: +- Provides another physical copy of the data in case of hardware, software, or network failures. +- Typically reduces the data loss window in disaster scenarios. +- Provides a quicker time to restore with a controlled failover in case of failures, as the standby is already installed and running.

+

Automatic Backups

+
    +
  • +

    Choreo runs full backups daily to automatically back up Choreo-managed PostgreSQL databases and copies the write-ahead logs (WAL) at 5-minute intervals or for every new file generated. +Choreo encrypts all backups at rest.

    +
  • +
  • +

    Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the database.

    +
  • +
+

Failure Recovery

+
    +
  • +

    Minor failures: Choreo automatically handles minor failures such as service process crashes or temporary loss of network access in all plans without requiring significant changes to the service deployment. Choreo automatically restores the service to normal operation once Choreo automatically restarts the crashed process or when Choreo restores the network access.

    +
  • +
  • +

    Severe failures: To handle severe failures such as losing a node entirely in case of hardware or severe software problems, requires more drastic recovery measures. The monitoring infrastructure automatically detects a failing node, both when the node starts reporting issues in the self-diagnostics or when it stops communicating. In such cases, the monitoring infrastructure automatically schedules a new replacement node to be created.

    +
    +
      +
    • In the event of database failover, the Service URI of your service remains the same; only the IP address will change to point to the new primary node.
    • +
    • Hobbyist and Startup plan provide a single node, and in case of failure, a new node starts up, restores its state from the latest available backup, and resumes serving traffic. +In this plan, as there is just a single node providing the service, the service will become unavailable for the duration of the restoration. In addition, any write operations made since the backup of the latest WAL file will be lost. Typically, this time window is limited to either five minutes of time or one WAL file.
    • +
    +
    +
  • +
+

Connection limits

+

The following connection limits apply to Choreo-managed PostgreSQL databases based on the selected service plan.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Service PlanMax Connections
Hobbyist25
Startup/Business/Premium-4100
Business-16400
Premium-8200
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-databases-and-caches/choreo-managed-redis-datastores/index.html b/manage-databases-and-caches/choreo-managed-redis-datastores/index.html new file mode 100644 index 000000000..8efb13a5d --- /dev/null +++ b/manage-databases-and-caches/choreo-managed-redis-datastores/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/manage-message-brokers/choreo-managed-message-brokers/index.html b/manage-message-brokers/choreo-managed-message-brokers/index.html new file mode 100644 index 000000000..2f0d345b3 --- /dev/null +++ b/manage-message-brokers/choreo-managed-message-brokers/index.html @@ -0,0 +1,3504 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Managed Message Brokers

+

Choreo allows you to create Apache Kafka services across major cloud providers (AWS, Azure, GCP, and DigitalOcean) as Choreo-managed platform services for your message brokering needs. These fully managed Kafka instances can seamlessly integrate with Choreo components, providing scalable messaging for real-time data pipelines and event-driven applications. Choreo offers multiple Kafka service plans, ranging from lightweight instances for development purposes to production-grade clusters with automatic backups, high-availability multi-nodes, and partitioning.

+
+

Note

+
    +
  • Kafka service creation is available only for paid Choreo users.
  • +
  • Kafka service billing will be included in your Choreo subscription, with pricing varying based on the service plan of the resources you create. For more details, see Choreo Platform Services Billing.
  • +
+
+

Apache Kafka on Choreo

+

Apache Kafka is an open-source platform for real-time event streaming and handling large-scale, event-driven data. You can create Kafka services on Choreo as fully-managed, scalable, message brokers, ideal for handling large volumes of event-driven data.

+ + + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-message-brokers/configure-a-kafka-service/index.html b/manage-message-brokers/configure-a-kafka-service/index.html new file mode 100644 index 000000000..4a49191a2 --- /dev/null +++ b/manage-message-brokers/configure-a-kafka-service/index.html @@ -0,0 +1,3630 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure a Kafka Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure a Kafka Service

+

After creating a Kafka service, you can create topics, configure advanced settings, and manage access to ensure secure and efficient message processing.

+

Create a Kafka topic

+

Kafka topics are logical channels used to organize and transfer messages between producers and consumers. They form the core of Kafka's architecture, enabling data streams to be written and read. Kafka topics can also be partitioned to improve scalability and fault tolerance.

+

To create a Kafka topic, follow these steps:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then click Message Brokers.
  6. +
  7. In the Message Brokers list, click the Kafka service for which you want to create a topic.
  8. +
  9. Click the Topics tab.
  10. +
  11. Click + Create.
  12. +
  13. In the Create Topic dialog that opens,
  14. +
  15. Enter a name for the topic.
  16. +
  17. To configure advanced settings, click to expand Advanced Configurations and apply the required settings. For details, see Advanced topic configurations.
  18. +
  19. Click Create.
  20. +
+

Advanced topic configurations

+

Choreo allows you to customize settings for Kafka topics, including the number of partitions, replication factor, cleanup policy, retention size (bytes), retention duration (hours), and the minimum number of in-sync replicas.

+

Cleanup Policy: Determines how messages that reach their retention limit are handled. There are three options:

+
    +
  • Delete (default): Messages are removed when the retention limit is exceeded.
  • +
  • Compact: Retains only the latest record for each unique key, ensuring only the most recent data is kept.
  • +
  • Compact and Delete: Combines both approaches, where old records are deleted based on retention limits, but the latest record for each key is retained.
  • +
+

Replication: Sets the number of partition copies to ensure data durability. The default is 3.

+

Partitions: Defines the number of segments the topic should be divided into for parallel processing. The default is 1 partition.

+

Retention Bytes: Sets the maximum size of retained messages. Older messages are discarded on reaching this limit. The default is unlimited (-1).

+

Retention Hours: Defines the retention period for messages before deletion. The default is 168 hours (7 days).

+

Min In-Sync Replicas: Specifies the minimum number of replicas that must acknowledge a write for it to be considered successful. The default is 2.

+

Manage service users and access control lists

+

Choreo-managed Kafka services use access control lists (ACLs) and user definitions to control access to topics. You can manage users and ACL entries from the corresponding tabs on the Kafka service details page.

+

Manage users

+

To manage users for a Choreo-managed Kafka service, follow these steps:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then click Message Brokers.
  6. +
  7. In the Message Brokers list, click the Kafka service for which you want to manage users.
  8. +
  9. Click the Users tab.
  10. +
  11. Click + Add User, specify a username, and then click Add.
  12. +
+

By default, new users do not have any permissions. You can grant necessary permissions to users through access control lists (ACLs).

+

Configure access control lists (ACLs)

+

An ACL entry defines access permission for a user. Each entry includes:

+
    +
  • Username: The username.
  • +
  • Topic: The associated Kafka topic to grant access to the user.
  • +
  • Permission: The permission to grant the user.
  • +
+

To add an ACL entry, follow these steps:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then click Message Brokers.
  6. +
  7. In the Message Brokers list, click the Kafka service for which you want to add an ACL entry.
  8. +
  9. Click the Access Control List tab.
  10. +
  11. Click + Add Entry, select a username, topic, and permission.
  12. +
  13. Click Add.
  14. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-message-brokers/create-choreo-managed-kafka-services/index.html b/manage-message-brokers/create-choreo-managed-kafka-services/index.html new file mode 100644 index 000000000..bf0e9ea7b --- /dev/null +++ b/manage-message-brokers/create-choreo-managed-kafka-services/index.html @@ -0,0 +1,3847 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create Choreo-Managed Kafka Services - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Create Choreo-Managed Kafka Services

+

Kafka on Choreo offers fully managed, distributed message broker services across AWS, Azure, GCP, and DigitalOcean. These services are designed to handle high-throughput, fault-tolerant data streaming use cases such as real-time analytics, event sourcing, and log aggregation.

+
+

Note

+
    +
  • Kafka service creation is available only for paid Choreo users.
  • +
  • Kafka service billing will be included in your Choreo subscription, with pricing varying based on the service plan of the resources you create. For more details, see Choreo Platform Services Billing.
  • +
+
+

Create a Choreo-managed Kafka service

+

Follow the steps below to create a Choreo-managed Kafka service:

+
    +
  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. +
  3. In the header, click the Organization list. This opens the organization home page.
  4. +
  5. In the left navigation menu, click Dependencies and then click Message Brokers.
  6. +
  7. Click + Create.
  8. +
  9. Specify a display name for the Kafka service and click Next.
  10. +
  11. Select your preferred cloud provider from AWS, Azure, GCP, or Digital Ocean.
      +
    • The cloud provider provisions the computing and storage infrastructure for your Kafka service.
    • +
    • There is no functional difference between Kafka services across providers except for variations in service plans and associated costs.
    • +
    +
  12. +
  13. Select a region for your Kafka service.
      +
    • Available regions depend on the selected cloud provider. Choreo currently supports US, EU, and AU regions across all providers.
    • +
    +
  14. +
  15. Select a service plan.
      +
    • Service plans differ based on the allocation of CPU, memory (RAM), and storage for your Kafka server, as well as backup retention periods and high-availability options suited for production environments.
    • +
    +
  16. +
  17. Click Create. This creates the Kafka service and takes you to the Overview tab on the service details page.
  18. +
+

Connect to your Choreo-managed Kafka service

+

To connect to your Choreo-managed Kafka service, use the connection parameters from the Overview tab on the service details page. Choreo secures Kafka connections via client certificate authentication.

+

Kafka service overview

+

To use the Kafka service with producer and consumer applications, you must configure them with the provided credentials and connection parameters.

+

By default, Kafka services accept traffic from the internet. However, if you want to restrict access to specific IP addresses or CIDR blocks, you can configure the necessary advanced settings.

+

To use the Kafka service in producer and consumer applications, you must add the required parameters as configurations and secrets in Choreo. You can obtain the parameter values from the Overview tab on the service details page and include key configurations such as the access key, access certificate, CA certificate, and service URI. Ensure you create a topic before producing or consuming Kafka messages. If a topic already exists, you can proceed.

+

Set up configurations and secrets

+

Follow these steps to set up required configurations and secrets:

+
    +
  1. Create two Choreo components. One for the producer and another for the consumer application. For a producer and consumer implementation in Go, see sample implementation
  2. +
  3. +

    Define the required configurations and secrets at the component level for each. + You can configure the service.key, service.cert, and ca.pem using file mounts. The following sample implementation uses a file mount for the CA certificate. You can follow the same approach for the other files.

    +

    Set CA certificate

    +
  4. +
  5. +

    Set other configurations, such as TOPIC_NAME and SERVICE_URI as environment variables. You can define these as shown in the following sample implementation.

    +

    Set environment variables

    +
  6. +
+

Sample implementation

+
+
+
+
    package main
+
+    import (
+        "context"
+        "crypto/tls"
+        "crypto/x509"
+        "fmt"
+        "log"
+        "os"
+        "time"
+
+        "github.com/segmentio/kafka-go"
+    )
+
+    // loadPEMFromFile reads a PEM file from the specified file path.
+    func loadPEMFromFile(filePath string) ([]byte, error) {
+        data, err := os.ReadFile(filePath)
+        if err != nil {
+            return nil, fmt.Errorf("failed to read file %s: %w", filePath, err)
+        }
+        return data, nil
+    }
+
+    // loadCertificates loads the necessary certificates for TLS configuration.
+    func loadCertificates() (tls.Certificate, *x509.CertPool, error) {
+        serviceCert, err := loadPEMFromFile("/service.cert")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load service cert: %v", err)
+        }
+
+        serviceKey, err := loadPEMFromFile("/service.key")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load service key: %v", err)
+        }
+
+        caCert, err := loadPEMFromFile("/ca.pem")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load ca cert: %v", err)
+        }
+
+        keypair, err := tls.X509KeyPair(serviceCert, serviceKey)
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load key and cert: %v", err)
+        }
+
+        caCertPool := x509.NewCertPool()
+        if !caCertPool.AppendCertsFromPEM(caCert) {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to append ca cert")
+        }
+
+        return keypair, caCertPool, nil
+    }
+
+    // createKafkaDialer initializes a Kafka dialer with the provided certificates and CA pool.
+    func createKafkaDialer(keypair tls.Certificate, caCertPool *x509.CertPool) *kafka.Dialer {
+        return &kafka.Dialer{
+            Timeout:   10 * time.Second,
+            DualStack: true,
+            TLS: &tls.Config{
+                Certificates: []tls.Certificate{keypair},
+                RootCAs:      caCertPool,
+            },
+        }
+    }
+
+    // setupKafkaProducer initializes and returns a Kafka producer.
+    func setupKafkaProducer(dialer *kafka.Dialer, serviceURI, topicName string) *kafka.Writer {
+        return kafka.NewWriter(kafka.WriterConfig{
+            Brokers: []string{serviceURI},
+            Topic:   topicName,
+            Dialer:  dialer,
+        })
+    }
+
+    // sendMessages sends a specified number of messages to the Kafka topic.
+    func sendMessages(producer *kafka.Writer, count int) {
+        for i := 0; i < count; i++ {
+            message := fmt.Sprintf("Hello from Go using SSL %d!", i+1)
+            err := producer.WriteMessages(context.Background(), kafka.Message{Value: []byte(message)})
+            if err != nil {
+                log.Printf("failed to send message: %v", err)
+            } else {
+                log.Printf("message sent: %s", message)
+            }
+            time.Sleep(time.Second)
+        }
+    }
+
+    func main() {
+        // Load environment variables
+        serviceURI := os.Getenv("SERVICE_URI")
+        if serviceURI == "" {
+            log.Fatalln("service uri is not set")
+        }
+
+        topicName := os.Getenv("TOPIC_NAME")
+        if topicName == "" {
+            log.Fatalln("topic name is not set")
+        }
+
+        // Load certificates and configure TLS
+        keypair, caCertPool, err := loadCertificates()
+        if err != nil {
+            log.Fatalf("failed to load certificates: %v", err)
+        }
+
+        // Create Kafka dialer
+        dialer := createKafkaDialer(keypair, caCertPool)
+
+        // Set up Kafka producer
+        producer := setupKafkaProducer(dialer, serviceURI, topicName)
+        defer func() {
+            if err := producer.Close(); err != nil {
+                log.Printf("failed to close producer: %v", err)
+            }
+        }()
+
+        // Send messages
+        sendMessages(producer, 100)
+    }
+
+ +
+
+
    package main
+
+    import (
+        "context"
+        "crypto/tls"
+        "crypto/x509"
+        "fmt"
+        "log"
+        "os"
+        "time"
+
+        "github.com/segmentio/kafka-go"
+    )
+
+    // loadPEMFromFile reads a PEM file from the specified file path.
+    func loadPEMFromFile(filePath string) ([]byte, error) {
+        data, err := os.ReadFile(filePath)
+        if err != nil {
+            return nil, fmt.Errorf("failed to read file %s: %w", filePath, err)
+        }
+        return data, nil
+    }
+
+    // loadCertificates loads the necessary certificates for TLS configuration.
+    func loadCertificates() (tls.Certificate, *x509.CertPool, error) {
+        serviceCert, err := loadPEMFromFile("/service.cert")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load service cert: %v", err)
+        }
+
+        serviceKey, err := loadPEMFromFile("/service.key")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load service key: %v", err)
+        }
+
+        caCert, err := loadPEMFromFile("/ca.pem")
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load ca cert: %v", err)
+        }
+
+        keypair, err := tls.X509KeyPair(serviceCert, serviceKey)
+        if err != nil {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to load key and cert: %v", err)
+        }
+
+        caCertPool := x509.NewCertPool()
+        if !caCertPool.AppendCertsFromPEM(caCert) {
+            return tls.Certificate{}, nil, fmt.Errorf("failed to append ca cert")
+        }
+
+        return keypair, caCertPool, nil
+    }
+
+    // createKafkaDialer initializes a Kafka dialer with the provided certificates and CA pool.
+    func createKafkaDialer(keypair tls.Certificate, caCertPool *x509.CertPool) *kafka.Dialer {
+        return &kafka.Dialer{
+            Timeout:   10 * time.Second,
+            DualStack: true,
+            TLS: &tls.Config{
+                Certificates: []tls.Certificate{keypair},
+                RootCAs:      caCertPool,
+            },
+        }
+    }
+
+    // setupKafkaConsumer initializes and returns a Kafka consumer.
+    func setupKafkaConsumer(dialer *kafka.Dialer, serviceURI, topicName string) *kafka.Reader {
+        return kafka.NewReader(kafka.ReaderConfig{
+            Brokers: []string{serviceURI},
+            Topic:   topicName,
+            Dialer:  dialer,
+        })
+    }
+
+    // consumeMessages continuously reads messages from the Kafka topic.
+    func consumeMessages(consumer *kafka.Reader) {
+        for {
+            msg, err := consumer.ReadMessage(context.Background())
+            if err != nil {
+                log.Printf("could not read message: %v", err)
+                continue
+            }
+            log.Printf("received: %s", msg.Value)
+        }
+    }
+
+    func main() {
+        // Load environment variables
+        serviceURI := os.Getenv("SERVICE_URI")
+        if serviceURI == "" {
+            log.Fatalln("service uri is not set")
+        }
+
+        topicName := os.Getenv("TOPIC_NAME")
+        if topicName == "" {
+            log.Fatalln("topic name is not set")
+        }
+
+        // Load certificates and configure TLS
+        keypair, caCertPool, err := loadCertificates()
+        if err != nil {
+            log.Fatalf("failed to load certificates: %v", err)
+        }
+
+        // Create Kafka dialer
+        dialer := createKafkaDialer(keypair, caCertPool)
+
+        // Set up Kafka consumer
+        consumer := setupKafkaConsumer(dialer, serviceURI, topicName)
+        defer func() {
+            if err := consumer.Close(); err != nil {
+                log.Printf("failed to close consumer: %v", err)
+            }
+        }()
+
+        // Consume messages
+        consumeMessages(consumer)
+    }
+
+ +
+
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage-message-brokers/monitor-a-kafka-service/index.html b/manage-message-brokers/monitor-a-kafka-service/index.html new file mode 100644 index 000000000..e3efa042d --- /dev/null +++ b/manage-message-brokers/monitor-a-kafka-service/index.html @@ -0,0 +1,3523 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Monitor a Kafka Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Monitor a Kafka Service

+

You can monitor the health and performance of your Kafka services via the service metrics and service logs.

+

Service metrics

+

Service metrics provide real-time insights into the performance of your Kafka service.

+

To view service metrics for a Kafka service, go to the Metrics tab on the service details page.

+

The service metrics include the following:

+
    +
  • CPU Usage %: Displays the percentage of CPU resources consumed by the service.
  • +
  • Disk Usage %: Represents the percentage of disk space utilized by the service.
  • +
  • Disk IO Reads: Displays the input/output operations per second (IOPS) for disk reads.
  • +
  • Disk IO Writes: Displays the input/output operations per second (IOPS) for disk writes.
  • +
  • Load Average: Displays the 5-minute average CPU load, indicating the system's computational load.
  • +
  • Memory Available %: Represents the percentage of memory resources utilized by the service.
  • +
  • Network Received: Indicates the volume of network traffic received by the service in bytes per second.
  • +
  • Network Sent: Indicates the amount of network traffic transmitted by the service in bytes per second.
  • +
+

Service logs

+

Service logs provide a detailed record of Kafka service activity, such as producer and consumer operations, connection statuses, and error reports. These logs are essential for troubleshooting issues and analyzing message flow. Logs are retained for up to 4 days.

+

To view Choreo-managed Kafka service logs, go to the Logs tab on the service details page.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manage/api-management/index.html b/manage/api-management/index.html new file mode 100644 index 000000000..b35a70318 --- /dev/null +++ b/manage/api-management/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/manage/api-rate-limiting/index.html b/manage/api-rate-limiting/index.html new file mode 100644 index 000000000..5a52bcf08 --- /dev/null +++ b/manage/api-rate-limiting/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/manage/api-security/pass-end-user-attributes-to-the-backend/index.html b/manage/api-security/pass-end-user-attributes-to-the-backend/index.html new file mode 100644 index 000000000..5a52bcf08 --- /dev/null +++ b/manage/api-security/pass-end-user-attributes-to-the-backend/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/manage/lifecycle/index.html b/manage/lifecycle/index.html new file mode 100644 index 000000000..b35a70318 --- /dev/null +++ b/manage/lifecycle/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/manual-triggers/index.html b/manual-triggers/index.html new file mode 100644 index 000000000..0ca9dfa19 --- /dev/null +++ b/manual-triggers/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/marketplace/index.html b/marketplace/index.html new file mode 100644 index 000000000..1bdd86271 --- /dev/null +++ b/marketplace/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/monitoring-and-insights/alerts/configure-alerts/index.html b/monitoring-and-insights/alerts/configure-alerts/index.html new file mode 100644 index 000000000..08f892855 --- /dev/null +++ b/monitoring-and-insights/alerts/configure-alerts/index.html @@ -0,0 +1,3595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Alerts - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure Alerts

+

This section explains how you can configure alerts for your API manager deployments. Setting up alerts allows you to proactively monitor your API ecosystem and take corrective measures when necessary.

+

You can configure alerts for each environment within your organization. You can add, modify, or delete alerts per API. Optionally, you can specify a list of emails for each alert configuration.

+

Alerts are subject to a suppression policy to prevent duplicate notifications within a specific time frame. By default, a 10-minute suppression window is applied, and this is not configurable. The suppression policy is specific to each alert configuration.

+
+

Info

+
    +
  • You can configure a maximum of 20 alerts per organization, environment, and tenant combination.
  • +
  • Adding email addresses to an alert configuration is optional. If necessary, you can add a maximum of 5 email addresses per alert.
  • +
+
+

Alerts can be categorized as either latency alerts or traffic alerts.

+

Latency alerts

+

Latency alerts notify you if the response latency of an API exceeds a predefined threshold. This is useful for APIs that need to meet specific SLAs and for proactively identifying slow APIs.

+

To configure a new latency alert, follow the steps given below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. Ensure you are in the correct organization where you have a project with the API to configure a latency alert.
  4. +
  5. In the Choreo Console left navigation menu, click Usage Insights.
  6. +
  7. In the left navigation menu on the Usage Insights page, click Alerts.
  8. +
  9. Click the Environment list and select the required environment.
  10. +
  11. +

    Click Alert Configuration.

    +

    Configure alerts

    +

    This opens the Alert Configuration pane with the Latency tab open by default.

    +
  12. +
  13. +

    In the API Name field, select the API for which you want to configure the alert.

    +
    +

    Info

    +

    Only the APIs that you have invoked at least once are listed here. For other APIs, you need to give the API name in the required format as instructed in the UI.

    +
    +
  14. +
  15. +

    In the Metric field, select the required metric against which you want to evaluate the alert configuration.

    +
    +

    Tip

    +

    The list includes all available options. If there are multiple metrics, you can select the required metric. If there is only one metric to choose, that metric is selected by default, and the field is disabled.

    +
    +
  16. +
  17. +

    In the Latency field, specify the threshold in milliseconds.

    +
    +

    Info

    +

    When the 95th percentile of the selected metric exceeds the threshold provided here, alerts are triggered.

    +
    +
  18. +
  19. +

    In the Emails field, specify the list of emails that should be notified when the alert is added.

    +
  20. +
  21. +

    Click + Add.

    +
  22. +
+

Once an alert is successfully added, the alert configuration is listed in the Alert Configuration pane. Each configuration can be edited and removed via this pane.

+

Traffic alerts

+

Traffic alerts notify you when the request count of an API exceeds a predefined threshold. This is useful for managing APIs with backend traffic limits or monetized backends that require proactive scaling based on incoming traffic.

+

To configure a new traffic alert, follow the steps below:

+
    +
  1. Sign in to the Choreo Console.
  2. +
  3. Ensure you are in the correct organization where you have a project with the API to configure a latency alert.
  4. +
  5. In the Choreo Console left navigation menu, click Usage Insights.
  6. +
  7. In the left navigation menu on the Usage Insights page, click Alerts.
  8. +
  9. Click the Environment list and select the required environment.
  10. +
  11. Click Alert Configuration. This opens the Alert Configuration pane.
  12. +
  13. Click the Traffic tab.
  14. +
  15. +

    In the API Name field, select the API for which you want to configure the alert.

    +
    +

    Info

    +

    Only the APIs that you have invoked at least once are listed here. For other APIs, you need to give the API name in the required format as instructed in the UI.

    +
    +
  16. +
  17. +

    In the Metric field, select the required metric against which you want to evaluate the alert configuration.

    +
    +

    Tip

    +

    The list includes all available options. If there are multiple metrics, you can select the required metric. If there is only one metric to choose, that metric is selected by default, and the field is disabled.

    +
    +
  18. +
  19. +

    In the Threshold field, specify the threshold number of requests per minute.

    +
  20. +
  21. +

    If required, specify the list of emails that should be notified when the alert is generated in the Emails field.

    +
  22. +
  23. +

    Click Add.

    +
  24. +
+

Once an alert is successfully added, the alert configuration is listed in the Alert Configuration pane. Each configuration can be edited and removed via this pane.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/delivery-insights/configure-dora-metrics/index.html b/monitoring-and-insights/delivery-insights/configure-dora-metrics/index.html new file mode 100644 index 000000000..a4435edad --- /dev/null +++ b/monitoring-and-insights/delivery-insights/configure-dora-metrics/index.html @@ -0,0 +1,3681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure DORA Metrics - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Configure CIO Dashboard

+

CIO dashboard

+

You can view DORA metrics in Choreo to use as KPIs to measure your organization's DevOps team's performance. Choreo enables this feature by default for all organizations. DORA includes the following four key metrics that are regarded as the most important metrics to indicate team performance:

+
    +
  • Deployment Frequency: How often an organization successfully releases to production
  • +
  • Lead Time for Changes: The amount of time it takes a commit to get into production
  • +
  • Change Failure Rate: The percentage of deployments causing a failure in production
  • +
  • Time to Restore Service: How long it takes an organization to recover from a failure in production
  • +
+

Choreo enables two DORA metrics by default; deployment frequency and lead time for change.

+

Configure the CIO Dashboard with all metrics

+

To configure the CIO dashboard by enabling the other two metrics, follow the steps below:

+
    +
  1. Sign in to Choreo using your Google, GitHub, or Microsoft account.
  2. +
  3. On the left navigation menu, click Delivery Insights.
  4. +
  5. Click on the DORA Metrics tab.
  6. +
  7. Scroll to the bottom of the dashboard and click Configure.
  8. +
  9. Select your incident management system. Currently, Choreo only supports GitHub.
  10. +
+

Configuring GitHub as the incident management system

+

Configure

+

To configure GitHub as the incident management system, follow the steps below:

+

Step 1: Authorize

+

Authorize

+

First, let's authorize Choreo to access the repositories used to record incidents.

+

On the Add Integration page, select GitHub and click Authorize with GitHub.

+

Once the authorization process is complete, you can start configuring the GitHub repository.

+

Step 2: Configure

+

Configure

+

By default, Choreo collects incident details(issues) from all repositories containing Choreo components. However, you can configure a GitHub account and a GitHub repository to allow Choreo to read issues from a specific repository, and then click Next.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescriptionValue
Data PlaneChoreo collects incident details by running a scheduled job which invokes the GitHub API periodically. This job runs on the user's data plane. This configuration allows users to specify a preferred data plane to run the job, especially when they have multiple data planes.Select a preferred data plane from the Data Plane list.
GitHub AccountThe GitHub account you have your repositories in.Select your GitHub account that includes the repository used for incident collection.
GitHub RepositoryBy default, Choreo will collect incident details(issues) from all repositories that already have Choreo components.
+

Step 3: Filter label

+

Filter Label

+

The filter label allows Choreo to scrape issues associated with that label.

+
    +
  • +

    Incident Label: The label Choreo uses to identify incidents. For example, Type/Incident.

    +
  • +
  • +

    Invalid incident label(Optional): Choreo will not scrape issues with this label and will proceed to skip these issues. For example, Resolution/Invalid. You can use this label when you want to ignore issues. For example, closing an issue after identifying that it doesn't qualify as an incident issue as it was due to a user error.

    +
  • +
+

Once you configure the labels, click Save.

+

Choreo will enable incident data publishing in the background once you save. Once completed, DORA metric charts will appear in the CIO dashboard for Mean Time To Recover and Change Failure Rate. If there are any issues in the configuration, the configure banner will reappear, and the user can proceed to reconfigure.

+

Step 4: Enrich incident tickets with deployment information

+

Choreo extracts deployment information from the relevant incident and generates DORA metrics that help you analyze the deployment statistics related to the incidents. Therefore, you must manually update the GitHub issue with the relevant deployment-related information. Follow the steps below to add the deployment information to the GitHub issue.

+

Get deployment details

+
    +
  1. On the Choreo Console header, select the project and the component for which the incident was reported.
  2. +
  3. On the left navigation menu, click Deploy.
  4. +
  5. On the Production Environment card, click Deployment History.
  6. +
  7. +

    On the right-hand side panel, select the relevant deployment, and click Release details to copy the deployment details to the clipboard.

    +

    Copy to clipboard

    +
  8. +
+

Add deployment information to the GitHub issue

+
    +
  1. Edit the GitHub issue to add the deployment information.
  2. +
  3. Paste the deployment information you copied (in step 4 under the section Get deployment details) at the end of the issue body.
  4. +
  5. Click Save.
  6. +
+

That's it! You have successfully configured your CIO dashboard to include the DORA metrics.

+
+

Note

+

The CIO Dashboard is expected to reflect the latest statistics within approximately 30 minutes.

+
+

Edit configurations

+

Edit configurations

+

You can edit or override the configurations you made via the edit option in the dashboard.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/delivery-insights/view-dora-metrics/index.html b/monitoring-and-insights/delivery-insights/view-dora-metrics/index.html new file mode 100644 index 000000000..ed8c98357 --- /dev/null +++ b/monitoring-and-insights/delivery-insights/view-dora-metrics/index.html @@ -0,0 +1,3779 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + View DORA Metrics - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

View DORA metrics

+

DORA metrics comprise four key metrics. Let's explore what each metric represents in Choreo. Choreo displays a summary and graphical representation of each metric.

+

Snapshot view

+

DORA metric summary

+

The snapshot view includes four tiles on the top of the dashboard, summarizing DORA metrics for the entire time period you select. The snapshot view categorizes each metric into four performance levels: elite, high, medium, and low. The categorization is based on the 2020 DORA metric report.

+

DORA matrix

+

Time series view

+

The time series view provides a graphical representation of how the statistics have changed over a period of time. You can use this view to analyze team performance and identify trends.

+

Time Series View

+

Deployment frequency

+

DORA team definition: The frequency at which an organization successfully releases to production.

+

In Choreo, this translates to the number of times an organization deploys a component to the production environment. Choreo does not count the deployment done to the development or other lower environments.

+

Snapshot view

+

Deployment Frequency Snapshot

+

The snapshot view of the Deployment Frequency metric shows the deployment frequency for all components within the selected organization. The frequency is dynamically determined and rounded to the nearest measurement. For example, if there is more than one deployment daily, the deployment frequency is measured in deployments per day. If the deployment frequency is less, it is measured in a higher granularity. For example, deployments per week.

+

A lower deployment frequency indicates that your organizational efficiency is low and that you need to evaluate and improve the processes to encourage frequent releases.

+

Choreo also displays the total number of deployments for the selected time range and the percentage increase or decrease compared to the previous time range.

+

Time series view

+

Deployment Frequency time series view

+

The time series view for the Deployment Frequency metric visualizes the deployment count as a bar chart for the selected time period. Deployment count is aggregated based on the ‘view by’ selector. Hovering over each bar shows the counts for the aggregated period. +Using this chart, organizations can identify deployment patterns, such as days of the week/months of the year where more deployments are likely to happen (near quarterly release days) and periods with fewer deployments. Decision-makers can then take steps to investigate and improve performance. +This chart displays the pattern before and after a process change so you can use it to evaluate the team's performance after a significant process change.

+

Lead Time for Change

+

DORA team definition: The time it takes for a commit to reach production.

+

In Choreo, this translates into the time between committing and promoting a deployment to production. Although this approach may overlook any commits you push to production between two commits, it effectively assesses the efficiency of the review, approval, and CI/CD processes. Therefore, focusing on the production commits is adequate. If a team commits locally for extended periods without deploying to production, this gets reflected in the Deployment Frequency charts.

+

Snapshot view

+

Lead Time For Change Frequency Snapshot

+

The snapshot view of this metric displays the 95th percentile of the lead time for the selected time period. 95th percentile serves as a better representation as it filters out large outliers that can taint the average value. Lower lead times for change suggest that your organization has efficient processes for change review, approval, and CI/CD, while longer times suggest that the process needs to improve. Organizations can also use the categorization label to determine their standpoint on global standards.

+

Additionally, Choreo also displays the percentage increase or decrease compared to the last time period.

+

Time series view

+

Lead Time For Change Frequency Time Series View

+

The time series view of this metric visualizes the lead time as a bar chart for the selected time period. The time is summed based on the ‘view by’ selector. To handle outliers, the y-axis employs a log scale that represents values read dynamically. Hovering over each bar displays the actual counts for the aggregated period. +Using this chart, organizations can identify trends in their release process. For example, organizations can identify the time of the year when lead time rises, such as summer break. Also, organizations can use this to benchmark and evaluate new process changes. For example, if you introduced a process to include peer programming and reviewing, this chart can be used to evaluate its effect on the lead time and provide leadership with factual information to proceed further.

+

Change failure rate

+

The DORA team definition: The percentage of deployments causing a failure in production.

+

In Choreo, this translates to the ratio of deployments causing production failures to the total number of deployments. If there is at least one incident reported against a deployment, Choreo considers that deployment as a failed deployment in production. Any deployment-time failures are not counted as production failures because such failures don't impact the end user. For this metric to be accurate, the organization is expected to open incidents adhering to the proper format as it is crucial for Choreo to identify production failures.

+

Snapshot view

+

Change Failure Rate Snapshot

+

The snapshot view of this metric visualizes the change failure rate as a percentage for the selected time period. This will be the absolute percentage for the entire time period. When deciding on the time, the time of deployment is considered instead of the incident reported time. For example, the change failure rate for January 2023 will reflect the following: + - All deployments that happened within January. + - Any incidents that were reported at any time (in or after January) against the January deployments.

+

This view helps leadership assess the quality of deliverables and identify areas for improvement. Higher rates suggest that the organization needs to improve its processes to bring in more quality assurance aspects such as improved code coverage and end-to-end test coverage.

+

Additionally, Choreo also shows the percentage increase or decrease compared to the previous time period.

+

Time series view

+

Change Failure Rate Time Series

+

The time series view of this metric displays it as a line chart with data points corresponding to the granularity selected by the ‘view by’ selector. The absolute percentage is shown for each granularity. Hovering over the line chart displays the actual counts for the aggregated period. +This chart helps leadership identify timely trends in product quality aspects. For example, this view displays the months of the year where the failure rate is high (for example, close to quarterly release/announcement dates). Also, you can use this to measure the effectiveness of changes introduced to improve quality. For example, if the organization introduced an end-to-end test pipeline integration to the PR approval process, they can use this view to factually observe the timely impact of that change and determine how it decreases the failure rate.

+

Mean Time to Recover(MTTR)

+

The DORA team definition: The time it takes for an organization to recover from a production failure.

+

In Choreo, this measures the time from identifying a production incident to resolving it. This metric reflects the responsiveness and agility of incident management teams.

+

Choreo depends on the open and close times of incidents to gather the relevant information. Therefore, for the dashboards to be accurate, organizations must follow process guidelines to update and close incident tickets efficiently in their incident management system.

+

Snapshot view

+

Mean Time to Recovery Snapshot

+

The snapshot view for this metric displays the mean recovery time for the selected time period. Choreo dynamically adjusts the time unit to measure this metric for better readability. +This chart helps organizations evaluate the response time and agility of their incident handling teams, which in turn is an indication of stability. Higher MTTR means the leadership should look at new ways of improving the efficiency and agility of the teams handling incidents.

+

Time series view

+

Mean Time to Recovery Time Series

+

The time series view of this metric shows how the mean time to recovery changes over time on a granularity based on the ‘view by’ selector. Each time the granularity mean would be used as the aggregation factor. Hovering over the line chart displays the actual counts for the aggregated period. +This view helps leadership understand timely trends on mean time to recovery, such as higher values during holiday periods when there is less staff. Also, you can use this measurement to evaluate the effectiveness of process changes such as introducing an incident response plan. The trend view clearly shows the before and after statistics and the effectiveness of the process change.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/engineering-insights/configure-cio-dashboard/index.html b/monitoring-and-insights/engineering-insights/configure-cio-dashboard/index.html new file mode 100644 index 000000000..107f383f6 --- /dev/null +++ b/monitoring-and-insights/engineering-insights/configure-cio-dashboard/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/monitoring-and-insights/engineering-insights/view-dora-metrics/index.html b/monitoring-and-insights/engineering-insights/view-dora-metrics/index.html new file mode 100644 index 000000000..df6441bd5 --- /dev/null +++ b/monitoring-and-insights/engineering-insights/view-dora-metrics/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/monitoring-and-insights/generate-custom-reports/index.html b/monitoring-and-insights/generate-custom-reports/index.html new file mode 100644 index 000000000..64bdc7fc2 --- /dev/null +++ b/monitoring-and-insights/generate-custom-reports/index.html @@ -0,0 +1,3576 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generate Custom Reports - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Generate Custom Reports

+

Choreo insights allow you to generate custom reports to view the information that is important to you to make timely decisions for the betterment of your business. With custom reports, you can generate reports for a set of metrics of your choice and aggregate results by specific fields. Once generated, the metrics can be filtered out using any selected group-by filters. Custom reports support three visualizations: overtime charts, pie charts, and tables.

+

Metrics

+

Choreo Insights allow you to retrieve data for the following metrics:

+
    +
  • Successful Hit Count
  • +
  • Response Cache Hits
  • +
  • Request Mediation Latency
  • +
  • Response Mediation Latency
  • +
  • Backend Latency
  • +
  • Total Latency
  • +
  • API Errors
  • +
  • Target Errors
  • +
+

Group-by

+

Group-by fields specify how to group the metric data. e.g., You can select Successful Hit Count in the Metrics field and API Name under Group-by to retrieve the successful hit count grouped by the API name.

+

Choreo Insights allow you to group metric data by the following fields:

+
    +
  • API Name
  • +
  • API Version
  • +
  • API Resource Template
  • +
  • API Method
  • +
  • API Creator
  • +
  • Application
  • +
  • Application Owner
  • +
  • Destination
  • +
  • User Agent
  • +
  • Platform
  • +
+

To generate a custom report, follow the steps below:

+
    +
  1. +

    In the left navigation menu, click Custom Reports.

    +

    Select Custom Reports

    +
  2. +
  3. +

    Select metric(s) from the Metrics drop-down selector.

    +

    Generate report

    +
  4. +
  5. +

    Select a minimum of 1 and a maximum of 3 group-by field(s) from the Group By drop down selector.

    +
  6. +
  7. +

    Set the order of the group-by filters by drag and drop to determine the grouping order of the selected metric(s).

    +
  8. +
  9. +

    Once you determine the order of the group-by fields, you can set values for each group-by field from the respective dropdown.

    +

    Group by field selection

    +
  10. +
  11. +

    Click Generate.

    +

    Generate

    +
  12. +
+

Download Reports

+

Choreo Insights allow you to download report data related to each chart as a PDF or a CSV file.

+

To do this, click the Download icon on the top right of the relevant chart and select the required file format. + Download Report

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/insights-overview/index.html b/monitoring-and-insights/insights-overview/index.html new file mode 100644 index 000000000..6fd394494 --- /dev/null +++ b/monitoring-and-insights/insights-overview/index.html @@ -0,0 +1,3987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Insights Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Insights Overview

+

Choreo provides comprehensive insights into APIs created within both the on-premises API Manager and the Choreo platform. Choreo insights provide a range of metrics, including API traffic, error rates, and latency, allowing you to monitor and optimize API performance effectively.

+

With Choreo insights, you can:

+
    +
  • Analyze API traffic: Monitor the volume of requests and responses to understand usage patterns.
  • +
  • Track errors: Identify and analyze errors to improve API reliability.
  • +
  • Monitor latency: Measure and optimize the response times of your APIs.
  • +
  • Generate reports: Generate detailed reports to keep stakeholders informed and support data-driven decision-making.
  • +
  • Configure alerts: Set up alerts for specific events or thresholds to proactively manage API performance.
  • +
  • Obtain granular insights: Obtain detailed information on a per-application, per-API, and per-user basis for more targeted analysis.
  • +
  • Drill down into data: Dive deeper into data to perform root cause analysis.
  • +
+

By leveraging these insights, businesses can make informed decisions to enhance their API strategies and drive their digital transformation initiatives forward.

+

View insights

+

To view usage insights, go to the Choreo Console and click Usage Insights in the left navigation menu.

+

If you are viewing insights on the Choreo platform at the organization level, note the following:

+
    +
  • Permission-based access: Signed-in users can only view insights for components or projects that they have permission to access.
  • +
  • Data exclusion: Insights exclude data from components you cannot access and the data related to deleted components.
  • +
  • Comprehensive view permission: To view insights for all components, including deleted ones, across the organization regardless of project visibility, you must have the View Organization Insights permission under OBSERVABILITY-MANAGEMENT with the mapping level defined at the Organization level.
  • +
  • Admin role: Users with the admin role have the View Organization Insights permission by default and can view organization-wide insights.
  • +
  • Configuring permissions: For detailed steps on configuring permissions, see Control Access in the Choreo Console.
  • +
+

By ensuring proper permissions are set, organizations can manage access to insights effectively while maintaining data security and relevance.

+

Analyze statistics

+

Once you access the Usage Insights page, you can access the following subpages.

+

Overview

+

The Overview page gives you a quick overview of the system status.

+

Overview

+

The information displayed is as follows:

+
    +
  • +

    Total Traffic

    +

    Total traffic

    +

    This widget displays the total traffic of the selected environment received during a given time interval. Both successful requests and failed requests are displayed. To investigate further, you can click the arrow icon on the bottom right corner of the widget to open the Traffic page.

    +
  • +
  • +

    Error Request Count

    +

    Error request count

    +

    This widget displays the total number of requests that have resulted in errors in your selected environment during the selected time range.

    +
  • +
  • +

    Average Error Rate

    +

    Average error rate

    +

    This widget displays the average error rate (i.e., error count/total request count) of the selected environment for a given time interval. You can use this widget as an indicator to understand the health of the system. If the error rate is high, you can investigate further by clicking the arrow on the bottom right of the widget and opening the Errors page.

    +
  • +
  • +

    95th Percentile Latency

    +

    95th percentile latency

    +

    This widget displays the 95th percentile of all API latencies in your selected environment for the given time interval. You can use this widget to know whether the complete system operates under given SLAs. This metric provides the first indication of slow APIs. To investigate further, you can click the arrow on the bottom right of the widget to open the Latency page where you can further analyze the latency.

    +
  • +
  • +

    API Request Summary

    +

    API request summary

    +

    This chart displays the total successful requests, the total requests that have resulted in errors, and the latency in a timeline. The y-axis on the left displays the request count and the error count. The x-axis shows time, and the y-axis on the right shows the latency in milliseconds. The granularity of the data points is decided based on the time range you have selected. The tooltip provides the exact value of all three metrics accurately.

    +
  • +
+

Traffic

+

The Traffic page shows information related to the traffic that goes through your API management deployments. This includes API usage, application usage, resource usage, etc. You can use this page to investigate the usage of APIs and applications, traffic patterns, etc.

+

Traffic

+

You can filter the information displayed in the widgets as follows:

+ + + + + + + + + + + + + + + + + +
Filtering OptionDescription
By APIIn the API field, you can select one or more APIs for which you want to view analytics. All is selected by default. Once you select an API, you can further filter by a specific application that uses the selected API via the Application field described below.
By ApplicationIn the Application field, you can select the applications for which you want to view analytics. All is selected by default. The available applications are all the applications that have subscribed to one or more of the APIs you selected in the API field.
+

You can view the following information for the APIs you have selected using the above filtering criteria:

+
    +
  • +

    API Usage Over Time

    +

    This timeline shows the count of API hits for the APIs for the filtered APIs. If multiple APIs are selected, the timeline shows each API in a separate line with a legend separating each line. You can also zoom in on a selected time range by selecting that area in the chart. To restore to the original view use the Zoom out button on the top right-hand corner of the plot.

    +

    API usage over time

    +
  • +
  • +

    API Usage By Application

    +

    This widget shows the per-application breakdown of requests for the APIs you selected. You can use the pie chart view or the line chart view. You can switch between the two views using the small icon at the upper-right corner of the widget.

    +

    API usage by application

    +
  • +
  • +

    API Usage By Target

    +

    This widget shows the per-backend breakdown of requests for the APIs you selected. This information is useful when multiple APIs share the same backend that has traffic restrictions. You can use these stats to scale your backends proactively. You can switch between the two views using the small icon at the upper-right corner of the widget.

    +

    API usage by target

    +
  • +
  • +

    API Resource Usage

    +

    This table shows a resource-level breakdown of API traffic. Each row represents an API resource and it shows the API name, resource path, API method, and the hit count for that combination.

    +

    API resource usage

    +
  • +
+

Errors

+

The Errors page shows information related to erroneous API calls that are received by your system. The errors are categorized based on the error type. You can further drill down using the error subtypes. Use this page as the starting point for debugging any API errors.

+

Error statistics

+

You can filter the information displayed in the widgets as follows:

+ + + + + + + + + + + + + + + + + + + + + +
Filtering OptionDescription
By APIIn the API field, select the APIs for which you want to view analytics. By default, all APIs are selected. You can select one or multiple APIs from this selector and view the aggregated result.
By CategoryThe Category field is displayed when you click Category in the upper right corner of the page. In this field, you can select one or all of the following error categories:
Authentication: Any kind of authentication error falls into this category including expired/missing/invalid credentials.
Target Connectivity: Any kind of back-end error falls into this category including connection time-outs/other back-end errors (for example, 4xx and 5xx status codes).
Throttling: Any request that fails due to rate-limiting falls into this category including application throttling/subscription throttling.
Other: All other errors fall into this category including mediation errors/resource not found errors.
By Status CodeThe Status Code field is displayed when you click Status Code in the upper right corner of the page. In this field, you can select all or any available HTTP status code categories (4xx, 5xx, etc.). These status codes represent the response status of the API Gateway.
+

Viewing errors by category

+

The following widgets are available for monitoring errors when you have selected Category in the upper-right corner of the page.

+
    +
  • +

    This graph shows the error by category over time for the selected period. Apply the required filters as explained above to select the APIs and the error categories to which this content applies. When you select multiple APIs, the error count is grouped by category.

    +

    Errors by category graph

    +
  • +
  • +

    This table provides further information about the errors such as application details and the error reason. For some authentication errors, the application name is not available. You can use this table to get more concrete information about the errors related to your APIs and then start the problem identification.

    +

    Errors by category table

    +
  • +
+

Viewing errors by status code

+

The following widgets are available for monitoring errors when you select Status Code in the upper-right corner of the page.

+
    +
  • +

    Errors by Status Code

    +

    This graph shows the distribution of HTTP status codes received for errors over time for the selected period. Apply the required filters as explained above to select the APIs and status code groups to which this content applies. When you select multiple APIs, the error count is grouped by the status code.

    +

    Errors by status code

    +
  • +
  • +

    Target Errors by Status Code

    +

    This graph shows the distribution of target errors that have occurred during the selected time interval by HTTP status code. Apply the required filters as explained in the table above to view the APIs and status code groups to which this content applies. If you select multiple APIs, the widget groups the target error count by the status code.

    +

    Target errors by status code

    +
  • +
  • +

    Errors

    +

    The Errors heat map shows the HTTP response codes of errors sent to the client by the API Gateway. Each row displays the number of times the system returned each status code for the selected APIs. The cell color is red for higher numbers and white for lower numbers. If required, you can further filter the results by the error code groups you identified with the Errors by Status Code graph.

    +

    Errors

    +
  • +
  • +

    Target Errors

    +

    The Target errors heat map shows the HTTP response codes of errors that the API Gateway received from the backend. Each row displays the number of times the system returned each status code for the selected APIs. The cell color is red for higher numbers and white for lower numbers. If required, you can further filter the results by the error code groups you identified with the Target Errors by Status Code graph.

    +

    Target errors

    +
  • +
+

Latency

+

The Latency page shows information related to the latency of API calls within the API management deployment. You can view a summary of the slowest APIs and then drill down into the API view for further analysis. Use this page as a starting point to debug API slowness.

+

Latency

+

The information displayed is as follows:

+
    +
  • +

    Top 10 Slowest APIs

    +

    This widget allows you to identify the slowest APIs of the API management system at a glance. Since these are the APIs that contribute to the higher 95th percentile of the system, improving these APIs lowers the 95th percentile of latency in the API Management deployments.

    +

    Slowest APIs

    +
  • +
  • +

    Latencies By Category

    +

    This widget allows you to further drill down details in the above chart. Use the API selector in this widget to select the slow API you identified in the earlier step and then analyze further. Use the charts available in the widget to view the 95th percentile and the median latency over the selected period of the following:

    +
      +
    • Backend
    • +
    • Request mediation
    • +
    • Response mediation
    • +
    +

    Latencies by category

    +
  • +
+

You can use these charts to further drill down and analyze whether the latency occurs in the backend, request mediation, or response mediation. Also, because you can see both the median and 95th percentile, you can easily identify whether the slowness is occurring in each request or whether it is intermittent.

+

Cache

+

The Cache page shows statistics that indicate the efficiency with which response caching is carried out for the requests sent to your APIs.

+

Cache statistics

+

The page displays the following statistics:

+
    +
  • +

    Cache Hit Percentage

    +

    This graph shows the percentage of requests the system has handled via the response cache over time and the total hits over time. This information allows you to assess how efficiently the backend handles API requests. For example, if the cache hit rate is low, it may indicate that the backend generates the same response each time a specific request is sent instead of returning the response via the cache. In such a scenario, there is scope to improve performance via response caching.

    +

    Cache hit percentage

    +
  • +
  • +

    Latency

    +

    This section shows the total latency reported during the same time interval applied to the Cache Hit Percentage graph above.

    +

    Cache hits and misses

    +
  • +
+

Devices

+

The Devices page displays information about operating systems and HTTP agents that end users use to invoke the APIs. You can use this page to get an idea of the distribution of your user base and improve your APIs to match the audience.

+

Device statistics

+

To filter the information displayed on this page by API, select the required API(s) in the API field. All is selected by default.

+

The information displayed is as follows:

+
    +
  • +

    Top Platforms

    +

    This chart shows the breakdown of the API clients by the operating system. The pie chart only shows platforms with a significant amount of requests. Other platforms are grouped under the Other category.

    +

    Top platforms

    +
  • +
  • +

    Top User Agents

    +

    This chart shows the breakdown of the API clients by user-agent. The pie chart only shows user agents with a significant amount of requests. Other platforms are grouped under the Other category.

    +

    Top user agents

    +
  • +
+

Alerts

+

The Alerts page shows information related to business alerts issued by Choreo for your currently selected environment and organization. You can use this page as a health monitoring dashboard and make it visible to your project team. Using this page you can drill down on each alert and discover possible anomalies in your published APIs. See the topics given below to get details of the available widgets and understand how to use them effectively.

+

Alerts statistics

+

Prerequisites

+

To use this page, be sure to configure alerts and have API invocations that trigger alerts.

+
+

Note

+

Alerts are retained only for a week.

+
+
    +
  • +

    Alert Summary

    +

    This table lists each alert generated during the selected time interval. The message of the alert can be viewed by expanding the arrow icon on the details column. The drop-downs can be used to filter alerts based on the alert type and API.

    +

    Alert summary

    +
  • +
  • +

    Top APIs by Alert Count

    +

    This shows a pie chart and a table to visualize the alert distribution during the selected time interval.

    +

    Top APIs by alert count

    +
  • +
+

Reports

+

The Reports page allows you to download monthly usage reports for your system. There are preconfigured reports with system-wide statistics, and a custom report generator to generate reports based on a subset of APIs/applications.

+

Report page

+

Download custom reports

+

This widget allows you to generate a custom report for the statistics that have been generated up to now and download it.

+

Custom report download

+

To generate a custom report, follow the steps below:

+
    +
  1. +

    In the API field, select one or more APIs for which you want to generate the report. If required, you can select all the APIs by selecting All.

    +
  2. +
  3. +

    If you need to further filter the content printed in the report, select one or more applications in the Application field. By default, all the applications that have subscribed to one or more of the selected APIs are selected.

    +
    +

    Tip

    +

    If you want to filter the report content by the API consumer instead of the application, click on the toggle switch to the right of the Application field, and then select the required consumer. Only consumers who have subscribed to one or more of the selected APIs are displayed in the list. You can either select one or all of them.

    +
    +
  4. +
  5. +

    Select the required year and the month in the Year and Month fields to specify the time interval for which you want to generate the report.

    +
  6. +
  7. +

    Click Download, and select the required format.

    +
  8. +
+

The report is downloaded in the specified format. The following is a sample report generated in PDF format.

+

Sample report

+

The contents of the report are as follows.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
Generated TimeThe date and the time the report was generated.
OrganizationThe organization to which the report applies. Each report always applies to a specific organization.
EnvironmentThe environment to which the report applies. Each report always applies to a specific environment.
TenantThe tenant to which the report applies. Each report always applies to a specific tenant.
Reporting periodThe time interval for which the report is generated.
Total request countThe total request count received by all selected APIs during the report time interval.
+

The table in the report contains the following rows.

+ + + + + + + + + + + + + + + + + + + + + +
ItemDescription
APIThe name of the API.
ApplicationThe name of the application. The name of the subscriber is also provided within brackets.
UsageThe usage count.
+

Download pregenerated reports

+

These widgets allow you to download monthly reports for the last three months.

+

Pre-generated reports

+

To download a pregenerated report, click Download for the relevant month and then click on the required format.

+

Geo Map

+

The Geo Map page allows you to see a geographical representation of your API usage. You can use this page to make business decisions such as identifying growing regions, analyzing the impact of a region-specific marketing campaign, etc.

+

Geo Map page

+

To filter the information displayed on this page by API, select the required API(s) in the API field. The default value is All.

+

This heat map highlights the countries with the appropriate color based on the hit count. It uses a relative color scale to depict the highest hit count to the lowest non-zero hit count.

+

Geo Map Hit Scale

+

Viewing the number of requests by country

+

You can hold the pointer over the highlighted countries to view the country name and the total number of hits from that location. You can also use the mouse to zoom the map or pan it. Optionally, you can download geo-map data in a tabular format using the PDF or CSV download options by clicking download on the top right corner.

+

Geo Map by country

+
+

Note

+
    +
  • Currently, this feature is only available for on-premises environments.
  • +
  • The geo-map page utilizes the IP address of the incoming request to derive the geolocation. The actual source IP address can be replaced if there are intermediate hosts between the client and the gateway node. Therefore, the reverse proxy or the load balancer fronting the gateway node must add the x-forwarded-for header to each request to preserve the source IP address. If you do not configure this correctly, the Geo Map page will not show any data. To test this, you can manually add an x-forwarded-for header to the request.
  • +
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/integrate-choreo-with-moesif/index.html b/monitoring-and-insights/integrate-choreo-with-moesif/index.html new file mode 100644 index 000000000..012326361 --- /dev/null +++ b/monitoring-and-insights/integrate-choreo-with-moesif/index.html @@ -0,0 +1,3655 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Integrate Choreo with Moesif - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Integrate Choreo with Moesif

+

Moesif is an API analytics and monetization service that helps you grow your API products. You can integrate Choreo with Moesif and gain valuable insights into your API's usage. While Moesif's API analytics capabilities empower you to make informed decision-making on behalf of your organization, its monetization options simplify revenue generation from your APIs, eliminating the need for complex coding.

+

In this guide, you will:

+
    +
  • Generate a key in Moesif.
  • +
  • Configure Choreo to connect to Moesif.
  • +
  • Invoke an API and observe the insights on the Moesif dashboard.
  • +
+

Step 1: Generate an API key in Moesif

+

Let's generate an API key in Moesif. +If you're an existing Moesif user with a registered organization, proceed to step 1.2.

+

Step 1.1: Generate a key in Moesif as a new user

+

If you are a new user, follow the steps below to register an organization and generate a key:

+
    +
  1. Go to https://www.moesif.com/.
  2. +
  3. Click Sign Up and select an authentication option and proceed.
  4. +
  5. +

    On the Get Started page, enter meaningful values for the fields and create a new organization.

    + + + + + + + + + + + + + + + + + +
    FieldDescription
    Organization NameThe name of your company or team.
    Application NameThe name of your application that represents one project or environment.
    +
  6. +
  7. +

    Click Next.

    +
  8. +
  9. +

    On the Overview page, click Next.

    +

    This opens the Quick Install page. As there is no data, you cannot proceed. Let's configure Moesif to receive data from Choreo.

    +
  10. +
  11. +

    Select a WSO2 Choreo as the Server Integration

    +
  12. +
  13. +

    Copy the Application Id.

    +

    First Time user API Key

    +
  14. +
+

Step 1.2: Access the API key in Moesif as an existing user

+

If you are an existing user with a registered organization, or you do not have an API key for the organization you created, follow the steps below to access the generated API key:

+
    +
  1. Go to https://www.moesif.com/.
  2. +
  3. Click on your profile in the bottom left corner, and navigate to the API Keys page.
  4. +
  5. Copy the Collection Application Id.
  6. +
+

Step 2: Integrate Choreo with Moesif

+

Let's configure Choreo to publish events to Moesif.

+
    +
  1. Go to https://console.choreo.dev/ and sign in.
  2. +
  3. On the left navigation, click Settings.
  4. +
  5. In the header, click the Organization list. This will open the organization level settings page.
  6. +
  7. Click the API Management tab, and click Moesif Dashboard.
  8. +
  9. Select the environment you want to publish data for.
  10. +
  11. Paste the Application Id you copied.
  12. +
  13. Click Add.
  14. +
+

Once you successfully add the key, you will see a delete option next to it. Currently, you can only configure one API key. If you need to add a new API key, you need to delete the existing key and add the new one.

+
+

Note

+

Once you configure the Moesif API key on Choreo, wait for five minutes before you publish any data to the Moesif API analytics platform.

+
+

Step 3: Invoke an API and observe the data on the Moesif Dashboard

+

You have configured Choreo to publish data to Moesif. Let's see how you can view the insights on Moesif.

+
+

Tip

+ +
+
    +
  1. +

    Invoke your API by following the Test REST Endpoints via the OpenAPI Console guide.

    +
  2. +
  3. +

    Once you publish data, your Moesif dashboard will receive events. Once Moesif receives events, you will see a notification on Moesif confirming that it received data.

    +

    Data Recieved Moesif Notification

    +
  4. +
  5. +

    Click Next on the notification. This will take you to the final step, where you can opt to add team members. In this guide, let's skip this step.

    +
  6. +
  7. Click Finish.
  8. +
+

You can now view your API's insights in the Moesif dashboard.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/logs/view-pdp-logs/index.html b/monitoring-and-insights/logs/view-pdp-logs/index.html new file mode 100644 index 000000000..363900a49 --- /dev/null +++ b/monitoring-and-insights/logs/view-pdp-logs/index.html @@ -0,0 +1,3488 @@ + + + + + + + + + + + + + + + + + + + + + + + + View Private Data Plane (PDP) Logs - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

View Private Data Plane (PDP) Logs

+

Choreo offers the capability to access runtime logs through its console. However, in cases where viewing logs for your PDP is not supported by Choreo yet, you can still view the runtime logs of your components via the log analyzing solution provided by your cloud vendor as a workaround.

+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  1. Go to https://console.choreo.dev/, and sign in using your preferred method.
  2. +
  3. Select your component from Components Listing. This will open the Overview page of your component.
  4. +
  5. In the left navigation menu, click Runtime under DevOps.
  6. +
  7. Copy the Release ID and the Namespace. Save it for later.
  8. +
+

View Private Data Plane (PDP) logs with Azure Log Analytics

+

You can view your PDP logs with Azure Log Analytics by following the steps below:

+
    +
  1. Go to https://portal.azure.com/.
  2. +
  3. Follow the Azure Log Analytics Tutorial and open log analytics of your relative log analytics workspace.
  4. +
  5. Copy and paste the query below into the query editor.
  6. +
  7. Replace the <START_TIME_STAMP EX: 2023-04-10T07:07:31.684Z> and <END_TIME_STAMP EX: 2023-04-21T07:27:31.684Z> values as required. Replace the '' and '' with the values you copied by following the steps in the prerequisites section. Replace the <OPTIONAL SEARCH PHRASE> with your search term, or leave it blank if you don't require any search filtering.
  8. +
  9. Run the query to extract the relevant logs.
  10. +
+
let startDateTime = datetime('<START_TIME_STAMP EX: 2023-04-10T07:07:31.684Z>');
+let endDateTime = datetime('<END_TIME_STAMP EX: 2023-04-21T07:27:31.684Z>');
+let releaseId = '<RELEASE_ID>';
+let namespace = '<NAMESPACE>';
+let searchPhrase = '<OPTIONAL SEARCH PHRASE>';
+let startDateTimeKPI = iff(datetime_diff('second', endDateTime, startDateTime) > 60, startDateTime, endDateTime - 2m);let endDateTimeKPI = iff(datetime_diff('second', endDateTime, startDateTime) > 60, endDateTime, startDateTime + 2m);let filteredLogLevels = dynamic([]);
+let hasNoLevelFilter = array_length(filteredLogLevels) == 0;
+let commonKeys = dynamic(['time', 'level', 'module', 'traceId', 'spanId', 'message']);
+let ContainerIdList = KubePodInventory
+| where TimeGenerated > startDateTimeKPI and TimeGenerated < endDateTimeKPI
+| where Namespace == namespace
+| where extractjson('$.[0].release_id', PodLabel) == releaseId
+| distinct ContainerID;
+let data = ContainerLog
+| where TimeGenerated > startDateTime and TimeGenerated < endDateTime
+| where ContainerID in (ContainerIdList)
+| where searchPhrase == "" or LogEntry contains searchPhrase
+| top 126 by TimeGenerated desc
+| extend logs = parse_json(LogEntry)
+| project TimeGenerated, 
+LogLevel = iif(isempty(logs['level']), iff(LogEntrySource == 'stderr', 'ERROR', 'INFO'), logs['level']), 
+LogEntry = iif(isempty(logs['message']), logs, logs['message']),
+KeyValuePair = bag_remove_keys(logs, commonKeys)
+| where hasNoLevelFilter or LogLevel in (filteredLogLevels);
+let lastTimeStamp = data 
+| top 1 by TimeGenerated asc | project TimeGenerated;
+let trimmedData = data | where TimeGenerated > toscalar(lastTimeStamp)| sort by TimeGenerated desc;
+let selected = iff(toscalar(data | count) == 126, 'trimmedData', 'data');
+let choose = (selector:string){   union   (trimmedData | where selector == 'trimmedData'),    (data | where selector == 'data')};
+choose(selected);
+
+ +

View Private Data Plane (PDP) logs with Amazon CloudWatch

+
    +
  1. Go to https://portal.azure.com/.
  2. +
  3. Follow the AWS Analyzing Log Data documentation and open Log Insights.
  4. +
  5. Select the relevant region and the relevant log group (the log group string has the cluster name and “/application” appended at the end).
  6. +
  7. Select the required time range.
  8. +
  9. Copy the query below and paste it into the query editor.
  10. +
  11. Replace the <RELEASE_ID> with the values you copied by following the steps in the prerequisites section. Replace the <OPTIONAL SEARCH PHRASE> with your search term, or leave it blank if you don't require any search filtering.
  12. +
  13. Run the query to extract the logs.
  14. +
+
fields @timestamp, @message
+| filter kubernetes.labels.release_id == "<RELEASE_ID>"
+| filter @message like "<OPTIONAL SEARCH PHRASE>"
+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/observability-overview/index.html b/monitoring-and-insights/observability-overview/index.html new file mode 100644 index 000000000..c69dcd31e --- /dev/null +++ b/monitoring-and-insights/observability-overview/index.html @@ -0,0 +1,3552 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Observability Overview - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Observability Overview

+

The Choreo observability dashboard provides a comprehensive interface to visualize and monitor the performance of services deployed on Choreo.

+

Dashboard overview

+

The Observability dashboard allows you to:

+
    +
  • Observe the throughput and latencies of requests served over a given period.
  • +
  • Compare metrics side-by-side to facilitate efficient diagnosis.
  • +
  • Observe the diagnostics view generated over a given period.
  • +
  • View logs generated over a specific timeframe.
  • +
+
+

Tip

+

If you are a Choreo private data plane customer and you want to observe your private data plane using New Relic, see Observing Choreo Private Data Planes With New Relic.

+
+

Throughput and latency graphs

+

The throughput graph depicts the throughput of requests per second for a selected timestamp.

+

Throughput and latency graph

+

By default, Choreo renders this graph for the data generated within the past 24 hours. You can change the default time window by selecting the time range and zone from the options bar. To expand the graph, click and drag the cursor over the period you want to drill down.

+

You can view the Choreo service logs in the Logs pane below the throughput and latency graph. Clicking on a graph updates the Logs view to contain the corresponding log entries generated at that time. You can use these logs to identify the reasons for any latency and throughput anomalies you detect using the graph.

+

Diagnostics view

+

The Diagnostics view allows you to simultaneously analyze errors, throughput, latencies, CPU usage, memory usage, and logs for a particular event. This facilitates detailed error detection and analysis.

+

By default, the time range selected for the Throughput & Latency graphs is the same time range used for the Diagnostics view.

+

Each horizontal section of the graph, termed a bin, represents a specific period and comprises:

+
    +
  • Date/Time: Indicates when the log entries began to appear.
  • +
  • Logs: List of log entries and respective log counts within the bin's timeframe, sorted by precedence (error logs followed by info logs). Each bin displays a maximum of five log entries.
  • +
  • Error: The number of HTTP errors that occurred at the selected time.
  • +
  • TP: Throughput of the requests at the selected time (req/s).
  • +
  • Latency: Request latency at the selected time (ms).
  • +
  • CPU: CPU usage at the selected time (millicores).
  • +
  • Memory: Memory usage at the selected time (MiB).
  • +
+

Logs

+

The Logs pane serves as a centralized view to observe logs of the components you deploy on Choreo. This facilitates rigorous troubleshooting and analysis.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/usage-insights/index.html b/monitoring-and-insights/usage-insights/index.html new file mode 100644 index 000000000..7945985b0 --- /dev/null +++ b/monitoring-and-insights/usage-insights/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/monitoring-and-insights/view-api-insights/index.html b/monitoring-and-insights/view-api-insights/index.html new file mode 100644 index 000000000..5edf3ed6e --- /dev/null +++ b/monitoring-and-insights/view-api-insights/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/monitoring-and-insights/view-logs/index.html b/monitoring-and-insights/view-logs/index.html new file mode 100644 index 000000000..5ead0af48 --- /dev/null +++ b/monitoring-and-insights/view-logs/index.html @@ -0,0 +1,3722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + View Logs - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

View Logs

+

The unified log view in Choreo allows you to view runtime and audit logs to gain application and user insights while ensuring data privacy.

+

Choreo provides real-time insights through live logs and allows you to view historical logs for insights into the past. You also have the flexibility to define a required time range to view relevant log entries, where an intuitive scrolling capability facilitates easy viewing of appropriate logs within the selected time frame.

+

The log view also provides advanced filtering capabilities that allow you to efficiently navigate through appropriate logs to expedite troubleshooting in distributed environments.

+
+

Note

All personally identifiable information (PII) gets resolved at the frontend service level, with only relevant UUIDs stored in logs.

+

+
+

Runtime logs

+

Choreo runtime logs provide insights into both project and component-level logs, covering application and gateway logs. These logs streamline the debugging process by centralizing diverse log sources.

+

In Choreo, any organization member can view runtime logs via the runtime logs page. Choreo allows you to apply filters based on parameters such as log level (error, warn, info, debug), log type (application, gateway), and environment (development, staging, production) to simplify the debugging process.

+

To access runtime logs, follow the steps below:

+
    +
  1. Sign in to Choreo.
  2. +
  3. +

    In the left navigation menu, click Observability and then click Runtime Logs. This displays runtime logs for the past 30 days by default.

    +

    To view logs based on a specific time range and other requirements, you can apply the necessary filter criteria.

    +

    Runtime logs

    +
  4. +
+

Understand runtime logs

+

When you view component-level logs on the Runtime Logs page, you will see both application and gateway logs.

+

Application logs

+

Each application log entry displays the following details:

+
    +
  • timestamp: The time when the request is received by the component.
  • +
  • level: Indicates the severity of the log message. Possible values are Debug, Info, Warn, and Error.
  • +
  • componentVersion: The version of the invoked component.
  • +
  • componentVersionId: The identifier of the invoked component’s version.
  • +
  • envName: The environment of the inbound request. For example, Development, Production, etc.
  • +
+

Gateway logs

+

Each gateway log entry displays the following details:

+
    +
  • timestamp: The time when the request is received by the gateway component.
  • +
  • logLine: Contains the following details about the request, including inbound and outbound information from the gateway perspective.
      +
    • Method: The HTTP method of the request.
    • +
    • RequestPath: The path of the inbound request.
    • +
    • ServicePath: The path of the outbound request.
    • +
    • UserAgent: The user-agent header of the request.
    • +
    • CorrelationID: The request identifier of the inbound request. This is useful to track a request.
    • +
    • ServiceHost: The host IP of the backend.
    • +
    • Duration: The time taken for the gateway to serve the request.  
    • +
    +
  • +
  • +

    gatewayCode: Indicates the state of the request from the gateway perspective. Possible values are as follows:

    +
      +
    • BACKEND_RESPONSE: Indicates successful processing of the request by the gateway with a response to the client from the backend application.
    • +
    • CORS_RESPONSE: Denotes a CORS (Cross Origin Resource Sharing) request.
    • +
    • AUTH_FAILURE: Indicates a request failure at the gateway due to authentication or authorization issues, such as an invalid token.
    • +
    • NO_HEALTHY_BACKEND: Indicates a request failure at the gateway due to a non-existent backend.
    • +
    • RATE_LIMITED: Indicates a request failure at the gateway due to surpassing the rate limit enforced within the component.
    • +
    • RESOURCE_NOT_FOUND: Indicates a request failure at the gateway due to the absence of a matching API resource for the inbound request. This can be caused by a mismatch in the HTTP method, path, or host.
    • +
    • BACKEND_TIMEOUT: Indicates a request timeout when calling the backend application from the gateway.
    • +
    • GATEWAY_ERROR: Indicates a request failure due to an erroneous behavior in the gateway.
    • +
    +
    +

    Note

    +

    Occasionally, a request may not fit into any of the above categories. In such instances, the gatewayCode is displayed as UNKNOWN.

    +
    +
  • +
  • +

    statusCode: The HTTP status code returned to the client.

    +
  • +
  • componentVersion: The version of the invoked component.
  • +
  • envName: The environment of the inbound request. For example, Development, Production, etc.
  • +
+

Audit logs

+

Audit logs, also called audit trails, enhance security, ensure compliance, provide operational insights, and help manage risks.

+

In Choreo, an audit log records organization-level user-specific operations performed via the Choreo Console. It also captures the timestamp and the outcome of the action.

+

As of now, Choreo captures the following user-specific operations as audit logs:

+
    +
  • Project creation, update, and deletion.
  • +
  • Component creation, update, and deletion.
  • +
  • Component promotion initiation.
  • +
  • Component version creation.
  • +
  • Component deployment, redeployment, and undeployment initiation for all components other than REST API Proxy components.
  • +
  • Component API access mode update.
  • +
  • Enabling and disabling component auto-deployment on commit.
  • +
  • Component build configuration update.
  • +
  • Component endpoint creation, update, and deletion.
  • +
  • Organization user management.
  • +
  • On-premises key management.
  • +
  • Project-level configuration management.
  • +
+

In Choreo, organization administrators are allowed to view audit logs by default. If other members need to access organization-specific audit logs, the administrator can create a role with the relevant permission and assign it to members. For step-by-step instructions on how to create and assign a role with relevant permission, see Manage audit log access.

+

To view audit logs, follow these steps:

+
    +
  1. Sign in to Choreo.
  2. +
  3. +

    In the Choreo Console, go to the top navigation menu and click Organization.

    +
    +

    Tip

    +

    As of now, you can only view organization-level audit logs.

    +
    +
  4. +
  5. +

    In the left navigation menu, click DevOps and then click Audit Logs. This displays audit logs for the past 30 days by default.

    +

    To view audit logs based on a specific time range and other requirements, you can apply the necessary filter criteria.

    +

    Audit logs

    +
  6. +
+

Audit log retention

+

Choreo retains audit logs for one year and archives them for an additional year. Therefore, the total retention period for audit logs is two years.

+

Manage audit log access

+

Follow the steps given below to create a role with audit log access permission and assign it to organization members who need access to audit logs:

+
+

Note

You must be the organization administrator to perform this action.

+

+
+

Step 1: Create a role with audit log access permission

+
    +
  1. In the Choreo Console, go to the top navigation menu and click Organization.
  2. +
  3. In the left navigation menu, click Settings.
  4. +
  5. On the Organization tab, click Roles and then click + Create Role.
  6. +
  7. +

    Enter a name and description for the role.

    +

    Create role

    +
  8. +
  9. +

    Click Next.

    +
  10. +
  11. +

    In the Create Role dialog, select LOG-MANAGEMENT under Permissions.

    +

    Select log management permission

    +
  12. +
  13. +

    Click Create.

    +
  14. +
+

Step 2: Assign the created role to an organization member

+
    +
  1. On the Organization tab, click Members. This lists the members of the organization with their respective details.
  2. +
  3. +

    Click on a member who needs to have access to audit logs, and then click + Add Role.

    +
    +

    Tip

    +

    If you want to invite one or more members and assign them the audit log viewer role, follow the steps given below:

    +
      +
    1. Click + Invite Member and then click to expand the Roles list.
    2. +
    3. Select the role you created in Step 1.
    4. +
    5. In the Emails field, enter the email addresses of members you want to invite and grant permission to access audit logs.
    6. +
    7. Click Invite. This sends an invitation email to each email address so that the members can accept and obtain access to view audit logs.
    8. +
    +
    +
  4. +
  5. +

    Click to expand the Roles list and select the role you created in Step 1.

    +
  6. +
  7. Click Add. This assigns the selected role to the member.
  8. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/index.html b/monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/index.html new file mode 100644 index 000000000..ac08e1778 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/index.html @@ -0,0 +1,3589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Access the Choreo Insights API - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Access the Choreo Insights API

+

The Usage Insights page in the Choreo Console displays data retrieved from the Insights API exposed over the Internet. However, in some scenarios, you may need to retrieve data from external systems and implement custom dashboards to display the data.

+

Choreo provides a secure and user-friendly approach to accomplish this requirement. Follow the steps given below:

+

Become a member of the Choreo System organization

+
    +
  1. +

    Access the Developer Portal of the Choreo System organization via https://devportal.choreo.dev/choreosystem/applications and sign in using your preferred method.

    +
  2. +
  3. +

    To obtain access to the Choreo System organization, click Request Access.

    +

    Request access

    +
  4. +
+

Create an application and generate keys

+

To create an application and generate keys, follow the steps below:

+
    +
  1. +

    To create a new application in the Choreo System organization, click + Create Application.

    +
  2. +
  3. +

    Enter a name for the application and click Create. This creates the application and takes you to the Overview page.

    +
  4. +
  5. +

    To subscribe to the Insights API via the newly created application, follow the steps below:

    +
      +
    1. In the left navigation menu, click Subscriptions.
    2. +
    3. In the Subscription Management pane, click + Add APIs.
    4. +
    5. Search for Insights and click Add.
    6. +
    +
  6. +
  7. +

    To generate credentials for the application, follow the steps given below:

    +
      +
    1. In the left navigation menu, click Production under Credentials.
    2. +
    3. Click Generate Credentials. Choreo generates tokens and populates the Consumer Key and Consumer Secret fields in the Application Keys pane.
    4. +
    +
  8. +
  9. +

    To specify an appropriate token expiry time for the application, follow the steps given below:

    +
      +
    1. In the Application Keys pane, click to expand Advanced Configurations.
    2. +
    3. +

      Specify an appropriate value in the Application access token expiry time field and click Update.

      +

      Update token expiry time

      +
    4. +
    +
  10. +
  11. +

    Execute the following cURL command to generate an access token:

    +
    curl --location --request POST 'https://sts.choreo.dev/oauth2/token' \
    +--header 'Authorization: Basic <BASE64_ENCODED_CONSUMER_KEY_AND_CONSUMER_SECRET_OF_YOUR_APP_HERE>' \
    +--header 'Content-Type: application/x-www-form-urlencoded' \
    +--data-urlencode 'grant_type=client_credentials' \
    +--data-urlencode 'orgHandle=<YOUR_ORG_HANDLE_HERE>' \
    +--data-urlencode 'scope=apim:api_manage'
    +
    + +
    +

    Info

    +

    To obtain your organization handle, follow the steps given below:

    +
      +
    1. Go to https://console.choreo.dev and sign in using your preferred method.
    2. +
    3. In the Choreo Console, click your username in the top right corner.
    4. +
    5. In the drop-down menu, click Settings.
    6. +
    7. In the Organization pane, click Copy Handle.
    8. +
    +
    +

    You can use the generated token to access the Insights API exposed via https://choreocontrolplane.choreo.dev/93tu/insights/1.0.0/query-api.

    +

    The following is a sample cURL command to invoke the Insights API:

    +
    curl --location --request POST 'https://choreocontrolplane.choreo.dev/93tu/insights/1.0.0/query-api' \
    +--header 'Content-Type: application/json' \
    +--header 'Authorization: Bearer <TOKEN_HERE>' \
    +--data-raw '{"query":"query ($org: OrgFilter!) {listEnvironments(org: $org){id\n name}}","variables":{"org":{"orgId":"<ORG_UUID_HERE>"}}}'
    +
    + +
    +

    Tip

    +
      +
    • When the token expires, you can generate a new token programmatically by making an API call to the token endpoint using the client credentials grant type.
    • +
    • If a token theft occurs, you can revoke the token by making an API call to the revoke endpoint.
    • +
    +

    Endpoints

    +
    +
  12. +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/index.html b/monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/index.html new file mode 100644 index 000000000..76bd17bcd --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/index.html @@ -0,0 +1,9458 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo Insights API - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Insights API

+

The Choreo Insights API is a GraphQL API that allows you to retrieve data from external systems based on specific criteria. This guide describes the operations and schema-defined types you can use to retrieve data via the Choreo Insights API.

+ +

Try out

+

You can try out the Choreo Insights API with your data via GraphQL Explorer.

+
+

Warning

+

The GraphQL Explorer is currently not compatible with the Safari web browser due to a known issue.

+
+

Query

+

The query root of the Choreo Insights GraphQL API.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
listAllAPI[API] + +Fetches all the APIs with the given combination of tenant ID, environment ID, and organization ID. Optionally, you +can configure the provider parameter to further filter the APIs by a specific provider. + +
providerString + +The name of the API provider. + +
dataFilterDataFilter! + +The data filter. + +
listApplications[Application] + +Fetches all the applications with the given combination of tenant ID, environment ID, and organization ID. Optionally, you +can configure the applicationFilter parameter to further filter the applications by a specific application filter. + +
applicationFilterApplicationFilter + +The application filter. + +
dataFilterDataFilter! + +The data filter. + +
listProviders[Provider] + +Fetches all the API providers with the given combination of tenant ID, environment ID, and organization ID. + +
dataFilterDataFilter! + +The data filter. + +
listSubscribers[Subscriber] + +Fetches all the API subscribers with the given combination of tenant ID, environment ID, and organization ID. Optionally, you +can configure the subscriberFilter parameter to further filter the subscribers. + +
subscriberFilterSubscriberFilter + +The subscriber filter. + +
dataFilterDataFilter! + +The data filter. + +
listOrganizations[Organization] + +Fetches all the organizations of a user. + +
listEnvironments[Environment] + +Fetches all the environments of an organization. + +
orgOrgFilter! + +The organization filter. + +
projectIdString + +The project ID by which the results need to be filtered. It is optional to specify a value for this +parameter. Note that providing a project ID with an on-prem key is not allowed. + +
listTenants[String] + +Fetches all the tenants with the given combination of environment ID and organization ID. + +
tenantDataFilterTenantDataFilter! + +The tenant filter. + +
getTotalTrafficInt + +Returns the total traffic during the given time range for the specified combination of tenant ID, environment ID, +and organization ID. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
getTotalErrorsInt + +Returns the total number of errors that occurred during the given time range for the specified combination of tenant +ID, environment ID, and organization ID. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
getOverallLatencyFloat + +Returns the overall response latency (95th percentile value) during the given time range for the specified +combination of tenant ID, environment ID, and organization ID. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
getLatencySummaryLatencySummary + +Returns the response latency value (95th percentile value) for each time granularity within the specified time range +for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +latencySummaryFilter parameter to further filter the results. + +
filterTimeFilter! + +The time filter. + +
latencySummaryFilterLatencySummaryFilter + +The latency summary filter. + +
dataFilterDataFilter! + +The data filter. + +
getSuccessSummarySuccessSummary + +Returns the number of successful (2xx response code) hit count for each time granularity within the specified time +range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +granularity parameter to override the default granularity value. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
granularityString + +The granularity value. + +
getErrorSummaryErrorSummary + +Returns the number of unsuccessful hits (i.e., the total of both 4xx and 5xx response codes) for each time +granularity within the specified time range for the given combination of tenant ID, environment ID, and organization +ID. Optionally, you can configure the granularity parameter to override the default granularity value. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
granularityString + +The granularity value. + +
getErrorsByCategoryErrorsByCategory + +Returns the number of proxy errors (i.e., the total of both 4xx and 5xx response codes) by each error category +for each time granularity within the specified time range for the given combination of tenant ID, environment ID, +and organization ID. Optionally, you can configure the errorsByCategoryFilter parameter to further filter the +results. + +
timeFilterTimeFilter! + +The time filter. + +
errorsByCategoryFilterErrorsByCategoryFilter + +The errors by category filter. + +
dataFilterDataFilter! + +The data filter. + +
getErrorsDetailsDetailsOfErrors + +Returns details of each proxy error (for both 4xx and 5xx response codes) within the specified time range for +the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +errorsDetailsFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
errorsDetailsFilterErrorsDetailsFilter + +The error details filter. + +
dataFilterDataFilter! + +The data filter. + +
getProxyTargetErrorsOverTime[ErrorsByStatusCodeCategory] + +Returns a list of hit counts for proxy and target errors for each time granularity within the specified time range +for the given combination of tenant ID, environment ID, and organization ID. The errors in each proxy and target +result set are grouped as 4xx, 5xx, and total. Optionally, you can configure the errorsByStatusCodeFilter +parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
errorsByStatusCodeFilterErrorsByStatusCodeFilter + +The errors by status code filter. + +
dataFilterDataFilter! + +The data filter. + +
getErrorsByStatusCodeErrorsByStatusCode + +Returns the hit count for each error response code (401, 404, and 500 etc.,) for each API within the specified +time range for the given combination of tenant ID, environment ID, and organization ID. + +
timeFilterTimeFilter! + +The time filter. + +
errorCountByStatusCodeFilterErrorCountByStatusCodeFilter! + +The error count by status code filter. + +
dataFilterDataFilter! + +The data filter. + +
getTotalErrorsByAPITotalError + +Returns the total proxy error hit count for an API across for the given combination of tenant ID, environment ID, +and organization ID. Optionally, you can configure the filter parameter to further filter the results by a given +time range. + +
filterTimeFilter + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
apiIdID! + +The API ID. + +
getAPIUsageOverTime[APIUsageOverTime] + +Returns a list of details related to the usage of each API over time for each time granularity within the specified +time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can +configure the apiUsageOvertimeFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
apiUsageOvertimeFilterAPIUsageOverTimeFilter + +The API usage overtime filter. + +
dataFilterDataFilter! + +The data filter. + +
getAPIUsageByAppOverTimeAPIUsageByAppOverTime + +Returns API usage by each application over time for each time granularity within the specified time range for the +given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +apiUsageOvertimeFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
apiUsageOvertimeFilterAPIUsageOverTimeFilter + +The API usage overtime filter. + +
dataFilterDataFilter! + +The data filter. + +
getAPIUsageByBackendOverTimeAPIUsageByBackendOverTime + +Returns API usage by each backend over time for each time granularity within the specified time range for the given +combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +apiUsageByBackendOverTimeFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
apiUsageByBackendOverTimeFilterAPIUsageByBackendOverTimeFilter + +The API usage by backend overtime filter. + +
dataFilterDataFilter! + +The data filter. + +
getResourceUsageResourceUsages + +Returns API usage by resource within the specified time range for the given combination of tenant ID, environment +ID, and organization ID. Optionally, you can configure the resourceUsageFilter parameter to further filter the +results. + +
timeFilterTimeFilter! + +The time filter. + +
resourceUsageFilterResourceUsageFilter + +The resource usage filter. + +
dataFilterDataFilter! + +The data filter. + +
getTotalTrafficByAPIInt + +Returns the total hit count for an API for the given combination of tenant ID, environment ID, and organization ID. +Optionally, you can configure the filter parameter to further filter the results by a given time range. + +
filterTimeFilter + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
apiIdID! + +The API ID. + +
topSlowestAPIs[SlowAPI] + +Returns a list of top slowest APIs based on the response latency (95th percentile value) within the specified time +range for the given combination of tenant ID, environment ID, and organization ID. + +
filterTimeFilter! + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
limitInt! + +The limit for the slow APIs list. + +
getLatencyAPILatency + +Returns different latency category values (95th percentile values) for a given API over time for each time +granularity within the specified time range for the given combination of tenant ID, environment ID, and organization +ID. + +
timeFilterTimeFilter! + +The time filter. + +
latencyFilterLatencyFilter! + +The latency filter. + +
dataFilterDataFilter! + +The data filter. + +
getOverallLatencyByAPIOverallLatency + +Returns the overall response latency (95th percentile value) for an API for the given combination of tenant ID, +environment ID, and organization ID. Optionally, you can configure the filter parameter to further filter the +results by a given time range. + +
filterTimeFilter + +The time filter. + +
dataFilterDataFilter! + +The data filter. + +
apiIdID! + +The API ID. + +
getCacheHitsAndMissesCacheHits + +Return the total number of response cache hits, misses, and hit percentage for an API over time for each time +granularity within the specified time range for the given combination of tenant ID, environment ID, and +organization ID. + +
timeFilterTimeFilter! + +The time filter. + +
cacheFilterCacheFilter + +The cache filter. + +
dataFilterDataFilter! + +The data filter. + +
getTopPlatforms[Platform] + +Returns a list of top platforms ranked based on the hit count within the specified time range for the given +combination of tenant ID, environment ID, and organization ID. The result list includes the top nine platforms with +the respective hit count, and all the rest of the platforms are labeled as **Other** with the cumulated hit count. +Optionally, you can configure the deviceFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
deviceFilterDeviceFilter + +The device filter. + +
dataFilterDataFilter! + +The data filter. + +
getTopUserAgents[UserAgent] + +Returns a list of top user agents ranked based on the hit count within the specified time range for the given +combination of tenant ID, environment ID, and organization ID. The result list includes the top nine user agents +with the respective hit count, and all the rest of the platforms are labeled as **Other** with the cumulated hit +count. Optionally, you can configure the deviceFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
deviceFilterDeviceFilter + +The device filter. + +
dataFilterDataFilter! + +The data filter. + +
getAPIUsageByGeoLocation[UsageByGeoLocation] + +NOTE: Currently, this operation returns data only for on-premise environments. + +Returns API usage by country within the specified time range for the given combination of tenant ID, environment ID, +and organization ID. Optionally, you can configure the geoLocationFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
geoLocationFilterGeoLocationFilter + +The geolocation filter. + +
dataFilterDataFilter! + +The data filter. + +
getAPIsUsageByApplications[APIUsageByApplication] + +Returns details relating to the usage of each API by application within the specified time range for the given +combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the +apiUsageByAppFilter parameter to further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
apiUsageByAppFilterAPIUsageByAppFilter + +The API usage by app filter. + +
dataFilterDataFilter! + +The data filter. + +
getTopAPIsByAlertCountTopAPIsByAlertCount + +Returns top APIs ranked based on the alert count within the specified time range for the given combination of tenant +ID, environment ID, and organization ID. Optionally, you can configure the topAPIsByAlertCountFilter parameter to +further filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
topAPIsByAlertCountFilterTopAPIsByAlertCountFilter + +The top APIs by alert count filter. + +
dataFilterDataFilter! + +The data filter. + +
getAlertSummaryAlertSummaries + +Returns a summary for each alert within the specified time range for the given combination of tenant ID, +environment ID, and organization ID. Optionally, you can configure the alertSummaryFilter parameter to further +filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
alertSummaryFilterAlertSummaryFilter + +The alert summary filter. + +
dataFilterDataFilter! + +The data filter. + +
getSuccessAPIsUsageByApplications[SuccessAPIUsageByApplication] + +NOTE: This operation can only be invoked via using an on-prem key as the authentication header. + +Returns a list of successful hit counts (i.e., 2xx response codes) within the specified time range for each API, +grouped by each application. Optionally, you can configure the successAPIUsageByAppFilter parameter to further +filter the results. + +
timeFilterTimeFilter! + +The time filter. + +
successAPIUsageByAppFilterSuccessAPIUsageByAppFilter + +The successful API usage by application filter. + +
getSuccessAPIsUsageByApplicationsWithOnPremKey[SuccessAPIUsageByApplication] + +Returns a list of successful hit counts (i.e., 2xx response codes) within the specified time range for each API, +grouped by each application. Optionally, you can configure the successAPIUsageByAppFilter parameter to further +filter the results. + +
onPremKeyString! + +The value of the On-Prem key. + +
timeFilterTimeFilter! + +The time filter. + +
successAPIUsageByAppFilterSuccessAPIUsageByAppFilter + +The successful API usage by application filter. + +
getCustomReportOvertimeCustomReportOvertime + +Returns the summary of hits or latency data as specified for the selected time duration, grouped by time spans. + +
dataFilterDataFilter! + +The data filter. + +
timeFilterTimeFilter! + +The time filter. + +
metricMetric! + +The metric for which data needs to be retrieved. + +
groupByFields[GroupByField]! + +The column/field by which data needs to be retrieved. + +
groupByValues[String]! + +The value used to filter by the groupByField. + +
granularityString! + +The granularity value for which data is retrieved. + +
getCustomReportTopOvertimeCustomReportTopOvertime + +Returns the summary of hits or latency data as specified for the selected time duration, grouped by time spans for +the top N values for the selected groupByField. + +
dataFilterDataFilter! + +The data filter. + +
timeFilterTimeFilter! + +The time filter. + +
metricMetric! + +The metric for which data needs to be retrieved. + +
groupByFields[GroupByField]! + +The column/field by which the data should be grouped. + +
groupByValues[String]! + +The value used to filter by the groupByField. + +
granularityString! + +The granularity value for which data is retrieved. + +
getGroupByValues[[String]] + +Returns a list of value sets by which you can group the data available for the selected groupBy fields. + +
dataFilterDataFilter! + +The data filter. + +
groupByFields[GroupByField]! + +The column/field for which the API needs to retrieve distinct values. + +
groupByValues[String]! + +The value used to filter by the groupByField. + +
+ +

Objects

+

API

+

Represents API details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
idID! + +The ID of the API. + +
nameString! + +The API name. + +
versionString! + +The API version. + +
providerString! + +The API provider name. + +
+ +

APILatency

+

Represents latency values for a single API over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
summary[Latency] + +A list containing latency category values over time. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

APIUsage

+

Represents the API usage for a single timestamp. The timestamp is calculated based on the granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
countInt! + +The API usage count. + +
+ +

APIUsageByApp

+

Represents API usage across APIs by a single application.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
applicationIdID! + +The application ID. + +
applicationNameString! + +The application name. + +
applicationOwnerString! + +The name of the application owner. + +
usage[APIUsage] + +A list containing the APIs usage values. Returns an empty array if no data is available. + +
+ +

APIUsageByAppOverTime

+

Represents API usage across APIs by applications over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[APIUsageByApp] + +A list containing the API usage values across APIs, grouped by the application. Returns an empty array if no data is +available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

APIUsageByApplication

+

Represents a single API usage by a single application.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdString! + +The ID of the API. + +
applicationIdString! + +The Application ID. + +
applicationNameString! + +The application name. + +
applicationOwnerString! + +The name of the application owner. + +
countInt! + +The usage of the API by the application. + +
+ +

APIUsageByBackend

+

Represents API usage across APIs by a single backend.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
backendString! + +The name of the backend. + +
usage[APIUsage] + +A list containing the APIs usage values. Returns an empty array if no data is available. + +
+ +

APIUsageByBackendOverTime

+

Represents API usage across APIs by each backend over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[APIUsageByBackend] + +A list containing the API usage values across APIs by each backend. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

APIUsageOverTime

+

Represents a single API usage over time.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID + +The ID of the API. + +
usage[APIUsage] + +A list containing the API usage values. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

AlertSummaries

+

Represents alert summaries.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[AlertSummary] + +A list containing the alert summary for each alert. Returns an empty array if no data is available. + +
paginationPagination! + +The pagination details. + +
+ +

AlertSummary

+

Represents a summary for an alert.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID! + +The ID of the API. + +
timestampString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
categoryString! + +The alert category. Possible values are LATENCY and TRAFFIC. + +
metricString! + +The alert metric. Possible values are RESPONSE_LATENCY and TOTAL_TRAFFIC. + +
severityString! + +The severity level of the alert. Possible values are LOW, MEDIUM, and HIGH. + +
messageString! + +The alert details. + +
+ +

Application

+

Represents application details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
idID! + +The Application ID. + +
nameString! + +The application name. + +
ownerString! + +The name of the application owner. + +
+ +

CacheHit

+

Represents the response cache hits and misses for a single timestamp. The timestamp is calculated based on the +granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
hitsInt! + +The number of times the response cache was hit. + +
missesInt! + +The number of times the response cache was missed. + +
hitPercentageFloat! + +The response cache hits as a percentage of the sum of hits and misses. + +
+ +

CacheHits

+

Represents the response cache hits and misses over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
summary[CacheHit] + +A list containing cache hits, misses, and the hit percentage over time. Returns an empty array if no data is +available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

CustomReportGroupBy

+

Represents the usage data overtime for the selected parameters of a specific groupByValue.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
groupByValueID! + +The distinct group-by value that is used as an ID. + +
usage[CustomReportUsage] + +A list containing the usage values. This returns an empty array if no data is available. + +
+ +

CustomReportOvertime

+

Represents usage data overtime for the selected parameters.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[CustomReportUsage] + +A list containing the usage values. This returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

CustomReportTopOvertime

+

Represents usage data overtime for the selected parameters grouped by the top N groupByValues.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[CustomReportGroupBy] + +A list containing the usage values grouped by the selected groupByField. This returns an empty array if no data is +available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

CustomReportUsage

+

Represents usage data for a single timestamp in CustomReports.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
valueInt! + +The usage value (Hit Count/ Latency). + +
+ +

DetailsOfErrors

+

Represents error details over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[ErrorDetails]! + +A list containing error details over time. Returns an empty array if no data is available. + +
paginationPagination! + +The pagination details. + +
+ +

Environment

+

Represents an environment.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
idString! + +The environment ID. + +
externalEnvIdString! + +The external environment ID. + +
internalEnvIdString + +The internal environment ID. + +
sandboxEnvIdString + +The sandbox environment ID. + +
nameString! + +The environment name. + +
typeEnvironmentType! + +The environment type. A Choreo environment is labeled as CHOREO, a private Choreo environment is labeled as +CHOREO_PRIVATE, and the on-premise environment is labeled as ON_PREM. + +
+ +

ErrorCountByCategory

+

Represents the number of errors from each category for a single timestamp. The timestamp is calculated according to the +provided granularity value. If you select some categories, the error counts are retrieved only for those categories, +and a null value is shown for the other categories that are not selected.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
authInt + +The count of authorization errors. + +
targetConnectivityInt + +The count of target connectivity errors. + +
throttledInt + +The count of throttling errors. + +
otherInt + +The count of other errors. + +
+ +

ErrorCountByCode

+

Represents the error count for a single error status code.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
statusCodeString! + +The error status code. + +
countInt! + +The error count. + +
+ +

ErrorCountByCodeForAPI

+

Represents the error count for each status code for a single API.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID! + +The ID of the API. + +
errorCountByCode[ErrorCountByCode] + +A list containing the error count for each error status code. Returns an empty array if no data is available. + +
+ +

ErrorDetails

+

Represents details of an error for a single timestamp. The timestamp is calculated according to the granularity value +provided.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID + +The ID of the API. + +
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
applicationIdString + +The Application ID. + +
applicationNameString + +The application name. + +
applicationOwnerString + +The name of the application owner. + +
reasonString! + +The reason for the error. + +
countInt! + +The error count. + +
+ +

ErrorStatusCodeCategoryCounts

+

Represents errors by the main status code (4xx or 5xx) and the total error count.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
_4xxInt + +The number of client errors. + +
_5xxInt + +The number of server errors. + +
totalInt + +The total number of client and server errors. + +
+ +

ErrorSummary

+

Provides the unsuccessful usage (i.e., 4xx and 5xx response codes) summary across all APIs.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
summary[ErrorValue]! + +A list containing unsuccessful usage values. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

ErrorValue

+

Represents the unsuccessful request count (i.e., 4xx and 5xx response codes) for a single timestamp. The timestamp +is calculated based on the granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
errorCountInt + +Represents the error request count. + +
+ +

ErrorsByCategory

+

Represents the errors by category over time.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
errors[ErrorCountByCategory] + +A list containing the error count for each error category over time. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

ErrorsByStatusCode

+

Represents the error counts grouped by status code for each API.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
errors[ErrorCountByCodeForAPI]! + +A list containing the error count for each status code for each API. Returns an empty array if no data is available. + +
paginationPagination! + +Pagination details. + +
+ +

ErrorsByStatusCodeCategory

+

Represents the error category values (grouped as 4xx, 5xx, and total) for both proxy and target errors for a +single timestamp. The timestamp is calculated based on the granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
proxyErrorStatusCodeCategoryCounts + +Represents proxy-related errors categorized as client errors (4xx response codes) or server errors (5xx response +codes), and the total of both categories. + +
targetErrorStatusCodeCategoryCounts + +Represents target-related errors categorized as client errors (4xx response codes) or server errors (5xx +response codes), and the total of both categories. + +
+ +

Latency

+

Represents latency values for each latency category for a single timestamp. The timestamp is calculated based on the +granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
responseInt + +The response latency (95th percentile) in milliseconds (ms). + +
backendInt + +The backend latency (95th percentile) in milliseconds (ms). + +
requestMediationInt + +The request mediation latency (95th percentile) in milliseconds (ms). + +
responseMediationInt + +The response mediation latency (95th percentile) in milliseconds (ms). + +
responseMedianInt + +The median (50th percentile) of the response latency in milliseconds (ms). + +
backendMedianInt + +The median (50th percentile) of the backend latency in milliseconds (ms). + +
requestMediationMedianInt + +The median (50th percentile) of the request mediation latency in milliseconds (ms). + +
responseMediationMedianInt + +The median (50th percentile) of the response mediation latency in milliseconds (ms). + +
+ +

LatencySummary

+

Provides the latency summary.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
summary[LatencyValue]! + +A list containing latency values. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

LatencyValue

+

Represents the latency value for a single timestamp. The timestamp is calculated according to the provided granularity +value.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
latencyTimeFloat! + +Represents the latency (95th percentile) time in milliseconds (ms). + +
+ +

Organization

+

Represents an organization.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
idString! + +The organization ID. + +
uuidID! + +The organization UUID. + +
handleString! + +The organization handle name. + +
nameString! + +The organization name. + +
+ +

OverallLatency

+

Represents the overall latency values.

+ + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
responseFloat + +The response latency (95th percentile value) in milliseconds (ms). + +
+ +

Pagination

+

Represents pagination details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
totalInt! + +The total number of results. + +
limitInt! + +The number of items in the result set. + +
offsetInt! + +The offset value for the result set. + +
sortByString! + +The sorting column name of the result set. + +
sortOrderString! + +The sorting order of the result set. Possible values are asc and desc. + +
+ +

Platform

+

Represents a platform.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
platformString! + +The name of the platform. + +
countInt! + +The usage of the platform. + +
+ +

Provider

+

Represents API Provider details.

+ + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
nameString! + +The API provider name. + +
+ +

ResourceUsage

+

Represents the usage of a single API resource.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID! + +The ID of the API. + +
apiResourceTemplateString! + +The API resource template. + +
apiMethodString! + +The API method. + +
countInt! + +The usage of the API resource. + +
+ +

ResourceUsages

+

Represents API resource usages.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[ResourceUsage] + +A list with the usage of each API resource. Returns an empty array if no data is available. + +
paginationPagination! + +Pagination details. + +
+ +

SlowAPI

+

A slow API identified based on the response latency (95th percentile).

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID! + +The ID of the API. + +
latencyInt! + +Represents the latency (95th percentile) time in milliseconds (ms). + +
+ +

Subscriber

+

Represents API Subscriber details.

+ + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
nameString! + +The name of the API subscriber. + +
+ +

SuccessAPIUsageByApplication

+

Represents successful usages(that have resulted in the 2xx response code) of an API by an application.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdString! + +The ID of the API. + +
apiNameString! + +The name of the API. + +
apiVersionString! + +The version of the API. + +
apiCreatorTenantDomainString! + +The tenant domain of the API creator. + +
applicationIdString! + +The application ID. + +
applicationNameString! + +The name of the application. + +
applicationOwnerString! + +The name of the application owner. + +
countInt!
+ +

SuccessSummary

+

Provides the successful (2xx response code) usage summary across all the APIs.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
summary[SuccessValue]! + +A list containing successful usage values. Returns an empty array if no data is available. + +
granularityString! + +The granularity value for which data is retrieved. + +
+ +

SuccessValue

+

Represents the successful request count (i.e., requests that have received the 2xx response code) for a single +timestamp. The timestamp is calculated according to the granularity value provided.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
timeSpanString! + +Represents a timestamp value that is calculated based on the specified granularity value. For example, if the +granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone +provided in the time filter. +e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' + +
requestCountInt! + +Represents the successful request count. + +
+ +

TopAPIByAlertCount

+

Represents a top API by alert count.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
apiIdID! + +The ID of the API. + +
countInt! + +The alert count. + +
+ +

TopAPIsByAlertCount

+

Represents the top APIs by alert count.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
usage[TopAPIByAlertCount] + +A list containing top APIs by alert count. Returns an empty array if no data is available. + +
paginationPagination! + +The pagination details. + +
+ +

TotalError

+

Represents the total errors.

+ + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
proxyInt + +The proxy-related error count. + +
+ +

UsageByGeoLocation

+

Represents the usage of a single API in a single country.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
countryString! + +The name of the country. + +
countInt! + +The usage of the API. + +
+ +

UserAgent

+

Represents a user agent.

+ + + + + + + + + + + + + + + + + + + + + +
FieldArgumentTypeDescription
userAgentString! + +The name of the user agent. + +
countInt! + +The usage of the user agent. + +
+ +

Inputs

+

APIUsageByAppFilter

+

Filters the API usage by application results.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
appIds[String] + +The results are filtered for the list of applications you specify here. A maximum of five application IDs can be +defined. + +
subscribers[String] + +The results are filtered for the list of subscribers you specify here. A maximum of five subscriber IDs can be +defined. + +
+ +

APIUsageByBackendOverTimeFilter

+

Filters the results for API usage by backend over time.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

APIUsageOverTimeFilter

+

Filters the results for API usage over time.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
appIds[String] + +The results are filtered for the list of applications you specify here. A maximum of five application IDs can be +defined. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

AlertSummaryFilter

+

Filters the alerts summary results.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
paginationFilterPaginationFilter + +The pagination filter. + +
searchFilterSearchFilter + +The search filter. + +
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
categoryString + +The alert category by which the results need to be filtered. The available categories to select are TRAFFIC and +LATENCY. + +
+ +

ApplicationFilter

+

Filters applications by the application owner and API IDs.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
ownerString
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
+ +

CacheFilter

+

Filters response cache results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The results are filtered by the API ID specified here. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

DataFilter

+

Filters results by the given combination of organization, environment, and tenant.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
orgIdString! + +The organization by which the results need to be filtered. It is required to specify a value for this parameter. + +
environmentIdString + +The environment ID by which the results need to be filtered. It is required to specify a value for this parameter. + +
environmentIds[String] + +The environment IDs by which the results need to be filtered. It is required to specify a value for this parameter. + +
tenantString! + +The name of the tenant by which the results need to be filtered. It is required to specify a value for this +parameter. + +
projectIdString + +The project ID by which the results need to be filtered. It is optional to specify a value for this +parameter. Note that providing a project ID with an on-prem key is not allowed. + +
+ +

DeviceFilter

+

Filters results related to devices.

+ + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
+ +

ErrorCountByStatusCodeFilter

+

Filters errors by status code results.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The results are filtered by the API ID specified here. + +
errorTypeErrorType! + +The type of the error. It is required to specify a value for this parameter. + +
errorCodeTypeErrorCodeType + +The error code type. If this parameter is not configured, both client-related error response codes (401, 404, +etc.) and server-related response codes (500, 501, etc.) are included in the result set. + +
paginationFilterPaginationFilter + +The pagination filter. + +
+ +

ErrorsByCategoryFilter

+

Filters errors by category results.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The ID of the API. + +
categories[String] + +The list of categories by which the results need to be filtered. Category values that you can specify here are +AUTH, TARGET_CONNECTIVITY, THROTTLED, and OTHER. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

ErrorsByStatusCodeFilter

+

Filters errors by status code results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The results are filtered by the API ID specified here. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

ErrorsDetailsFilter

+

Filters the results for error details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The results are filtered by the API ID specified here. + +
appIdString + +The application ID by which the results need to be filtered. + +
categoryString + +The error category by which the results need to be filtered. The error category that you can specify here must be +one of the AUTH TARGET_CONNECTIVITY, THROTTLED, and OTHER values. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
paginationFilterPaginationFilter + +The pagination filter. + +
searchFilterSearchFilter + +The search filter. + +
+ +

GeoLocationFilter

+

Filters the API usage by geolocation results.

+ + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. + +
+ +

LatencyFilter

+

Filters latency results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString! + +The results are filtered by the API ID specified here. It is required to specify a value for this parameter. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

LatencySummaryFilter

+

Filters latency summary results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIdString + +The results are filtered by the API ID specified here. + +
granularityString + +The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity +for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, +1d, and 7d. + +
+ +

OrgFilter

+

Filters results for the given organization.

+ + + + + + + + + + + + + + + +
FieldTypeDescription
orgIdString! + +The ID of the organization by which the results need to be filtered. It is required to specify a value for this +parameter. + +
+ +

PaginationFilter

+

Filters related to pagination.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
limitInt + +The total number of rows in the result set. This value must be a positive integer. If this limit value is not set, +the total number of rows is five by default. + +
offsetInt + +The offset value to set when filtering results. This value must be zero or a positive integer. If you do not specify +an offset value, the default offset value (i.e., 0) applies. + +
sortByString + +The column name by which the results are sorted. If the sortBy value is not set, the default column of the related +operation that is available for sorting purposes is used. + +
sortOrderString + +The order in which the results are sorted. Possible values are asc (to sort in ascending order) and desc (to +sort in descending order). If no value is specified, the results are sorted in ascending order by default (except +for count-specific operations such as getTopAPIsByAlertCount where the results are always sorted in descending +order). + +
+ +

ResourceUsageFilter

+

Filters resource usage results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
paginationFilterPaginationFilter + +The pagination filter. + +
searchFilterSearchFilter + +The search filter. + +
+ +

SearchFilter

+

Filters results by searching matching results for the provided search text.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The list of API IDs that need to be searched with the given search text. Note that it is not possible to define API +IDs without a search text in the search filter. + +
searchTextString! + +Text which needs to be searched among the results. It is required to specify a value for this parameter. + +
+ +

SubscriberFilter

+

Filters the subscriber results.

+ + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. + +
+ +

SuccessAPIUsageByAppFilter

+

Filters successful API usage by application results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
apiIds[String] + +The list of API IDs by which the results need to be filtered. + +
tenantDomains[String] + +The tenant domain name by which the results need to be filtered. + +
+ +

TenantDataFilter

+

Filters results by the tenant.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
orgIdString! + +The ID of the organization by which the results need to be filtered. It is required to specify a value for this +parameter. + +
envIdString + +The ID of the environment by which the results need to be filtered. It is required to specify a value for this +parameter. + +
environmentIds[String] + +The environment IDs by which the results need to be filtered. It is required to specify a value for this parameter. + +
+ +

TimeFilter

+

Filters results by the provided date range.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
fromString! + +The start date of the time range. The date specified here must be a date earlier than the date specified via the +to parameter. If the defined date and time entry do not have a timezone, the UTC time zone (z) is used. It is +required to specify a value for this parameter. +e.g., '2021-08-16T12:00:00.000+05:30'. + +
toString! + +The end date of the time range. The date specified here must be a date later than the date specified via the from +parameter. If the defined date and time entry do not have a timezone, the UTC time zone (z) is used. It is +required to specify a value for this parameter. +e.g., '2021-08-16T12:30:00.000+05:30'. + +
+ +

TopAPIsByAlertCountFilter

+

Filters the top APIs by alert count results.

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
paginationFilterPaginationFilter + +The pagination filter. + +
searchFilterSearchFilter + +The search filter. + +
+ +

Enums

+

EnvironmentType

+

Represents an error type.

+ + + + + + + + + + + + + + + + + + + +
ValueDescription
CHOREO + +The Choreo environments. + +
CHOREO_PRIVATE + +The private data-plane Choreo environments. + +
ON_PREM + +The On-Premise environments. + +
+ +

ErrorCodeType

+

Represents an error code type.

+ + + + + + + + + + + + + + + +
ValueDescription
_4XX + +The client-side errors. + +
_5XX + +The server-side errors. + +
+ +

ErrorType

+

Represents an error type.

+ + + + + + + + + + + + + + + +
ValueDescription
PROXY + +The proxy-related errors. + +
TARGET + +The target-related errors. + +
+ +

GroupByField

+

Represents an groupByField used in CustomReports.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
API_NAME + +The API name. + +
API_VERSION + +The API version. + +
API_RESOURCE_TEMPLATE + +The API resource template. + +
API_METHOD + +The API method. + +
API_CREATOR + +The API creator. + +
APPLICATION_NAME + +The name of the application. + +
APPLICATION_OWNER + +The owner of the application. + +
DESTINATION + +The destination. + +
USER_AGENT + +The user Agent. + +
PLATFORM + +The platform. + +
TARGET_RESPONSE_CODE + +The target response code. + +
+ +

Metric

+

Represents a metric used in CustomReports.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
HIT_COUNT + +The number of API calls. + +
RESPONSE_CACHE_HIT + +The number of API calls that used the response cache. + +
REQUEST_MEDIATION_LATENCY + +The request mediation latency. + +
RESPONSE_MEDIATION_LATENCY + +The response mediation latency. + +
BACKEND_LATENCY + +The backend latency. + +
TOTAL_LATENCY + +The total latency. + +
API_ERRORS + +The number of hits for which API errors are returned. + +
TARGET_ERRORS + +The number of hits for which target errors are returned. + +
+ +

Scalars

+

Boolean

+

The Boolean scalar type represents true or false.

+

Float

+

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

+

ID

+

The ID scalar type represents a unique identifier, often used to re-fetch an object or as the key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value is accepted as an ID.

+

Int

+

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.

+

String

+

The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/asset-manifest.json b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/asset-manifest.json new file mode 100644 index 000000000..103619fe6 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/asset-manifest.json @@ -0,0 +1,25 @@ +{ + "files": { + "main.css": "./static/css/main.dd389ba7.chunk.css", + "main.js": "./static/js/main.78fb288a.chunk.js", + "main.js.map": "./static/js/main.78fb288a.chunk.js.map", + "runtime-main.js": "./static/js/runtime-main.8245b2d9.js", + "runtime-main.js.map": "./static/js/runtime-main.8245b2d9.js.map", + "static/css/2.dff3c244.chunk.css": "./static/css/2.dff3c244.chunk.css", + "static/js/2.e5757962.chunk.js": "./static/js/2.e5757962.chunk.js", + "static/js/2.e5757962.chunk.js.map": "./static/js/2.e5757962.chunk.js.map", + "index.html": "./index.html", + "static/css/2.dff3c244.chunk.css.map": "./static/css/2.dff3c244.chunk.css.map", + "static/css/main.dd389ba7.chunk.css.map": "./static/css/main.dd389ba7.chunk.css.map", + "static/js/2.e5757962.chunk.js.LICENSE.txt": "./static/js/2.e5757962.chunk.js.LICENSE.txt", + "static/media/index.css": "./static/media/gilmer-regular.dadefd19.eot", + "static/media/logout.ab831324.svg": "./static/media/logout.ab831324.svg" + }, + "entrypoints": [ + "static/js/runtime-main.8245b2d9.js", + "static/css/2.dff3c244.chunk.css", + "static/js/2.e5757962.chunk.js", + "static/css/main.dd389ba7.chunk.css", + "static/js/main.78fb288a.chunk.js" + ] +} \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/favicon.ico b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/favicon.ico new file mode 100644 index 000000000..0b5e9a76a Binary files /dev/null and b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/favicon.ico differ diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/index.html b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/index.html new file mode 100644 index 000000000..2cfa2a288 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/index.html @@ -0,0 +1,79 @@ + + + + + + + + + + Choreo Analytics API GraphiQL Client + + + + + +
+ + + + + diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/insight.config.js b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/insight.config.js new file mode 100644 index 000000000..5ece3345f --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/insight.config.js @@ -0,0 +1,24 @@ +window.__RUNTIME_CONFIG__ = { + ASGARDEO_CONFIG: { + endpoints: { + authorizationEndpoint: 'https://api.asgardeo.io/t/a/oauth2/authorize', + tokenEndpoint: 'https://api.asgardeo.io/t/a/oauth2/token', + endSessionEndpoint: 'https://api.asgardeo.io/t/a/oidc/logout' + }, + signInRedirectURL: 'https://wso2.com/choreo/docs/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/', + signOutRedirectURL: 'https://wso2.com/choreo/docs/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/', + clientID: 'BDXalD9exTskS5bt7xYfIK5TsnIa' + }, + TOKEN_EXCHANGE_CONFIG: { + tokenEndpoint: 'https://sts.choreo.dev:443/oauth2/token', + data: { + client_id: 'hNq2_2JV9d44DgT7Wv1OHBLTO1sa', + grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', + subject_token_type: 'urn:ietf:params:oauth:token-type:jwt', + requested_token_type: 'urn:ietf:params:oauth:token-type:jwt', + scope: 'apim:admin' + } + }, + INSIGHTS_API_URL: 'https://choreocontrolplane.choreo.dev/93tu/insights/1.0.0/query-api', + VALIDATE_USER_ENDPOINT: 'https://apis.choreo.dev/user-mgt/1.0.0/validate/user' +} diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/manifest.json b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/manifest.json new file mode 100644 index 000000000..c4d5327d9 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "Choreo Insights API", + "name": "Choreo Insights API", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css new file mode 100644 index 000000000..8a4b7fac9 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css @@ -0,0 +1,2 @@ +.graphiql-container,.graphiql-container button,.graphiql-container input{color:#141823;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:14px}.graphiql-container{display:flex;flex-direction:row;height:100%;margin:0;overflow:hidden;width:100%}.graphiql-container .editorWrap{display:flex;flex-direction:column;flex:1 1;overflow-x:hidden}.graphiql-container .title{font-size:18px}.graphiql-container .title em{font-family:georgia;font-size:19px}.graphiql-container .topBarWrap{display:flex;flex-direction:row}.graphiql-container .topBar{align-items:center;background:linear-gradient(#f7f7f7,#e2e2e2);border-bottom:1px solid #d0d0d0;cursor:default;display:flex;flex-direction:row;flex:1 1;height:34px;overflow-y:visible;padding:7px 14px 6px;-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .toolbar{overflow-x:visible;display:flex}.graphiql-container .docExplorerShow,.graphiql-container .historyShow{background:linear-gradient(#f7f7f7,#e2e2e2);border-radius:0;border-bottom:1px solid #d0d0d0;border-right:none;border-top:none;color:#3b5998;cursor:pointer;font-size:14px;margin:0;padding:2px 20px 0 18px}.graphiql-container .docExplorerShow{border-left:1px solid rgba(0,0,0,.2)}.graphiql-container .historyShow{border-right:1px solid rgba(0,0,0,.2);border-left:0}.graphiql-container .docExplorerShow:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:"";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:9px}.graphiql-container .editorBar{display:flex;flex-direction:row;flex:1 1}.graphiql-container .queryWrap,.graphiql-container .resultWrap{display:flex;flex-direction:column;flex:1 1}.graphiql-container .resultWrap{border-left:1px solid #e0e0e0;flex-basis:1em;position:relative}.graphiql-container .docExplorerWrap,.graphiql-container .historyPaneWrap{background:#fff;box-shadow:0 0 8px rgba(0,0,0,.15);position:relative;z-index:3}.graphiql-container .historyPaneWrap{min-width:230px;z-index:5}.graphiql-container .docExplorerResizer{cursor:col-resize;height:100%;left:-5px;position:absolute;top:0;width:10px;z-index:10}.graphiql-container .docExplorerHide{cursor:pointer;font-size:18px;margin:-7px -8px -6px 0;padding:18px 16px 15px 12px;background:0;border:0;line-height:14px}.graphiql-container div .query-editor{flex:1 1;position:relative}.graphiql-container .secondary-editor{display:flex;flex-direction:column;height:30px;position:relative}.graphiql-container .secondary-editor-title{background:#eee;border-bottom:1px solid #d6d6d6;border-top:1px solid #e0e0e0;color:#777;-webkit-font-feature-settings:"smcp";font-feature-settings:"smcp";font-variant:small-caps;font-weight:700;letter-spacing:1px;line-height:14px;padding:6px 0 8px 43px;text-transform:lowercase;-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .codemirrorWrap,.graphiql-container .result-window{flex:1 1;height:100%;position:relative}.graphiql-container .footer{background:#f6f7f8;border-left:1px solid #e0e0e0;border-top:1px solid #e0e0e0;margin-left:12px;position:relative}.graphiql-container .footer:before{background:#eee;bottom:0;content:" ";left:-13px;position:absolute;top:-1px;width:12px}.result-window .CodeMirror{background:#f6f7f8}.graphiql-container .result-window .CodeMirror-gutters{background-color:#eee;border-color:#e0e0e0;cursor:col-resize}.graphiql-container .result-window .CodeMirror-foldgutter,.graphiql-container .result-window .CodeMirror-foldgutter-folded:after,.graphiql-container .result-window .CodeMirror-foldgutter-open:after{padding-left:3px}.graphiql-container .toolbar-button{background:#fdfdfd;background:linear-gradient(#f9f9f9,#ececec);border:0;border-radius:3px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.2),0 1px 0 hsla(0,0%,100%,.7),inset 0 1px #fff;color:#555;cursor:pointer;display:inline-block;margin:0 5px;padding:3px 11px 5px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;max-width:150px}.graphiql-container .toolbar-button:active{background:linear-gradient(#ececec,#d5d5d5);box-shadow:0 1px 0 hsla(0,0%,100%,.7),inset 0 0 0 1px rgba(0,0,0,.1),inset 0 1px 1px 1px rgba(0,0,0,.12),inset 0 0 5px rgba(0,0,0,.1)}.graphiql-container .toolbar-button.error{background:linear-gradient(#fdf3f3,#e6d6d7);color:#b00}.graphiql-container .toolbar-button-group{margin:0 5px;white-space:nowrap}.graphiql-container .toolbar-button-group>*{margin:0}.graphiql-container .toolbar-button-group>:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.graphiql-container .toolbar-button-group>:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-1px}.graphiql-container .execute-button-wrap{height:34px;margin:0 14px 0 28px;position:relative}.graphiql-container .execute-button{background:linear-gradient(#fdfdfd,#d2d3d6);border-radius:17px;border:1px solid rgba(0,0,0,.25);box-shadow:0 1px 0 #fff;cursor:pointer;fill:#444;height:34px;margin:0;padding:0;width:34px}.graphiql-container .execute-button svg{pointer-events:none}.graphiql-container .execute-button:active{background:linear-gradient(#e6e6e6,#c3c3c3);box-shadow:0 1px 0 #fff,inset 0 0 2px rgba(0,0,0,.2),inset 0 0 6px rgba(0,0,0,.1)}.graphiql-container .toolbar-menu,.graphiql-container .toolbar-select{position:relative}.graphiql-container .execute-options,.graphiql-container .toolbar-menu-items,.graphiql-container .toolbar-select-options{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 2px 4px rgba(0,0,0,.25);margin:0;padding:6px 0;position:absolute;z-index:100}.graphiql-container .execute-options{min-width:100px;top:37px;left:-1px}.graphiql-container .toolbar-menu-items{left:1px;margin-top:-1px;min-width:110%;top:100%;visibility:hidden}.graphiql-container .toolbar-menu-items.open{visibility:visible}.graphiql-container .toolbar-select-options{left:0;min-width:100%;top:-5px;visibility:hidden}.graphiql-container .toolbar-select-options.open{visibility:visible}.graphiql-container .execute-options>li,.graphiql-container .toolbar-menu-items>li,.graphiql-container .toolbar-select-options>li{cursor:pointer;display:block;margin:none;max-width:300px;overflow:hidden;padding:2px 20px 4px 11px;white-space:nowrap}.graphiql-container .execute-options>li.selected,.graphiql-container .history-contents>li:active,.graphiql-container .history-contents>li:hover,.graphiql-container .toolbar-menu-items>li.hover,.graphiql-container .toolbar-menu-items>li:active,.graphiql-container .toolbar-menu-items>li:hover,.graphiql-container .toolbar-select-options>li.hover,.graphiql-container .toolbar-select-options>li:active,.graphiql-container .toolbar-select-options>li:hover{background:#e10098;color:#fff}.graphiql-container .toolbar-select-options>li>svg{display:inline;fill:#666;margin:0 -6px 0 6px;pointer-events:none;vertical-align:middle}.graphiql-container .toolbar-select-options>li.hover>svg,.graphiql-container .toolbar-select-options>li:active>svg,.graphiql-container .toolbar-select-options>li:hover>svg{fill:#fff}.graphiql-container .CodeMirror-scroll{overflow-scrolling:touch}.graphiql-container .CodeMirror{color:#141823;font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;height:100%;left:0;position:absolute;top:0;width:100%}.graphiql-container .CodeMirror-lines{padding:20px 0}.CodeMirror-hint-information .content{box-orient:vertical;color:#141823;display:flex;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-clamp:3;line-height:16px;max-height:48px;overflow:hidden;text-overflow:-o-ellipsis-lastline}.CodeMirror-hint-information .content p:first-child{margin-top:0}.CodeMirror-hint-information .content p:last-child{margin-bottom:0}.CodeMirror-hint-information .infoType{color:#ca9800;cursor:pointer;display:inline;margin-right:.5em}.autoInsertedLeaf.cm-property{-webkit-animation-duration:6s;animation-duration:6s;-webkit-animation-name:insertionFade;animation-name:insertionFade;border-bottom:2px solid hsla(0,0%,100%,0);border-radius:2px;margin:-2px -4px -1px;padding:2px 4px 1px}@-webkit-keyframes insertionFade{0%,to{background:hsla(0,0%,100%,0);border-color:hsla(0,0%,100%,0)}15%,85%{background:#fbffc9;border-color:#f0f3c0}}@keyframes insertionFade{0%,to{background:hsla(0,0%,100%,0);border-color:hsla(0,0%,100%,0)}15%,85%{background:#fbffc9;border-color:#f0f3c0}}div.CodeMirror-lint-tooltip{background-color:#fff;border-radius:2px;border:0;color:#141823;box-shadow:0 1px 3px rgba(0,0,0,.45);font-size:13px;line-height:16px;max-width:430px;opacity:0;padding:8px 10px;transition:opacity .15s;white-space:pre-wrap}div.CodeMirror-lint-tooltip>*{padding-left:23px}div.CodeMirror-lint-tooltip>*+*{margin-top:12px}.graphiql-container .CodeMirror-foldmarker{border-radius:4px;background:#08f;background:linear-gradient(#43a8ff,#0f83e8);box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 0 0 1px rgba(0,0,0,.1);color:#fff;font-family:arial;font-size:12px;line-height:0;margin:0 3px;padding:0 4px 1px;text-shadow:0 -1px rgba(0,0,0,.1)}.graphiql-container div.CodeMirror span.CodeMirror-matchingbracket{color:#555;text-decoration:underline}.graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket{color:red}.cm-comment{color:#999}.cm-punctuation{color:#555}.cm-keyword{color:#b11a04}.cm-def{color:#d2054e}.cm-property{color:#1f61a0}.cm-qualifier{color:#1c92a9}.cm-attribute{color:#8b2bb9}.cm-number{color:#2882f9}.cm-string{color:#d64292}.cm-builtin{color:#d47509}.cm-string-2{color:#0b7fc7}.cm-variable{color:#397d13}.cm-meta{color:#b33086}.cm-atom{color:#ca9800}.CodeMirror{color:#000;font-family:monospace;height:300px}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{color:#999;min-width:20px;padding:0 3px 0 5px;text-align:right;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror .CodeMirror-cursor{border-left:1px solid #000}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-fat-cursor div.CodeMirror-cursor{background:#7e7;border:0;width:auto}.CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{-webkit-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;border:0;width:auto}@-webkit-keyframes blink{0%{background:#7e7}50%{background:none}to{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:none}to{background:#7e7}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{background:#fff;overflow:hidden;position:relative}.CodeMirror-scroll{height:100%;margin-bottom:-30px;margin-right:-30px;outline:none;overflow:scroll!important;padding-bottom:30px;position:relative}.CodeMirror-sizer{border-right:30px solid transparent;position:relative}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{display:none;position:absolute;z-index:6}.CodeMirror-vscrollbar{overflow-x:hidden;overflow-y:scroll;right:0;top:0}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-x:scroll;overflow-y:hidden}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{min-height:100%;position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{display:inline-block;height:100%;margin-bottom:-30px;vertical-align:top;white-space:normal;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{background:none!important;border:none!important;position:absolute;z-index:4}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{cursor:default;position:absolute;z-index:4}.CodeMirror-gutter-wrapper{-webkit-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-webkit-tap-highlight-color:transparent;background:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;-webkit-font-feature-settings:none;font-feature-settings:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;line-height:inherit;margin:0;overflow:visible;position:relative;white-space:pre;word-wrap:normal;z-index:2}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{overflow:auto;position:relative;z-index:2}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{box-sizing:content-box}.CodeMirror-measure{height:0;overflow:hidden;position:absolute;visibility:hidden;width:100%}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{position:relative;visibility:hidden;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}.CodeMirror-dialog{background:inherit;color:inherit;left:0;right:0;overflow:hidden;padding:.1em .8em;position:absolute;z-index:15}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{background:transparent;border:1px solid #d3d6db;color:inherit;font-family:monospace;outline:none;width:20em}.CodeMirror-dialog button{font-size:70%}.CodeMirror-foldmarker{color:#00f;cursor:pointer;font-family:arial;line-height:.3;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-folded,.CodeMirror-foldgutter-open{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25BE"}.CodeMirror-foldgutter-folded:after{content:"\25B8"}.CodeMirror-info{background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.45);box-sizing:border-box;color:#555;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin:8px -8px;max-width:400px;opacity:0;overflow:hidden;padding:8px;position:fixed;transition:opacity .15s;z-index:50}.CodeMirror-info :first-child{margin-top:0}.CodeMirror-info :last-child{margin-bottom:0}.CodeMirror-info p{margin:1em 0}.CodeMirror-info .info-description{color:#777;line-height:16px;margin-top:1em;max-height:80px;overflow:hidden}.CodeMirror-info .info-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px -8px;max-height:80px;overflow:hidden;padding:8px}.CodeMirror-info .info-deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-info .info-deprecation-label+*{margin-top:0}.CodeMirror-info a{text-decoration:none}.CodeMirror-info a:hover{text-decoration:underline}.CodeMirror-info .type-name{color:#ca9800}.CodeMirror-info .field-name{color:#1f61a0}.CodeMirror-info .enum-value{color:#0b7fc7}.CodeMirror-info .arg-name{color:#8b2bb9}.CodeMirror-info .directive-name{color:#b33086}.CodeMirror-jump-token{text-decoration:underline;cursor:pointer}.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:infobackground;border-radius:4px 4px 4px 4px;border:1px solid #000;color:infotext;font-family:monospace;font-size:10pt;max-width:600px;opacity:0;overflow:hidden;padding:2px 5px;position:fixed;transition:opacity .4s;white-space:pre-wrap;z-index:100}.CodeMirror-lint-mark-error,.CodeMirror-lint-mark-warning{background-position:0 100%;background-repeat:repeat-x}.CodeMirror-lint-mark-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")}.CodeMirror-lint-mark-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=")}.CodeMirror-lint-marker-error,.CodeMirror-lint-marker-warning{background-position:50%;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:16px}.CodeMirror-lint-message-error,.CodeMirror-lint-message-warning{background-position:0 0;background-repeat:no-repeat;padding-left:18px}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=")}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=")}.CodeMirror-lint-marker-multiple{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");background-position:100% 100%;background-repeat:no-repeat;width:100%;height:100%}.graphiql-container .spinner-container{height:36px;left:50%;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:36px;z-index:10}.graphiql-container .spinner{-webkit-animation:rotation .6s linear infinite;animation:rotation .6s linear infinite;border-radius:100%;border:6px solid hsla(0,0%,58.8%,.15);border-top-color:hsla(0,0%,58.8%,.8);display:inline-block;height:24px;position:absolute;vertical-align:middle;width:24px}@-webkit-keyframes rotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes rotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.CodeMirror-hints{background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.45);font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;list-style:none;margin:0;max-height:14.5em;overflow:hidden;overflow-y:auto;padding:0;position:absolute;z-index:10}.CodeMirror-hint{border-top:1px solid #f7f7f7;color:#141823;cursor:pointer;margin:0;max-width:300px;overflow:hidden;padding:2px 6px;white-space:pre}li.CodeMirror-hint-active{background-color:#08f;border-top-color:#fff;color:#fff}.CodeMirror-hint-information{border-top:1px solid silver;max-width:300px;padding:4px 6px;position:relative;z-index:1}.CodeMirror-hint-information:first-child{border-bottom:1px solid silver;border-top:none;margin-bottom:-1px}.CodeMirror-hint-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin-top:4px;max-height:80px;overflow:hidden;padding:6px}.CodeMirror-hint-deprecation .deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-hint-deprecation .deprecation-label+*{margin-top:0}.CodeMirror-hint-deprecation :last-child{margin-bottom:0}.graphiql-container .doc-explorer{background:#fff}.graphiql-container .doc-explorer-title-bar,.graphiql-container .history-title-bar{cursor:default;display:flex;height:34px;line-height:14px;padding:8px 8px 5px;position:relative;-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-explorer-title,.graphiql-container .history-title{flex:1 1;font-weight:700;overflow-x:hidden;padding:10px 0 10px 10px;text-align:center;text-overflow:ellipsis;-webkit-user-select:text;-ms-user-select:text;user-select:text;white-space:nowrap}.graphiql-container .doc-explorer-back{color:#3b5998;cursor:pointer;margin:-7px 0 -6px -8px;overflow-x:hidden;padding:17px 12px 16px 16px;text-overflow:ellipsis;white-space:nowrap;background:0;border:0;line-height:14px}.doc-explorer-narrow .doc-explorer-back{width:0}.graphiql-container .doc-explorer-back:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:"";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:9px}.graphiql-container .doc-explorer-rhs{position:relative}.graphiql-container .doc-explorer-contents,.graphiql-container .history-contents{background-color:#fff;border-top:1px solid #d6d6d6;bottom:0;left:0;overflow-y:auto;padding:20px 15px;position:absolute;right:0;top:47px}.graphiql-container .doc-explorer-contents{min-width:300px}.graphiql-container .doc-type-description blockquote:first-child,.graphiql-container .doc-type-description p:first-child{margin-top:0}.graphiql-container .doc-explorer-contents a{cursor:pointer;text-decoration:none}.graphiql-container .doc-explorer-contents a:hover{text-decoration:underline}.graphiql-container .doc-value-description>:first-child{margin-top:4px}.graphiql-container .doc-value-description>:last-child{margin-bottom:4px}.graphiql-container .doc-category code,.graphiql-container .doc-category pre,.graphiql-container .doc-type-description code,.graphiql-container .doc-type-description pre{--saf-0:rgba(var(--sk_foreground_low,29,28,29),0.13);font-size:12px;line-height:1.50001;-webkit-font-feature-settings:none;font-feature-settings:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;white-space:pre;white-space:pre-wrap;word-wrap:break-word;word-break:normal;-webkit-tab-size:4;-moz-tab-size:4;tab-size:4}.graphiql-container .doc-category code,.graphiql-container .doc-type-description code{padding:2px 3px 1px;border:1px solid var(--saf-0);border-radius:3px;background-color:rgba(29,28,29,.04);background-color:rgba(var(--sk_foreground_min,29,28,29),.04);color:#e01e5a;background-color:#fff}.graphiql-container .doc-category{margin:20px 0}.graphiql-container .doc-category-title{border-bottom:1px solid #e0e0e0;color:#777;cursor:default;font-size:14px;-webkit-font-feature-settings:"smcp";font-feature-settings:"smcp";font-variant:small-caps;font-weight:700;letter-spacing:1px;margin:0 -15px 10px 0;padding:10px 0;-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-category-item{margin:12px 0;color:#555}.graphiql-container .keyword{color:#b11a04}.graphiql-container .type-name{color:#ca9800}.graphiql-container .field-name{color:#1f61a0}.graphiql-container .field-short-description{color:#999;margin-left:5px;overflow:hidden;text-overflow:ellipsis}.graphiql-container .enum-value{color:#0b7fc7}.graphiql-container .arg-name{color:#8b2bb9}.graphiql-container .arg{display:block;margin-left:1em}.graphiql-container .arg:first-child:last-child,.graphiql-container .arg:first-child:nth-last-child(2),.graphiql-container .arg:first-child:nth-last-child(2)~.arg{display:inherit;margin:inherit}.graphiql-container .arg:first-child:nth-last-child(2):after{content:", "}.graphiql-container .arg-default-value{color:#43a047}.graphiql-container .doc-deprecation{background:#fffae8;box-shadow:inset 0 0 1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px;max-height:80px;overflow:hidden;padding:8px;border-radius:3px}.graphiql-container .doc-deprecation:before{content:"Deprecated:";color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-deprecation>:first-child{margin-top:0}.graphiql-container .doc-deprecation>:last-child{margin-bottom:0}.graphiql-container .show-btn{-webkit-appearance:initial;display:block;border-radius:3px;border:1px solid #ccc;text-align:center;padding:8px 12px 10px;width:100%;box-sizing:border-box;background:#fbfcfc;color:#555;cursor:pointer}.graphiql-container .search-box{border-bottom:1px solid #d3d6db;display:flex;align-items:center;font-size:14px;margin:-15px -15px 12px 0;position:relative}.graphiql-container .search-box-icon{cursor:pointer;display:block;font-size:24px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .search-box .search-box-clear{background-color:#d0d0d0;border-radius:12px;color:#fff;cursor:pointer;font-size:11px;padding:1px 5px 2px;position:absolute;right:3px;-webkit-user-select:none;-ms-user-select:none;user-select:none;border:0}.graphiql-container .search-box .search-box-clear:hover{background-color:#b9b9b9}.graphiql-container .search-box>input{border:none;box-sizing:border-box;font-size:14px;outline:none;padding:6px 24px 8px 20px;width:100%}.graphiql-container .error-container{font-weight:700;left:0;letter-spacing:1px;opacity:.5;position:absolute;right:0;text-align:center;text-transform:uppercase;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.graphiql-container .history-contents{font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;margin:0;padding:0}.graphiql-container .history-contents li{align-items:center;display:flex;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;padding:8px;border-bottom:1px solid #e0e0e0}.graphiql-container .history-contents li button:not(.history-label){display:none;margin-left:10px}.graphiql-container .history-contents li:focus-within button:not(.history-label),.graphiql-container .history-contents li:hover button:not(.history-label){display:inline-block}.graphiql-container .history-contents button,.graphiql-container .history-contents input{padding:0;background:0;border:0;font-size:inherit;font-family:inherit;line-height:14px;color:inherit}.graphiql-container .history-contents input{flex-grow:1}.graphiql-container .history-contents input::-webkit-input-placeholder{color:inherit}.graphiql-container .history-contents input:-ms-input-placeholder{color:inherit}.graphiql-container .history-contents input::placeholder{color:inherit}.graphiql-container .history-contents button{cursor:pointer;text-align:left}.graphiql-container .history-contents .history-label{flex-grow:1;overflow:hidden;text-overflow:ellipsis} +/*# sourceMappingURL=2.dff3c244.chunk.css.map */ \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css.map b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css.map new file mode 100644 index 000000000..55b85dc68 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/2.dff3c244.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://node_modules/graphiql/graphiql.min.css"],"names":[],"mappings":"AAAA,yEAAyE,aAAa,CAAC,oJAAoJ,CAAC,cAAc,CAAC,oBAAoB,YAAY,CAAC,kBAAkB,CAAC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,gCAAgC,YAAY,CAAC,qBAAqB,CAAC,QAAM,CAAC,iBAAiB,CAAC,2BAA2B,cAAc,CAAC,8BAA8B,mBAAmB,CAAC,cAAc,CAAC,gCAAgC,YAAY,CAAC,kBAAkB,CAAC,4BAA4B,kBAAkB,CAAC,2CAA2C,CAAC,+BAA+B,CAAC,cAAc,CAAC,YAAY,CAAC,kBAAkB,CAAC,QAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,6BAA6B,kBAAkB,CAAC,YAAY,CAAC,sEAAsE,2CAA2C,CAAC,eAAe,CAAC,+BAA+B,CAAC,iBAAiB,CAAC,eAAe,CAAC,aAAa,CAAC,cAAc,CAAC,cAAc,CAAC,QAAQ,CAAC,uBAAuB,CAAC,qCAAqC,oCAAoC,CAAC,iCAAiC,qCAAqC,CAAC,aAAa,CAAC,4CAA4C,6BAA6B,CAAC,4BAA4B,CAAC,UAAU,CAAC,oBAAoB,CAAC,UAAU,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,gCAAwB,CAAxB,wBAAwB,CAAC,SAAS,CAAC,+BAA+B,YAAY,CAAC,kBAAkB,CAAC,QAAM,CAAC,+DAA+D,YAAY,CAAC,qBAAqB,CAAC,QAAM,CAAC,gCAAgC,6BAA6B,CAAC,cAAc,CAAC,iBAAiB,CAAC,0EAA0E,eAAe,CAAC,kCAAkC,CAAC,iBAAiB,CAAC,SAAS,CAAC,qCAAqC,eAAe,CAAC,SAAS,CAAC,wCAAwC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,qCAAqC,cAAc,CAAC,cAAc,CAAC,uBAAuB,CAAC,2BAA2B,CAAC,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,sCAAsC,QAAM,CAAC,iBAAiB,CAAC,sCAAsC,YAAY,CAAC,qBAAqB,CAAC,WAAW,CAAC,iBAAiB,CAAC,4CAA4C,eAAe,CAAC,+BAA+B,CAAC,4BAA4B,CAAC,UAAU,CAAC,oCAAuB,CAAvB,4BAAuB,CAAvB,uBAAuB,CAAC,eAAe,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,uEAAuE,QAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,4BAA4B,kBAAkB,CAAC,6BAA6B,CAAC,4BAA4B,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,mCAAmC,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,QAAQ,CAAC,UAAU,CAAC,2BAA2B,kBAAkB,CAAC,uDAAuD,qBAAqB,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,sMAAsM,gBAAgB,CAAC,oCAAoC,kBAAkB,CAAC,2CAA2C,CAAC,QAAQ,CAAC,iBAAiB,CAAC,qFAAqF,CAAC,UAAU,CAAC,cAAc,CAAC,oBAAoB,CAAC,YAAY,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,eAAe,CAAC,2CAA2C,2CAA2C,CAAC,qIAAqI,CAAC,0CAA0C,2CAA2C,CAAC,UAAU,CAAC,0CAA0C,YAAY,CAAC,kBAAkB,CAAC,4CAA4C,QAAQ,CAAC,4DAA4D,yBAAyB,CAAC,4BAA4B,CAAC,6DAA6D,wBAAwB,CAAC,2BAA2B,CAAC,gBAAgB,CAAC,yCAAyC,WAAW,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,oCAAoC,2CAA2C,CAAC,kBAAkB,CAAC,gCAAgC,CAAC,uBAAuB,CAAC,cAAc,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,wCAAwC,mBAAmB,CAAC,2CAA2C,2CAA2C,CAAC,iFAAiF,CAAC,sEAAsE,iBAAiB,CAAC,yHAAyH,eAAe,CAAC,6DAA6D,CAAC,QAAQ,CAAC,aAAa,CAAC,iBAAiB,CAAC,WAAW,CAAC,qCAAqC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,wCAAwC,QAAQ,CAAC,eAAe,CAAC,cAAc,CAAC,QAAQ,CAAC,iBAAiB,CAAC,6CAA6C,kBAAkB,CAAC,4CAA4C,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,iBAAiB,CAAC,iDAAiD,kBAAkB,CAAC,kIAAkI,cAAc,CAAC,aAAa,CAAC,WAAW,CAAC,eAAe,CAAC,eAAe,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,ocAAoc,kBAAkB,CAAC,UAAU,CAAC,mDAAmD,cAAc,CAAC,SAAS,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,4KAA4K,SAAS,CAAC,uCAAuC,wBAAwB,CAAC,gCAAgC,aAAa,CAAC,iEAAiE,CAAC,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,sCAAsC,cAAc,CAAC,sCAAsC,mBAAmB,CAAC,aAAa,CAAC,YAAY,CAAC,oJAAoJ,CAAC,cAAc,CAAC,YAAY,CAAC,gBAAgB,CAAC,eAAe,CAAC,eAAe,CAAC,kCAAkC,CAAC,oDAAoD,YAAY,CAAC,mDAAmD,eAAe,CAAC,uCAAuC,aAAa,CAAC,cAAc,CAAC,cAAc,CAAC,iBAAiB,CAAC,8BAA8B,6BAAqB,CAArB,qBAAqB,CAAC,oCAA4B,CAA5B,4BAA4B,CAAC,yCAAyC,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,iCAAyB,MAAM,4BAA4B,CAAC,8BAA8B,CAAC,QAAQ,kBAAkB,CAAC,oBAAoB,CAAC,CAA3I,yBAAyB,MAAM,4BAA4B,CAAC,8BAA8B,CAAC,QAAQ,kBAAkB,CAAC,oBAAoB,CAAC,CAAC,4BAA4B,qBAAqB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,aAAa,CAAC,oCAAoC,CAAC,cAAc,CAAC,gBAAgB,CAAC,eAAe,CAAC,SAAS,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,oBAAoB,CAAC,8BAA8B,iBAAiB,CAAC,gCAAgC,eAAe,CAAC,2CAA2C,iBAAiB,CAAC,eAAe,CAAC,2CAA2C,CAAC,kEAAkE,CAAC,UAAU,CAAC,iBAAiB,CAAC,cAAc,CAAC,aAAa,CAAC,YAAY,CAAC,iBAAiB,CAAC,iCAAiC,CAAC,mEAAmE,UAAU,CAAC,yBAAyB,CAAC,sEAAsE,SAAS,CAAC,YAAY,UAAU,CAAC,gBAAgB,UAAU,CAAC,YAAY,aAAa,CAAC,QAAQ,aAAa,CAAC,aAAa,aAAa,CAAC,cAAc,aAAa,CAAC,cAAc,aAAa,CAAC,WAAW,aAAa,CAAC,WAAW,aAAa,CAAC,YAAY,aAAa,CAAC,aAAa,aAAa,CAAC,aAAa,aAAa,CAAC,SAAS,aAAa,CAAC,SAAS,aAAa,CAC5mS,YAAY,UAAU,CAAC,qBAAqB,CAAC,YAAY,CAAC,kBAAkB,aAAa,CAAC,gBAAgB,aAAa,CAAC,uDAAuD,qBAAqB,CAAC,oBAAoB,2BAA2B,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,uBAAuB,UAAU,CAAC,cAAc,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,yBAAyB,UAAU,CAAC,gCAAgC,UAAU,CAAC,+BAA+B,0BAA0B,CAAC,2CAA2C,4BAA4B,CAAC,gDAAgD,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,iDAAiD,SAAS,CAAC,uBAAuB,+CAAuC,CAAvC,uCAAuC,CAAC,QAAQ,CAAC,UAAU,CAAC,yBAAiB,GAAG,eAAe,CAAC,IAAI,eAAe,CAAC,GAAG,eAAe,CAAC,CAA3E,iBAAiB,GAAG,eAAe,CAAC,IAAI,eAAe,CAAC,GAAG,eAAe,CAAC,CAAC,QAAQ,oBAAoB,CAAC,uBAAuB,CAAC,kBAAkB,0BAA0B,CAAC,iBAAiB,CAAC,0BAA0B,UAAU,CAAC,uBAAuB,UAAU,CAAC,yBAAyB,UAAU,CAAC,sBAAsB,UAAU,CAAC,6BAA6B,UAAU,CAAC,6BAA6B,UAAU,CAAC,0BAA0B,UAAU,CAAC,yBAAyB,UAAU,CAAC,2BAA2B,UAAU,CAAC,mDAAmD,UAAU,CAAC,0BAA0B,UAAU,CAAC,0BAA0B,UAAU,CAAC,sBAAsB,UAAU,CAAC,4BAA4B,UAAU,CAAC,yBAAyB,UAAU,CAAC,wBAAwB,UAAU,CAAC,qBAAqB,UAAU,CAAC,uBAAuB,UAAU,CAAC,aAAa,UAAU,CAAC,aAAa,UAAU,CAAC,sBAAsB,eAAe,CAAC,OAAO,iBAAiB,CAAC,SAAS,yBAAyB,CAAC,kBAAkB,4BAA4B,CAAC,wCAAwC,SAAS,CAAC,sBAAsB,uBAAuB,CAAC,+CAA+C,UAAU,CAAC,kDAAkD,UAAU,CAAC,wBAAwB,6BAA6B,CAAC,kCAAkC,kBAAkB,CAAC,YAAY,eAAe,CAAC,eAAe,CAAC,iBAAiB,CAAC,mBAAmB,WAAW,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,YAAY,CAAC,yBAAyB,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,kBAAkB,mCAAmC,CAAC,iBAAiB,CAAC,qGAAqG,YAAY,CAAC,iBAAiB,CAAC,SAAS,CAAC,uBAAuB,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,6BAA6B,OAAO,CAAC,QAAQ,CAAC,0BAA0B,MAAM,CAAC,QAAQ,CAAC,oBAAoB,eAAe,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,mBAAmB,oBAAoB,CAAC,WAAW,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,kBAAkB,EAAA,MAAQ,EAAA,cAAgB,CAAC,2BAA2B,yBAAyB,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,SAAS,CAAC,8BAA8B,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,uBAAuB,cAAc,CAAC,iBAAiB,CAAC,SAAS,CAAC,2BAA2B,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,kBAAkB,WAAW,CAAC,cAAc,CAAC,gBAAgB,uCAAuC,CAAC,sBAAsB,CAAC,eAAe,CAAC,cAAc,CAAC,aAAa,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,kCAA2B,CAA3B,0BAA2B,CAA3B,mCAA2B,CAA3B,2BAA2B,CAAC,mBAAmB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,eAAe,CAAC,gBAAgB,CAAC,SAAS,CAAC,qBAAqB,oBAAoB,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,2BAA2B,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,uBAAuB,aAAa,CAAC,iBAAiB,CAAC,SAAS,CAAC,iBAAiB,YAAY,CAAC,mGAAmG,sBAAsB,CAAC,oBAAoB,QAAQ,CAAC,eAAe,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,UAAU,CAAC,mBAAmB,iBAAiB,CAAC,wBAAwB,eAAe,CAAC,uBAAuB,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC,sEAAsE,kBAAkB,CAAC,qBAAqB,kBAAkB,CAAC,yCAAyC,kBAAkB,CAAC,sBAAsB,gBAAgB,CAAC,mGAAmG,kBAAkB,CAAC,kHAAkH,kBAAkB,CAAC,cAAc,eAAe,CAAC,6BAA6B,CAAC,kBAAA,0BAA4C,CAAC,iBAAiB,kBAAkB,CAAC,aAAa,mCAAmC,iBAAiB,CAAC,CAAC,wBAAwB,UAAU,CAAC,6BAA6B,eAAe,CAAC,mBAAmB,kBAAkB,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,UAAU,CAAC,uBAAuB,4BAA4B,CAAC,KAAK,CAAC,0BAA0B,yBAAyB,CAAC,QAAQ,CAAC,yBAAyB,sBAAsB,CAAC,wBAAwB,CAAC,aAAa,CAAC,qBAAqB,CAAC,YAAY,CAAC,UAAU,CAAC,0BAA0B,aAAa,CAC/4K,uBAAuB,UAAU,CAAC,cAAc,CAAC,iBAAiB,CAAC,cAAc,CAAC,mFAAmF,CAAC,uBAAuB,UAAU,CAAC,0DAA0D,cAAc,CAAC,kCAAkC,eAAe,CAAC,oCAAoC,eAAe,CACtX,iBAAiB,eAAe,CAAC,iBAAiB,CAAC,oCAAoC,CAAC,qBAAqB,CAAC,UAAU,CAAC,oJAAoJ,CAAC,cAAc,CAAC,gBAAgB,CAAC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,eAAe,CAAC,WAAW,CAAC,cAAc,CAAC,uBAAuB,CAAC,UAAU,CAAC,8BAA8B,YAAY,CAAC,6BAA6B,eAAe,CAAC,mBAAmB,YAAY,CAAC,mCAAmC,UAAU,CAAC,gBAAgB,CAAC,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,mCAAmC,kBAAkB,CAAC,uCAAuC,CAAC,aAAa,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,eAAe,CAAC,eAAe,CAAC,WAAW,CAAC,yCAAyC,aAAa,CAAC,cAAc,CAAC,aAAa,CAAC,aAAa,CAAC,eAAe,CAAC,kBAAkB,CAAC,aAAa,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,2CAA2C,YAAY,CAAC,mBAAmB,oBAAoB,CAAC,yBAAyB,yBAAyB,CAAC,4BAA4B,aAAa,CAAC,6BAA6B,aAAa,CAAC,6BAA6B,aAAa,CAAC,2BAA2B,aAAa,CAAC,iCAAiC,aAAa,CACp4C,uBAAuB,yBAAyB,CAAC,cAAc,CAC/D,yBAAyB,UAAU,CAAC,yBAAyB,+BAA+B,CAAC,6BAA6B,CAAC,qBAAqB,CAAC,cAAc,CAAC,qBAAqB,CAAC,cAAc,CAAC,eAAe,CAAC,SAAS,CAAC,eAAe,CAAC,eAAe,CAAC,cAAc,CAAC,sBAAsB,CAAC,oBAAoB,CAAC,WAAW,CAAC,0DAA0D,0BAA0B,CAAC,0BAA0B,CAAC,4BAA4B,kTAAkT,CAAC,8BAA8B,8UAA8U,CAAC,8DAA8D,uBAAuB,CAAC,2BAA2B,CAAC,cAAc,CAAC,oBAAoB,CAAC,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC,gEAAgE,uBAAuB,CAAC,2BAA2B,CAAC,iBAAiB,CAAC,6DAA6D,kTAAkT,CAAC,iEAAiE,sWAAsW,CAAC,iCAAiC,sNAAsN,CAAC,6BAA6B,CAAC,2BAA2B,CAAC,UAAU,CAAC,WAAW,CAC7iF,uCAAuC,WAAW,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,CAAC,sCAA8B,CAA9B,8BAA8B,CAAC,UAAU,CAAC,UAAU,CAAC,6BAA6B,8CAAsC,CAAtC,sCAAsC,CAAC,kBAAkB,CAAuC,qCAAoC,CAApC,oCAAoC,CAAC,oBAAoB,CAAC,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC,4BAAoB,GAAG,8BAAqB,CAArB,sBAAsB,CAAC,GAAG,gCAAuB,CAAvB,wBAAwB,CAAC,CAA1E,oBAAoB,GAAG,8BAAqB,CAArB,sBAAsB,CAAC,GAAG,gCAAuB,CAAvB,wBAAwB,CAAC,CAC3c,kBAAkB,eAAe,CAAC,oCAAoC,CAAC,iEAAiE,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,iBAAiB,CAAC,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,iBAAiB,CAAC,UAAU,CAAC,iBAAiB,4BAA4B,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,0BAA0B,qBAAqB,CAAC,qBAAqB,CAAC,UAAU,CAAC,6BAA6B,2BAA2B,CAAC,eAAe,CAAC,eAAe,CAAC,iBAAiB,CAAC,SAAS,CAAC,yCAAyC,8BAA8B,CAAC,eAAe,CAAC,kBAAkB,CAAC,6BAA6B,kBAAkB,CAAC,uCAAuC,CAAC,aAAa,CAAC,oJAAoJ,CAAC,cAAc,CAAC,gBAAgB,CAAC,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,WAAW,CAAC,gDAAgD,aAAa,CAAC,cAAc,CAAC,aAAa,CAAC,aAAa,CAAC,eAAe,CAAC,kBAAkB,CAAC,aAAa,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,kDAAkD,YAAY,CAAC,yCAAyC,eAAe,CACn3C,kCAAkC,eAAe,CAAC,mFAAmF,cAAc,CAAC,YAAY,CAAC,WAAW,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,2EAA2E,QAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,wBAAgB,CAAhB,oBAAgB,CAAhB,gBAAgB,CAAC,kBAAkB,CAAC,uCAAuC,aAAa,CAAC,cAAc,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,YAAY,CAAC,QAAQ,CAAC,gBAAgB,CAAC,wCAAwC,OAAO,CAAC,8CAA8C,6BAA6B,CAAC,4BAA4B,CAAC,UAAU,CAAC,oBAAoB,CAAC,UAAU,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,gCAAwB,CAAxB,wBAAwB,CAAC,SAAS,CAAC,sCAAsC,iBAAiB,CAAC,iFAAiF,qBAAqB,CAAC,4BAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,2CAA2C,eAAe,CAAC,yHAAyH,YAAY,CAAC,6CAA6C,cAAc,CAAC,oBAAoB,CAAC,mDAAmD,yBAAyB,CAAC,wDAAwD,cAAc,CAAC,uDAAuD,iBAAiB,CAAC,0KAA0K,oDAAoD,CAAC,cAAc,CAAC,mBAAmB,CAAC,kCAA2B,CAA3B,0BAA2B,CAA3B,mCAA2B,CAA3B,2BAA2B,CAAC,eAAe,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,eAAe,CAAC,UAAU,CAAC,sFAAsF,mBAAmB,CAAC,6BAA6B,CAAC,iBAAiB,CAAC,mCAA4D,CAA5D,4DAA4D,CAAC,aAAa,CAAC,qBAAqB,CAAC,kCAAkC,aAAa,CAAC,wCAAwC,+BAA+B,CAAC,UAAU,CAAC,cAAc,CAAC,cAAc,CAAC,oCAAuB,CAAvB,4BAAuB,CAAvB,uBAAuB,CAAC,eAAe,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,cAAc,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,uCAAuC,aAAa,CAAC,UAAU,CAAC,6BAA6B,aAAa,CAAC,+BAA+B,aAAa,CAAC,gCAAgC,aAAa,CAAC,6CAA6C,UAAU,CAAC,eAAe,CAAC,eAAe,CAAC,sBAAsB,CAAC,gCAAgC,aAAa,CAAC,8BAA8B,aAAa,CAAC,yBAAyB,aAAa,CAAC,eAAe,CAAC,mKAAmK,eAAe,CAAC,cAAc,CAAC,6DAA6D,YAAY,CAAC,uCAAuC,aAAa,CAAC,qCAAqC,kBAAkB,CAAC,gCAAgC,CAAC,aAAa,CAAC,gBAAgB,CAAC,eAAe,CAAC,eAAe,CAAC,eAAe,CAAC,WAAW,CAAC,iBAAiB,CAAC,4CAA4C,qBAAqB,CAAC,aAAa,CAAC,cAAc,CAAC,aAAa,CAAC,aAAa,CAAC,eAAe,CAAC,kBAAkB,CAAC,aAAa,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,kDAAkD,YAAY,CAAC,iDAAiD,eAAe,CAAC,8BAA8B,0BAA0B,CAAC,aAAa,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,UAAU,CAAC,cAAc,CAAC,gCAAgC,+BAA+B,CAAC,YAAY,CAAC,kBAAkB,CAAC,cAAc,CAAC,yBAAyB,CAAC,iBAAiB,CAAC,qCAAqC,cAAc,CAAC,aAAa,CAAC,cAAc,CAAC,gCAAwB,CAAxB,wBAAwB,CAAC,wBAAe,CAAf,oBAAe,CAAf,gBAAgB,CAAC,kDAAkD,wBAAwB,CAAC,kBAAkB,CAAC,UAAU,CAAC,cAAc,CAAC,cAAc,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,SAAS,CAAC,wBAAgB,CAAhB,oBAAgB,CAAhB,gBAAgB,CAAC,QAAQ,CAAC,wDAAwD,wBAAwB,CAAC,sCAAsC,WAAW,CAAC,qBAAqB,CAAC,cAAc,CAAC,YAAY,CAAC,yBAAyB,CAAC,UAAU,CAAC,qCAAqC,eAAe,CAAC,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,iBAAiB,CAAC,OAAO,CAAC,iBAAiB,CAAC,wBAAwB,CAAC,OAAO,CAAC,kCAAyB,CAAzB,0BAA0B,CACz/J,sCAAsC,iEAAiE,CAAC,QAAQ,CAAC,SAAS,CAAC,yCAAyC,kBAAkB,CAAC,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,+BAA+B,CAAC,oEAAoE,YAAY,CAAC,gBAAgB,CAAC,2JAA2J,oBAAoB,CAAC,yFAAyF,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,aAAa,CAAC,4CAA4C,WAAW,CAAC,uEAAyD,aAAa,CAAtE,kEAAyD,aAAa,CAAtE,yDAAyD,aAAa,CAAC,6CAA6C,cAAc,CAAC,eAAe,CAAC,qDAAqD,WAAW,CAAC,eAAe,CAAC,sBAAsB","file":"2.dff3c244.chunk.css","sourcesContent":[".graphiql-container,.graphiql-container button,.graphiql-container input{color:#141823;font-family:system,-apple-system,San Francisco,\\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:14px}.graphiql-container{display:flex;flex-direction:row;height:100%;margin:0;overflow:hidden;width:100%}.graphiql-container .editorWrap{display:flex;flex-direction:column;flex:1;overflow-x:hidden}.graphiql-container .title{font-size:18px}.graphiql-container .title em{font-family:georgia;font-size:19px}.graphiql-container .topBarWrap{display:flex;flex-direction:row}.graphiql-container .topBar{align-items:center;background:linear-gradient(#f7f7f7,#e2e2e2);border-bottom:1px solid #d0d0d0;cursor:default;display:flex;flex-direction:row;flex:1;height:34px;overflow-y:visible;padding:7px 14px 6px;user-select:none}.graphiql-container .toolbar{overflow-x:visible;display:flex}.graphiql-container .docExplorerShow,.graphiql-container .historyShow{background:linear-gradient(#f7f7f7,#e2e2e2);border-radius:0;border-bottom:1px solid #d0d0d0;border-right:none;border-top:none;color:#3b5998;cursor:pointer;font-size:14px;margin:0;padding:2px 20px 0 18px}.graphiql-container .docExplorerShow{border-left:1px solid rgba(0,0,0,.2)}.graphiql-container .historyShow{border-right:1px solid rgba(0,0,0,.2);border-left:0}.graphiql-container .docExplorerShow:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:\"\";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;transform:rotate(-45deg);width:9px}.graphiql-container .editorBar{display:flex;flex-direction:row;flex:1}.graphiql-container .queryWrap,.graphiql-container .resultWrap{display:flex;flex-direction:column;flex:1}.graphiql-container .resultWrap{border-left:1px solid #e0e0e0;flex-basis:1em;position:relative}.graphiql-container .docExplorerWrap,.graphiql-container .historyPaneWrap{background:#fff;box-shadow:0 0 8px rgba(0,0,0,.15);position:relative;z-index:3}.graphiql-container .historyPaneWrap{min-width:230px;z-index:5}.graphiql-container .docExplorerResizer{cursor:col-resize;height:100%;left:-5px;position:absolute;top:0;width:10px;z-index:10}.graphiql-container .docExplorerHide{cursor:pointer;font-size:18px;margin:-7px -8px -6px 0;padding:18px 16px 15px 12px;background:0;border:0;line-height:14px}.graphiql-container div .query-editor{flex:1;position:relative}.graphiql-container .secondary-editor{display:flex;flex-direction:column;height:30px;position:relative}.graphiql-container .secondary-editor-title{background:#eee;border-bottom:1px solid #d6d6d6;border-top:1px solid #e0e0e0;color:#777;font-variant:small-caps;font-weight:700;letter-spacing:1px;line-height:14px;padding:6px 0 8px 43px;text-transform:lowercase;user-select:none}.graphiql-container .codemirrorWrap,.graphiql-container .result-window{flex:1;height:100%;position:relative}.graphiql-container .footer{background:#f6f7f8;border-left:1px solid #e0e0e0;border-top:1px solid #e0e0e0;margin-left:12px;position:relative}.graphiql-container .footer:before{background:#eee;bottom:0;content:\" \";left:-13px;position:absolute;top:-1px;width:12px}.result-window .CodeMirror{background:#f6f7f8}.graphiql-container .result-window .CodeMirror-gutters{background-color:#eee;border-color:#e0e0e0;cursor:col-resize}.graphiql-container .result-window .CodeMirror-foldgutter,.graphiql-container .result-window .CodeMirror-foldgutter-folded:after,.graphiql-container .result-window .CodeMirror-foldgutter-open:after{padding-left:3px}.graphiql-container .toolbar-button{background:#fdfdfd;background:linear-gradient(#f9f9f9,#ececec);border:0;border-radius:3px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.2),0 1px 0 hsla(0,0%,100%,.7),inset 0 1px #fff;color:#555;cursor:pointer;display:inline-block;margin:0 5px;padding:3px 11px 5px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;max-width:150px}.graphiql-container .toolbar-button:active{background:linear-gradient(#ececec,#d5d5d5);box-shadow:0 1px 0 hsla(0,0%,100%,.7),inset 0 0 0 1px rgba(0,0,0,.1),inset 0 1px 1px 1px rgba(0,0,0,.12),inset 0 0 5px rgba(0,0,0,.1)}.graphiql-container .toolbar-button.error{background:linear-gradient(#fdf3f3,#e6d6d7);color:#b00}.graphiql-container .toolbar-button-group{margin:0 5px;white-space:nowrap}.graphiql-container .toolbar-button-group>*{margin:0}.graphiql-container .toolbar-button-group>:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.graphiql-container .toolbar-button-group>:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-1px}.graphiql-container .execute-button-wrap{height:34px;margin:0 14px 0 28px;position:relative}.graphiql-container .execute-button{background:linear-gradient(#fdfdfd,#d2d3d6);border-radius:17px;border:1px solid rgba(0,0,0,.25);box-shadow:0 1px 0 #fff;cursor:pointer;fill:#444;height:34px;margin:0;padding:0;width:34px}.graphiql-container .execute-button svg{pointer-events:none}.graphiql-container .execute-button:active{background:linear-gradient(#e6e6e6,#c3c3c3);box-shadow:0 1px 0 #fff,inset 0 0 2px rgba(0,0,0,.2),inset 0 0 6px rgba(0,0,0,.1)}.graphiql-container .toolbar-menu,.graphiql-container .toolbar-select{position:relative}.graphiql-container .execute-options,.graphiql-container .toolbar-menu-items,.graphiql-container .toolbar-select-options{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 2px 4px rgba(0,0,0,.25);margin:0;padding:6px 0;position:absolute;z-index:100}.graphiql-container .execute-options{min-width:100px;top:37px;left:-1px}.graphiql-container .toolbar-menu-items{left:1px;margin-top:-1px;min-width:110%;top:100%;visibility:hidden}.graphiql-container .toolbar-menu-items.open{visibility:visible}.graphiql-container .toolbar-select-options{left:0;min-width:100%;top:-5px;visibility:hidden}.graphiql-container .toolbar-select-options.open{visibility:visible}.graphiql-container .execute-options>li,.graphiql-container .toolbar-menu-items>li,.graphiql-container .toolbar-select-options>li{cursor:pointer;display:block;margin:none;max-width:300px;overflow:hidden;padding:2px 20px 4px 11px;white-space:nowrap}.graphiql-container .execute-options>li.selected,.graphiql-container .history-contents>li:active,.graphiql-container .history-contents>li:hover,.graphiql-container .toolbar-menu-items>li.hover,.graphiql-container .toolbar-menu-items>li:active,.graphiql-container .toolbar-menu-items>li:hover,.graphiql-container .toolbar-select-options>li.hover,.graphiql-container .toolbar-select-options>li:active,.graphiql-container .toolbar-select-options>li:hover{background:#e10098;color:#fff}.graphiql-container .toolbar-select-options>li>svg{display:inline;fill:#666;margin:0 -6px 0 6px;pointer-events:none;vertical-align:middle}.graphiql-container .toolbar-select-options>li.hover>svg,.graphiql-container .toolbar-select-options>li:active>svg,.graphiql-container .toolbar-select-options>li:hover>svg{fill:#fff}.graphiql-container .CodeMirror-scroll{overflow-scrolling:touch}.graphiql-container .CodeMirror{color:#141823;font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;height:100%;left:0;position:absolute;top:0;width:100%}.graphiql-container .CodeMirror-lines{padding:20px 0}.CodeMirror-hint-information .content{box-orient:vertical;color:#141823;display:flex;font-family:system,-apple-system,San Francisco,\\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-clamp:3;line-height:16px;max-height:48px;overflow:hidden;text-overflow:-o-ellipsis-lastline}.CodeMirror-hint-information .content p:first-child{margin-top:0}.CodeMirror-hint-information .content p:last-child{margin-bottom:0}.CodeMirror-hint-information .infoType{color:#ca9800;cursor:pointer;display:inline;margin-right:.5em}.autoInsertedLeaf.cm-property{animation-duration:6s;animation-name:insertionFade;border-bottom:2px solid hsla(0,0%,100%,0);border-radius:2px;margin:-2px -4px -1px;padding:2px 4px 1px}@keyframes insertionFade{0%,to{background:hsla(0,0%,100%,0);border-color:hsla(0,0%,100%,0)}15%,85%{background:#fbffc9;border-color:#f0f3c0}}div.CodeMirror-lint-tooltip{background-color:#fff;border-radius:2px;border:0;color:#141823;box-shadow:0 1px 3px rgba(0,0,0,.45);font-size:13px;line-height:16px;max-width:430px;opacity:0;padding:8px 10px;transition:opacity .15s;white-space:pre-wrap}div.CodeMirror-lint-tooltip>*{padding-left:23px}div.CodeMirror-lint-tooltip>*+*{margin-top:12px}.graphiql-container .CodeMirror-foldmarker{border-radius:4px;background:#08f;background:linear-gradient(#43a8ff,#0f83e8);box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 0 0 1px rgba(0,0,0,.1);color:#fff;font-family:arial;font-size:12px;line-height:0;margin:0 3px;padding:0 4px 1px;text-shadow:0 -1px rgba(0,0,0,.1)}.graphiql-container div.CodeMirror span.CodeMirror-matchingbracket{color:#555;text-decoration:underline}.graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket{color:red}.cm-comment{color:#999}.cm-punctuation{color:#555}.cm-keyword{color:#b11a04}.cm-def{color:#d2054e}.cm-property{color:#1f61a0}.cm-qualifier{color:#1c92a9}.cm-attribute{color:#8b2bb9}.cm-number{color:#2882f9}.cm-string{color:#d64292}.cm-builtin{color:#d47509}.cm-string-2{color:#0b7fc7}.cm-variable{color:#397d13}.cm-meta{color:#b33086}.cm-atom{color:#ca9800}\n.CodeMirror{color:#000;font-family:monospace;height:300px}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{color:#999;min-width:20px;padding:0 3px 0 5px;text-align:right;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror .CodeMirror-cursor{border-left:1px solid #000}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-fat-cursor div.CodeMirror-cursor{background:#7e7;border:0;width:auto}.CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{animation:blink 1.06s steps(1) infinite;border:0;width:auto}@keyframes blink{0%{background:#7e7}50%{background:none}to{background:#7e7}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{background:#fff;overflow:hidden;position:relative}.CodeMirror-scroll{height:100%;margin-bottom:-30px;margin-right:-30px;outline:none;overflow:scroll!important;padding-bottom:30px;position:relative}.CodeMirror-sizer{border-right:30px solid transparent;position:relative}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{display:none;position:absolute;z-index:6}.CodeMirror-vscrollbar{overflow-x:hidden;overflow-y:scroll;right:0;top:0}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-x:scroll;overflow-y:hidden}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{min-height:100%;position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{display:inline-block;height:100%;margin-bottom:-30px;vertical-align:top;white-space:normal;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{background:none!important;border:none!important;position:absolute;z-index:4}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{cursor:default;position:absolute;z-index:4}.CodeMirror-gutter-wrapper{user-select:none}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-webkit-tap-highlight-color:transparent;background:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;font-variant-ligatures:none;line-height:inherit;margin:0;overflow:visible;position:relative;white-space:pre;word-wrap:normal;z-index:2}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{overflow:auto;position:relative;z-index:2}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{box-sizing:content-box}.CodeMirror-measure{height:0;overflow:hidden;position:absolute;visibility:hidden;width:100%}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{position:relative;visibility:hidden;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:\"\"}span.CodeMirror-selectedtext{background:none}.CodeMirror-dialog{background:inherit;color:inherit;left:0;right:0;overflow:hidden;padding:.1em .8em;position:absolute;z-index:15}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{background:transparent;border:1px solid #d3d6db;color:inherit;font-family:monospace;outline:none;width:20em}.CodeMirror-dialog button{font-size:70%}\n.CodeMirror-foldmarker{color:#00f;cursor:pointer;font-family:arial;line-height:.3;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-folded,.CodeMirror-foldgutter-open{cursor:pointer}.CodeMirror-foldgutter-open:after{content:\"\\25BE\"}.CodeMirror-foldgutter-folded:after{content:\"\\25B8\"}\n.CodeMirror-info{background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.45);box-sizing:border-box;color:#555;font-family:system,-apple-system,San Francisco,\\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin:8px -8px;max-width:400px;opacity:0;overflow:hidden;padding:8px;position:fixed;transition:opacity .15s;z-index:50}.CodeMirror-info :first-child{margin-top:0}.CodeMirror-info :last-child{margin-bottom:0}.CodeMirror-info p{margin:1em 0}.CodeMirror-info .info-description{color:#777;line-height:16px;margin-top:1em;max-height:80px;overflow:hidden}.CodeMirror-info .info-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px -8px;max-height:80px;overflow:hidden;padding:8px}.CodeMirror-info .info-deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;user-select:none}.CodeMirror-info .info-deprecation-label+*{margin-top:0}.CodeMirror-info a{text-decoration:none}.CodeMirror-info a:hover{text-decoration:underline}.CodeMirror-info .type-name{color:#ca9800}.CodeMirror-info .field-name{color:#1f61a0}.CodeMirror-info .enum-value{color:#0b7fc7}.CodeMirror-info .arg-name{color:#8b2bb9}.CodeMirror-info .directive-name{color:#b33086}\n.CodeMirror-jump-token{text-decoration:underline;cursor:pointer}\n.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:infobackground;border-radius:4px 4px 4px 4px;border:1px solid #000;color:infotext;font-family:monospace;font-size:10pt;max-width:600px;opacity:0;overflow:hidden;padding:2px 5px;position:fixed;transition:opacity .4s;white-space:pre-wrap;z-index:100}.CodeMirror-lint-mark-error,.CodeMirror-lint-mark-warning{background-position:0 100%;background-repeat:repeat-x}.CodeMirror-lint-mark-error{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==\")}.CodeMirror-lint-mark-warning{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=\")}.CodeMirror-lint-marker-error,.CodeMirror-lint-marker-warning{background-position:50%;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:16px}.CodeMirror-lint-message-error,.CodeMirror-lint-message-warning{background-position:0 0;background-repeat:no-repeat;padding-left:18px}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=\")}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=\")}.CodeMirror-lint-marker-multiple{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC\");background-position:100% 100%;background-repeat:no-repeat;width:100%;height:100%}\n.graphiql-container .spinner-container{height:36px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:36px;z-index:10}.graphiql-container .spinner{animation:rotation .6s linear infinite;border-radius:100%;border:6px solid hsla(0,0%,58.8%,.15);border-top-color:hsla(0,0%,58.8%,.8);display:inline-block;height:24px;position:absolute;vertical-align:middle;width:24px}@keyframes rotation{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}\n.CodeMirror-hints{background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.45);font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;list-style:none;margin:0;max-height:14.5em;overflow:hidden;overflow-y:auto;padding:0;position:absolute;z-index:10}.CodeMirror-hint{border-top:1px solid #f7f7f7;color:#141823;cursor:pointer;margin:0;max-width:300px;overflow:hidden;padding:2px 6px;white-space:pre}li.CodeMirror-hint-active{background-color:#08f;border-top-color:#fff;color:#fff}.CodeMirror-hint-information{border-top:1px solid silver;max-width:300px;padding:4px 6px;position:relative;z-index:1}.CodeMirror-hint-information:first-child{border-bottom:1px solid silver;border-top:none;margin-bottom:-1px}.CodeMirror-hint-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;font-family:system,-apple-system,San Francisco,\\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin-top:4px;max-height:80px;overflow:hidden;padding:6px}.CodeMirror-hint-deprecation .deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;user-select:none}.CodeMirror-hint-deprecation .deprecation-label+*{margin-top:0}.CodeMirror-hint-deprecation :last-child{margin-bottom:0}\n.graphiql-container .doc-explorer{background:#fff}.graphiql-container .doc-explorer-title-bar,.graphiql-container .history-title-bar{cursor:default;display:flex;height:34px;line-height:14px;padding:8px 8px 5px;position:relative;user-select:none}.graphiql-container .doc-explorer-title,.graphiql-container .history-title{flex:1;font-weight:700;overflow-x:hidden;padding:10px 0 10px 10px;text-align:center;text-overflow:ellipsis;user-select:text;white-space:nowrap}.graphiql-container .doc-explorer-back{color:#3b5998;cursor:pointer;margin:-7px 0 -6px -8px;overflow-x:hidden;padding:17px 12px 16px 16px;text-overflow:ellipsis;white-space:nowrap;background:0;border:0;line-height:14px}.doc-explorer-narrow .doc-explorer-back{width:0}.graphiql-container .doc-explorer-back:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:\"\";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;transform:rotate(-45deg);width:9px}.graphiql-container .doc-explorer-rhs{position:relative}.graphiql-container .doc-explorer-contents,.graphiql-container .history-contents{background-color:#fff;border-top:1px solid #d6d6d6;bottom:0;left:0;overflow-y:auto;padding:20px 15px;position:absolute;right:0;top:47px}.graphiql-container .doc-explorer-contents{min-width:300px}.graphiql-container .doc-type-description blockquote:first-child,.graphiql-container .doc-type-description p:first-child{margin-top:0}.graphiql-container .doc-explorer-contents a{cursor:pointer;text-decoration:none}.graphiql-container .doc-explorer-contents a:hover{text-decoration:underline}.graphiql-container .doc-value-description>:first-child{margin-top:4px}.graphiql-container .doc-value-description>:last-child{margin-bottom:4px}.graphiql-container .doc-category code,.graphiql-container .doc-category pre,.graphiql-container .doc-type-description code,.graphiql-container .doc-type-description pre{--saf-0:rgba(var(--sk_foreground_low,29,28,29),0.13);font-size:12px;line-height:1.50001;font-variant-ligatures:none;white-space:pre;white-space:pre-wrap;word-wrap:break-word;word-break:normal;-webkit-tab-size:4;-moz-tab-size:4;tab-size:4}.graphiql-container .doc-category code,.graphiql-container .doc-type-description code{padding:2px 3px 1px;border:1px solid var(--saf-0);border-radius:3px;background-color:rgba(var(--sk_foreground_min,29,28,29),.04);color:#e01e5a;background-color:#fff}.graphiql-container .doc-category{margin:20px 0}.graphiql-container .doc-category-title{border-bottom:1px solid #e0e0e0;color:#777;cursor:default;font-size:14px;font-variant:small-caps;font-weight:700;letter-spacing:1px;margin:0 -15px 10px 0;padding:10px 0;user-select:none}.graphiql-container .doc-category-item{margin:12px 0;color:#555}.graphiql-container .keyword{color:#b11a04}.graphiql-container .type-name{color:#ca9800}.graphiql-container .field-name{color:#1f61a0}.graphiql-container .field-short-description{color:#999;margin-left:5px;overflow:hidden;text-overflow:ellipsis}.graphiql-container .enum-value{color:#0b7fc7}.graphiql-container .arg-name{color:#8b2bb9}.graphiql-container .arg{display:block;margin-left:1em}.graphiql-container .arg:first-child:last-child,.graphiql-container .arg:first-child:nth-last-child(2),.graphiql-container .arg:first-child:nth-last-child(2)~.arg{display:inherit;margin:inherit}.graphiql-container .arg:first-child:nth-last-child(2):after{content:\", \"}.graphiql-container .arg-default-value{color:#43a047}.graphiql-container .doc-deprecation{background:#fffae8;box-shadow:inset 0 0 1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px;max-height:80px;overflow:hidden;padding:8px;border-radius:3px}.graphiql-container .doc-deprecation:before{content:\"Deprecated:\";color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;user-select:none}.graphiql-container .doc-deprecation>:first-child{margin-top:0}.graphiql-container .doc-deprecation>:last-child{margin-bottom:0}.graphiql-container .show-btn{-webkit-appearance:initial;display:block;border-radius:3px;border:1px solid #ccc;text-align:center;padding:8px 12px 10px;width:100%;box-sizing:border-box;background:#fbfcfc;color:#555;cursor:pointer}.graphiql-container .search-box{border-bottom:1px solid #d3d6db;display:flex;align-items:center;font-size:14px;margin:-15px -15px 12px 0;position:relative}.graphiql-container .search-box-icon{cursor:pointer;display:block;font-size:24px;transform:rotate(-45deg);user-select:none}.graphiql-container .search-box .search-box-clear{background-color:#d0d0d0;border-radius:12px;color:#fff;cursor:pointer;font-size:11px;padding:1px 5px 2px;position:absolute;right:3px;user-select:none;border:0}.graphiql-container .search-box .search-box-clear:hover{background-color:#b9b9b9}.graphiql-container .search-box>input{border:none;box-sizing:border-box;font-size:14px;outline:none;padding:6px 24px 8px 20px;width:100%}.graphiql-container .error-container{font-weight:700;left:0;letter-spacing:1px;opacity:.5;position:absolute;right:0;text-align:center;text-transform:uppercase;top:50%;transform:translateY(-50%)}\n.graphiql-container .history-contents{font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;margin:0;padding:0}.graphiql-container .history-contents li{align-items:center;display:flex;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;padding:8px;border-bottom:1px solid #e0e0e0}.graphiql-container .history-contents li button:not(.history-label){display:none;margin-left:10px}.graphiql-container .history-contents li:focus-within button:not(.history-label),.graphiql-container .history-contents li:hover button:not(.history-label){display:inline-block}.graphiql-container .history-contents button,.graphiql-container .history-contents input{padding:0;background:0;border:0;font-size:inherit;font-family:inherit;line-height:14px;color:inherit}.graphiql-container .history-contents input{flex-grow:1}.graphiql-container .history-contents input::placeholder{color:inherit}.graphiql-container .history-contents button{cursor:pointer;text-align:left}.graphiql-container .history-contents .history-label{flex-grow:1;overflow:hidden;text-overflow:ellipsis}\n\n/*# sourceMappingURL=graphiql.min.css.map*/"]} \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css new file mode 100644 index 000000000..bda6d1335 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css @@ -0,0 +1,2 @@ +body{padding:0;margin:0;min-height:100vh}#root{height:100vh}@font-face{font-family:"Gilmer";src:url(../../static/media/gilmer-regular.dadefd19.eot);src:url(../../static/media/gilmer-regular.dadefd19.eot?#iefix) format("embedded-opentype"),url(../../static/media/gilmer-regular.ac841c91.woff2) format("woff2"),url(../../static/media/gilmer-regular.34195eed.woff) format("woff"),url(../../static/media/gilmer-regular.4e0de531.ttf) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"GilmerMedium";src:url(../../static/media/gilmer-medium.8feb26bf.eot);src:url(../../static/media/gilmer-medium.8feb26bf.eot?#iefix) format("embedded-opentype"),url(../../static/media/gilmer-medium.18a9997c.woff2) format("woff2"),url(../../static/media/gilmer-medium.9eb8c454.woff) format("woff"),url(../../static/media/gilmer-medium.721edb3d.ttf) format("truetype");font-weight:500;font-style:normal}@font-face{font-family:"GilmerBold";src:url(../../static/media/gilmer-bold.1b0f0f29.eot);src:url(../../static/media/gilmer-bold.1b0f0f29.eot?#iefix) format("embedded-opentype"),url(../../static/media/gilmer-bold.703ca0a7.woff2) format("woff2"),url(../../static/media/gilmer-bold.fb7355ad.woff) format("woff"),url(../../static/media/gilmer-bold.9cf9669b.ttf) format("truetype");font-weight:700;font-style:normal} +/*# sourceMappingURL=main.dd389ba7.chunk.css.map */ \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css.map b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css.map new file mode 100644 index 000000000..8a2be1074 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/css/main.dd389ba7.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://src/index.css"],"names":[],"mappings":"AAaA,KACE,SAAU,CACV,QAAS,CACT,gBACF,CACA,MACE,YACF,CAkBA,WACE,oBAAqB,CACrB,uDAAoD,CACpD,2SAI0E,CAC1E,eAAmB,CACnB,iBACF,CAkBA,WACE,0BAA2B,CAC3B,sDAAmD,CACnD,uSAIyE,CACzE,eAAgB,CAChB,iBACF,CAkBA,WACE,wBAAyB,CACzB,oDAAiD,CACjD,+RAIuE,CACvE,eAAiB,CACjB,iBACF","file":"main.dd389ba7.chunk.css","sourcesContent":["/*\n * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com). All Rights Reserved.\n *\n * This software is the property of WSO2 Inc. and its suppliers, if any.\n * Dissemination of any information or reproduction of any material contained\n * herein is strictly forbidden, unless permitted by WSO2 in accordance with\n * the WSO2 Commercial License available at http://wso2.com/licenses.\n * For specific language governing the permissions and limitations under\n * this license, please see the license as well as any agreement you’ve\n * entered into with WSO2 governing the purchase of this software and any\n * associated services.\n */\n\nbody {\n padding: 0;\n margin: 0;\n min-height: 100vh;\n}\n#root {\n height: 100vh;\n}\n\n/*\nFont: \t\tGilmer\nStyle: \t\tRegular\nURL: \t\thttps://www.youworkforthem.com/font/T9758/gilmer\nFoundry: \tPiotr Lapa\nFoundry: \thttps://www.youworkforthem.com/designer/1166/piotr-lapa\nCopyright:\tCopyright © 2018 by Piotr _apa. All rights reserved.\nVersion: \t17\nCreated:\tAugust 17, 2018\nLicense: \thttps://www.youworkforthem.com/font-license\nLicense: \tThe WebFont(s) listed in this document must follow the YouWorkForThem\n\t\t\tWebFont license rules. All other parties are strictly restricted\n\t\t\tfrom using the WebFonts(s) listed without a purchased license.\n\t\t\tAll details above must always remain unaltered and visible in your CSS.\n*/\n\n@font-face {\n font-family: 'Gilmer';\n src: url('./assets/fonts/Glimer/gilmer-regular.eot');\n src:\n url('./assets/fonts/Glimer/gilmer-regular.eot?#iefix') format('embedded-opentype'),\n url('./assets/fonts/Glimer/gilmer-regular.woff2') format('woff2'),\n url('./assets/fonts/Glimer/gilmer-regular.woff') format('woff'),\n url('./assets/fonts/Glimer/gilmer-regular.ttf') format('truetype');\n font-weight: normal;\n font-style: normal;\n}\n\n/*\nFont: \t\tGilmer\nStyle: \t\tMedium\nURL: \t\thttps://www.youworkforthem.com/font/T9758/gilmer\nFoundry: \tPiotr Lapa\nFoundry: \thttps://www.youworkforthem.com/designer/1166/piotr-lapa\nCopyright:\tCopyright © 2018 by Piotr _apa. All rights reserved.\nVersion: \t17\nCreated:\tAugust 17, 2018\nLicense: \thttps://www.youworkforthem.com/font-license\nLicense: \tThe WebFont(s) listed in this document must follow the YouWorkForThem\n WebFont license rules. All other parties are strictly restricted\n from using the WebFonts(s) listed without a purchased license.\n All details above must always remain unaltered and visible in your CSS.\n*/\n\n@font-face {\n font-family: 'GilmerMedium';\n src: url('./assets/fonts/Glimer/gilmer-medium.eot');\n src:\n url('./assets/fonts/Glimer/gilmer-medium.eot?#iefix') format('embedded-opentype'),\n url('./assets/fonts/Glimer/gilmer-medium.woff2') format('woff2'),\n url('./assets/fonts/Glimer/gilmer-medium.woff') format('woff'),\n url('./assets/fonts/Glimer/gilmer-medium.ttf') format('truetype');\n font-weight: 500;\n font-style: normal;\n}\n\n/*\nFont: \t\tGilmer\nStyle: \t\tBold\nURL: \t\thttps://www.youworkforthem.com/font/T9758/gilmer\nFoundry: \tPiotr Lapa\nFoundry: \thttps://www.youworkforthem.com/designer/1166/piotr-lapa\nCopyright:\tCopyright © 2018 by Piotr _apa. All rights reserved.\nVersion: \t17\nCreated:\tAugust 17, 2018\nLicense: \thttps://www.youworkforthem.com/font-license\nLicense: \tThe WebFont(s) listed in this document must follow the YouWorkForThem\n WebFont license rules. All other parties are strictly restricted\n from using the WebFonts(s) listed without a purchased license.\n All details above must always remain unaltered and visible in your CSS.\n*/\n\n@font-face {\n font-family: 'GilmerBold';\n src: url('./assets/fonts/Glimer/gilmer-bold.eot');\n src:\n url('./assets/fonts/Glimer/gilmer-bold.eot?#iefix') format('embedded-opentype'),\n url('./assets/fonts/Glimer/gilmer-bold.woff2') format('woff2'),\n url('./assets/fonts/Glimer/gilmer-bold.woff') format('woff'),\n url('./assets/fonts/Glimer/gilmer-bold.ttf') format('truetype');\n font-weight: bold;\n font-style: normal;\n}\n"]} \ No newline at end of file diff --git a/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/js/2.e5757962.chunk.js b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/js/2.e5757962.chunk.js new file mode 100644 index 000000000..847ff5488 --- /dev/null +++ b/monitoring-and-insights/work-with-choreo-insights-api/graphiql-explorer/static/js/2.e5757962.chunk.js @@ -0,0 +1,3 @@ +/*! For license information please see 2.e5757962.chunk.js.LICENSE.txt */ +(this["webpackJsonpchoreo-graphiql-explorer"]=this["webpackJsonpchoreo-graphiql-explorer"]||[]).push([[2],[function(e,t,n){"use strict";e.exports=n(384)},function(e,t,n){"use strict";n.d(t,"S",(function(){return E})),n.d(t,"x",(function(){return S})),n.d(t,"R",(function(){return x})),n.d(t,"w",(function(){return k})),n.d(t,"N",(function(){return T})),n.d(t,"u",(function(){return C})),n.d(t,"H",(function(){return O})),n.d(t,"o",(function(){return A})),n.d(t,"T",(function(){return D})),n.d(t,"y",(function(){return P})),n.d(t,"E",(function(){return I})),n.d(t,"l",(function(){return N})),n.d(t,"F",(function(){return R})),n.d(t,"m",(function(){return j})),n.d(t,"J",(function(){return L})),n.d(t,"q",(function(){return F})),n.d(t,"L",(function(){return B})),n.d(t,"s",(function(){return V})),n.d(t,"G",(function(){return z})),n.d(t,"n",(function(){return U})),n.d(t,"O",(function(){return q})),n.d(t,"v",(function(){return H})),n.d(t,"I",(function(){return G})),n.d(t,"p",(function(){return W})),n.d(t,"D",(function(){return K})),n.d(t,"k",(function(){return Y})),n.d(t,"C",(function(){return Q})),n.d(t,"j",(function(){return Z})),n.d(t,"d",(function(){return $})),n.d(t,"e",(function(){return J})),n.d(t,"U",(function(){return X})),n.d(t,"z",(function(){return ee})),n.d(t,"M",(function(){return te})),n.d(t,"t",(function(){return ne})),n.d(t,"B",(function(){return re})),n.d(t,"K",(function(){return ie})),n.d(t,"r",(function(){return oe})),n.d(t,"A",(function(){return ae})),n.d(t,"g",(function(){return le})),n.d(t,"f",(function(){return ce})),n.d(t,"i",(function(){return me})),n.d(t,"P",(function(){return ve})),n.d(t,"c",(function(){return ge})),n.d(t,"h",(function(){return ye})),n.d(t,"a",(function(){return we})),n.d(t,"b",(function(){return Me})),n.d(t,"Q",(function(){return Se}));var r=n(59),i=n(28),o=n(4),a=n(39),s=n(63),u=n(43),l=n(9),c=n(55),f=n(46),h=n(42),d=n(31);function p(e){return e}var m=n(49),v=n(44),g=n(3),y=n(2),b=n(17),w=n(336);function _(e,t){for(var n=0;n0?e:void 0}$.prototype.toString=function(){return"["+String(this.ofType)+"]"},$.prototype.toJSON=function(){return this.toString()},Object.defineProperty($.prototype,i.c,{get:function(){return"GraphQLList"}}),Object(m.a)($),J.prototype.toString=function(){return String(this.ofType)+"!"},J.prototype.toJSON=function(){return this.toString()},Object.defineProperty(J.prototype,i.c,{get:function(){return"GraphQLNonNull"}}),Object(m.a)(J);var le=function(){function e(e){var t,n,r,i=null!==(t=e.parseValue)&&void 0!==t?t:p;this.name=e.name,this.description=e.description,this.specifiedByUrl=e.specifiedByUrl,this.serialize=null!==(n=e.serialize)&&void 0!==n?n:p,this.parseValue=i,this.parseLiteral=null!==(r=e.parseLiteral)&&void 0!==r?r:function(e,t){return i(Object(w.a)(e,t))},this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),"string"===typeof e.name||Object(l.a)(0,"Must provide name."),null==e.specifiedByUrl||"string"===typeof e.specifiedByUrl||Object(l.a)(0,"".concat(this.name,' must provide "specifiedByUrl" as a string, ')+"but got: ".concat(Object(o.a)(e.specifiedByUrl),".")),null==e.serialize||"function"===typeof e.serialize||Object(l.a)(0,"".concat(this.name,' must provide "serialize" function. If this custom Scalar is also used as an input type, ensure "parseValue" and "parseLiteral" functions are also provided.')),e.parseLiteral&&("function"===typeof e.parseValue&&"function"===typeof e.parseLiteral||Object(l.a)(0,"".concat(this.name,' must provide both "parseValue" and "parseLiteral" functions.')))}var t=e.prototype;return t.toConfig=function(){var e;return{name:this.name,description:this.description,specifiedByUrl:this.specifiedByUrl,serialize:this.serialize,parseValue:this.parseValue,parseLiteral:this.parseLiteral,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:null!==(e=this.extensionASTNodes)&&void 0!==e?e:[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLScalarType"}}]),e}();Object(m.a)(le);var ce=function(){function e(e){this.name=e.name,this.description=e.description,this.isTypeOf=e.isTypeOf,this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),this._fields=he.bind(void 0,e),this._interfaces=fe.bind(void 0,e),"string"===typeof e.name||Object(l.a)(0,"Must provide name."),null==e.isTypeOf||"function"===typeof e.isTypeOf||Object(l.a)(0,"".concat(this.name,' must provide "isTypeOf" as a function, ')+"but got: ".concat(Object(o.a)(e.isTypeOf),"."))}var t=e.prototype;return t.getFields=function(){return"function"===typeof this._fields&&(this._fields=this._fields()),this._fields},t.getInterfaces=function(){return"function"===typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces},t.toConfig=function(){return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:pe(this.getFields()),isTypeOf:this.isTypeOf,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes||[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLObjectType"}}]),e}();function fe(e){var t,n=null!==(t=se(e.interfaces))&&void 0!==t?t:[];return Array.isArray(n)||Object(l.a)(0,"".concat(e.name," interfaces must be an Array or a function which returns an Array.")),n}function he(e){var t=se(e.fields);return de(t)||Object(l.a)(0,"".concat(e.name," fields must be an object with field names as keys or a function which returns such an object.")),Object(s.a)(t,(function(t,n){var i;de(t)||Object(l.a)(0,"".concat(e.name,".").concat(n," field config must be an object.")),!("isDeprecated"in t)||Object(l.a)(0,"".concat(e.name,".").concat(n,' should provide "deprecationReason" instead of "isDeprecated".')),null==t.resolve||"function"===typeof t.resolve||Object(l.a)(0,"".concat(e.name,".").concat(n," field resolver must be a function if ")+"provided, but got: ".concat(Object(o.a)(t.resolve),"."));var a=null!==(i=t.args)&&void 0!==i?i:{};de(a)||Object(l.a)(0,"".concat(e.name,".").concat(n," args must be an object with argument names as keys."));var s=Object(r.a)(a).map((function(e){var t=e[0],n=e[1];return{name:t,description:n.description,type:n.type,defaultValue:n.defaultValue,deprecationReason:n.deprecationReason,extensions:n.extensions&&Object(u.a)(n.extensions),astNode:n.astNode}}));return{name:n,description:t.description,type:t.type,args:s,resolve:t.resolve,subscribe:t.subscribe,isDeprecated:null!=t.deprecationReason,deprecationReason:t.deprecationReason,extensions:t.extensions&&Object(u.a)(t.extensions),astNode:t.astNode}}))}function de(e){return Object(d.a)(e)&&!Array.isArray(e)}function pe(e){return Object(s.a)(e,(function(e){return{description:e.description,type:e.type,args:me(e.args),resolve:e.resolve,subscribe:e.subscribe,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode}}))}function me(e){return Object(c.a)(e,(function(e){return e.name}),(function(e){return{description:e.description,type:e.type,defaultValue:e.defaultValue,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode}}))}function ve(e){return B(e.type)&&void 0===e.defaultValue}Object(m.a)(ce);var ge=function(){function e(e){this.name=e.name,this.description=e.description,this.resolveType=e.resolveType,this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),this._fields=he.bind(void 0,e),this._interfaces=fe.bind(void 0,e),"string"===typeof e.name||Object(l.a)(0,"Must provide name."),null==e.resolveType||"function"===typeof e.resolveType||Object(l.a)(0,"".concat(this.name,' must provide "resolveType" as a function, ')+"but got: ".concat(Object(o.a)(e.resolveType),"."))}var t=e.prototype;return t.getFields=function(){return"function"===typeof this._fields&&(this._fields=this._fields()),this._fields},t.getInterfaces=function(){return"function"===typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces},t.toConfig=function(){var e;return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:pe(this.getFields()),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:null!==(e=this.extensionASTNodes)&&void 0!==e?e:[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLInterfaceType"}}]),e}();Object(m.a)(ge);var ye=function(){function e(e){this.name=e.name,this.description=e.description,this.resolveType=e.resolveType,this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),this._types=be.bind(void 0,e),"string"===typeof e.name||Object(l.a)(0,"Must provide name."),null==e.resolveType||"function"===typeof e.resolveType||Object(l.a)(0,"".concat(this.name,' must provide "resolveType" as a function, ')+"but got: ".concat(Object(o.a)(e.resolveType),"."))}var t=e.prototype;return t.getTypes=function(){return"function"===typeof this._types&&(this._types=this._types()),this._types},t.toConfig=function(){var e;return{name:this.name,description:this.description,types:this.getTypes(),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:null!==(e=this.extensionASTNodes)&&void 0!==e?e:[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLUnionType"}}]),e}();function be(e){var t=se(e.types);return Array.isArray(t)||Object(l.a)(0,"Must provide Array of types or a function which returns such an array for Union ".concat(e.name,".")),t}Object(m.a)(ye);var we=function(){function e(e){var t,n;this.name=e.name,this.description=e.description,this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),this._values=(t=this.name,de(n=e.values)||Object(l.a)(0,"".concat(t," values must be an object with value names as keys.")),Object(r.a)(n).map((function(e){var n=e[0],r=e[1];return de(r)||Object(l.a)(0,"".concat(t,".").concat(n,' must refer to an object with a "value" key ')+"representing an internal value but got: ".concat(Object(o.a)(r),".")),!("isDeprecated"in r)||Object(l.a)(0,"".concat(t,".").concat(n,' should provide "deprecationReason" instead of "isDeprecated".')),{name:n,description:r.description,value:void 0!==r.value?r.value:n,isDeprecated:null!=r.deprecationReason,deprecationReason:r.deprecationReason,extensions:r.extensions&&Object(u.a)(r.extensions),astNode:r.astNode}}))),this._valueLookup=new Map(this._values.map((function(e){return[e.value,e]}))),this._nameLookup=Object(a.a)(this._values,(function(e){return e.name})),"string"===typeof e.name||Object(l.a)(0,"Must provide name.")}var t=e.prototype;return t.getValues=function(){return this._values},t.getValue=function(e){return this._nameLookup[e]},t.serialize=function(e){var t=this._valueLookup.get(e);if(void 0===t)throw new g.a('Enum "'.concat(this.name,'" cannot represent value: ').concat(Object(o.a)(e)));return t.name},t.parseValue=function(e){if("string"!==typeof e){var t=Object(o.a)(e);throw new g.a('Enum "'.concat(this.name,'" cannot represent non-string value: ').concat(t,".")+_e(this,t))}var n=this.getValue(e);if(null==n)throw new g.a('Value "'.concat(e,'" does not exist in "').concat(this.name,'" enum.')+_e(this,e));return n.value},t.parseLiteral=function(e,t){if(e.kind!==y.a.ENUM){var n=Object(b.a)(e);throw new g.a('Enum "'.concat(this.name,'" cannot represent non-enum value: ').concat(n,".")+_e(this,n),e)}var r=this.getValue(e.value);if(null==r){var i=Object(b.a)(e);throw new g.a('Value "'.concat(i,'" does not exist in "').concat(this.name,'" enum.')+_e(this,i),e)}return r.value},t.toConfig=function(){var e,t=Object(c.a)(this.getValues(),(function(e){return e.name}),(function(e){return{description:e.description,value:e.value,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode}}));return{name:this.name,description:this.description,values:t,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:null!==(e=this.extensionASTNodes)&&void 0!==e?e:[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLEnumType"}}]),e}();function _e(e,t){var n=e.getValues().map((function(e){return e.name})),r=Object(v.a)(t,n);return Object(h.a)("the enum value",r)}Object(m.a)(we);var Me=function(){function e(e){this.name=e.name,this.description=e.description,this.extensions=e.extensions&&Object(u.a)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=ue(e.extensionASTNodes),this._fields=Ee.bind(void 0,e),"string"===typeof e.name||Object(l.a)(0,"Must provide name.")}var t=e.prototype;return t.getFields=function(){return"function"===typeof this._fields&&(this._fields=this._fields()),this._fields},t.toConfig=function(){var e,t=Object(s.a)(this.getFields(),(function(e){return{description:e.description,type:e.type,defaultValue:e.defaultValue,extensions:e.extensions,astNode:e.astNode}}));return{name:this.name,description:this.description,fields:t,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:null!==(e=this.extensionASTNodes)&&void 0!==e?e:[]}},t.toString=function(){return this.name},t.toJSON=function(){return this.toString()},M(e,[{key:i.c,get:function(){return"GraphQLInputObjectType"}}]),e}();function Ee(e){var t=se(e.fields);return de(t)||Object(l.a)(0,"".concat(e.name," fields must be an object with field names as keys or a function which returns such an object.")),Object(s.a)(t,(function(t,n){return!("resolve"in t)||Object(l.a)(0,"".concat(e.name,".").concat(n," field has a resolve property, but Input Types cannot define resolvers.")),{name:n,description:t.description,type:t.type,defaultValue:t.defaultValue,deprecationReason:t.deprecationReason,extensions:t.extensions&&Object(u.a)(t.extensions),astNode:t.astNode}}))}function Se(e){return B(e.type)&&void 0===e.defaultValue}Object(m.a)(Me)},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},function(e,t,n){"use strict";n.d(t,"a",(function(){return v})),n.d(t,"b",(function(){return g}));var r=n(31),i=n(28),o=n(136),a=n(226);function s(e){return(s="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function u(e,t){for(var n=0;n2)return"[Array]";for(var n=Math.min(10,e.length),r=e.length-n,i=[],o=0;o1&&i.push("... ".concat(r," more items"));return"["+i.join(", ")+"]"}(e,n);return function(e,t){var n=Object.keys(e);if(0===n.length)return"{}";if(t.length>2)return"["+function(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"===typeof e.constructor){var n=e.constructor.name;if("string"===typeof n&&""!==n)return n}return t}(e)+"]";return"{ "+n.map((function(n){return n+": "+a(e[n],t)})).join(", ")+" }"}(e,n)}(e,t);default:return String(e)}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=Object.freeze({SOF:"",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"})},function(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1])||arguments[1],r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=null,o=null;if("string"===typeof e){var a=new RegExp(e,r?"i":"g");o=a.test(n._sourceText.substr(n._pos,e.length)),i=e}else e instanceof RegExp&&(i=(o=n._sourceText.slice(n._pos).match(e))&&o[0]);return!(null==o||!("string"===typeof e||o instanceof Array&&n._sourceText.startsWith(o[0],n._pos)))&&(t&&(n._start=n._pos,i&&i.length&&(n._pos+=i.length)),o)},this.backUp=function(e){n._pos-=e},this.column=function(){return n._pos},this.indentation=function(){var e=n._sourceText.match(/\s*/),t=0;if(e&&0!==e.length)for(var r=e[0],i=0;r.length>i;)9===r.charCodeAt(i)?t+=2:t++,i++;return t},this.current=function(){return n._sourceText.slice(n._start,n._pos)},this._start=0,this._pos=0,this._sourceText=t}return Object(i.a)(e,[{key:"_testNextCharacter",value:function(e){var t=this._sourceText.charAt(this._pos);return"string"===typeof e?t===e:e instanceof RegExp?e.test(t):e(t)}}]),e}();function a(e){return{ofRule:e}}function s(e,t){return{ofRule:e,isList:!0,separator:t}}function u(e,t){var n=e.match;return e.match=function(e){var r=!1;return n&&(r=n(e)),r&&t.every((function(t){return t.match&&!t.match(e)}))},e}function l(e,t){return{style:t,match:function(t){return t.kind===e}}}function c(e,t){return{style:t||"punctuation",match:function(t){return"Punctuation"===t.kind&&t.value===e}}}var f,h=function(e){return" "===e||"\t"===e||","===e||"\n"===e||"\r"===e||"\ufeff"===e||"\xa0"===e},d={Name:/^[_A-Za-z][_0-9A-Za-z]*/,Punctuation:/^(?:!|\$|\(|\)|\.\.\.|:|=|&|@|\[|]|\{|\||\})/,Number:/^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,String:/^(?:"""(?:\\"""|[^"]|"[^"]|""[^"])*(?:""")?|"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?)/,Comment:/^#.*/},p={Document:[s("Definition")],Definition:function(e){switch(e.value){case"{":return"ShortQuery";case"query":return"Query";case"mutation":return"Mutation";case"subscription":return"Subscription";case"fragment":return"FragmentDefinition";case"schema":return"SchemaDef";case"scalar":return"ScalarDef";case"type":return"ObjectTypeDef";case"interface":return"InterfaceDef";case"union":return"UnionDef";case"enum":return"EnumDef";case"input":return"InputDef";case"extend":return"ExtendDef";case"directive":return"DirectiveDef"}},ShortQuery:["SelectionSet"],Query:[m("query"),a(v("def")),a("VariableDefinitions"),s("Directive"),"SelectionSet"],Mutation:[m("mutation"),a(v("def")),a("VariableDefinitions"),s("Directive"),"SelectionSet"],Subscription:[m("subscription"),a(v("def")),a("VariableDefinitions"),s("Directive"),"SelectionSet"],VariableDefinitions:[c("("),s("VariableDefinition"),c(")")],VariableDefinition:["Variable",c(":"),"Type",a("DefaultValue")],Variable:[c("$","variable"),v("variable")],DefaultValue:[c("="),"Value"],SelectionSet:[c("{"),s("Selection"),c("}")],Selection:function(e,t){return"..."===e.value?t.match(/[\s\u00a0,]*(on\b|@|{)/,!1)?"InlineFragment":"FragmentSpread":t.match(/[\s\u00a0,]*:/,!1)?"AliasedField":"Field"},AliasedField:[v("property"),c(":"),v("qualifier"),a("Arguments"),s("Directive"),a("SelectionSet")],Field:[v("property"),a("Arguments"),s("Directive"),a("SelectionSet")],Arguments:[c("("),s("Argument"),c(")")],Argument:[v("attribute"),c(":"),"Value"],FragmentSpread:[c("..."),v("def"),s("Directive")],InlineFragment:[c("..."),a("TypeCondition"),s("Directive"),"SelectionSet"],FragmentDefinition:[m("fragment"),a(u(v("def"),[m("on")])),"TypeCondition",s("Directive"),"SelectionSet"],TypeCondition:[m("on"),"NamedType"],Value:function(e){switch(e.kind){case"Number":return"NumberValue";case"String":return"StringValue";case"Punctuation":switch(e.value){case"[":return"ListValue";case"{":return"ObjectValue";case"$":return"Variable";case"&":return"NamedType"}return null;case"Name":switch(e.value){case"true":case"false":return"BooleanValue"}return"null"===e.value?"NullValue":"EnumValue"}},NumberValue:[l("Number","number")],StringValue:[l("String","string")],BooleanValue:[l("Name","builtin")],NullValue:[l("Name","keyword")],EnumValue:[v("string-2")],ListValue:[c("["),s("Value"),c("]")],ObjectValue:[c("{"),s("ObjectField"),c("}")],ObjectField:[v("attribute"),c(":"),"Value"],Type:function(e){return"["===e.value?"ListType":"NonNullType"},ListType:[c("["),"Type",c("]"),a(c("!"))],NonNullType:["NamedType",a(c("!"))],NamedType:[(f="atom",{style:f,match:function(e){return"Name"===e.kind},update:function(e,t){e.prevState&&e.prevState.prevState&&(e.name=t.value,e.prevState.prevState.type=t.value)}})],Directive:[c("@","meta"),v("meta"),a("Arguments")],DirectiveDef:[m("directive"),c("@","meta"),v("meta"),a("ArgumentsDef"),m("on"),s("DirectiveLocation",c("|"))],InterfaceDef:[m("interface"),v("atom"),a("Implements"),s("Directive"),c("{"),s("FieldDef"),c("}")],Implements:[m("implements"),s("NamedType",c("&"))],DirectiveLocation:[v("string-2")],SchemaDef:[m("schema"),s("Directive"),c("{"),s("OperationTypeDef"),c("}")],OperationTypeDef:[v("keyword"),c(":"),v("atom")],ScalarDef:[m("scalar"),v("atom"),s("Directive")],ObjectTypeDef:[m("type"),v("atom"),a("Implements"),s("Directive"),c("{"),s("FieldDef"),c("}")],FieldDef:[v("property"),a("ArgumentsDef"),c(":"),"Type",s("Directive")],ArgumentsDef:[c("("),s("InputValueDef"),c(")")],InputValueDef:[v("attribute"),c(":"),"Type",a("DefaultValue"),s("Directive")],UnionDef:[m("union"),v("atom"),s("Directive"),c("="),s("UnionMember",c("|"))],UnionMember:["NamedType"],EnumDef:[m("enum"),v("atom"),s("Directive"),c("{"),s("EnumValueDef"),c("}")],EnumValueDef:[v("string-2"),s("Directive")],InputDef:[m("input"),v("atom"),s("Directive"),c("{"),s("InputValueDef"),c("}")],ExtendDef:[m("extend"),"ObjectTypeDef"]};function m(e){return{style:"keyword",match:function(t){return"Name"===t.kind&&t.value===e}}}function v(e){return{style:e,match:function(e){return"Name"===e.kind},update:function(e,t){e.name=t.value}}}function g(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{eatWhitespace:function(e){return e.eatWhile(h)},lexRules:d,parseRules:p,editorConfig:{}};return{startState:function(){var t={level:0,step:0,name:null,kind:null,type:null,rule:null,needsSeperator:!1,prevState:null};return _(e.parseRules,t,"Document"),t},token:function(t,n){return y(t,n,e)}}}function y(e,t,n){var r=n.lexRules,i=n.parseRules,o=n.eatWhitespace,a=n.editorConfig;if(t.rule&&0===t.rule.length?M(t):t.needsAdvance&&(t.needsAdvance=!1,E(t,!0)),e.sol()){var s=a&&a.tabSize||2;t.indentLevel=Math.floor(e.indentation()/s)}if(o(e))return"ws";var u=function(e,t){for(var n=Object.keys(e),r=0;r0&&c[c.length-1]=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}},function(e,t){"function"===typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},function(e,t,n){"use strict";n.r(t),n.d(t,"__Schema",(function(){return f})),n.d(t,"__Directive",(function(){return h})),n.d(t,"__DirectiveLocation",(function(){return d})),n.d(t,"__Type",(function(){return p})),n.d(t,"__Field",(function(){return m})),n.d(t,"__InputValue",(function(){return v})),n.d(t,"__EnumValue",(function(){return g})),n.d(t,"TypeKind",(function(){return y})),n.d(t,"__TypeKind",(function(){return b})),n.d(t,"SchemaMetaFieldDef",(function(){return w})),n.d(t,"TypeMetaFieldDef",(function(){return _})),n.d(t,"TypeNameMetaFieldDef",(function(){return M})),n.d(t,"introspectionTypes",(function(){return E})),n.d(t,"isIntrospectionType",(function(){return S}));var r=n(16),i=n(4),o=n(15),a=n(17),s=n(8),u=n(84),l=n(13),c=n(1),f=new c.f({name:"__Schema",description:"A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",fields:function(){return{description:{type:l.e,resolve:function(e){return e.description}},types:{description:"A list of all types supported by this server.",type:new c.e(new c.d(new c.e(p))),resolve:function(e){return Object(r.a)(e.getTypeMap())}},queryType:{description:"The type that query operations will be rooted at.",type:new c.e(p),resolve:function(e){return e.getQueryType()}},mutationType:{description:"If this server supports mutation, the type that mutation operations will be rooted at.",type:p,resolve:function(e){return e.getMutationType()}},subscriptionType:{description:"If this server support subscription, the type that subscription operations will be rooted at.",type:p,resolve:function(e){return e.getSubscriptionType()}},directives:{description:"A list of all directives supported by this server.",type:new c.e(new c.d(new c.e(h))),resolve:function(e){return e.getDirectives()}}}}}),h=new c.f({name:"__Directive",description:"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",fields:function(){return{name:{type:new c.e(l.e),resolve:function(e){return e.name}},description:{type:l.e,resolve:function(e){return e.description}},isRepeatable:{type:new c.e(l.a),resolve:function(e){return e.isRepeatable}},locations:{type:new c.e(new c.d(new c.e(d))),resolve:function(e){return e.locations}},args:{type:new c.e(new c.d(new c.e(v))),resolve:function(e){return e.args}}}}}),d=new c.a({name:"__DirectiveLocation",description:"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",values:{QUERY:{value:s.a.QUERY,description:"Location adjacent to a query operation."},MUTATION:{value:s.a.MUTATION,description:"Location adjacent to a mutation operation."},SUBSCRIPTION:{value:s.a.SUBSCRIPTION,description:"Location adjacent to a subscription operation."},FIELD:{value:s.a.FIELD,description:"Location adjacent to a field."},FRAGMENT_DEFINITION:{value:s.a.FRAGMENT_DEFINITION,description:"Location adjacent to a fragment definition."},FRAGMENT_SPREAD:{value:s.a.FRAGMENT_SPREAD,description:"Location adjacent to a fragment spread."},INLINE_FRAGMENT:{value:s.a.INLINE_FRAGMENT,description:"Location adjacent to an inline fragment."},VARIABLE_DEFINITION:{value:s.a.VARIABLE_DEFINITION,description:"Location adjacent to a variable definition."},SCHEMA:{value:s.a.SCHEMA,description:"Location adjacent to a schema definition."},SCALAR:{value:s.a.SCALAR,description:"Location adjacent to a scalar definition."},OBJECT:{value:s.a.OBJECT,description:"Location adjacent to an object type definition."},FIELD_DEFINITION:{value:s.a.FIELD_DEFINITION,description:"Location adjacent to a field definition."},ARGUMENT_DEFINITION:{value:s.a.ARGUMENT_DEFINITION,description:"Location adjacent to an argument definition."},INTERFACE:{value:s.a.INTERFACE,description:"Location adjacent to an interface definition."},UNION:{value:s.a.UNION,description:"Location adjacent to a union definition."},ENUM:{value:s.a.ENUM,description:"Location adjacent to an enum definition."},ENUM_VALUE:{value:s.a.ENUM_VALUE,description:"Location adjacent to an enum value definition."},INPUT_OBJECT:{value:s.a.INPUT_OBJECT,description:"Location adjacent to an input object type definition."},INPUT_FIELD_DEFINITION:{value:s.a.INPUT_FIELD_DEFINITION,description:"Location adjacent to an input object field definition."}}}),p=new c.f({name:"__Type",description:"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name, description and optional `specifiedByUrl`, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",fields:function(){return{kind:{type:new c.e(b),resolve:function(e){return Object(c.R)(e)?y.SCALAR:Object(c.N)(e)?y.OBJECT:Object(c.H)(e)?y.INTERFACE:Object(c.T)(e)?y.UNION:Object(c.E)(e)?y.ENUM:Object(c.F)(e)?y.INPUT_OBJECT:Object(c.J)(e)?y.LIST:Object(c.L)(e)?y.NON_NULL:void Object(o.a)(0,'Unexpected type: "'.concat(Object(i.a)(e),'".'))}},name:{type:l.e,resolve:function(e){return void 0!==e.name?e.name:void 0}},description:{type:l.e,resolve:function(e){return void 0!==e.description?e.description:void 0}},specifiedByUrl:{type:l.e,resolve:function(e){return void 0!==e.specifiedByUrl?e.specifiedByUrl:void 0}},fields:{type:new c.d(new c.e(m)),args:{includeDeprecated:{type:l.a,defaultValue:!1}},resolve:function(e,t){var n=t.includeDeprecated;if(Object(c.N)(e)||Object(c.H)(e)){var i=Object(r.a)(e.getFields());return n?i:i.filter((function(e){return null==e.deprecationReason}))}}},interfaces:{type:new c.d(new c.e(p)),resolve:function(e){if(Object(c.N)(e)||Object(c.H)(e))return e.getInterfaces()}},possibleTypes:{type:new c.d(new c.e(p)),resolve:function(e,t,n,r){var i=r.schema;if(Object(c.C)(e))return i.getPossibleTypes(e)}},enumValues:{type:new c.d(new c.e(g)),args:{includeDeprecated:{type:l.a,defaultValue:!1}},resolve:function(e,t){var n=t.includeDeprecated;if(Object(c.E)(e)){var r=e.getValues();return n?r:r.filter((function(e){return null==e.deprecationReason}))}}},inputFields:{type:new c.d(new c.e(v)),args:{includeDeprecated:{type:l.a,defaultValue:!1}},resolve:function(e,t){var n=t.includeDeprecated;if(Object(c.F)(e)){var i=Object(r.a)(e.getFields());return n?i:i.filter((function(e){return null==e.deprecationReason}))}}},ofType:{type:p,resolve:function(e){return void 0!==e.ofType?e.ofType:void 0}}}}}),m=new c.f({name:"__Field",description:"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",fields:function(){return{name:{type:new c.e(l.e),resolve:function(e){return e.name}},description:{type:l.e,resolve:function(e){return e.description}},args:{type:new c.e(new c.d(new c.e(v))),args:{includeDeprecated:{type:l.a,defaultValue:!1}},resolve:function(e,t){return t.includeDeprecated?e.args:e.args.filter((function(e){return null==e.deprecationReason}))}},type:{type:new c.e(p),resolve:function(e){return e.type}},isDeprecated:{type:new c.e(l.a),resolve:function(e){return null!=e.deprecationReason}},deprecationReason:{type:l.e,resolve:function(e){return e.deprecationReason}}}}}),v=new c.f({name:"__InputValue",description:"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",fields:function(){return{name:{type:new c.e(l.e),resolve:function(e){return e.name}},description:{type:l.e,resolve:function(e){return e.description}},type:{type:new c.e(p),resolve:function(e){return e.type}},defaultValue:{type:l.e,description:"A GraphQL-formatted string representing the default value for this input value.",resolve:function(e){var t=e.type,n=e.defaultValue,r=Object(u.a)(n,t);return r?Object(a.a)(r):null}},isDeprecated:{type:new c.e(l.a),resolve:function(e){return null!=e.deprecationReason}},deprecationReason:{type:l.e,resolve:function(e){return e.deprecationReason}}}}}),g=new c.f({name:"__EnumValue",description:"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",fields:function(){return{name:{type:new c.e(l.e),resolve:function(e){return e.name}},description:{type:l.e,resolve:function(e){return e.description}},isDeprecated:{type:new c.e(l.a),resolve:function(e){return null!=e.deprecationReason}},deprecationReason:{type:l.e,resolve:function(e){return e.deprecationReason}}}}}),y=Object.freeze({SCALAR:"SCALAR",OBJECT:"OBJECT",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",INPUT_OBJECT:"INPUT_OBJECT",LIST:"LIST",NON_NULL:"NON_NULL"}),b=new c.a({name:"__TypeKind",description:"An enum describing what kind of type a given `__Type` is.",values:{SCALAR:{value:y.SCALAR,description:"Indicates this type is a scalar."},OBJECT:{value:y.OBJECT,description:"Indicates this type is an object. `fields` and `interfaces` are valid fields."},INTERFACE:{value:y.INTERFACE,description:"Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields."},UNION:{value:y.UNION,description:"Indicates this type is a union. `possibleTypes` is a valid field."},ENUM:{value:y.ENUM,description:"Indicates this type is an enum. `enumValues` is a valid field."},INPUT_OBJECT:{value:y.INPUT_OBJECT,description:"Indicates this type is an input object. `inputFields` is a valid field."},LIST:{value:y.LIST,description:"Indicates this type is a list. `ofType` is a valid field."},NON_NULL:{value:y.NON_NULL,description:"Indicates this type is a non-null. `ofType` is a valid field."}}}),w={name:"__schema",type:new c.e(f),description:"Access the current type schema of this server.",args:[],resolve:function(e,t,n,r){return r.schema},isDeprecated:!1,deprecationReason:void 0,extensions:void 0,astNode:void 0},_={name:"__type",type:p,description:"Request the type information of a single type.",args:[{name:"name",description:void 0,type:new c.e(l.e),defaultValue:void 0,deprecationReason:void 0,extensions:void 0,astNode:void 0}],resolve:function(e,t,n,r){var i=t.name;return r.schema.getType(i)},isDeprecated:!1,deprecationReason:void 0,extensions:void 0,astNode:void 0},M={name:"__typename",type:new c.e(l.e),description:"The name of the current Object type at runtime.",args:[],resolve:function(e,t,n,r){return r.parentType.name},isDeprecated:!1,deprecationReason:void 0,extensions:void 0,astNode:void 0},E=Object.freeze([f,h,d,p,m,v,g,b]);function S(e){return E.some((function(t){var n=t.name;return e.name===n}))}},function(e,t,n){"use strict";n.d(t,"d",(function(){return d})),n.d(t,"b",(function(){return p})),n.d(t,"e",(function(){return v})),n.d(t,"a",(function(){return g})),n.d(t,"c",(function(){return y})),n.d(t,"g",(function(){return b})),n.d(t,"f",(function(){return w}));var r=n(97),i=Number.isInteger||function(e){return"number"===typeof e&&isFinite(e)&&Math.floor(e)===e},o=n(4),a=n(31),s=n(2),u=n(17),l=n(3),c=n(1),f=2147483647,h=-2147483648;var d=new c.g({name:"Int",description:"The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",serialize:function(e){var t=m(e);if("boolean"===typeof t)return t?1:0;var n=t;if("string"===typeof t&&""!==t&&(n=Number(t)),!i(n))throw new l.a("Int cannot represent non-integer value: ".concat(Object(o.a)(t)));if(n>f||nf||ef||t80&&(s=a+c("(\n",f(u(r,"\n")),"\n)")),u([s,u(i," "),o]," ")},Argument:function(e){return e.name+": "+e.value},FragmentSpread:function(e){return"..."+e.name+c(" ",u(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return u(["...",c("on ",t),u(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,o=e.selectionSet;return"fragment ".concat(t).concat(c("(",u(r,", "),")")," ")+"on ".concat(n," ").concat(c("",u(i," ")," "))+o},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?Object(i.c)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+u(e.values,", ")+"]"},ObjectValue:function(e){return"{"+u(e.fields,", ")+"}"},ObjectField:function(e){return e.name+": "+e.value},Directive:function(e){return"@"+e.name+c("(",u(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:s((function(e){var t=e.directives,n=e.operationTypes;return u(["schema",u(t," "),l(n)]," ")})),OperationTypeDefinition:function(e){return e.operation+": "+e.type},ScalarTypeDefinition:s((function(e){return u(["scalar",e.name,u(e.directives," ")]," ")})),ObjectTypeDefinition:s((function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return u(["type",t,c("implements ",u(n," & ")),u(r," "),l(i)]," ")})),FieldDefinition:s((function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(d(n)?c("(\n",f(u(n,"\n")),"\n)"):c("(",u(n,", "),")"))+": "+r+c(" ",u(i," "))})),InputValueDefinition:s((function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return u([t+": "+n,c("= ",r),u(i," ")]," ")})),InterfaceTypeDefinition:s((function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return u(["interface",t,c("implements ",u(n," & ")),u(r," "),l(i)]," ")})),UnionTypeDefinition:s((function(e){var t=e.name,n=e.directives,r=e.types;return u(["union",t,u(n," "),r&&0!==r.length?"= "+u(r," | "):""]," ")})),EnumTypeDefinition:s((function(e){var t=e.name,n=e.directives,r=e.values;return u(["enum",t,u(n," "),l(r)]," ")})),EnumValueDefinition:s((function(e){return u([e.name,u(e.directives," ")]," ")})),InputObjectTypeDefinition:s((function(e){var t=e.name,n=e.directives,r=e.fields;return u(["input",t,u(n," "),l(r)]," ")})),DirectiveDefinition:s((function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(d(n)?c("(\n",f(u(n,"\n")),"\n)"):c("(",u(n,", "),")"))+(r?" repeatable":"")+" on "+u(i," | ")})),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return u(["extend schema",u(t," "),l(n)]," ")},ScalarTypeExtension:function(e){return u(["extend scalar",e.name,u(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return u(["extend type",t,c("implements ",u(n," & ")),u(r," "),l(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return u(["extend interface",t,c("implements ",u(n," & ")),u(r," "),l(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return u(["extend union",t,u(n," "),r&&0!==r.length?"= "+u(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return u(["extend enum",t,u(n," "),l(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return u(["extend input",t,u(n," "),l(r)]," ")}};function s(e){return function(t){return u([t.description,e(t)],"\n")}}function u(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null===e||void 0===e?void 0:e.filter((function(e){return e})).join(n))&&void 0!==t?t:""}function l(e){return c("{\n",f(u(e,"\n")),"\n}")}function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function f(e){return c(" ",e.replace(/\n/g,"\n "))}function h(e){return-1!==e.indexOf("\n")}function d(e){return null!=e&&e.some(h)}},function(e,t,n){var r=n(33),i=r.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function a(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(o(r,t),t.Buffer=a),o(i,a),a.from=function(e,t,n){if("number"===typeof e)throw new TypeError("Argument must not be a number");return i(e,t,n)},a.alloc=function(e,t,n){if("number"!==typeof e)throw new TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"===typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},a.allocUnsafe=function(e){if("number"!==typeof e)throw new TypeError("Argument must be a number");return i(e)},a.allocUnsafeSlow=function(e){if("number"!==typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){e.exports=n(389)},function(e,t,n){e.exports=function(){"use strict";var e=navigator.userAgent,t=navigator.platform,n=/gecko\/\d/i.test(e),r=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),a=r||i||o,s=a&&(r?document.documentMode||6:+(o||i)[1]),u=!o&&/WebKit\//.test(e),l=u&&/Qt\/\d+\.\d+/.test(e),c=!o&&/Chrome\//.test(e),f=/Opera\//.test(e),h=/Apple Computer/.test(navigator.vendor),d=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),m=h&&(/Mobile\/\w+/.test(e)||navigator.maxTouchPoints>2),v=/Android/.test(e),g=m||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=m||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),_=f&&e.match(/Version\/(\d*\.\d*)/);_&&(_=Number(_[1])),_&&_>=15&&(f=!1,u=!0);var M=y&&(l||f&&(null==_||_<12.11)),E=n||a&&s>=9;function S(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var x,k=function(e,t){var n=e.className,r=S(t).exec(n);if(r){var i=n.slice(r.index+r[0].length);e.className=n.slice(0,r.index)+(i?r[1]+i:"")}};function T(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function C(e,t){return T(e).appendChild(t)}function O(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return a+(t-o);a+=s-o,a+=n-a%n,o=s+1}}m?R=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:a&&(R=function(e){try{e.select()}catch(t){}});var B=function(){this.id=null,this.f=null,this.time=0,this.handler=j(this.onTimeout,this)};function V(e,t){for(var n=0;n=t)return r+Math.min(a,t-i);if(i+=o-r,r=o+1,(i+=n-i%n)>=t)return r}}var K=[""];function Y(e){for(;K.length<=e;)K.push(Q(K)+" ");return K[e]}function Q(e){return e[e.length-1]}function Z(e,t){for(var n=[],r=0;r"\x80"&&(e.toUpperCase()!=e.toLowerCase()||ee.test(e))}function ne(e,t){return t?!!(t.source.indexOf("\\w")>-1&&te(e))||t.test(e):te(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var ie=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function oe(e){return e.charCodeAt(0)>=768&&ie.test(e)}function ae(e,t,n){for(;(n<0?t>0:tn?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}function ue(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;ot||t==n&&a.to==t)&&(r(Math.max(a.from,t),Math.min(a.to,n),1==a.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}var le=null;function ce(e,t,n){var r;le=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:le=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:le=i)}return null!=r?r:le}var fe=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";function n(n){return n<=247?e.charAt(n):1424<=n&&n<=1524?"R":1536<=n&&n<=1785?t.charAt(n-1536):1774<=n&&n<=2220?"r":8192<=n&&n<=8203?"w":8204==n?"b":"L"}var r=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,i=/[stwN]/,o=/[LRr]/,a=/[Lb1n]/,s=/[1n]/;function u(e,t,n){this.level=e,this.from=t,this.to=n}return function(e,t){var l="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!r.test(e))return!1;for(var c=e.length,f=[],h=0;h-1&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ge(e,t){var n=me(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i0}function _e(e){e.prototype.on=function(e,t){pe(this,e,t)},e.prototype.off=function(e,t){ve(this,e,t)}}function Me(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ee(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Se(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function xe(e){Me(e),Ee(e)}function ke(e){return e.target||e.srcElement}function Te(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Ce,Oe,Ae=function(){if(a&&s<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function De(e){if(null==Ce){var t=O("span","\u200b");C(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Ce=t.offsetWidth<=1&&t.offsetHeight>2&&!(a&&s<8))}var n=Ce?O("span","\u200b"):O("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}function Pe(e){if(null!=Oe)return Oe;var t=C(e,document.createTextNode("A\u062eA")),n=x(t,0,1).getBoundingClientRect(),r=x(t,1,2).getBoundingClientRect();return T(e),!(!n||n.left==n.right)&&(Oe=r.right-n.right<3)}var Ie=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),a=o.indexOf("\r");-1!=a?(n.push(o.slice(0,a)),t+=a+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},Ne=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(t){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(n){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Re=function(){var e=O("div");return"oncopy"in e||(e.setAttribute("oncopy","return;"),"function"==typeof e.oncopy)}(),je=null;function Le(e){if(null!=je)return je;var t=C(e,O("span","x")),n=t.getBoundingClientRect(),r=x(t,0,1).getBoundingClientRect();return je=Math.abs(n.left-r.left)>1}var Fe={},Be={};function Ve(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Fe[e]=t}function ze(e,t){Be[e]=t}function Ue(e){if("string"==typeof e&&Be.hasOwnProperty(e))e=Be[e];else if(e&&"string"==typeof e.name&&Be.hasOwnProperty(e.name)){var t=Be[e.name];"string"==typeof t&&(t={name:t}),(e=X(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ue("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ue("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function qe(e,t){t=Ue(t);var n=Fe[t.name];if(!n)return qe(e,"text/plain");var r=n(e,t);if(He.hasOwnProperty(t.name)){var i=He[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)r[a]=t.modeProps[a];return r}var He={};function Ge(e,t){L(t,He.hasOwnProperty(e)?He[e]:He[e]={})}function We(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function Ke(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function Ye(e,t,n){return!e.startState||e.startState(t,n)}var Qe=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Ze(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t=e.first&&tn?it(n,Ze(e,n).text.length):ht(t,Ze(e,t.line).text.length)}function ht(e,t){var n=e.ch;return null==n||n>t?it(e.line,t):n<0?it(e.line,0):e}function dt(e,t){for(var n=[],r=0;r=this.string.length},Qe.prototype.sol=function(){return this.pos==this.lineStart},Qe.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Qe.prototype.next=function(){if(this.post},Qe.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Qe.prototype.skipToEnd=function(){this.pos=this.string.length},Qe.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Qe.prototype.backUp=function(e){this.pos-=e},Qe.prototype.column=function(){return this.lastColumnPos0?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}var i=function(e){return n?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},Qe.prototype.current=function(){return this.string.slice(this.start,this.pos)},Qe.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Qe.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Qe.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var pt=function(e,t){this.state=e,this.lookAhead=t},mt=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function vt(e,t,n,r){var i=[e.state.modeGen],o={};xt(e,t.text,e.doc.mode,n,(function(e,t){return i.push(e,t)}),o,r);for(var a=n.state,s=function(r){n.baseTokens=i;var s=e.state.overlays[r],u=1,l=0;n.state=!0,xt(e,t.text,s.mode,n,(function(e,t){for(var n=u;le&&i.splice(u,1,e,i[u+1],r),u+=2,l=Math.min(e,r)}if(t)if(s.opaque)i.splice(n,u-n,e,"overlay "+t),u=n+2;else for(;ne.options.maxHighlightLength&&We(e.doc.mode,r.state),o=vt(e,t,r);i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function yt(e,t,n){var r=e.doc,i=e.display;if(!r.mode.startState)return new mt(r,!0,t);var o=kt(e,t,n),a=o>r.first&&Ze(r,o-1).stateAfter,s=a?mt.fromSaved(r,a,o):new mt(r,Ye(r.mode),o);return r.iter(o,t,(function(n){bt(e,n.text,s);var r=s.line;n.stateAfter=r==t-1||r%5==0||r>=i.viewFrom&&rt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}mt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},mt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},mt.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},mt.fromSaved=function(e,t,n){return t instanceof pt?new mt(e,We(e.mode,t.state),n,t.lookAhead):new mt(e,We(e.mode,t),n)},mt.prototype.save=function(e){var t=!1!==e?We(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new pt(t,this.maxLookAhead):t};var Mt=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Et(e,t,n,r){var i,o,a=e.doc,s=a.mode,u=Ze(a,(t=ft(a,t)).line),l=yt(e,t.line,n),c=new Qe(u.text,e.options.tabSize,l);for(r&&(o=[]);(r||c.pose.options.maxHighlightLength?(s=!1,a&&bt(e,t,r,f.pos),f.pos=t.length,u=null):u=St(_t(n,f,r.state,h),o),h){var d=h[0].name;d&&(u="m-"+(u?d+" "+u:d))}if(!s||c!=u){for(;la;--s){if(s<=o.first)return o.first;var u=Ze(o,s-1),l=u.stateAfter;if(l&&(!n||s+(l instanceof pt?l.lookAhead:0)<=o.modeFrontier))return s;var c=F(u.text,null,e.options.tabSize);(null==i||r>c)&&(i=s-1,r=c)}return i}function Tt(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontiern;r--){var i=Ze(e,r).stateAfter;if(i&&(!(i instanceof pt)||r+i.lookAhead=t:o.to>t);(r||(r=[])).push(new Pt(a,o.from,s?null:o.to))}}return r}function Lt(e,t,n){var r;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==a.type&&(!n||o.marker.insertLeft)){var s=null==o.from||(a.inclusiveLeft?o.from<=t:o.from0&&s)for(var b=0;b0)){var c=[u,1],f=ot(l.from,s.from),h=ot(l.to,s.to);(f<0||!a.inclusiveLeft&&!f)&&c.push({from:l.from,to:s.from}),(h>0||!a.inclusiveRight&&!h)&&c.push({from:s.to,to:l.to}),i.splice.apply(i,c),u+=c.length-3}}return i}function zt(e){var t=e.markedSpans;if(t){for(var n=0;nt)&&(!n||Gt(n,o.marker)<0)&&(n=o.marker)}return n}function Zt(e,t,n,r,i){var o=Ze(e,t),a=Ot&&o.markedSpans;if(a)for(var s=0;s=0&&f<=0||c<=0&&f>=0)&&(c<=0&&(u.marker.inclusiveRight&&i.inclusiveLeft?ot(l.to,n)>=0:ot(l.to,n)>0)||c>=0&&(u.marker.inclusiveRight&&i.inclusiveLeft?ot(l.from,r)<=0:ot(l.from,r)<0)))return!0}}}function $t(e){for(var t;t=Kt(e);)e=t.find(-1,!0).line;return e}function Jt(e){for(var t;t=Yt(e);)e=t.find(1,!0).line;return e}function Xt(e){for(var t,n;t=Yt(e);)e=t.find(1,!0).line,(n||(n=[])).push(e);return n}function en(e,t){var n=Ze(e,t),r=$t(n);return n==r?t:et(r)}function tn(e,t){if(t>e.lastLine())return t;var n,r=Ze(e,t);if(!nn(e,r))return t;for(;n=Yt(r);)r=n.find(1,!0).line;return et(r)+1}function nn(e,t){var n=Ot&&t.markedSpans;if(n)for(var r=void 0,i=0;it.maxLineLength&&(t.maxLineLength=n,t.maxLine=e)}))}var un=function(e,t,n){this.text=e,Ut(this,t),this.height=n?n(this):1};function ln(e,t,n,r){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),zt(e),Ut(e,n);var i=r?r(e):1;i!=e.height&&Xe(e,i)}function cn(e){e.parent=null,zt(e)}un.prototype.lineNo=function(){return et(this)},_e(un);var fn={},hn={};function dn(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?hn:fn;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function pn(e,t){var n=A("span",null,null,u?"padding-right: .1px":null),r={pre:A("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,a=void 0;r.pos=0,r.addToken=vn,Pe(e.display.measure)&&(a=he(o,e.doc.direction))&&(r.addToken=yn(r.addToken,a)),r.map=[],wn(o,r,gt(e,o,t!=e.display.externalMeasured&&et(o))),o.styleClasses&&(o.styleClasses.bgClass&&(r.bgClass=N(o.styleClasses.bgClass,r.bgClass||"")),o.styleClasses.textClass&&(r.textClass=N(o.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(De(e.display.measure))),0==i?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(u){var s=r.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")}return ge(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=N(r.pre.className,r.textClass||"")),r}function mn(e){var t=O("span","\u2022","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function vn(e,t,n,r,i,o,u){if(t){var l,c=e.splitSpaces?gn(t,e.trailingSpace):t,f=e.cm.state.specialChars,h=!1;if(f.test(t)){l=document.createDocumentFragment();for(var d=0;;){f.lastIndex=d;var p=f.exec(t),m=p?p.index-d:t.length-d;if(m){var v=document.createTextNode(c.slice(d,d+m));a&&s<9?l.appendChild(O("span",[v])):l.appendChild(v),e.map.push(e.pos,e.pos+m,v),e.col+=m,e.pos+=m}if(!p)break;d+=m+1;var g=void 0;if("\t"==p[0]){var y=e.cm.options.tabSize,b=y-e.col%y;(g=l.appendChild(O("span",Y(b),"cm-tab"))).setAttribute("role","presentation"),g.setAttribute("cm-text","\t"),e.col+=b}else"\r"==p[0]||"\n"==p[0]?((g=l.appendChild(O("span","\r"==p[0]?"\u240d":"\u2424","cm-invalidchar"))).setAttribute("cm-text",p[0]),e.col+=1):((g=e.cm.options.specialCharPlaceholder(p[0])).setAttribute("cm-text",p[0]),a&&s<9?l.appendChild(O("span",[g])):l.appendChild(g),e.col+=1);e.map.push(e.pos,e.pos+1,g),e.pos++}}else e.col+=t.length,l=document.createTextNode(c),e.map.push(e.pos,e.pos+t.length,l),a&&s<9&&(h=!0),e.pos+=t.length;if(e.trailingSpace=32==c.charCodeAt(t.length-1),n||r||i||h||o||u){var w=n||"";r&&(w+=r),i&&(w+=i);var _=O("span",[l],w,o);if(u)for(var M in u)u.hasOwnProperty(M)&&"style"!=M&&"class"!=M&&_.setAttribute(M,u[M]);return e.content.appendChild(_)}e.content.appendChild(l)}}function gn(e,t){if(e.length>1&&!/ /.test(e))return e;for(var n=t,r="",i=0;il&&f.from<=l);h++);if(f.to>=c)return e(n,r,i,o,a,s,u);e(n,r.slice(0,f.to-l),i,o,null,s,u),o=null,r=r.slice(f.to-l),l=f.to}}}function bn(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",n.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function wn(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(r)for(var a,s,u,l,c,f,h,d=i.length,p=0,m=1,v="",g=0;;){if(g==p){u=l=c=s="",h=null,f=null,g=1/0;for(var y=[],b=void 0,w=0;wp||M.collapsed&&_.to==p&&_.from==p)){if(null!=_.to&&_.to!=p&&g>_.to&&(g=_.to,l=""),M.className&&(u+=" "+M.className),M.css&&(s=(s?s+";":"")+M.css),M.startStyle&&_.from==p&&(c+=" "+M.startStyle),M.endStyle&&_.to==g&&(b||(b=[])).push(M.endStyle,_.to),M.title&&((h||(h={})).title=M.title),M.attributes)for(var E in M.attributes)(h||(h={}))[E]=M.attributes[E];M.collapsed&&(!f||Gt(f.marker,M)<0)&&(f=_)}else _.from>p&&g>_.from&&(g=_.from)}if(b)for(var S=0;S=d)break;for(var k=Math.min(d,g);;){if(v){var T=p+v.length;if(!f){var C=T>k?v.slice(0,k-p):v;t.addToken(t,C,a?a+u:u,c,p+C.length==g?l:"",s,h)}if(T>=k){v=v.slice(k-p),p=k;break}p=T,c=""}v=i.slice(o,o=n[m++]),a=dn(n[m++],t.cm.options)}}else for(var O=1;O2&&o.push((u.bottom+l.top)/2-n.top)}}o.push(n.bottom-n.top)}}function $n(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var r=0;rn)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Jn(e,t){var n=et(t=$t(t)),r=e.display.externalMeasured=new _n(e.doc,t,n);r.lineN=n;var i=r.built=pn(e,r);return r.text=i.pre,C(e.display.lineMeasure,i.pre),r}function Xn(e,t,n,r){return nr(e,tr(e,t),n,r)}function er(e,t){if(t>=e.display.viewFrom&&t=n.lineN&&tt)&&(i=(o=u-s)-1,t>=u&&(a="right")),null!=i){if(r=e[l+2],s==u&&n==(r.insertLeft?"left":"right")&&(a=n),"left"==n&&0==i)for(;l&&e[l-2]==e[l-3]&&e[l-1].insertLeft;)r=e[2+(l-=3)],a="left";if("right"==n&&i==u-s)for(;l=0&&(n=e[i]).left==n.right;i--);return n}function sr(e,t,n,r){var i,o=or(t.map,n,r),u=o.node,l=o.start,c=o.end,f=o.collapse;if(3==u.nodeType){for(var h=0;h<4;h++){for(;l&&oe(t.line.text.charAt(o.coverStart+l));)--l;for(;o.coverStart+c0&&(f=r="right"),i=e.options.lineWrapping&&(d=u.getClientRects()).length>1?d["right"==r?d.length-1:0]:u.getBoundingClientRect()}if(a&&s<9&&!l&&(!i||!i.left&&!i.right)){var p=u.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+Or(e.display),top:p.top,bottom:p.bottom}:ir}for(var m=i.top-t.rect.top,v=i.bottom-t.rect.top,g=(m+v)/2,y=t.view.measure.heights,b=0;b=r.text.length?(u=r.text.length,l="before"):u<=0&&(u=0,l="after"),!s)return a("before"==l?u-1:u,"before"==l);function c(e,t,n){return a(n?e-1:e,1==s[t].level!=n)}var f=ce(s,u,l),h=le,d=c(u,f,"before"==l);return null!=h&&(d.other=c(u,h,"before"!=l)),d}function br(e,t){var n=0;t=ft(e.doc,t),e.options.lineWrapping||(n=Or(e.display)*t.ch);var r=Ze(e.doc,t.line),i=on(r)+Hn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function wr(e,t,n,r,i){var o=it(e,t,n);return o.xRel=i,r&&(o.outside=r),o}function _r(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return wr(r.first,0,null,-1,-1);var i=tt(r,n),o=r.first+r.size-1;if(i>o)return wr(r.first+r.size-1,Ze(r,o).text.length,null,1,1);t<0&&(t=0);for(var a=Ze(r,i);;){var s=xr(e,a,i,t,n),u=Qt(a,s.ch+(s.xRel>0||s.outside>0?1:0));if(!u)return s;var l=u.find(1);if(l.line==i)return l;a=Ze(r,i=l.line)}}function Mr(e,t,n,r){r-=pr(t);var i=t.text.length,o=se((function(t){return nr(e,n,t-1).bottom<=r}),i,0);return{begin:o,end:i=se((function(t){return nr(e,n,t).top>r}),o,i)}}function Er(e,t,n,r){return n||(n=tr(e,t)),Mr(e,t,n,mr(e,t,nr(e,n,r),"line").top)}function Sr(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function xr(e,t,n,r,i){i-=on(t);var o=tr(e,t),a=pr(t),s=0,u=t.text.length,l=!0,c=he(t,e.doc.direction);if(c){var f=(e.options.lineWrapping?Tr:kr)(e,t,n,o,c,r,i);s=(l=1!=f.level)?f.from:f.to-1,u=l?f.to:f.from-1}var h,d,p=null,m=null,v=se((function(t){var n=nr(e,o,t);return n.top+=a,n.bottom+=a,!!Sr(n,r,i,!1)&&(n.top<=i&&n.left<=r&&(p=t,m=n),!0)}),s,u),g=!1;if(m){var y=r-m.left=w.bottom?1:0}return wr(n,v=ae(t.text,v,1),d,g,r-h)}function kr(e,t,n,r,i,o,a){var s=se((function(s){var u=i[s],l=1!=u.level;return Sr(yr(e,it(n,l?u.to:u.from,l?"before":"after"),"line",t,r),o,a,!0)}),0,i.length-1),u=i[s];if(s>0){var l=1!=u.level,c=yr(e,it(n,l?u.from:u.to,l?"after":"before"),"line",t,r);Sr(c,o,a,!0)&&c.top>a&&(u=i[s-1])}return u}function Tr(e,t,n,r,i,o,a){var s=Mr(e,t,r,a),u=s.begin,l=s.end;/\s/.test(t.text.charAt(l-1))&&l--;for(var c=null,f=null,h=0;h=l||d.to<=u)){var p=nr(e,r,1!=d.level?Math.min(l,d.to)-1:Math.max(u,d.from)).right,m=pm)&&(c=d,f=m)}}return c||(c=i[i.length-1]),c.froml&&(c={from:c.from,to:l,level:c.level}),c}function Cr(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==rr){rr=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)rr.appendChild(document.createTextNode("x")),rr.appendChild(O("br"));rr.appendChild(document.createTextNode("x"))}C(e.measure,rr);var n=rr.offsetHeight/50;return n>3&&(e.cachedTextHeight=n),T(e.measure),n||1}function Or(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),n=O("pre",[t],"CodeMirror-line-like");C(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function Ar(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,a=0;o;o=o.nextSibling,++a){var s=e.display.gutterSpecs[a].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:Dr(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function Dr(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function Pr(e){var t=Cr(e.display),n=e.options.lineWrapping,r=n&&Math.max(5,e.display.scroller.clientWidth/Or(e.display)-3);return function(i){if(nn(e.doc,i))return 0;var o=0;if(i.widgets)for(var a=0;a0&&(u=Ze(e.doc,l.line).text).length==l.ch){var c=F(u,u.length,e.options.tabSize)-u.length;l=it(l.line,Math.max(0,Math.round((o-Wn(e.display).left)/Or(e.display))-c))}return l}function Rr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;rt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ot&&en(e.doc,t)i.viewFrom?Fr(e):(i.viewFrom+=r,i.viewTo+=r);else if(t<=i.viewFrom&&n>=i.viewTo)Fr(e);else if(t<=i.viewFrom){var o=Br(e,n,n+r,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=r):Fr(e)}else if(n>=i.viewTo){var a=Br(e,t,t,-1);a?(i.view=i.view.slice(0,a.index),i.viewTo=a.lineN):Fr(e)}else{var s=Br(e,t,t,-1),u=Br(e,n,n+r,1);s&&u?(i.view=i.view.slice(0,s.index).concat(Mn(e,s.lineN,u.lineN)).concat(i.view.slice(u.index)),i.viewTo+=r):Fr(e)}var l=i.externalMeasured;l&&(n=i.lineN&&t=r.viewTo)){var o=r.view[Rr(e,t)];if(null!=o.node){var a=o.changes||(o.changes=[]);-1==V(a,n)&&a.push(n)}}}function Fr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Br(e,t,n,r){var i,o=Rr(e,t),a=e.display.view;if(!Ot||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,u=0;u0){if(o==a.length-1)return null;i=s+a[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;en(e.doc,n)!=n;){if(o==(r<0?0:a.length-1))return null;n+=r*a[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function Vr(e,t,n){var r=e.display;0==r.view.length||t>=r.viewTo||n<=r.viewFrom?(r.view=Mn(e,t,n),r.viewFrom=t):(r.viewFrom>t?r.view=Mn(e,t,r.viewFrom).concat(r.view):r.viewFromn&&(r.view=r.view.slice(0,Rr(e,n)))),r.viewTo=n}function zr(e){for(var t=e.display.view,n=0,r=0;r=e.display.viewTo||s.to().line0?t.blinker=setInterval((function(){e.hasFocus()||$r(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"}),e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Yr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Zr(e))}function Qr(e){e.state.delayingBlurEvent=!0,setTimeout((function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&$r(e))}),100)}function Zr(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ge(e,"focus",e,t),e.state.focused=!0,I(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),u&&setTimeout((function(){return e.display.input.reset(!0)}),20)),e.display.input.receivedFocus()),Kr(e))}function $r(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ge(e,"blur",e,t),e.state.focused=!1,k(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout((function(){e.state.focused||(e.display.shift=!1)}),150))}function Jr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r.005||h<-.005)&&(Xe(i.line,u),Xr(i.line),i.rest))for(var d=0;de.display.sizerWidth){var p=Math.ceil(l/Or(e.display));p>e.display.maxLineLength&&(e.display.maxLineLength=p,e.display.maxLine=i.line,e.display.maxLineChanged=!0)}}}}function Xr(e){if(e.widgets)for(var t=0;t=a&&(o=tt(t,on(Ze(t,u))-e.wrapper.clientHeight),a=u)}return{from:o,to:Math.max(a,o+1)}}function ti(e,t){if(!ye(e,"scrollCursorIntoView")){var n=e.display,r=n.sizer.getBoundingClientRect(),i=null;if(t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","\u200b",null,"position: absolute;\n top: "+(t.top-n.viewOffset-Hn(e.display))+"px;\n height: "+(t.bottom-t.top+Kn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}function ni(e,t,n,r){var i;null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==t.sticky?it(t.line,t.ch+1,"before"):t,t=t.ch?it(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t);for(var o=0;o<5;o++){var a=!1,s=yr(e,t),u=n&&n!=t?yr(e,n):s,l=ii(e,i={left:Math.min(s.left,u.left),top:Math.min(s.top,u.top)-r,right:Math.max(s.left,u.left),bottom:Math.max(s.bottom,u.bottom)+r}),c=e.doc.scrollTop,f=e.doc.scrollLeft;if(null!=l.scrollTop&&(fi(e,l.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(a=!0)),null!=l.scrollLeft&&(di(e,l.scrollLeft),Math.abs(e.doc.scrollLeft-f)>1&&(a=!0)),!a)break}return i}function ri(e,t){var n=ii(e,t);null!=n.scrollTop&&fi(e,n.scrollTop),null!=n.scrollLeft&&di(e,n.scrollLeft)}function ii(e,t){var n=e.display,r=Cr(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=Qn(e),a={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Gn(n),u=t.tops-r;if(t.topi+o){var c=Math.min(t.top,(l?s:t.bottom)-o);c!=i&&(a.scrollTop=c)}var f=e.options.fixedGutter?0:n.gutters.offsetWidth,h=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-f,d=Yn(e)-n.gutters.offsetWidth,p=t.right-t.left>d;return p&&(t.right=t.left+d),t.left<10?a.scrollLeft=0:t.leftd+h-3&&(a.scrollLeft=t.right+(p?0:10)-d),a}function oi(e,t){null!=t&&(li(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function ai(e){li(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function si(e,t,n){null==t&&null==n||li(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function ui(e,t){li(e),e.curOp.scrollToPos=t}function li(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,ci(e,br(e,t.from),br(e,t.to),t.margin))}function ci(e,t,n,r){var i=ii(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});si(e,i.scrollLeft,i.scrollTop)}function fi(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||Ui(e,{top:t}),hi(e,t,!0),n&&Ui(e),Ni(e,100))}function hi(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function di(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Wi(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function pi(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+Gn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Kn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}var mi=function(e,t,n){this.cm=n;var r=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),pe(r,"scroll",(function(){r.clientHeight&&t(r.scrollTop,"vertical")})),pe(i,"scroll",(function(){i.clientWidth&&t(i.scrollLeft,"horizontal")})),this.checkedZeroWidth=!1,a&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};mi.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,r=e.nativeBarWidth;if(n){this.vert.style.display="block",this.vert.style.bottom=t?r+"px":"0";var i=e.viewHeight-(t?r:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=n?r+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(n?r:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==r&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?r:0,bottom:t?r:0}},mi.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},mi.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},mi.prototype.zeroWidthHack=function(){var e=y&&!d?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new B,this.disableVert=new B},mi.prototype.enableZeroWidthBar=function(e,t,n){function r(){var i=e.getBoundingClientRect();("vert"==n?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,r)}e.style.pointerEvents="auto",t.set(1e3,r)},mi.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var vi=function(){};function gi(e,t){t||(t=pi(e));var n=e.display.barWidth,r=e.display.barHeight;yi(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&Jr(e),yi(e,pi(e)),n=e.display.barWidth,r=e.display.barHeight}function yi(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}vi.prototype.update=function(){return{bottom:0,right:0}},vi.prototype.setScrollLeft=function(){},vi.prototype.setScrollTop=function(){},vi.prototype.clear=function(){};var bi={native:mi,null:vi};function wi(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&k(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new bi[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),pe(t,"mousedown",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute("cm-not-content","true")}),(function(t,n){"horizontal"==n?di(e,t):fi(e,t)}),e),e.display.scrollbars.addClass&&I(e.display.wrapper,e.display.scrollbars.addClass)}var _i=0;function Mi(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++_i,markArrays:null},Sn(e.curOp)}function Ei(e){var t=e.curOp;t&&kn(t,(function(e){for(var t=0;t=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ji(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function ki(e){e.updatedDisplay=e.mustUpdate&&Vi(e.cm,e.update)}function Ti(e){var t=e.cm,n=t.display;e.updatedDisplay&&Jr(t),e.barMeasure=pi(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Xn(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Kn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Yn(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}function Ci(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft=e.display.viewTo)){var n=+new Date+e.options.workTime,r=yt(e,t.highlightFrontier),i=[];t.iter(r.line,Math.min(t.first+t.size,e.display.viewTo+500),(function(o){if(r.line>=e.display.viewFrom){var a=o.styles,s=o.text.length>e.options.maxHighlightLength?We(t.mode,r.state):null,u=vt(e,o,r,!0);s&&(r.state=s),o.styles=u.styles;var l=o.styleClasses,c=u.classes;c?o.styleClasses=c:l&&(o.styleClasses=null);for(var f=!a||a.length!=o.styles.length||l!=c&&(!l||!c||l.bgClass!=c.bgClass||l.textClass!=c.textClass),h=0;!f&&hn)return Ni(e,e.options.workDelay),!0})),t.highlightFrontier=r.line,t.modeFrontier=Math.max(t.modeFrontier,r.line),i.length&&Ai(e,(function(){for(var t=0;t=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==zr(e))return!1;Ki(e)&&(Fr(e),t.dims=Ar(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),a=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFroma&&n.viewTo-a<20&&(a=Math.min(i,n.viewTo)),Ot&&(o=en(e.doc,o),a=tn(e.doc,a));var s=o!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;Vr(e,o,a),n.viewOffset=on(Ze(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var u=zr(e);if(!s&&0==u&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var l=Fi(e);return u>4&&(n.lineDiv.style.display="none"),qi(e,n.updateLineNumbers,t.dims),u>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,Bi(l),T(n.cursorDiv),T(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,s&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,Ni(e,400)),n.updateLineNumbers=null,!0}function zi(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Yn(e))r&&(t.visible=ei(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+Gn(e.display)-Qn(e),n.top)}),t.visible=ei(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Vi(e,t))break;Jr(e);var i=pi(e);Ur(e),gi(e,i),Gi(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function Ui(e,t){var n=new ji(e,t);if(Vi(e,n)){Jr(e),zi(e,n);var r=pi(e);Ur(e),gi(e,r),Gi(e,r),n.finish()}}function qi(e,t,n){var r=e.display,i=e.options.lineNumbers,o=r.lineDiv,a=o.firstChild;function s(t){var n=t.nextSibling;return u&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),n}for(var l=r.view,c=r.viewFrom,f=0;f-1&&(d=!1),An(e,h,c,n)),d&&(T(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(rt(e.options,c)))),a=h.node.nextSibling}else{var p=Fn(e,h,c,n);o.insertBefore(p,a)}c+=h.size}for(;a;)a=s(a)}function Hi(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px",Cn(e,"gutterChanged",e)}function Gi(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Kn(e)+"px"}function Wi(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=Dr(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",a=0;as.clientWidth,c=s.scrollHeight>s.clientHeight;if(i&&l||o&&c){if(o&&y&&u)e:for(var h=t.target,d=a.view;h!=s;h=h.parentNode)for(var p=0;p=0&&ot(e,r.to())<=0)return n}return-1};var io=function(e,t){this.anchor=e,this.head=t};function oo(e,t,n){var r=e&&e.options.selectionsMayTouch,i=t[n];t.sort((function(e,t){return ot(e.from(),t.from())})),n=V(t,i);for(var o=1;o0:u>=0){var l=lt(s.from(),a.from()),c=ut(s.to(),a.to()),f=s.empty()?a.from()==a.head:s.from()==s.head;o<=n&&--n,t.splice(--o,2,new io(f?c:l,f?l:c))}}return new ro(t,n)}function ao(e,t){return new ro([new io(e,t||e)],0)}function so(e){return e.text?it(e.from.line+e.text.length-1,Q(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function uo(e,t){if(ot(e,t.from)<0)return e;if(ot(e,t.to)<=0)return so(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=so(t).ch-t.to.ch),it(n,r)}function lo(e,t){for(var n=[],r=0;r1&&e.remove(s.line+1,p-1),e.insert(s.line+1,g)}Cn(e,"change",e,t)}function go(e,t,n){function r(e,i,o){if(e.linked)for(var a=0;a1&&!e.done[e.done.length-2].ranges?(e.done.pop(),Q(e.done)):void 0}function xo(e,t,n,r){var i=e.history;i.undone.length=0;var o,a,s=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>s-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=So(i,i.lastOp==r)))a=Q(o.changes),0==ot(t.from,t.to)&&0==ot(t.from,a.to)?a.to=so(t):o.changes.push(Mo(e,t));else{var u=Q(i.done);for(u&&u.ranges||Co(e.sel,i.done),o={changes:[Mo(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,a||ge(e,"historyAdded")}function ko(e,t,n,r){var i=t.charAt(0);return"*"==i||"+"==i&&n.ranges.length==r.ranges.length&&n.somethingSelected()==r.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function To(e,t,n,r){var i=e.history,o=r&&r.origin;n==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||ko(e,o,Q(i.done),t))?i.done[i.done.length-1]=t:Co(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=n,r&&!1!==r.clearRedo&&Eo(i.undone)}function Co(e,t){var n=Q(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Oo(e,t,n,r){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,n),Math.min(e.first+e.size,r),(function(n){n.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=n.markedSpans),++o}))}function Ao(e){if(!e)return null;for(var t,n=0;n-1&&(Q(s)[f]=l[f],delete l[f])}}}return r}function No(e,t,n,r){if(r){var i=e.anchor;if(n){var o=ot(t,i)<0;o!=ot(n,i)<0?(i=t,t=n):o!=ot(t,n)<0&&(t=n)}return new io(i,t)}return new io(n||t,t)}function Ro(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),zo(e,new ro([No(e.sel.primary(),t,n,i)],0),r)}function jo(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:s.to>t.ch))){if(i&&(ge(u,"beforeCursorEnter"),u.explicitlyCleared)){if(o.markedSpans){--a;continue}break}if(!u.atomic)continue;if(n){var f=u.find(r<0?1:-1),h=void 0;if((r<0?c:l)&&(f=Yo(e,f,-r,f&&f.line==t.line?o:null)),f&&f.line==t.line&&(h=ot(f,n))&&(r<0?h<0:h>0))return Wo(e,f,t,r,i)}var d=u.find(r<0?-1:1);return(r<0?l:c)&&(d=Yo(e,d,r,d.line==t.line?o:null)),d?Wo(e,d,t,r,i):null}}return t}function Ko(e,t,n,r,i){var o=r||1,a=Wo(e,t,n,o,i)||!i&&Wo(e,t,n,o,!0)||Wo(e,t,n,-o,i)||!i&&Wo(e,t,n,-o,!0);return a||(e.cantEdit=!0,it(e.first,0))}function Yo(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ft(e,it(t.line-1)):null:n>0&&t.ch==(r||Ze(e,t.line)).text.length?t.line=0;--i)Jo(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else Jo(e,t)}}function Jo(e,t){if(1!=t.text.length||""!=t.text[0]||0!=ot(t.from,t.to)){var n=lo(e,t);xo(e,t,n,e.cm?e.cm.curOp.id:NaN),ta(e,t,n,Ft(e,t));var r=[];go(e,(function(e,n){n||-1!=V(r,e.history)||(aa(e.history,t),r.push(e.history)),ta(e,t,null,Ft(e,t))}))}}function Xo(e,t,n){var r=e.cm&&e.cm.state.suppressEdits;if(!r||n){for(var i,o=e.history,a=e.sel,s="undo"==t?o.done:o.undone,u="undo"==t?o.undone:o.done,l=0;l=0;--d){var p=h(d);if(p)return p.v}}}}function ea(e,t){if(0!=t&&(e.first+=t,e.sel=new ro(Z(e.sel.ranges,(function(e){return new io(it(e.anchor.line+t,e.anchor.ch),it(e.head.line+t,e.head.ch))})),e.sel.primIndex),e.cm)){jr(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;re.lastLine())){if(t.from.lineo&&(t={from:t.from,to:it(o,Ze(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=$e(e,t.from,t.to),n||(n=lo(e,t)),e.cm?na(e.cm,t,r):vo(e,t,r),Uo(e,n,q),e.cantEdit&&Ko(e,it(e.firstLine(),0))&&(e.cantEdit=!1)}}function na(e,t,n){var r=e.doc,i=e.display,o=t.from,a=t.to,s=!1,u=o.line;e.options.lineWrapping||(u=et($t(Ze(r,o.line))),r.iter(u,a.line+1,(function(e){if(e==i.maxLine)return s=!0,!0}))),r.sel.contains(t.from,t.to)>-1&&be(e),vo(r,t,n,Pr(e)),e.options.lineWrapping||(r.iter(u,o.line+t.text.length,(function(e){var t=an(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)})),s&&(e.curOp.updateMaxLine=!0)),Tt(r,o.line),Ni(e,400);var l=t.text.length-(a.line-o.line)-1;t.full?jr(e):o.line!=a.line||1!=t.text.length||mo(e.doc,t)?jr(e,o.line,a.line+1,l):Lr(e,o.line,"text");var c=we(e,"changes"),f=we(e,"change");if(f||c){var h={from:o,to:a,text:t.text,removed:t.removed,origin:t.origin};f&&Cn(e,"change",e,h),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(h)}e.display.selForContextMenu=null}function ra(e,t,n,r,i){var o;r||(r=n),ot(r,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),$o(e,{from:n,to:r,text:t,origin:i})}function ia(e,t,n,r){n1||!(this.children[0]instanceof ua))){var s=[];this.collapse(s),this.children=[new ua(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=i.lines.length%25+25,s=a;s10);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r0||0==a&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),r.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),r.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Zt(e,t.line,t,n,o)||t.line!=n.line&&Zt(e,n.line,t,n,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Dt()}o.addToHistory&&xo(e,{from:t,to:n,origin:"markText"},e.sel,NaN);var s,u=t.line,l=e.cm;if(e.iter(u,n.line+1,(function(r){l&&o.collapsed&&!l.options.lineWrapping&&$t(r)==l.display.maxLine&&(s=!0),o.collapsed&&u!=t.line&&Xe(r,0),Rt(r,new Pt(o,u==t.line?t.ch:null,u==n.line?n.ch:null),e.cm&&e.cm.curOp),++u})),o.collapsed&&e.iter(t.line,n.line+1,(function(t){nn(e,t)&&Xe(t,0)})),o.clearOnEnter&&pe(o,"beforeCursorEnter",(function(){return o.clear()})),o.readOnly&&(At(),(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++da,o.atomic=!0),l){if(s&&(l.curOp.updateMaxLine=!0),o.collapsed)jr(l,t.line,n.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=n.line;c++)Lr(l,c,"text");o.atomic&&Ho(l.doc),Cn(l,"markerAdded",l,o)}return o}pa.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Mi(e),we(this,"clear")){var n=this.find();n&&Cn(this,"clear",n.from,n.to)}for(var r=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=l,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=r&&e&&this.collapsed&&jr(e,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Ho(e.doc)),e&&Cn(e,"markerCleared",e,this,r,i),t&&Ei(e),this.parent&&this.parent.clear()}},pa.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;u--)$o(this,r[u]);s?Vo(this,s):this.cm&&ai(this.cm)})),undo:Ii((function(){Xo(this,"undo")})),redo:Ii((function(){Xo(this,"redo")})),undoSelection:Ii((function(){Xo(this,"undo",!0)})),redoSelection:Ii((function(){Xo(this,"redo",!0)})),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,n){e=ft(this,e),t=ft(this,t);var r=[],i=e.line;return this.iter(e.line,t.line+1,(function(o){var a=o.markedSpans;if(a)for(var s=0;s=u.to||null==u.from&&i!=e.line||null!=u.from&&i==t.line&&u.from>=t.ch||n&&!n(u.marker)||r.push(u.marker.parent||u.marker)}++i})),r},getAllMarks:function(){var e=[];return this.iter((function(t){var n=t.markedSpans;if(n)for(var r=0;re)return t=e,!0;e-=o,++n})),ft(this,it(n,t))},indexFromPos:function(e){var t=(e=ft(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout((function(){return t.display.input.focus()}),20);try{var f=e.dataTransfer.getData("Text");if(f){var h;if(t.state.draggingText&&!t.state.draggingText.copy&&(h=t.listSelections()),Uo(t.doc,ao(n,n)),h)for(var d=0;d=0;t--)ra(e.doc,"",r[t].from,r[t].to,"+delete");ai(e)}))}function Wa(e,t,n){var r=ae(e.text,t+n,n);return r<0||r>e.text.length?null:r}function Ka(e,t,n){var r=Wa(e,t.ch,n);return null==r?null:new it(t.line,r,n<0?"after":"before")}function Ya(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=he(n,t.doc.direction);if(o){var a,s=i<0?Q(o):o[0],u=i<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var l=tr(t,n);a=i<0?n.text.length-1:0;var c=nr(t,l,a).top;a=se((function(e){return nr(t,l,e).top==c}),i<0==(1==s.level)?s.from:s.to-1,a),"before"==u&&(a=Wa(n,a,1))}else a=i<0?s.to:s.from;return new it(r,a,u)}}return new it(r,i<0?n.text.length:0,i<0?"before":"after")}function Qa(e,t,n,r){var i=he(t,e.doc.direction);if(!i)return Ka(t,n,r);n.ch>=t.text.length?(n.ch=t.text.length,n.sticky="before"):n.ch<=0&&(n.ch=0,n.sticky="after");var o=ce(i,n.ch,n.sticky),a=i[o];if("ltr"==e.doc.direction&&a.level%2==0&&(r>0?a.to>n.ch:a.from=a.from&&h>=c.begin)){var d=f?"before":"after";return new it(n.line,h,d)}}var p=function(e,t,r){for(var o=function(e,t){return t?new it(n.line,u(e,1),"before"):new it(n.line,e,"after")};e>=0&&e0==(1!=a.level),l=s?r.begin:u(r.end,-1);if(a.from<=l&&l0?c.end:u(c.begin,-1);return null==v||r>0&&v==t.text.length||!(m=p(r>0?0:i.length-1,r,l(v)))?null:m}La.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},La.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},La.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},La.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},La.default=y?La.macDefault:La.pcDefault;var Za={selectAll:Qo,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),q)},killLine:function(e){return Ga(e,(function(t){if(t.empty()){var n=Ze(e.doc,t.head.line).text.length;return t.head.ch==n&&t.head.line0)i=new it(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),it(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var a=Ze(e.doc,i.line-1).text;a&&(i=new it(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),it(i.line-1,a.length-1),i,"+transpose"))}n.push(new io(i,i))}e.setSelections(n)}))},newlineAndIndent:function(e){return Ai(e,(function(){for(var t=e.listSelections(),n=t.length-1;n>=0;n--)e.replaceRange(e.doc.lineSeparator(),t[n].anchor,t[n].head,"+input");t=e.listSelections();for(var r=0;r-1&&(ot((i=s.ranges[i]).from(),t)<0||t.xRel>0)&&(ot(i.to(),t)>0||t.xRel<0)?_s(e,r,t,o):Es(e,r,t,o)}function _s(e,t,n,r){var i=e.display,o=!1,l=Di(e,(function(t){u&&(i.scroller.draggable=!1),e.state.draggingText=!1,e.state.delayingBlurEvent&&(e.hasFocus()?e.state.delayingBlurEvent=!1:Qr(e)),ve(i.wrapper.ownerDocument,"mouseup",l),ve(i.wrapper.ownerDocument,"mousemove",c),ve(i.scroller,"dragstart",f),ve(i.scroller,"drop",l),o||(Me(t),r.addNew||Ro(e.doc,n,null,null,r.extend),u&&!h||a&&9==s?setTimeout((function(){i.wrapper.ownerDocument.body.focus({preventScroll:!0}),i.input.focus()}),20):i.input.focus())})),c=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},f=function(){return o=!0};u&&(i.scroller.draggable=!0),e.state.draggingText=l,l.copy=!r.moveOnDrag,pe(i.wrapper.ownerDocument,"mouseup",l),pe(i.wrapper.ownerDocument,"mousemove",c),pe(i.scroller,"dragstart",f),pe(i.scroller,"drop",l),e.state.delayingBlurEvent=!0,setTimeout((function(){return i.input.focus()}),20),i.scroller.dragDrop&&i.scroller.dragDrop()}function Ms(e,t,n){if("char"==n)return new io(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new io(it(t.line,0),ft(e.doc,it(t.line+1,0)));var r=n(e,t);return new io(r.from,r.to)}function Es(e,t,n,r){a&&Qr(e);var i=e.display,o=e.doc;Me(t);var s,u,l=o.sel,c=l.ranges;if(r.addNew&&!r.extend?(u=o.sel.contains(n),s=u>-1?c[u]:new io(n,n)):(s=o.sel.primary(),u=o.sel.primIndex),"rectangle"==r.unit)r.addNew||(s=new io(n,n)),n=Nr(e,t,!0,!0),u=-1;else{var f=Ms(e,n,r.unit);s=r.extend?No(s,f.anchor,f.head,r.extend):f}r.addNew?-1==u?(u=c.length,zo(o,oo(e,c.concat([s]),u),{scroll:!1,origin:"*mouse"})):c.length>1&&c[u].empty()&&"char"==r.unit&&!r.extend?(zo(o,oo(e,c.slice(0,u).concat(c.slice(u+1)),0),{scroll:!1,origin:"*mouse"}),l=o.sel):Lo(o,u,s,H):(u=0,zo(o,new ro([s],0),H),l=o.sel);var h=n;function d(t){if(0!=ot(h,t))if(h=t,"rectangle"==r.unit){for(var i=[],a=e.options.tabSize,c=F(Ze(o,n.line).text,n.ch,a),f=F(Ze(o,t.line).text,t.ch,a),d=Math.min(c,f),p=Math.max(c,f),m=Math.min(n.line,t.line),v=Math.min(e.lastLine(),Math.max(n.line,t.line));m<=v;m++){var g=Ze(o,m).text,y=W(g,d,a);d==p?i.push(new io(it(m,y),it(m,y))):g.length>y&&i.push(new io(it(m,y),it(m,W(g,p,a))))}i.length||i.push(new io(n,n)),zo(o,oo(e,l.ranges.slice(0,u).concat(i),u),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=s,_=Ms(e,t,r.unit),M=w.anchor;ot(_.anchor,M)>0?(b=_.head,M=lt(w.from(),_.anchor)):(b=_.anchor,M=ut(w.to(),_.head));var E=l.ranges.slice(0);E[u]=Ss(e,new io(ft(o,M),b)),zo(o,oo(e,E,u),H)}}var p=i.wrapper.getBoundingClientRect(),m=0;function v(t){var n=++m,a=Nr(e,t,!0,"rectangle"==r.unit);if(a)if(0!=ot(a,h)){e.curOp.focus=P(),d(a);var s=ei(i,o);(a.line>=s.to||a.linep.bottom?20:0;u&&setTimeout(Di(e,(function(){m==n&&(i.scroller.scrollTop+=u,v(t))})),50)}}function g(t){e.state.selectingText=!1,m=1/0,t&&(Me(t),i.input.focus()),ve(i.wrapper.ownerDocument,"mousemove",y),ve(i.wrapper.ownerDocument,"mouseup",b),o.history.lastSelOrigin=null}var y=Di(e,(function(e){0!==e.buttons&&Te(e)?v(e):g(e)})),b=Di(e,g);e.state.selectingText=b,pe(i.wrapper.ownerDocument,"mousemove",y),pe(i.wrapper.ownerDocument,"mouseup",b)}function Ss(e,t){var n=t.anchor,r=t.head,i=Ze(e.doc,n.line);if(0==ot(n,r)&&n.sticky==r.sticky)return t;var o=he(i);if(!o)return t;var a=ce(o,n.ch,n.sticky),s=o[a];if(s.from!=n.ch&&s.to!=n.ch)return t;var u,l=a+(s.from==n.ch==(1!=s.level)?0:1);if(0==l||l==o.length)return t;if(r.line!=n.line)u=(r.line-n.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ce(o,r.ch,r.sticky),f=c-a||(r.ch-n.ch)*(1==s.level?-1:1);u=c==l-1||c==l?f<0:f>0}var h=o[l+(u?-1:0)],d=u==(1==h.level),p=d?h.from:h.to,m=d?"after":"before";return n.ch==p&&n.sticky==m?t:new io(new it(n.line,p,m),r)}function xs(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(c){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Me(t);var a=e.display,s=a.lineDiv.getBoundingClientRect();if(o>s.bottom||!we(e,n))return Se(t);o-=s.top-a.viewOffset;for(var u=0;u=i)return ge(e,n,e,tt(e.doc,o),e.display.gutterSpecs[u].className,t),Se(t)}}function ks(e,t){return xs(e,t,"gutterClick",!0)}function Ts(e,t){qn(e.display,t)||Cs(e,t)||ye(e,t,"contextmenu")||E||e.display.input.onContextMenu(t)}function Cs(e,t){return!!we(e,"gutterContextMenu")&&xs(e,t,"gutterContextMenu",!1)}function Os(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),fr(e)}ms.prototype.compare=function(e,t,n){return this.time+ps>e&&0==ot(t,this.pos)&&n==this.button};var As={toString:function(){return"CodeMirror.Init"}},Ds={},Ps={};function Is(e){var t=e.optionHandlers;function n(n,r,i,o){e.defaults[n]=r,i&&(t[n]=o?function(e,t,n){n!=As&&i(e,t,n)}:i)}e.defineOption=n,e.Init=As,n("value","",(function(e,t){return e.setValue(t)}),!0),n("mode",null,(function(e,t){e.doc.modeOption=t,ho(e)}),!0),n("indentUnit",2,ho,!0),n("indentWithTabs",!1),n("smartIndent",!0),n("tabSize",4,(function(e){po(e),fr(e),jr(e)}),!0),n("lineSeparator",null,(function(e,t){if(e.doc.lineSep=t,t){var n=[],r=e.doc.first;e.doc.iter((function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,n.push(it(r,o))}r++}));for(var i=n.length-1;i>=0;i--)ra(e.doc,t,n[i],it(n[i].line,n[i].ch+t.length))}})),n("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,(function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=As&&e.refresh()})),n("specialCharPlaceholder",mn,(function(e){return e.refresh()}),!0),n("electricChars",!0),n("inputStyle",g?"contenteditable":"textarea",(function(){throw new Error("inputStyle can not (yet) be changed in a running editor")}),!0),n("spellcheck",!1,(function(e,t){return e.getInputField().spellcheck=t}),!0),n("autocorrect",!1,(function(e,t){return e.getInputField().autocorrect=t}),!0),n("autocapitalize",!1,(function(e,t){return e.getInputField().autocapitalize=t}),!0),n("rtlMoveVisually",!w),n("wholeLineUpdateBefore",!0),n("theme","default",(function(e){Os(e),Zi(e)}),!0),n("keyMap","default",(function(e,t,n){var r=Ha(t),i=n!=As&&Ha(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)})),n("extraKeys",null),n("configureMouse",null),n("lineWrapping",!1,Rs,!0),n("gutters",[],(function(e,t){e.display.gutterSpecs=Yi(t,e.options.lineNumbers),Zi(e)}),!0),n("fixedGutter",!0,(function(e,t){e.display.gutters.style.left=t?Dr(e.display)+"px":"0",e.refresh()}),!0),n("coverGutterNextToScrollbar",!1,(function(e){return gi(e)}),!0),n("scrollbarStyle","native",(function(e){wi(e),gi(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)}),!0),n("lineNumbers",!1,(function(e,t){e.display.gutterSpecs=Yi(e.options.gutters,t),Zi(e)}),!0),n("firstLineNumber",1,Zi,!0),n("lineNumberFormatter",(function(e){return e}),Zi,!0),n("showCursorWhenSelecting",!1,Ur,!0),n("resetSelectionOnContextMenu",!0),n("lineWiseCopyCut",!0),n("pasteLinesPerSelection",!0),n("selectionsMayTouch",!1),n("readOnly",!1,(function(e,t){"nocursor"==t&&($r(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)})),n("screenReaderLabel",null,(function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)})),n("disableInput",!1,(function(e,t){t||e.display.input.reset()}),!0),n("dragDrop",!0,Ns),n("allowDropFileTypes",null),n("cursorBlinkRate",530),n("cursorScrollMargin",0),n("cursorHeight",1,Ur,!0),n("singleCursorHeightPerLine",!0,Ur,!0),n("workTime",100),n("workDelay",100),n("flattenSpans",!0,po,!0),n("addModeClass",!1,po,!0),n("pollInterval",100),n("undoDepth",200,(function(e,t){return e.doc.history.undoDepth=t})),n("historyEventDelay",1250),n("viewportMargin",10,(function(e){return e.refresh()}),!0),n("maxHighlightLength",1e4,po,!0),n("moveInputWithCursor",!0,(function(e,t){t||e.display.input.resetPosition()})),n("tabindex",null,(function(e,t){return e.display.input.getField().tabIndex=t||""})),n("autofocus",null),n("direction","ltr",(function(e,t){return e.doc.setDirection(t)}),!0),n("phrases",null)}function Ns(e,t,n){if(!t!=!(n&&n!=As)){var r=e.display.dragFunctions,i=t?pe:ve;i(e.display.scroller,"dragstart",r.start),i(e.display.scroller,"dragenter",r.enter),i(e.display.scroller,"dragover",r.over),i(e.display.scroller,"dragleave",r.leave),i(e.display.scroller,"drop",r.drop)}}function Rs(e){e.options.lineWrapping?(I(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(k(e.display.wrapper,"CodeMirror-wrap"),sn(e)),Ir(e),jr(e),fr(e),setTimeout((function(){return gi(e)}),100)}function js(e,t){var n=this;if(!(this instanceof js))return new js(e,t);this.options=t=t?L(t):{},L(Ds,t,!1);var r=t.value;"string"==typeof r?r=new Ma(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i=new js.inputStyles[t.inputStyle](this),o=this.display=new $i(e,r,i,t);for(var l in o.wrapper.CodeMirror=this,Os(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),wi(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new B,keySeq:null,specialChars:null},t.autofocus&&!g&&o.input.focus(),a&&s<11&&setTimeout((function(){return n.display.input.reset(!0)}),20),Ls(this),Aa(),Mi(this),this.curOp.forceUpdate=!0,yo(this,r),t.autofocus&&!g||this.hasFocus()?setTimeout((function(){n.hasFocus()&&!n.state.focused&&Zr(n)}),20):$r(this),Ps)Ps.hasOwnProperty(l)&&Ps[l](this,t[l],As);Ki(this),t.finishInit&&t.finishInit(this);for(var c=0;c400}pe(t.scroller,"touchstart",(function(i){if(!ye(e,i)&&!o(i)&&!ks(e,i)){t.input.ensurePolled(),clearTimeout(n);var a=+new Date;t.activeTouch={start:a,moved:!1,prev:a-r.end<=300?r:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}})),pe(t.scroller,"touchmove",(function(){t.activeTouch&&(t.activeTouch.moved=!0)})),pe(t.scroller,"touchend",(function(n){var r=t.activeTouch;if(r&&!qn(t,n)&&null!=r.left&&!r.moved&&new Date-r.start<300){var o,a=e.coordsChar(t.activeTouch,"page");o=!r.prev||u(r,r.prev)?new io(a,a):!r.prev.prev||u(r,r.prev.prev)?e.findWordAt(a):new io(it(a.line,0),ft(e.doc,it(a.line+1,0))),e.setSelection(o.anchor,o.head),e.focus(),Me(n)}i()})),pe(t.scroller,"touchcancel",i),pe(t.scroller,"scroll",(function(){t.scroller.clientHeight&&(fi(e,t.scroller.scrollTop),di(e,t.scroller.scrollLeft,!0),ge(e,"scroll",e))})),pe(t.scroller,"mousewheel",(function(t){return no(e,t)})),pe(t.scroller,"DOMMouseScroll",(function(t){return no(e,t)})),pe(t.wrapper,"scroll",(function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0})),t.dragFunctions={enter:function(t){ye(e,t)||xe(t)},over:function(t){ye(e,t)||(ka(e,t),xe(t))},start:function(t){return xa(e,t)},drop:Di(e,Sa),leave:function(t){ye(e,t)||Ta(e)}};var l=t.input.getField();pe(l,"keyup",(function(t){return cs.call(e,t)})),pe(l,"keydown",Di(e,us)),pe(l,"keypress",Di(e,fs)),pe(l,"focus",(function(t){return Zr(e,t)})),pe(l,"blur",(function(t){return $r(e,t)}))}js.defaults=Ds,js.optionHandlers=Ps;var Fs=[];function Bs(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=yt(e,t).state:n="prev");var a=e.options.tabSize,s=Ze(o,t),u=F(s.text,null,a);s.stateAfter&&(s.stateAfter=null);var l,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((l=o.mode.indent(i,s.text.slice(c.length),s.text))==U||l>150)){if(!r)return;n="prev"}}else l=0,n="not";"prev"==n?l=t>o.first?F(Ze(o,t-1).text,null,a):0:"add"==n?l=u+e.options.indentUnit:"subtract"==n?l=u-e.options.indentUnit:"number"==typeof n&&(l=u+n),l=Math.max(0,l);var f="",h=0;if(e.options.indentWithTabs)for(var d=Math.floor(l/a);d;--d)h+=a,f+="\t";if(ha,u=Ie(t),l=null;if(s&&r.ranges.length>1)if(Vs&&Vs.text.join("\n")==t){if(r.ranges.length%Vs.text.length==0){l=[];for(var c=0;c=0;h--){var d=r.ranges[h],p=d.from(),m=d.to();d.empty()&&(n&&n>0?p=it(p.line,p.ch-n):e.state.overwrite&&!s?m=it(m.line,Math.min(Ze(o,m.line).text.length,m.ch+Q(u).length)):s&&Vs&&Vs.lineWise&&Vs.text.join("\n")==u.join("\n")&&(p=m=it(p.line,0)));var v={from:p,to:m,text:l?l[h%l.length]:u,origin:i||(s?"paste":e.state.cutIncoming>a?"cut":"+input")};$o(e.doc,v),Cn(e,"inputRead",e,v)}t&&!s&&Hs(e,t),ai(e),e.curOp.updateInput<2&&(e.curOp.updateInput=f),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function qs(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");if(n)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||Ai(t,(function(){return Us(t,n,0,null,"paste")})),!0}function Hs(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;r>=0;r--){var i=n.ranges[r];if(!(i.head.ch>100||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),a=!1;if(o.electricChars){for(var s=0;s-1){a=Bs(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Ze(e.doc,i.head.line).text.slice(0,i.head.ch))&&(a=Bs(e,i.head.line,"smart"));a&&Cn(e,"electricInput",e,i.head.line)}}}function Gs(e){for(var t=[],n=[],r=0;rn&&(Bs(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&ai(this));else{var o=i.from(),a=i.to(),s=Math.max(n,o.line);n=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var u=s;u0&&Lo(this.doc,r,new io(o,l[r].to()),q)}}})),getTokenAt:function(e,t){return Et(this,e,t)},getLineTokens:function(e,t){return Et(this,it(e),t,!0)},getTokenTypeAt:function(e){e=ft(this.doc,e);var t,n=gt(this,Ze(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var a=r+i>>1;if((a?n[2*a-1]:0)>=o)i=a;else{if(!(n[2*a+1]o&&(e=o,i=!0),r=Ze(this.doc,e)}else r=e;return mr(this,r,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-on(r):0)},defaultTextHeight:function(){return Cr(this.display)},defaultCharWidth:function(){return Or(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o=this.display,a=(e=yr(this,ft(this.doc,e))).bottom,s=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==r)a=e.top;else if("above"==r||"near"==r){var u=Math.max(o.wrapper.clientHeight,this.doc.height),l=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==r||e.bottom+t.offsetHeight>u)&&e.top>t.offsetHeight?a=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=u&&(a=e.bottom),s+t.offsetWidth>l&&(s=l-t.offsetWidth)}t.style.top=a+"px",t.style.left=t.style.right="","right"==i?(s=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?s=0:"middle"==i&&(s=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=s+"px"),n&&ri(this,{left:s,top:a,right:s+t.offsetWidth,bottom:a+t.offsetHeight})},triggerOnKeyDown:Pi(us),triggerOnKeyPress:Pi(fs),triggerOnKeyUp:cs,triggerOnMouseDown:Pi(gs),execCommand:function(e){if(Za.hasOwnProperty(e))return Za[e].call(null,this)},triggerElectric:Pi((function(e){Hs(this,e)})),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ft(this.doc,e),a=0;a0&&a(t.charAt(n-1));)--n;for(;r.5||this.options.lineWrapping)&&Ir(this),ge(this,"refresh",this)})),swapDoc:Pi((function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),yo(this,e),fr(this),this.display.input.reset(),si(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,Cn(this,"swapDoc",this,t),t})),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},_e(e),e.registerHelper=function(t,r,i){n.hasOwnProperty(t)||(n[t]=e[t]={_global:[]}),n[t][r]=i},e.registerGlobalHelper=function(t,r,i,o){e.registerHelper(t,r,o),n[t]._global.push({pred:i,val:o})}}function Qs(e,t,n,r,i){var o=t,a=n,s=Ze(e,t.line),u=i&&"rtl"==e.direction?-n:n;function l(){var n=t.line+u;return!(n=e.first+e.size)&&(t=new it(n,t.ch,t.sticky),s=Ze(e,n))}function c(o){var a;if("codepoint"==r){var c=s.text.charCodeAt(t.ch+(n>0?0:-1));if(isNaN(c))a=null;else{var f=n>0?c>=55296&&c<56320:c>=56320&&c<57343;a=new it(t.line,Math.max(0,Math.min(s.text.length,t.ch+n*(f?2:1))),-n)}}else a=i?Qa(e.cm,s,t,n):Ka(s,t,n);if(null==a){if(o||!l())return!1;t=Ya(i,e.cm,s,t.line,u)}else t=a;return!0}if("char"==r||"codepoint"==r)c();else if("column"==r)c(!0);else if("word"==r||"group"==r)for(var f=null,h="group"==r,d=e.cm&&e.cm.getHelper(t,"wordChars"),p=!0;!(n<0)||c(!p);p=!1){var m=s.text.charAt(t.ch)||"\n",v=ne(m,d)?"w":h&&"\n"==m?"n":!h||/\s/.test(m)?null:"p";if(!h||p||v||(v="s"),f&&f!=v){n<0&&(n=1,c(),t.sticky="after");break}if(v&&(f=v),n>0&&!c(!p))break}var g=Ko(e,t,o,a,!0);return at(o,g)&&(g.hitSide=!0),g}function Zs(e,t,n,r){var i,o,a=e.doc,s=t.left;if("page"==r){var u=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),l=Math.max(u-.5*Cr(e.display),3);i=(n>0?t.bottom:t.top)+n*l}else"line"==r&&(i=n>0?t.bottom+3:t.top-3);for(;(o=_r(e,s,i)).outside;){if(n<0?i<=0:i>=a.height){o.hitSide=!0;break}i+=5*n}return o}var $s=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new B,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Js(e,t){var n=er(e,t.line);if(!n||n.hidden)return null;var r=Ze(e.doc,t.line),i=$n(n,r,t.line),o=he(r,e.doc.direction),a="left";o&&(a=ce(o,t.ch)%2?"right":"left");var s=or(i.map,t.ch,a);return s.offset="right"==s.collapse?s.end:s.start,s}function Xs(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}function eu(e,t){return t&&(e.bad=!0),e}function tu(e,t,n,r,i){var o="",a=!1,s=e.doc.lineSeparator(),u=!1;function l(e){return function(t){return t.id==e}}function c(){a&&(o+=s,u&&(o+=s),a=u=!1)}function f(e){e&&(c(),o+=e)}function h(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void f(n);var o,d=t.getAttribute("cm-marker");if(d){var p=e.findMarks(it(r,0),it(i+1,0),l(+d));return void(p.length&&(o=p[0].find(0))&&f($e(e.doc,o.from,o.to).join(s)))}if("false"==t.getAttribute("contenteditable"))return;var m=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;m&&c();for(var v=0;v=t.display.viewTo||o.line=t.display.viewFrom&&Js(t,i)||{node:u[0].measure.map[2],offset:0},c=o.liner.firstLine()&&(a=it(a.line-1,Ze(r.doc,a.line-1).length)),s.ch==Ze(r.doc,s.line).text.length&&s.linei.viewTo-1)return!1;a.line==i.viewFrom||0==(e=Rr(r,a.line))?(t=et(i.view[0].line),n=i.view[0].node):(t=et(i.view[e].line),n=i.view[e-1].node.nextSibling);var u,l,c=Rr(r,s.line);if(c==i.view.length-1?(u=i.viewTo-1,l=i.lineDiv.lastChild):(u=et(i.view[c+1].line)-1,l=i.view[c+1].node.previousSibling),!n)return!1;for(var f=r.doc.splitLines(tu(r,n,l,t,u)),h=$e(r.doc,it(t,0),it(u,Ze(r.doc,u).text.length));f.length>1&&h.length>1;)if(Q(f)==Q(h))f.pop(),h.pop(),u--;else{if(f[0]!=h[0])break;f.shift(),h.shift(),t++}for(var d=0,p=0,m=f[0],v=h[0],g=Math.min(m.length,v.length);da.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)d--,p++;f[f.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),f[0]=f[0].slice(d).replace(/\u200b+$/,"");var _=it(t,d),M=it(u,h.length?Q(h).length-p:0);return f.length>1||f[0]||ot(_,M)?(ra(r.doc,f,_,M,"+input"),!0):void 0},$s.prototype.ensurePolled=function(){this.forceCompositionEnd()},$s.prototype.reset=function(){this.forceCompositionEnd()},$s.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},$s.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout((function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()}),80))},$s.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Ai(this.cm,(function(){return jr(e.cm)}))},$s.prototype.setUneditable=function(e){e.contentEditable="false"},$s.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Di(this.cm,Us)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},$s.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},$s.prototype.onContextMenu=function(){},$s.prototype.resetPosition=function(){},$s.prototype.needsContentAttribute=!0;var iu=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new B,this.hasSelection=!1,this.composing=null};function ou(e,t){if((t=t?L(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=P();t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}function r(){e.value=s.getValue()}var i;if(e.form&&(pe(e.form,"submit",r),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var a=o.submit=function(){r(),o.submit=i,o.submit(),o.submit=a}}catch(u){}}t.finishInit=function(n){n.save=r,n.getTextArea=function(){return e},n.toTextArea=function(){n.toTextArea=isNaN,r(),e.parentNode.removeChild(n.getWrapperElement()),e.style.display="",e.form&&(ve(e.form,"submit",r),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=i))}},e.style.display="none";var s=js((function(t){return e.parentNode.insertBefore(t,e.nextSibling)}),t);return s}function au(e){e.off=ve,e.on=pe,e.wheelEventPixels=to,e.Doc=Ma,e.splitLines=Ie,e.countColumn=F,e.findColumn=W,e.isWordChar=te,e.Pass=U,e.signal=ge,e.Line=un,e.changeEnd=so,e.scrollbarModel=bi,e.Pos=it,e.cmpPos=ot,e.modes=Fe,e.mimeModes=Be,e.resolveMode=Ue,e.getMode=qe,e.modeExtensions=He,e.extendMode=Ge,e.copyState=We,e.startState=Ye,e.innerMode=Ke,e.commands=Za,e.keyMap=La,e.keyName=qa,e.isModifierKey=za,e.lookupKey=Va,e.normalizeKeyMap=Ba,e.StringStream=Qe,e.SharedTextMarker=va,e.TextMarker=pa,e.LineWidget=ca,e.e_preventDefault=Me,e.e_stopPropagation=Ee,e.e_stop=xe,e.addClass=I,e.contains=D,e.rmClass=k,e.keyNames=Ia}iu.prototype.init=function(e){var t=this,n=this,r=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!ye(r,e)){if(r.somethingSelected())zs({lineWise:!1,text:r.getSelections()});else{if(!r.options.lineWiseCopyCut)return;var t=Gs(r);zs({lineWise:!0,text:t.text}),"cut"==e.type?r.setSelections(t.ranges,null,q):(n.prevInput="",i.value=t.text.join("\n"),R(i))}"cut"==e.type&&(r.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),m&&(i.style.width="0px"),pe(i,"input",(function(){a&&s>=9&&t.hasSelection&&(t.hasSelection=null),n.poll()})),pe(i,"paste",(function(e){ye(r,e)||qs(e,r)||(r.state.pasteIncoming=+new Date,n.fastPoll())})),pe(i,"cut",o),pe(i,"copy",o),pe(e.scroller,"paste",(function(t){if(!qn(e,t)&&!ye(r,t)){if(!i.dispatchEvent)return r.state.pasteIncoming=+new Date,void n.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,i.dispatchEvent(o)}})),pe(e.lineSpace,"selectstart",(function(t){qn(e,t)||Me(t)})),pe(i,"compositionstart",(function(){var e=r.getCursor("from");n.composing&&n.composing.range.clear(),n.composing={start:e,range:r.markText(e,r.getCursor("to"),{className:"CodeMirror-composing"})}})),pe(i,"compositionend",(function(){n.composing&&(n.poll(),n.composing.range.clear(),n.composing=null)}))},iu.prototype.createField=function(e){this.wrapper=Ks(),this.textarea=this.wrapper.firstChild},iu.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},iu.prototype.prepareSelection=function(){var e=this.cm,t=e.display,n=e.doc,r=qr(e);if(e.options.moveInputWithCursor){var i=yr(e,n.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();r.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+a.top-o.top)),r.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+a.left-o.left))}return r},iu.prototype.showSelection=function(e){var t=this.cm.display;C(t.cursorDiv,e.cursors),C(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},iu.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var n=t.getSelection();this.textarea.value=n,t.state.focused&&R(this.textarea),a&&s>=9&&(this.hasSelection=n)}else e||(this.prevInput=this.textarea.value="",a&&s>=9&&(this.hasSelection=null))}},iu.prototype.getField=function(){return this.textarea},iu.prototype.supportsTouch=function(){return!1},iu.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!g||P()!=this.textarea))try{this.textarea.focus()}catch(e){}},iu.prototype.blur=function(){this.textarea.blur()},iu.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},iu.prototype.receivedFocus=function(){this.slowPoll()},iu.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,(function(){e.poll(),e.cm.state.focused&&e.slowPoll()}))},iu.prototype.fastPoll=function(){var e=!1,t=this;function n(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,n))}t.pollingFast=!0,t.polling.set(20,n)},iu.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||Ne(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(a&&s>=9&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="\u200b"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var u=0,l=Math.min(r.length,i.length);u1e3||i.indexOf("\n")>-1?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))})),!0},iu.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},iu.prototype.onKeyPress=function(){a&&s>=9&&(this.hasSelection=null),this.fastPoll()},iu.prototype.onContextMenu=function(e){var t=this,n=t.cm,r=n.display,i=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=Nr(n,e),l=r.scroller.scrollTop;if(o&&!f){n.options.resetSelectionOnContextMenu&&-1==n.doc.sel.contains(o)&&Di(n,zo)(n.doc,ao(o),q);var c,h=i.style.cssText,d=t.wrapper.style.cssText,p=t.wrapper.offsetParent.getBoundingClientRect();t.wrapper.style.cssText="position: static",i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-p.top-5)+"px; left: "+(e.clientX-p.left-5)+"px;\n z-index: 1000; background: "+(a?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",u&&(c=window.scrollY),r.input.focus(),u&&window.scrollTo(null,c),r.input.reset(),n.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=v,r.selForContextMenu=n.doc.sel,clearTimeout(r.detectingSelectAll),a&&s>=9&&m(),E?(xe(e),pe(window,"mouseup",(function e(){ve(window,"mouseup",e),setTimeout(v,20)}))):setTimeout(v,50)}function m(){if(null!=i.selectionStart){var e=n.somethingSelected(),o="\u200b"+(e?i.value:"");i.value="\u21da",i.value=o,t.prevInput=e?"":"\u200b",i.selectionStart=1,i.selectionEnd=o.length,r.selForContextMenu=n.doc.sel}}function v(){if(t.contextMenuPending==v&&(t.contextMenuPending=!1,t.wrapper.style.cssText=d,i.style.cssText=h,a&&s<9&&r.scrollbars.setScrollTop(r.scroller.scrollTop=l),null!=i.selectionStart)){(!a||a&&s<9)&&m();var e=0,o=function o(){r.selForContextMenu==n.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"\u200b"==t.prevInput?Di(n,Qo)(n):e++<10?r.detectingSelectAll=setTimeout(o,500):(r.selForContextMenu=null,r.input.reset())};r.detectingSelectAll=setTimeout(o,200)}}},iu.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},iu.prototype.setUneditable=function(){},iu.prototype.needsContentAttribute=!1,Is(js),Ys(js);var su="iter insert remove copy getEditor constructor".split(" ");for(var uu in Ma.prototype)Ma.prototype.hasOwnProperty(uu)&&V(su,uu)<0&&(js.prototype[uu]=function(e){return function(){return e.apply(this.doc,arguments)}}(Ma.prototype[uu]));return _e(Ma),js.inputStyles={textarea:iu,contenteditable:$s},js.defineMode=function(e){js.defaults.mode||"null"==e||(js.defaults.mode=e),Ve.apply(this,arguments)},js.defineMIME=ze,js.defineMode("null",(function(){return{token:function(e){return e.skipToEnd()}}})),js.defineMIME("text/plain","null"),js.defineExtension=function(e,t){js.prototype[e]=t},js.defineDocExtension=function(e,t){Ma.prototype[e]=t},js.fromTextArea=ou,au(js),js.version="5.62.3",js}()},function(e,t,n){"use strict";function r(e){var t,n,i="";if("string"===typeof e||"number"===typeof e)i+=e;else if("object"===typeof e)if(Array.isArray(e))for(t=0;t=55296&&e<=57343)&&(!(e>=64976&&e<=65007)&&(65535!==(65535&e)&&65534!==(65535&e)&&(!(e>=0&&e<=8)&&(11!==e&&(!(e>=14&&e<=31)&&(!(e>=127&&e<=159)&&!(e>1114111)))))))}function a(e){if(e>65535){var t=55296+((e-=65536)>>10),n=56320+(1023&e);return String.fromCharCode(t,n)}return String.fromCharCode(e)}var s=/\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g,u=new RegExp(s.source+"|"+/&([a-z#][a-z0-9]{1,31});/gi.source,"gi"),l=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i,c=n(303);var f=/[&<>"]/,h=/[&<>"]/g,d={"&":"&","<":"<",">":">",'"':"""};function p(e){return d[e]}var m=/[.?*+^$[\]\\(){}|-]/g;var v=n(201);t.lib={},t.lib.mdurl=n(304),t.lib.ucmicro=n(518),t.assign=function(e){var t=Array.prototype.slice.call(arguments,1);return t.forEach((function(t){if(t){if("object"!==typeof t)throw new TypeError(t+"must be object");Object.keys(t).forEach((function(n){e[n]=t[n]}))}})),e},t.isString=function(e){return"[object String]"===function(e){return Object.prototype.toString.call(e)}(e)},t.has=i,t.unescapeMd=function(e){return e.indexOf("\\")<0?e:e.replace(s,"$1")},t.unescapeAll=function(e){return e.indexOf("\\")<0&&e.indexOf("&")<0?e:e.replace(u,(function(e,t,n){return t||function(e,t){var n=0;return i(c,t)?c[t]:35===t.charCodeAt(0)&&l.test(t)&&o(n="x"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10))?a(n):e}(e,n)}))},t.isValidEntityCode=o,t.fromCodePoint=a,t.escapeHtml=function(e){return f.test(e)?e.replace(h,p):e},t.arrayReplaceAt=function(e,t,n){return[].concat(e.slice(0,t),n,e.slice(t+1))},t.isSpace=function(e){switch(e){case 9:case 32:return!0}return!1},t.isWhiteSpace=function(e){if(e>=8192&&e<=8202)return!0;switch(e){case 9:case 10:case 11:case 12:case 13:case 32:case 160:case 5760:case 8239:case 8287:case 12288:return!0}return!1},t.isMdAsciiPunct=function(e){switch(e){case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 58:case 59:case 60:case 61:case 62:case 63:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 124:case 125:case 126:return!0;default:return!1}},t.isPunctChar=function(e){return v.test(e)},t.escapeRE=function(e){return e.replace(m,"\\$&")},t.normalizeReference=function(e){return e=e.trim().replace(/\s+/g," "),"\u1e7e"==="\u1e9e".toLowerCase()&&(e=e.replace(/\u1e9e/g,"\xdf")),e.toLowerCase().toUpperCase()}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i})),n.d(t,"b",(function(){return o})),n.d(t,"c",(function(){return a}));var r=n(49),i=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();Object(r.a)(i);var o=function(){function e(e,t,n,r,i,o,a){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=a,this.prev=o,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function a(e){return null!=e&&"string"===typeof e.kind}Object(r.a)(o)},function(e,t,n){"use strict";n.r(t),n.d(t,"version",(function(){return r})),n.d(t,"versionInfo",(function(){return i})),n.d(t,"graphql",(function(){return se})),n.d(t,"graphqlSync",(function(){return ue})),n.d(t,"GraphQLSchema",(function(){return ce.a})),n.d(t,"GraphQLDirective",(function(){return w.c})),n.d(t,"GraphQLScalarType",(function(){return _.g})),n.d(t,"GraphQLObjectType",(function(){return _.f})),n.d(t,"GraphQLInterfaceType",(function(){return _.c})),n.d(t,"GraphQLUnionType",(function(){return _.h})),n.d(t,"GraphQLEnumType",(function(){return _.a})),n.d(t,"GraphQLInputObjectType",(function(){return _.b})),n.d(t,"GraphQLList",(function(){return _.d})),n.d(t,"GraphQLNonNull",(function(){return _.e})),n.d(t,"specifiedScalarTypes",(function(){return fe.g})),n.d(t,"GraphQLInt",(function(){return fe.d})),n.d(t,"GraphQLFloat",(function(){return fe.b})),n.d(t,"GraphQLString",(function(){return fe.e})),n.d(t,"GraphQLBoolean",(function(){return fe.a})),n.d(t,"GraphQLID",(function(){return fe.c})),n.d(t,"specifiedDirectives",(function(){return w.j})),n.d(t,"GraphQLIncludeDirective",(function(){return w.d})),n.d(t,"GraphQLSkipDirective",(function(){return w.e})),n.d(t,"GraphQLDeprecatedDirective",(function(){return w.b})),n.d(t,"GraphQLSpecifiedByDirective",(function(){return w.f})),n.d(t,"TypeKind",(function(){return b.TypeKind})),n.d(t,"DEFAULT_DEPRECATION_REASON",(function(){return w.a})),n.d(t,"introspectionTypes",(function(){return b.introspectionTypes})),n.d(t,"__Schema",(function(){return b.__Schema})),n.d(t,"__Directive",(function(){return b.__Directive})),n.d(t,"__DirectiveLocation",(function(){return b.__DirectiveLocation})),n.d(t,"__Type",(function(){return b.__Type})),n.d(t,"__Field",(function(){return b.__Field})),n.d(t,"__InputValue",(function(){return b.__InputValue})),n.d(t,"__EnumValue",(function(){return b.__EnumValue})),n.d(t,"__TypeKind",(function(){return b.__TypeKind})),n.d(t,"SchemaMetaFieldDef",(function(){return b.SchemaMetaFieldDef})),n.d(t,"TypeMetaFieldDef",(function(){return b.TypeMetaFieldDef})),n.d(t,"TypeNameMetaFieldDef",(function(){return b.TypeNameMetaFieldDef})),n.d(t,"isSchema",(function(){return ce.c})),n.d(t,"isDirective",(function(){return w.h})),n.d(t,"isType",(function(){return _.S})),n.d(t,"isScalarType",(function(){return _.R})),n.d(t,"isObjectType",(function(){return _.N})),n.d(t,"isInterfaceType",(function(){return _.H})),n.d(t,"isUnionType",(function(){return _.T})),n.d(t,"isEnumType",(function(){return _.E})),n.d(t,"isInputObjectType",(function(){return _.F})),n.d(t,"isListType",(function(){return _.J})),n.d(t,"isNonNullType",(function(){return _.L})),n.d(t,"isInputType",(function(){return _.G})),n.d(t,"isOutputType",(function(){return _.O})),n.d(t,"isLeafType",(function(){return _.I})),n.d(t,"isCompositeType",(function(){return _.D})),n.d(t,"isAbstractType",(function(){return _.C})),n.d(t,"isWrappingType",(function(){return _.U})),n.d(t,"isNullableType",(function(){return _.M})),n.d(t,"isNamedType",(function(){return _.K})),n.d(t,"isRequiredArgument",(function(){return _.P})),n.d(t,"isRequiredInputField",(function(){return _.Q})),n.d(t,"isSpecifiedScalarType",(function(){return fe.f})),n.d(t,"isIntrospectionType",(function(){return b.isIntrospectionType})),n.d(t,"isSpecifiedDirective",(function(){return w.i})),n.d(t,"assertSchema",(function(){return ce.b})),n.d(t,"assertDirective",(function(){return w.g})),n.d(t,"assertType",(function(){return _.x})),n.d(t,"assertScalarType",(function(){return _.w})),n.d(t,"assertObjectType",(function(){return _.u})),n.d(t,"assertInterfaceType",(function(){return _.o})),n.d(t,"assertUnionType",(function(){return _.y})),n.d(t,"assertEnumType",(function(){return _.l})),n.d(t,"assertInputObjectType",(function(){return _.m})),n.d(t,"assertListType",(function(){return _.q})),n.d(t,"assertNonNullType",(function(){return _.s})),n.d(t,"assertInputType",(function(){return _.n})),n.d(t,"assertOutputType",(function(){return _.v})),n.d(t,"assertLeafType",(function(){return _.p})),n.d(t,"assertCompositeType",(function(){return _.k})),n.d(t,"assertAbstractType",(function(){return _.j})),n.d(t,"assertWrappingType",(function(){return _.z})),n.d(t,"assertNullableType",(function(){return _.t})),n.d(t,"assertNamedType",(function(){return _.r})),n.d(t,"getNullableType",(function(){return _.B})),n.d(t,"getNamedType",(function(){return _.A})),n.d(t,"validateSchema",(function(){return u.b})),n.d(t,"assertValidSchema",(function(){return u.a})),n.d(t,"Token",(function(){return he.b})),n.d(t,"Source",(function(){return de.a})),n.d(t,"Location",(function(){return he.a})),n.d(t,"getLocation",(function(){return pe.a})),n.d(t,"printLocation",(function(){return me.a})),n.d(t,"printSourceLocation",(function(){return me.b})),n.d(t,"Lexer",(function(){return ve.a})),n.d(t,"TokenKind",(function(){return ge.a})),n.d(t,"parse",(function(){return a.a})),n.d(t,"parseValue",(function(){return a.c})),n.d(t,"parseType",(function(){return a.b})),n.d(t,"print",(function(){return T.a})),n.d(t,"visit",(function(){return ye.c})),n.d(t,"visitInParallel",(function(){return ye.d})),n.d(t,"getVisitFn",(function(){return ye.b})),n.d(t,"BREAK",(function(){return ye.a})),n.d(t,"Kind",(function(){return y.a})),n.d(t,"DirectiveLocation",(function(){return be.a})),n.d(t,"isDefinitionNode",(function(){return we.a})),n.d(t,"isExecutableDefinitionNode",(function(){return we.b})),n.d(t,"isSelectionNode",(function(){return we.c})),n.d(t,"isValueNode",(function(){return we.i})),n.d(t,"isTypeNode",(function(){return we.f})),n.d(t,"isTypeSystemDefinitionNode",(function(){return we.g})),n.d(t,"isTypeDefinitionNode",(function(){return we.d})),n.d(t,"isTypeSystemExtensionNode",(function(){return we.h})),n.d(t,"isTypeExtensionNode",(function(){return we.e})),n.d(t,"execute",(function(){return B})),n.d(t,"executeSync",(function(){return V})),n.d(t,"defaultFieldResolver",(function(){return oe})),n.d(t,"defaultTypeResolver",(function(){return ie})),n.d(t,"responsePathAsArray",(function(){return m})),n.d(t,"getDirectiveValues",(function(){return L})),n.d(t,"subscribe",(function(){return ke})),n.d(t,"createSourceEventStream",(function(){return Oe})),n.d(t,"validate",(function(){return s.c})),n.d(t,"ValidationContext",(function(){return Ae.b})),n.d(t,"specifiedRules",(function(){return De.a})),n.d(t,"ExecutableDefinitionsRule",(function(){return Pe.a})),n.d(t,"FieldsOnCorrectTypeRule",(function(){return Ie.a})),n.d(t,"FragmentsOnCompositeTypesRule",(function(){return Ne.a})),n.d(t,"KnownArgumentNamesRule",(function(){return Re.b})),n.d(t,"KnownDirectivesRule",(function(){return je.a})),n.d(t,"KnownFragmentNamesRule",(function(){return Le.a})),n.d(t,"KnownTypeNamesRule",(function(){return Fe.a})),n.d(t,"LoneAnonymousOperationRule",(function(){return Be.a})),n.d(t,"NoFragmentCyclesRule",(function(){return Ve.a})),n.d(t,"NoUndefinedVariablesRule",(function(){return ze.a})),n.d(t,"NoUnusedFragmentsRule",(function(){return Ue.a})),n.d(t,"NoUnusedVariablesRule",(function(){return qe.a})),n.d(t,"OverlappingFieldsCanBeMergedRule",(function(){return He.a})),n.d(t,"PossibleFragmentSpreadsRule",(function(){return Ge.a})),n.d(t,"ProvidedRequiredArgumentsRule",(function(){return We.b})),n.d(t,"ScalarLeafsRule",(function(){return Ke.a})),n.d(t,"SingleFieldSubscriptionsRule",(function(){return Ye.a})),n.d(t,"UniqueArgumentNamesRule",(function(){return Qe.a})),n.d(t,"UniqueDirectivesPerLocationRule",(function(){return Ze.a})),n.d(t,"UniqueFragmentNamesRule",(function(){return $e.a})),n.d(t,"UniqueInputFieldNamesRule",(function(){return Je.a})),n.d(t,"UniqueOperationNamesRule",(function(){return Xe.a})),n.d(t,"UniqueVariableNamesRule",(function(){return et.a})),n.d(t,"ValuesOfCorrectTypeRule",(function(){return tt.a})),n.d(t,"VariablesAreInputTypesRule",(function(){return nt.a})),n.d(t,"VariablesInAllowedPositionRule",(function(){return rt.a})),n.d(t,"LoneSchemaDefinitionRule",(function(){return it.a})),n.d(t,"UniqueOperationTypesRule",(function(){return ot.a})),n.d(t,"UniqueTypeNamesRule",(function(){return at.a})),n.d(t,"UniqueEnumValueNamesRule",(function(){return st.a})),n.d(t,"UniqueFieldDefinitionNamesRule",(function(){return ut.a})),n.d(t,"UniqueDirectiveNamesRule",(function(){return lt.a})),n.d(t,"PossibleTypeExtensionsRule",(function(){return ct.a})),n.d(t,"NoDeprecatedCustomRule",(function(){return ft.a})),n.d(t,"NoSchemaIntrospectionCustomRule",(function(){return ht})),n.d(t,"GraphQLError",(function(){return v.a})),n.d(t,"syntaxError",(function(){return dt.a})),n.d(t,"locatedError",(function(){return g.a})),n.d(t,"printError",(function(){return v.b})),n.d(t,"formatError",(function(){return pt})),n.d(t,"getIntrospectionQuery",(function(){return mt.a})),n.d(t,"getOperationAST",(function(){return vt})),n.d(t,"getOperationRootType",(function(){return E})),n.d(t,"introspectionFromSchema",(function(){return bt})),n.d(t,"buildClientSchema",(function(){return wt.a})),n.d(t,"buildASTSchema",(function(){return Pt})),n.d(t,"buildSchema",(function(){return It})),n.d(t,"getDescription",(function(){return Dt})),n.d(t,"extendSchema",(function(){return kt})),n.d(t,"lexicographicSortSchema",(function(){return Bt})),n.d(t,"printSchema",(function(){return Ht})),n.d(t,"printType",(function(){return Qt})),n.d(t,"printIntrospectionSchema",(function(){return Gt})),n.d(t,"typeFromAST",(function(){return M.a})),n.d(t,"valueFromAST",(function(){return C.a})),n.d(t,"valueFromASTUntyped",(function(){return on.a})),n.d(t,"astFromValue",(function(){return qt.a})),n.d(t,"TypeInfo",(function(){return an.a})),n.d(t,"visitWithTypeInfo",(function(){return an.b})),n.d(t,"coerceInputValue",(function(){return P})),n.d(t,"concatAST",(function(){return sn})),n.d(t,"separateOperations",(function(){return un})),n.d(t,"stripIgnoredCharacters",(function(){return fn})),n.d(t,"isEqualType",(function(){return dn.b})),n.d(t,"isTypeSubTypeOf",(function(){return dn.c})),n.d(t,"doTypesOverlap",(function(){return dn.a})),n.d(t,"assertValidName",(function(){return pn.a})),n.d(t,"isValidNameError",(function(){return pn.b})),n.d(t,"BreakingChangeType",(function(){return yn})),n.d(t,"DangerousChangeType",(function(){return bn})),n.d(t,"findBreakingChanges",(function(){return wn})),n.d(t,"findDangerousChanges",(function(){return _n})),n.d(t,"findDeprecatedUsages",(function(){return Nn.a}));var r="15.5.0",i=Object.freeze({major:15,minor:5,patch:0,preReleaseTag:null});function o(e){return"function"===typeof(null===e||void 0===e?void 0:e.then)}var a=n(54),s=n(80),u=n(115),l=n(4);var c=n(15),f=n(9),h=n(31),d=n(114);function p(e,t,n){return{prev:e,key:t,typename:n}}function m(e){for(var t=[],n=e;n;)t.push(n.key),n=n.prev;return t.reverse()}var v=n(3),g=n(67),y=n(2),b=n(12),w=n(22),_=n(1),M=n(34);function E(e,t){if("query"===t.operation){var n=e.getQueryType();if(!n)throw new v.a("Schema does not define the required query root type.",t);return n}if("mutation"===t.operation){var r=e.getMutationType();if(!r)throw new v.a("Schema is not configured for mutations.",t);return r}if("subscription"===t.operation){var i=e.getSubscriptionType();if(!i)throw new v.a("Schema is not configured for subscriptions.",t);return i}throw new v.a("Can only have query, mutation and subscription operations.",t)}var S=n(60),x=n(39);function k(e){return e.map((function(e){return"number"===typeof e?"["+e.toString()+"]":"."+e})).join("")}var T=n(17),C=n(85),O=n(16),A=n(42),D=n(44);function P(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:I;return N(e,t,n)}function I(e,t,n){var r="Invalid value "+Object(l.a)(t);throw e.length>0&&(r+=' at "value'.concat(k(e),'"')),n.message=r+": "+n.message,n}function N(e,t,n,r){if(Object(_.L)(t))return null!=e?N(e,t.ofType,n,r):void n(m(r),e,new v.a('Expected non-nullable type "'.concat(Object(l.a)(t),'" not to be null.')));if(null==e)return null;if(Object(_.J)(t)){var i=t.ofType,o=Object(d.a)(e,(function(e,t){var o=p(r,t,void 0);return N(e,i,n,o)}));return null!=o?o:[N(e,i,n,r)]}if(Object(_.F)(t)){if(!Object(h.a)(e))return void n(m(r),e,new v.a('Expected type "'.concat(t.name,'" to be an object.')));for(var a={},s=t.getFields(),u=0,f=Object(O.a)(s);u0&&(i+=' at "'.concat(s).concat(k(e),'"')),r(new v.a(i+"; "+n.message,a,void 0,void 0,void 0,n.originalError))}))},a=0;a=o)throw new v.a("Too many errors processing variables, error limit reached. Execution aborted.");i.push(e)}));if(0===i.length)return{coerced:a}}catch(s){i.push(s)}return{errors:i}}function j(e,t,n){for(var r,i={},o=null!==(r=t.arguments)&&void 0!==r?r:[],a=Object(x.a)(o,(function(e){return e.name.value})),s=0,u=e.args;s0)return{errors:d};try{t=Object(a.a)(r)}catch(dt){return{errors:[dt]}}var p=Object(s.c)(n,t);return p.length>0?{errors:p}:B({schema:n,document:t,rootValue:i,contextValue:o,variableValues:l,operationName:c,fieldResolver:f,typeResolver:h})}var ce=n(61),fe=n(13),he=n(24),de=n(119),pe=n(136),me=n(226),ve=n(120),ge=n(5),ye=n(35),be=n(8),we=n(48),_e=n(28);function Me(e){return"function"===typeof(null===e||void 0===e?void 0:e[_e.a])}function Ee(e,t,n){var r,i,o,a,s,u,l=e[_e.a].call(e);function c(e){return e.done?e:Se(e.value,t).then(xe,i)}if("function"===typeof l.return&&(r=l.return,i=function(e){var t=function(){return Promise.reject(e)};return r.call(l).then(t,t)}),n){var f=n;o=function(e){return Se(e,f).then(xe,i)}}return a={next:function(){return l.next().then(c,o)},return:function(){return r?r.call(l).then(c,o):Promise.resolve({value:void 0,done:!0})},throw:function(e){return"function"===typeof l.throw?l.throw(e).then(c,o):Promise.reject(e).catch(i)}},s=_e.a,u=function(){return this},s in a?Object.defineProperty(a,s,{value:u,enumerable:!0,configurable:!0,writable:!0}):a[s]=u,a}function Se(e,t){return new Promise((function(n){return n(t(e))}))}function xe(e){return{value:e,done:!1}}function ke(e,t,n,r,i,o,a,s){return Ce(1===arguments.length?e:{schema:e,document:t,rootValue:n,contextValue:r,variableValues:i,operationName:o,fieldResolver:a,subscribeFieldResolver:s})}function Te(e){if(e instanceof v.a)return{errors:[e]};throw e}function Ce(e){var t=e.schema,n=e.document,r=e.rootValue,i=e.contextValue,o=e.variableValues,a=e.operationName,s=e.fieldResolver,u=e.subscribeFieldResolver,l=Oe(t,n,r,i,o,a,u),c=function(e){return B({schema:t,document:n,rootValue:e,contextValue:i,variableValues:o,operationName:a,fieldResolver:s})};return l.then((function(e){return Me(e)?Ee(e,c,Te):e}))}function Oe(e,t,n,r,i,o,a){return q(e,t,i),new Promise((function(s){var u=H(e,t,n,r,i,o,a);s(Array.isArray(u)?{errors:u}:function(e){var t=e.schema,n=e.operation,r=e.variableValues,i=e.rootValue,o=E(t,n),a=W(e,o,n.selectionSet,Object.create(null),Object.create(null)),s=Object.keys(a)[0],u=a[s],c=u[0].name.value,f=ae(t,o,c);if(!f)throw new v.a('The subscription field "'.concat(c,'" is not defined.'),u);var h=p(void 0,s,o.name),d=Z(e,f,u,o,h);return new Promise((function(t){var n,o=j(f,u[0],r),a=e.contextValue;t((null!==(n=f.subscribe)&&void 0!==n?n:e.fieldResolver)(i,o,a,d))})).then((function(e){if(e instanceof Error)throw Object(g.a)(e,u,m(h));if(!Me(e))throw new Error("Subscription field must return Async Iterable. "+"Received: ".concat(Object(l.a)(e),"."));return e}),(function(e){throw Object(g.a)(e,u,m(h))}))}(u))})).catch(Te)}var Ae=n(235),De=n(227),Pe=n(332),Ie=n(340),Ne=n(337),Re=n(231),je=n(229),Le=n(342),Fe=n(228),Be=n(334),Ve=n(345),ze=n(347),Ue=n(343),qe=n(348),He=n(351),Ge=n(344),We=n(233),Ke=n(339),Ye=n(335),Qe=n(232),Ze=n(230),$e=n(341),Je=n(234),Xe=n(333),et=n(346),tt=n(349),nt=n(338),rt=n(350),it=n(352),ot=n(353),at=n(354),st=n(355),ut=n(356),lt=n(357),ct=n(358),ft=n(362);function ht(e){return{Field:function(t){var n=Object(_.A)(e.getType());n&&Object(b.isIntrospectionType)(n)&&e.reportError(new v.a('GraphQL introspection has been disabled, but the requested query contained the field "'.concat(t.name.value,'".'),t))}}}var dt=n(47);function pt(e){var t;e||Object(f.a)(0,"Received null or undefined error.");var n=null!==(t=e.message)&&void 0!==t?t:"An unknown error occurred.",r=e.locations,i=e.path,o=e.extensions;return o?{message:n,locations:r,path:i,extensions:o}:{message:n,locations:r,path:i}}var mt=n(236);function vt(e,t){for(var n=null,r=0,i=e.definitions;r0?n.reverse().join("\n"):void 0}(e);if(void 0!==n)return Object(Mt.a)("\n"+n)}}function Pt(e,t){null!=e&&e.kind===y.a.DOCUMENT||Object(f.a)(0,"Must provide valid Document AST."),!0!==(null===t||void 0===t?void 0:t.assumeValid)&&!0!==(null===t||void 0===t?void 0:t.assumeValidSDL)&&Object(s.a)(e);var n=Tt({description:void 0,types:[],directives:[],extensions:void 0,extensionASTNodes:[],assumeValid:!1},e,t);if(null==n.astNode)for(var r=0,i=n.types;r2&&void 0!==arguments[2]?arguments[2]:"";return 0===t.length?"":t.every((function(e){return!e.description}))?"("+t.map(en).join(", ")+")":"(\n"+t.map((function(t,r){return nn(e,t," "+n,!r)+" "+n+en(t)})).join("\n")+"\n"+n+")"}function en(e){var t=Object(qt.a)(e.defaultValue,e.type),n=e.name+": "+String(e.type);return t&&(n+=" = ".concat(Object(T.a)(t))),n+tn(e.deprecationReason)}function tn(e){if(null==e)return"";var t=Object(qt.a)(e,fe.e);return t&&e!==w.a?" @deprecated(reason: "+Object(T.a)(t)+")":" @deprecated"}function nn(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],i=t.description;if(null==i)return"";if(!0===(null===e||void 0===e?void 0:e.commentDescriptions))return rn(i,n,r);var o=i.length>70,a=Object(Mt.c)(i,"",o),s=n&&!r?"\n"+n:n;return s+a.replace(/\n/g,"\n"+n)+"\n"}function rn(e,t,n){return(t&&!n?"\n":"")+e.split("\n").map((function(e){return t+(""!==e?"# "+e:"#")})).join("\n")+"\n"}var on=n(336),an=n(73);function sn(e){for(var t=[],n=0;n0&&(n="\n"+n);var r=n[n.length-1];return('"'===r&&'\\"""'!==n.slice(-4)||"\\"===r)&&(n+="\n"),'"""'+n+'"""'}var dn=n(71),pn=n(359);function mn(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function vn(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{};return function(n){var o=t.defaultTheme,s=t.withTheme,h=void 0!==s&&s,d=t.name,p=Object(i.a)(t,["defaultTheme","withTheme","name"]);var m=d,v=Object(l.a)(e,Object(r.a)({defaultTheme:o,Component:n,name:d||n.displayName,classNamePrefix:m},p)),g=a.a.forwardRef((function(e,t){e.classes;var s,u=e.innerRef,l=Object(i.a)(e,["classes","innerRef"]),p=v(Object(r.a)({},n.defaultProps,e)),m=l;return("string"===typeof d||h)&&(s=Object(f.a)()||o,d&&(m=Object(c.a)({theme:s,name:d,props:l})),h&&!m.theme&&(m.theme=s)),a.a.createElement(n,Object(r.a)({ref:u||t,classes:p},m))}));return u()(g,n),g}},d=n(118);t.a=function(e,t){return h(e,Object(r.a)({defaultTheme:d.a},t))}},function(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e){return(r="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return"object"==r(e)&&null!==e}n.d(t,"a",(function(){return i}))},,function(e,t,n){"use strict";(function(e){var r=n(410),i=n(411),o=n(250);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function p(e,t){if(u.isBuffer(e))return e.length;if("undefined"!==typeof ArrayBuffer&&"function"===typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!==typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return z(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(e).length;default:if(r)return z(e).length;t=(""+t).toLowerCase(),r=!0}}function m(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return A(this,t,n);case"utf8":case"utf-8":return k(this,t,n);case"ascii":return C(this,t,n);case"latin1":case"binary":return O(this,t,n);case"base64":return x(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return D(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function v(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function g(e,t,n,r,i){if(0===e.length)return-1;if("string"===typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=i?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(i)return-1;n=e.length-1}else if(n<0){if(!i)return-1;n=0}if("string"===typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:y(e,t,n,r,i);if("number"===typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"===typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):y(e,[t],n,r,i);throw new TypeError("val must be string, number or Buffer")}function y(e,t,n,r,i){var o,a=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,u/=2,n/=2}function l(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(i){var c=-1;for(o=n;os&&(n=s-u),o=n;o>=0;o--){for(var f=!0,h=0;hi&&(r=i):r=i;var o=t.length;if(o%2!==0)throw new TypeError("Invalid hex string");r>o/2&&(r=o/2);for(var a=0;a>8,i=n%256,o.push(i),o.push(r);return o}(t,e.length-n),e,n,r)}function x(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function k(e,t,n){n=Math.min(e.length,n);for(var r=[],i=t;i239?4:l>223?3:l>191?2:1;if(i+f<=n)switch(f){case 1:l<128&&(c=l);break;case 2:128===(192&(o=e[i+1]))&&(u=(31&l)<<6|63&o)>127&&(c=u);break;case 3:o=e[i+1],a=e[i+2],128===(192&o)&&128===(192&a)&&(u=(15&l)<<12|(63&o)<<6|63&a)>2047&&(u<55296||u>57343)&&(c=u);break;case 4:o=e[i+1],a=e[i+2],s=e[i+3],128===(192&o)&&128===(192&a)&&128===(192&s)&&(u=(15&l)<<18|(63&o)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(c=u)}null===c?(c=65533,f=1):c>65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c),i+=f}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,i){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),t<0||n>e.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&t>=n)return 0;if(r>=i)return-1;if(t>=n)return 1;if(this===e)return 0;for(var o=(i>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(o,a),l=this.slice(r,i),c=e.slice(t,n),f=0;fi)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var o=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return w(this,e,t,n);case"ascii":return _(this,e,t,n);case"latin1":case"binary":return M(this,e,t,n);case"base64":return E(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,n);default:if(o)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),o=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function C(e,t,n){var r="";n=Math.min(e.length,n);for(var i=t;ir)&&(n=r);for(var i="",o=t;on)throw new RangeError("Trying to access beyond buffer length")}function I(e,t,n,r,i,o){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||te.length)throw new RangeError("Index out of range")}function N(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-n,2);i>>8*(r?i:1-i)}function R(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-n,4);i>>8*(r?i:3-i)&255}function j(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function L(e,t,n,r,o){return o||j(e,0,n,4),i.write(e,t,n,r,23,4),n+4}function F(e,t,n,r,o){return o||j(e,0,n,8),i.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(i*=256);)r+=this[e+--t]*i;return r},u.prototype.readUInt8=function(e,t){return t||P(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||P(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||P(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||P(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||P(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=this[e],i=1,o=0;++o=(i*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=t,i=1,o=this[e+--r];r>0&&(i*=256);)o+=this[e+--r]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},u.prototype.readInt8=function(e,t){return t||P(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||P(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||P(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||P(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||P(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||P(e,4,this.length),i.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||P(e,4,this.length),i.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||P(e,8,this.length),i.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||P(e,8,this.length),i.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||I(this,e,t,n,Math.pow(2,8*n)-1,0);var i=1,o=0;for(this[t]=255&e;++o=0&&(o*=256);)this[t+i]=e/o&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):R(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);I(this,e,t,n,i-1,-i)}var o=0,a=1,s=0;for(this[t]=255&e;++o>0)-s&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);I(this,e,t,n,i-1,-i)}var o=n-1,a=1,s=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===s&&0!==this[t+o+1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):R(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||I(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return L(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return L(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return F(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return F(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--i)e[i+t]=this[i+n];else if(o<1e3||!u.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"===typeof e)for(o=t;o55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&o.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&o.push(239,191,189),i=n;continue}n=65536+(i-55296<<10|n-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;o.push(n)}else if(n<2048){if((t-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function U(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(B,"")).length<2)return"";for(;e.length%4!==0;)e+="=";return e}(e))}function q(e,t,n,r){for(var i=0;i=t.length||i>=e.length);++i)t[i+n]=e[i];return i}}).call(this,n(40))},function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r=n(4),i=n(15),o=n(2),a=n(1);function s(e,t){var n;return t.kind===o.a.LIST_TYPE?(n=s(e,t.type))&&new a.d(n):t.kind===o.a.NON_NULL_TYPE?(n=s(e,t.type))&&new a.e(n):t.kind===o.a.NAMED_TYPE?e.getType(t.name.value):void Object(i.a)(0,"Unexpected type node: "+Object(r.a)(t))}},function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"c",(function(){return s})),n.d(t,"d",(function(){return u})),n.d(t,"b",(function(){return l}));var r=n(4),i=n(24),o={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},a=Object.freeze({});function s(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:o,s=void 0,u=Array.isArray(e),c=[e],f=-1,h=[],d=void 0,p=void 0,m=void 0,v=[],g=[],y=e;do{var b=++f===c.length,w=b&&0!==h.length;if(b){if(p=0===g.length?void 0:v[v.length-1],d=m,m=g.pop(),w){if(u)d=d.slice();else{for(var _={},M=0,E=Object.keys(d);M1)for(var n=1;n=e.character:r.start.line<=e.line&&r.end.line>=e.line},this.start=t,this.end=n}return Object(h.a)(e,[{key:"setStart",value:function(e,t){this.start=new p(e,t)}},{key:"setEnd",value:function(e,t){this.end=new p(e,t)}}]),e}(),p=function(){function e(t,n){var r=this;Object(f.a)(this,e),this.lessThanOrEqualTo=function(e){return r.linet)){for(var l=this._rows,c=0;c<=u;c++)l[0][c]=c;for(var f=1;f<=s;f++){for(var h=l[(f-1)%3],d=l[f%3],p=d[0]=f,m=1;m<=u;m++){var v=r[f-1]===i[m-1]?0:1,g=Math.min(h[m]+1,d[m-1]+1,h[m-1]+v);if(f>1&&m>1&&r[f-1]===i[m-2]&&r[f-2]===i[m-1]){var y=l[(f-2)%3][m-2];g=Math.min(g,y+1)}gt)return}var b=l[s%3][u];return b<=t?b:void 0}},e}();function a(e){for(var t=e.length,n=new Array(t),r=0;r(i>>1)-1?(i>>1)-u:u,o.isubn(s)):s=0,r[a]=s,o.iushrn(1)}return r},r.getJSF=function(e,t){var n=[[],[]];e=e.clone(),t=t.clone();for(var r,i=0,o=0;e.cmpn(-i)>0||t.cmpn(-o)>0;){var a,s,u=e.andln(3)+i&3,l=t.andln(3)+o&3;3===u&&(u=-1),3===l&&(l=-1),a=0===(1&u)?0:3!==(r=e.andln(7)+i&7)&&5!==r||2!==l?u:-u,n[0].push(a),s=0===(1&l)?0:3!==(r=t.andln(7)+o&7)&&5!==r||2!==u?l:-l,n[1].push(s),2*i===a+1&&(i=1-i),2*o===s+1&&(o=1-o),e.iushrn(1),t.iushrn(1)}return n},r.cachedProperty=function(e,t,n){var r="_"+t;e.prototype[t]=function(){return void 0!==this[r]?this[r]:this[r]=n.call(this)}},r.parseBytes=function(e){return"string"===typeof e?r.toArray(e,"hex"):e},r.intFromLE=function(e){return new i(e,"hex","le")}},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(0),i="undefined"!==typeof window?r.useLayoutEffect:r.useEffect;function o(e){var t=r.useRef(e);return i((function(){t.current=e})),r.useCallback((function(){return t.current.apply(void 0,arguments)}),[])}},function(e,t,n){"use strict";n.d(t,"a",(function(){return c})),n.d(t,"c",(function(){return f})),n.d(t,"b",(function(){return h}));var r=n(47),i=n(2),o=n(24),a=n(5),s=n(119),u=n(8),l=n(120);function c(e,t){return new d(e,t).parseDocument()}function f(e,t){var n=new d(e,t);n.expectToken(a.a.SOF);var r=n.parseValueLiteral(!1);return n.expectToken(a.a.EOF),r}function h(e,t){var n=new d(e,t);n.expectToken(a.a.SOF);var r=n.parseTypeReference();return n.expectToken(a.a.EOF),r}var d=function(){function e(e,t){var n=Object(s.b)(e)?e:new s.a(e);this._lexer=new l.a(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(a.a.NAME);return{kind:i.a.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:i.a.DOCUMENT,definitions:this.many(a.a.SOF,this.parseDefinition,a.a.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(a.a.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else{if(this.peek(a.a.BRACE_L))return this.parseOperationDefinition();if(this.peekDescription())return this.parseTypeSystemDefinition()}throw this.unexpected()},t.parseOperationDefinition=function(){var e=this._lexer.token;if(this.peek(a.a.BRACE_L))return{kind:i.a.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(e)};var t,n=this.parseOperationType();return this.peek(a.a.NAME)&&(t=this.parseName()),{kind:i.a.OPERATION_DEFINITION,operation:n,name:t,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseOperationType=function(){var e=this.expectToken(a.a.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(a.a.PAREN_L,this.parseVariableDefinition,a.a.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:i.a.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(a.a.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(a.a.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(a.a.DOLLAR),{kind:i.a.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:i.a.SELECTION_SET,selections:this.many(a.a.BRACE_L,this.parseSelection,a.a.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(a.a.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(a.a.COLON)?(e=r,t=this.parseName()):t=r,{kind:i.a.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(a.a.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(a.a.PAREN_L,t,a.a.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(a.a.COLON),{kind:i.a.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:i.a.ARGUMENT,name:this.parseName(),value:(this.expectToken(a.a.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(a.a.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(a.a.NAME)?{kind:i.a.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:i.a.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return this.expectKeyword("fragment"),!0===(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)?{kind:i.a.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:i.a.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case a.a.BRACKET_L:return this.parseList(e);case a.a.BRACE_L:return this.parseObject(e);case a.a.INT:return this._lexer.advance(),{kind:i.a.INT,value:t.value,loc:this.loc(t)};case a.a.FLOAT:return this._lexer.advance(),{kind:i.a.FLOAT,value:t.value,loc:this.loc(t)};case a.a.STRING:case a.a.BLOCK_STRING:return this.parseStringLiteral();case a.a.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:i.a.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:i.a.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:i.a.NULL,loc:this.loc(t)};default:return{kind:i.a.ENUM,value:t.value,loc:this.loc(t)}}case a.a.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:i.a.STRING,value:e.value,block:e.kind===a.a.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token;return{kind:i.a.LIST,values:this.any(a.a.BRACKET_L,(function(){return t.parseValueLiteral(e)}),a.a.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token;return{kind:i.a.OBJECT,fields:this.any(a.a.BRACE_L,(function(){return t.parseObjectField(e)}),a.a.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(a.a.COLON),{kind:i.a.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(a.a.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(a.a.AT),{kind:i.a.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return this.expectOptionalToken(a.a.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(a.a.BRACKET_R),e={kind:i.a.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(a.a.BANG)?{kind:i.a.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:i.a.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===a.a.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(a.a.STRING)||this.peek(a.a.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(a.a.BRACE_L,this.parseOperationTypeDefinition,a.a.BRACE_R);return{kind:i.a.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(a.a.COLON);var n=this.parseNamedType();return{kind:i.a.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:i.a.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),o=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:i.a.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:o,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if(!0===(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)){var t=[];this.expectOptionalToken(a.a.AMP);do{t.push(this.parseNamedType())}while(this.expectOptionalToken(a.a.AMP)||this.peek(a.a.NAME));return t}return this.delimitedMany(a.a.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return!0===(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)&&this.peek(a.a.BRACE_L)&&this._lexer.lookahead().kind===a.a.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(a.a.BRACE_L,this.parseFieldDefinition,a.a.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(a.a.COLON);var o=this.parseTypeReference(),s=this.parseDirectives(!0);return{kind:i.a.FIELD_DEFINITION,description:t,name:n,arguments:r,type:o,directives:s,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(a.a.PAREN_L,this.parseInputValueDef,a.a.PAREN_R)},t.parseInputValueDef=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName();this.expectToken(a.a.COLON);var r,o=this.parseTypeReference();this.expectOptionalToken(a.a.EQUALS)&&(r=this.parseValueLiteral(!0));var s=this.parseDirectives(!0);return{kind:i.a.INPUT_VALUE_DEFINITION,description:t,name:n,type:o,defaultValue:r,directives:s,loc:this.loc(e)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),o=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:i.a.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:o,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),o=this.parseUnionMemberTypes();return{kind:i.a.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:o,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(a.a.EQUALS)?this.delimitedMany(a.a.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),o=this.parseEnumValuesDefinition();return{kind:i.a.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:o,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(a.a.BRACE_L,this.parseEnumValueDefinition,a.a.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:i.a.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),o=this.parseInputFieldsDefinition();return{kind:i.a.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:o,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(a.a.BRACE_L,this.parseInputValueDef,a.a.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===a.a.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(a.a.BRACE_L,this.parseOperationTypeDefinition,a.a.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:i.a.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:i.a.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),o=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===o.length)throw this.unexpected();return{kind:i.a.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:o,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),o=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===o.length)throw this.unexpected();return{kind:i.a.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:o,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:i.a.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:i.a.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:i.a.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(a.a.AT);var n=this.parseName(),r=this.parseArgumentDefs(),o=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var s=this.parseDirectiveLocations();return{kind:i.a.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:o,locations:s,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(a.a.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==u.a[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if(!0!==(null===(t=this._options)||void 0===t?void 0:t.noLocation))return new o.a(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw Object(r.a)(this._lexer.source,t.start,"Expected ".concat(m(e),", found ").concat(p(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind!==a.a.NAME||t.value!==e)throw Object(r.a)(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(p(t),"."));this._lexer.advance()},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===a.a.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!==e&&void 0!==e?e:this._lexer.token;return Object(r.a)(this._lexer.source,t.start,"Unexpected ".concat(p(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do{r.push(t.call(this))}while(!this.expectOptionalToken(n));return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do{r.push(t.call(this))}while(!this.expectOptionalToken(n));return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do{n.push(t.call(this))}while(this.expectOptionalToken(e));return n},e}();function p(e){var t=e.value;return m(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function m(e){return Object(l.b)(e)?'"'.concat(e,'"'):e}},function(e,t,n){"use strict";function r(e,t,n){return e.reduce((function(e,r){return e[t(r)]=n(r),e}),Object.create(null))}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e,t){var n;return function(){for(var r=this,i=[],o=0;o1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return Math.min(Math.max(t,e),n)}function o(e){if(e.type)return e;if("#"===e.charAt(0))return o(function(e){e=e.substr(1);var t=new RegExp(".{1,".concat(e.length>=6?2:1,"}"),"g"),n=e.match(t);return n&&1===n[0].length&&(n=n.map((function(e){return e+e}))),n?"rgb".concat(4===n.length?"a":"","(").concat(n.map((function(e,t){return t<3?parseInt(e,16):Math.round(parseInt(e,16)/255*1e3)/1e3})).join(", "),")"):""}(e));var t=e.indexOf("("),n=e.substring(0,t);if(-1===["rgb","rgba","hsl","hsla"].indexOf(n))throw new Error(Object(r.a)(3,e));var i=e.substring(t+1,e.length-1).split(",");return{type:n,values:i=i.map((function(e){return parseFloat(e)}))}}function a(e){var t=e.type,n=e.values;return-1!==t.indexOf("rgb")?n=n.map((function(e,t){return t<3?parseInt(e,10):e})):-1!==t.indexOf("hsl")&&(n[1]="".concat(n[1],"%"),n[2]="".concat(n[2],"%")),"".concat(t,"(").concat(n.join(", "),")")}function s(e,t){var n=u(e),r=u(t);return(Math.max(n,r)+.05)/(Math.min(n,r)+.05)}function u(e){var t="hsl"===(e=o(e)).type?o(function(e){var t=(e=o(e)).values,n=t[0],r=t[1]/100,i=t[2]/100,s=r*Math.min(i,1-i),u=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(e+n/30)%12;return i-s*Math.max(Math.min(t-3,9-t,1),-1)},l="rgb",c=[Math.round(255*u(0)),Math.round(255*u(8)),Math.round(255*u(4))];return"hsla"===e.type&&(l+="a",c.push(t[3])),a({type:l,values:c})}(e)).values:e.values;return t=t.map((function(e){return(e/=255)<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4)})),Number((.2126*t[0]+.7152*t[1]+.0722*t[2]).toFixed(3))}function l(e,t){return e=o(e),t=i(t),"rgb"!==e.type&&"hsl"!==e.type||(e.type+="a"),e.values[3]=t,a(e)}function c(e,t){if(e=o(e),t=i(t),-1!==e.type.indexOf("hsl"))e.values[2]*=1-t;else if(-1!==e.type.indexOf("rgb"))for(var n=0;n<3;n+=1)e.values[n]*=1-t;return a(e)}function f(e,t){if(e=o(e),t=i(t),-1!==e.type.indexOf("hsl"))e.values[2]+=(100-e.values[2])*t;else if(-1!==e.type.indexOf("rgb"))for(var n=0;n<3;n+=1)e.values[n]+=(255-e.values[n])*t;return a(e)}},function(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=o(e);if(0!==n)for(var r=1;ra&&i(t[s-1]);)--s;return t.slice(a,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||"\t"===e[0],o='"'===e[e.length-1],a="\\"===e[e.length-1],s=!r||o||a||n,u="";return!s||r&&i||(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return o})),n.d(t,"c",(function(){return a}))},function(e,t,n){"use strict";var r=Object.entries||function(e){return Object.keys(e).map((function(t){return[t,e[t]]}))};t.a=r},function(e,t,n){"use strict";var r=Array.prototype.find?function(e,t){return Array.prototype.find.call(e,t)}:function(e,t){for(var n=0;n=e.length)&&56320===(64512&e.charCodeAt(t+1)))}function a(e){return(e>>>24|e>>>8&65280|e<<8&16711680|(255&e)<<24)>>>0}function s(e){return 1===e.length?"0"+e:e}function u(e){return 7===e.length?"0"+e:6===e.length?"00"+e:5===e.length?"000"+e:4===e.length?"0000"+e:3===e.length?"00000"+e:2===e.length?"000000"+e:1===e.length?"0000000"+e:e}t.inherits=i,t.toArray=function(e,t){if(Array.isArray(e))return e.slice();if(!e)return[];var n=[];if("string"===typeof e)if(t){if("hex"===t)for((e=e.replace(/[^a-z0-9]+/gi,"")).length%2!==0&&(e="0"+e),i=0;i>6|192,n[r++]=63&a|128):o(e,i)?(a=65536+((1023&a)<<10)+(1023&e.charCodeAt(++i)),n[r++]=a>>18|240,n[r++]=a>>12&63|128,n[r++]=a>>6&63|128,n[r++]=63&a|128):(n[r++]=a>>12|224,n[r++]=a>>6&63|128,n[r++]=63&a|128)}else for(i=0;i>>0}return a},t.split32=function(e,t){for(var n=new Array(4*e.length),r=0,i=0;r>>24,n[i+1]=o>>>16&255,n[i+2]=o>>>8&255,n[i+3]=255&o):(n[i+3]=o>>>24,n[i+2]=o>>>16&255,n[i+1]=o>>>8&255,n[i]=255&o)}return n},t.rotr32=function(e,t){return e>>>t|e<<32-t},t.rotl32=function(e,t){return e<>>32-t},t.sum32=function(e,t){return e+t>>>0},t.sum32_3=function(e,t,n){return e+t+n>>>0},t.sum32_4=function(e,t,n,r){return e+t+n+r>>>0},t.sum32_5=function(e,t,n,r,i){return e+t+n+r+i>>>0},t.sum64=function(e,t,n,r){var i=e[t],o=r+e[t+1]>>>0,a=(o>>0,e[t+1]=o},t.sum64_hi=function(e,t,n,r){return(t+r>>>0>>0},t.sum64_lo=function(e,t,n,r){return t+r>>>0},t.sum64_4_hi=function(e,t,n,r,i,o,a,s){var u=0,l=t;return u+=(l=l+r>>>0)>>0)>>0)>>0},t.sum64_4_lo=function(e,t,n,r,i,o,a,s){return t+r+o+s>>>0},t.sum64_5_hi=function(e,t,n,r,i,o,a,s,u,l){var c=0,f=t;return c+=(f=f+r>>>0)>>0)>>0)>>0)>>0},t.sum64_5_lo=function(e,t,n,r,i,o,a,s,u,l){return t+r+o+s+l>>>0},t.rotr64_hi=function(e,t,n){return(t<<32-n|e>>>n)>>>0},t.rotr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0},t.shr64_hi=function(e,t,n){return e>>>n},t.shr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0}},function(e,t){var n=e.exports={version:"2.6.12"};"number"==typeof __e&&(__e=n)},function(e,t,n){"use strict";function r(e,t){"function"===typeof e?e(t):e&&(e.current=t)}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(4),i=n(3);function o(e,t,n){var o,a=e instanceof Error?e:new Error("Unexpected error value: "+Object(r.a)(e));return Array.isArray(a.path)?a:new i.a(a.message,null!==(o=a.nodes)&&void 0!==o?o:t,a.source,a.positions,n,a)}},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var a;"object"===typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{a="undefined"!==typeof window&&"undefined"!==typeof window.Buffer?window.Buffer:n(474).Buffer}catch(x){}function s(e,t){var n=e.charCodeAt(t);return n>=65&&n<=70?n-55:n>=97&&n<=102?n-87:n-48&15}function u(e,t,n){var r=s(e,n);return n-1>=t&&(r|=s(e,n-1)<<4),r}function l(e,t,n,r){for(var i=0,o=Math.min(e.length,n),a=t;a=49?s-49+10:s>=17?s-17+10:s}return i}o.isBN=function(e){return e instanceof o||null!==e&&"object"===typeof e&&e.constructor.wordSize===o.wordSize&&Array.isArray(e.words)},o.max=function(e,t){return e.cmp(t)>0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"===typeof e)return this._initNumber(e,t,n);if("object"===typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&(i++,this.negative=1),i=0;i-=3)a=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=a<>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);else if("le"===n)for(i=0,o=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);return this.strip()},o.prototype._parseHex=function(e,t,n){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var r=0;r=t;r-=2)i=u(e,t,r)<=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;else for(r=(e.length-t)%2===0?t+1:t;r=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;this.strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,a=o%r,s=Math.min(o,o-a)+n,u=0,c=n;c1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},o.prototype.inspect=function(){return(this.red?""};var c=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],f=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],h=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function d(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],a=i*o,s=67108863&a,u=a/67108864|0;n.words[0]=s;for(var l=1;l>>26,f=67108863&u,h=Math.min(l,t.length-1),d=Math.max(0,l-e.length+1);d<=h;d++){var p=l-d|0;c+=(a=(i=0|e.words[p])*(o=0|t.words[d])+f)/67108864|0,f=67108863&a}n.words[l]=0|f,u=0|c}return 0!==u?n.words[l]=0|u:n.length--,n.strip()}o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,a=0;a>>24-i&16777215)||a!==this.length-1?c[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,a--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var l=f[e],d=h[e];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var m=p.modn(d).toString(e);n=(p=p.idivn(d)).isZero()?m+n:c[l-m.length]+m+n}for(this.isZero()&&(n="0"+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16)},o.prototype.toBuffer=function(e,t){return r("undefined"!==typeof a),this.toArrayLike(a,e,t)},o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)},o.prototype.toArrayLike=function(e,t,n){var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0"),this.strip();var a,s,u="le"===t,l=new e(o),c=this.clone();if(u){for(s=0;!c.isZero();s++)a=c.andln(255),c.iushrn(8),l[s]=a;for(;s=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0===(8191&t)&&(n+=13,t>>>=13),0===(127&t)&&(n+=7,t>>>=7),0===(15&t)&&(n+=4,t>>>=4),0===(3&t)&&(n+=2,t>>>=2),0===(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;te.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;ne.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;re.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"===typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-n),this.strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"===typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o>>26;for(;0!==i&&o>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;oe.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,a=0;a>26,this.words[a]=67108863&t;for(;0!==o&&a>26,this.words[a]=67108863&t;if(0===o&&a>>13,d=0|a[1],p=8191&d,m=d>>>13,v=0|a[2],g=8191&v,y=v>>>13,b=0|a[3],w=8191&b,_=b>>>13,M=0|a[4],E=8191&M,S=M>>>13,x=0|a[5],k=8191&x,T=x>>>13,C=0|a[6],O=8191&C,A=C>>>13,D=0|a[7],P=8191&D,I=D>>>13,N=0|a[8],R=8191&N,j=N>>>13,L=0|a[9],F=8191&L,B=L>>>13,V=0|s[0],z=8191&V,U=V>>>13,q=0|s[1],H=8191&q,G=q>>>13,W=0|s[2],K=8191&W,Y=W>>>13,Q=0|s[3],Z=8191&Q,$=Q>>>13,J=0|s[4],X=8191&J,ee=J>>>13,te=0|s[5],ne=8191&te,re=te>>>13,ie=0|s[6],oe=8191&ie,ae=ie>>>13,se=0|s[7],ue=8191&se,le=se>>>13,ce=0|s[8],fe=8191&ce,he=ce>>>13,de=0|s[9],pe=8191&de,me=de>>>13;n.negative=e.negative^t.negative,n.length=19;var ve=(l+(r=Math.imul(f,z))|0)+((8191&(i=(i=Math.imul(f,U))+Math.imul(h,z)|0))<<13)|0;l=((o=Math.imul(h,U))+(i>>>13)|0)+(ve>>>26)|0,ve&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,U))+Math.imul(m,z)|0,o=Math.imul(m,U);var ge=(l+(r=r+Math.imul(f,H)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,H)|0))<<13)|0;l=((o=o+Math.imul(h,G)|0)+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(g,z),i=(i=Math.imul(g,U))+Math.imul(y,z)|0,o=Math.imul(y,U),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,G)|0)+Math.imul(m,H)|0,o=o+Math.imul(m,G)|0;var ye=(l+(r=r+Math.imul(f,K)|0)|0)+((8191&(i=(i=i+Math.imul(f,Y)|0)+Math.imul(h,K)|0))<<13)|0;l=((o=o+Math.imul(h,Y)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,U))+Math.imul(_,z)|0,o=Math.imul(_,U),r=r+Math.imul(g,H)|0,i=(i=i+Math.imul(g,G)|0)+Math.imul(y,H)|0,o=o+Math.imul(y,G)|0,r=r+Math.imul(p,K)|0,i=(i=i+Math.imul(p,Y)|0)+Math.imul(m,K)|0,o=o+Math.imul(m,Y)|0;var be=(l+(r=r+Math.imul(f,Z)|0)|0)+((8191&(i=(i=i+Math.imul(f,$)|0)+Math.imul(h,Z)|0))<<13)|0;l=((o=o+Math.imul(h,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,U))+Math.imul(S,z)|0,o=Math.imul(S,U),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,G)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,G)|0,r=r+Math.imul(g,K)|0,i=(i=i+Math.imul(g,Y)|0)+Math.imul(y,K)|0,o=o+Math.imul(y,Y)|0,r=r+Math.imul(p,Z)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(m,Z)|0,o=o+Math.imul(m,$)|0;var we=(l+(r=r+Math.imul(f,X)|0)|0)+((8191&(i=(i=i+Math.imul(f,ee)|0)+Math.imul(h,X)|0))<<13)|0;l=((o=o+Math.imul(h,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(k,z),i=(i=Math.imul(k,U))+Math.imul(T,z)|0,o=Math.imul(T,U),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,G)|0)+Math.imul(S,H)|0,o=o+Math.imul(S,G)|0,r=r+Math.imul(w,K)|0,i=(i=i+Math.imul(w,Y)|0)+Math.imul(_,K)|0,o=o+Math.imul(_,Y)|0,r=r+Math.imul(g,Z)|0,i=(i=i+Math.imul(g,$)|0)+Math.imul(y,Z)|0,o=o+Math.imul(y,$)|0,r=r+Math.imul(p,X)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(m,X)|0,o=o+Math.imul(m,ee)|0;var _e=(l+(r=r+Math.imul(f,ne)|0)|0)+((8191&(i=(i=i+Math.imul(f,re)|0)+Math.imul(h,ne)|0))<<13)|0;l=((o=o+Math.imul(h,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(O,z),i=(i=Math.imul(O,U))+Math.imul(A,z)|0,o=Math.imul(A,U),r=r+Math.imul(k,H)|0,i=(i=i+Math.imul(k,G)|0)+Math.imul(T,H)|0,o=o+Math.imul(T,G)|0,r=r+Math.imul(E,K)|0,i=(i=i+Math.imul(E,Y)|0)+Math.imul(S,K)|0,o=o+Math.imul(S,Y)|0,r=r+Math.imul(w,Z)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,Z)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(g,X)|0,i=(i=i+Math.imul(g,ee)|0)+Math.imul(y,X)|0,o=o+Math.imul(y,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(m,ne)|0,o=o+Math.imul(m,re)|0;var Me=(l+(r=r+Math.imul(f,oe)|0)|0)+((8191&(i=(i=i+Math.imul(f,ae)|0)+Math.imul(h,oe)|0))<<13)|0;l=((o=o+Math.imul(h,ae)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,U))+Math.imul(I,z)|0,o=Math.imul(I,U),r=r+Math.imul(O,H)|0,i=(i=i+Math.imul(O,G)|0)+Math.imul(A,H)|0,o=o+Math.imul(A,G)|0,r=r+Math.imul(k,K)|0,i=(i=i+Math.imul(k,Y)|0)+Math.imul(T,K)|0,o=o+Math.imul(T,Y)|0,r=r+Math.imul(E,Z)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(S,Z)|0,o=o+Math.imul(S,$)|0,r=r+Math.imul(w,X)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,X)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(g,ne)|0,i=(i=i+Math.imul(g,re)|0)+Math.imul(y,ne)|0,o=o+Math.imul(y,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,ae)|0)+Math.imul(m,oe)|0,o=o+Math.imul(m,ae)|0;var Ee=(l+(r=r+Math.imul(f,ue)|0)|0)+((8191&(i=(i=i+Math.imul(f,le)|0)+Math.imul(h,ue)|0))<<13)|0;l=((o=o+Math.imul(h,le)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(R,z),i=(i=Math.imul(R,U))+Math.imul(j,z)|0,o=Math.imul(j,U),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,G)|0)+Math.imul(I,H)|0,o=o+Math.imul(I,G)|0,r=r+Math.imul(O,K)|0,i=(i=i+Math.imul(O,Y)|0)+Math.imul(A,K)|0,o=o+Math.imul(A,Y)|0,r=r+Math.imul(k,Z)|0,i=(i=i+Math.imul(k,$)|0)+Math.imul(T,Z)|0,o=o+Math.imul(T,$)|0,r=r+Math.imul(E,X)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(S,X)|0,o=o+Math.imul(S,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(g,oe)|0,i=(i=i+Math.imul(g,ae)|0)+Math.imul(y,oe)|0,o=o+Math.imul(y,ae)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,le)|0)+Math.imul(m,ue)|0,o=o+Math.imul(m,le)|0;var Se=(l+(r=r+Math.imul(f,fe)|0)|0)+((8191&(i=(i=i+Math.imul(f,he)|0)+Math.imul(h,fe)|0))<<13)|0;l=((o=o+Math.imul(h,he)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(F,z),i=(i=Math.imul(F,U))+Math.imul(B,z)|0,o=Math.imul(B,U),r=r+Math.imul(R,H)|0,i=(i=i+Math.imul(R,G)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,G)|0,r=r+Math.imul(P,K)|0,i=(i=i+Math.imul(P,Y)|0)+Math.imul(I,K)|0,o=o+Math.imul(I,Y)|0,r=r+Math.imul(O,Z)|0,i=(i=i+Math.imul(O,$)|0)+Math.imul(A,Z)|0,o=o+Math.imul(A,$)|0,r=r+Math.imul(k,X)|0,i=(i=i+Math.imul(k,ee)|0)+Math.imul(T,X)|0,o=o+Math.imul(T,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(S,ne)|0,o=o+Math.imul(S,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,ae)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,ae)|0,r=r+Math.imul(g,ue)|0,i=(i=i+Math.imul(g,le)|0)+Math.imul(y,ue)|0,o=o+Math.imul(y,le)|0,r=r+Math.imul(p,fe)|0,i=(i=i+Math.imul(p,he)|0)+Math.imul(m,fe)|0,o=o+Math.imul(m,he)|0;var xe=(l+(r=r+Math.imul(f,pe)|0)|0)+((8191&(i=(i=i+Math.imul(f,me)|0)+Math.imul(h,pe)|0))<<13)|0;l=((o=o+Math.imul(h,me)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(F,H),i=(i=Math.imul(F,G))+Math.imul(B,H)|0,o=Math.imul(B,G),r=r+Math.imul(R,K)|0,i=(i=i+Math.imul(R,Y)|0)+Math.imul(j,K)|0,o=o+Math.imul(j,Y)|0,r=r+Math.imul(P,Z)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(I,Z)|0,o=o+Math.imul(I,$)|0,r=r+Math.imul(O,X)|0,i=(i=i+Math.imul(O,ee)|0)+Math.imul(A,X)|0,o=o+Math.imul(A,ee)|0,r=r+Math.imul(k,ne)|0,i=(i=i+Math.imul(k,re)|0)+Math.imul(T,ne)|0,o=o+Math.imul(T,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,ae)|0)+Math.imul(S,oe)|0,o=o+Math.imul(S,ae)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,le)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,le)|0,r=r+Math.imul(g,fe)|0,i=(i=i+Math.imul(g,he)|0)+Math.imul(y,fe)|0,o=o+Math.imul(y,he)|0;var ke=(l+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,me)|0)+Math.imul(m,pe)|0))<<13)|0;l=((o=o+Math.imul(m,me)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(F,K),i=(i=Math.imul(F,Y))+Math.imul(B,K)|0,o=Math.imul(B,Y),r=r+Math.imul(R,Z)|0,i=(i=i+Math.imul(R,$)|0)+Math.imul(j,Z)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,X)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(I,X)|0,o=o+Math.imul(I,ee)|0,r=r+Math.imul(O,ne)|0,i=(i=i+Math.imul(O,re)|0)+Math.imul(A,ne)|0,o=o+Math.imul(A,re)|0,r=r+Math.imul(k,oe)|0,i=(i=i+Math.imul(k,ae)|0)+Math.imul(T,oe)|0,o=o+Math.imul(T,ae)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,le)|0)+Math.imul(S,ue)|0,o=o+Math.imul(S,le)|0,r=r+Math.imul(w,fe)|0,i=(i=i+Math.imul(w,he)|0)+Math.imul(_,fe)|0,o=o+Math.imul(_,he)|0;var Te=(l+(r=r+Math.imul(g,pe)|0)|0)+((8191&(i=(i=i+Math.imul(g,me)|0)+Math.imul(y,pe)|0))<<13)|0;l=((o=o+Math.imul(y,me)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(F,Z),i=(i=Math.imul(F,$))+Math.imul(B,Z)|0,o=Math.imul(B,$),r=r+Math.imul(R,X)|0,i=(i=i+Math.imul(R,ee)|0)+Math.imul(j,X)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(I,ne)|0,o=o+Math.imul(I,re)|0,r=r+Math.imul(O,oe)|0,i=(i=i+Math.imul(O,ae)|0)+Math.imul(A,oe)|0,o=o+Math.imul(A,ae)|0,r=r+Math.imul(k,ue)|0,i=(i=i+Math.imul(k,le)|0)+Math.imul(T,ue)|0,o=o+Math.imul(T,le)|0,r=r+Math.imul(E,fe)|0,i=(i=i+Math.imul(E,he)|0)+Math.imul(S,fe)|0,o=o+Math.imul(S,he)|0;var Ce=(l+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,me)|0)+Math.imul(_,pe)|0))<<13)|0;l=((o=o+Math.imul(_,me)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(F,X),i=(i=Math.imul(F,ee))+Math.imul(B,X)|0,o=Math.imul(B,ee),r=r+Math.imul(R,ne)|0,i=(i=i+Math.imul(R,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,ae)|0)+Math.imul(I,oe)|0,o=o+Math.imul(I,ae)|0,r=r+Math.imul(O,ue)|0,i=(i=i+Math.imul(O,le)|0)+Math.imul(A,ue)|0,o=o+Math.imul(A,le)|0,r=r+Math.imul(k,fe)|0,i=(i=i+Math.imul(k,he)|0)+Math.imul(T,fe)|0,o=o+Math.imul(T,he)|0;var Oe=(l+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,me)|0)+Math.imul(S,pe)|0))<<13)|0;l=((o=o+Math.imul(S,me)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(F,ne),i=(i=Math.imul(F,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(R,oe)|0,i=(i=i+Math.imul(R,ae)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,ae)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,le)|0)+Math.imul(I,ue)|0,o=o+Math.imul(I,le)|0,r=r+Math.imul(O,fe)|0,i=(i=i+Math.imul(O,he)|0)+Math.imul(A,fe)|0,o=o+Math.imul(A,he)|0;var Ae=(l+(r=r+Math.imul(k,pe)|0)|0)+((8191&(i=(i=i+Math.imul(k,me)|0)+Math.imul(T,pe)|0))<<13)|0;l=((o=o+Math.imul(T,me)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(F,oe),i=(i=Math.imul(F,ae))+Math.imul(B,oe)|0,o=Math.imul(B,ae),r=r+Math.imul(R,ue)|0,i=(i=i+Math.imul(R,le)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,le)|0,r=r+Math.imul(P,fe)|0,i=(i=i+Math.imul(P,he)|0)+Math.imul(I,fe)|0,o=o+Math.imul(I,he)|0;var De=(l+(r=r+Math.imul(O,pe)|0)|0)+((8191&(i=(i=i+Math.imul(O,me)|0)+Math.imul(A,pe)|0))<<13)|0;l=((o=o+Math.imul(A,me)|0)+(i>>>13)|0)+(De>>>26)|0,De&=67108863,r=Math.imul(F,ue),i=(i=Math.imul(F,le))+Math.imul(B,ue)|0,o=Math.imul(B,le),r=r+Math.imul(R,fe)|0,i=(i=i+Math.imul(R,he)|0)+Math.imul(j,fe)|0,o=o+Math.imul(j,he)|0;var Pe=(l+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,me)|0)+Math.imul(I,pe)|0))<<13)|0;l=((o=o+Math.imul(I,me)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(F,fe),i=(i=Math.imul(F,he))+Math.imul(B,fe)|0,o=Math.imul(B,he);var Ie=(l+(r=r+Math.imul(R,pe)|0)|0)+((8191&(i=(i=i+Math.imul(R,me)|0)+Math.imul(j,pe)|0))<<13)|0;l=((o=o+Math.imul(j,me)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863;var Ne=(l+(r=Math.imul(F,pe))|0)+((8191&(i=(i=Math.imul(F,me))+Math.imul(B,pe)|0))<<13)|0;return l=((o=Math.imul(B,me))+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863,u[0]=ve,u[1]=ge,u[2]=ye,u[3]=be,u[4]=we,u[5]=_e,u[6]=Me,u[7]=Ee,u[8]=Se,u[9]=xe,u[10]=ke,u[11]=Te,u[12]=Ce,u[13]=Oe,u[14]=Ae,u[15]=De,u[16]=Pe,u[17]=Ie,u[18]=Ne,0!==l&&(u[19]=l,n.length++),n};function m(e,t,n){return(new v).mulp(e,t,n)}function v(e,t){this.x=e,this.y=t}Math.imul||(p=d),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?p(this,e,t):n<63?d(this,e,t):n<1024?function(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o>>26)|0)>>>26,a&=67108863}n.words[o]=s,r=a,a=i}return 0!==r?n.words[o]=r:n.length--,n.strip()}(this,e,t):m(this,e,t)},v.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r>=1;return r},v.prototype.permute=function(e,t,n,r,i,o){for(var a=0;a>>=1)i++;return 1<>>=13,n[2*a+1]=8191&o,o>>>=13;for(a=2*t;a>=26,t+=i/67108864|0,t+=o>>>26,this.words[n]=67108863&o}return 0!==t&&(this.words[n]=t,this.length++),this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n>>i}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var a=0;for(t=0;t>>26-n}a&&(this.words[t]=a,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t=0),i=t?(t-t%26)/26:0;var o=e%26,a=Math.min((e-o)/26,this.length),s=67108863^67108863>>>o<a)for(this.length-=a,l=0;l=0&&(0!==c||l>=i);l--){var f=0|this.words[l];this.words[l]=c<<26-o|f>>>o,c=f&s}return u&&0!==c&&(u.words[u.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"===typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"===typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i>26,this.words[i+n]=67108863&o;if(0===s)return this.strip();for(r(-1===s),s=0,i=0;i>26,this.words[i]=67108863&o;return this.negative=1,this.strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,a=0|i.words[i.length-1];0!==(n=26-this._countBits(a))&&(i=i.ushln(n),r.iushln(n),a=0|i.words[i.length-1]);var s,u=r.length-i.length;if("mod"!==t){(s=new o(null)).length=u+1,s.words=new Array(s.length);for(var l=0;l=0;f--){var h=67108864*(0|r.words[i.length+f])+(0|r.words[i.length+f-1]);for(h=Math.min(h/a|0,67108863),r._ishlnsubmul(i,h,f);0!==r.negative;)h--,r.negative=0,r._ishlnsubmul(i,1,f),r.isZero()||(r.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),r.strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:s||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(s=this.neg().divmod(e,t),"mod"!==t&&(i=s.div.neg()),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.iadd(e)),{div:i,mod:a}):0===this.negative&&0!==e.negative?(s=this.divmod(e.neg(),t),"mod"!==t&&(i=s.div.neg()),{div:i,mod:s.mod}):0!==(this.negative&e.negative)?(s=this.neg().divmod(e.neg(),t),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.isub(e)),{div:s.div,mod:a}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modn(e.words[0]))}:this._wordDiv(e,t);var i,a,s},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modn=function(e){r(e<=67108863);for(var t=(1<<26)%e,n=0,i=this.length-1;i>=0;i--)n=(t*n+(0|this.words[i]))%e;return n},o.prototype.idivn=function(e){r(e<=67108863);for(var t=0,n=this.length-1;n>=0;n--){var i=(0|this.words[n])+67108864*t;this.words[n]=i/e|0,t=i%e}return this.strip()},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),a=new o(0),s=new o(0),u=new o(1),l=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++l;for(var c=n.clone(),f=t.clone();!t.isZero();){for(var h=0,d=1;0===(t.words[0]&d)&&h<26;++h,d<<=1);if(h>0)for(t.iushrn(h);h-- >0;)(i.isOdd()||a.isOdd())&&(i.iadd(c),a.isub(f)),i.iushrn(1),a.iushrn(1);for(var p=0,m=1;0===(n.words[0]&m)&&p<26;++p,m<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(s.isOdd()||u.isOdd())&&(s.iadd(c),u.isub(f)),s.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(s),a.isub(u)):(n.isub(t),s.isub(i),u.isub(a))}return{a:s,b:u,gcd:n.iushln(l)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,a=new o(1),s=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var l=0,c=1;0===(t.words[0]&c)&&l<26;++l,c<<=1);if(l>0)for(t.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);for(var f=0,h=1;0===(n.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(n.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);t.cmp(n)>=0?(t.isub(n),a.isub(s)):(n.isub(t),s.isub(a))}return(i=0===t.cmpn(1)?a:s).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0===(1&this.words[0])},o.prototype.isOdd=function(){return 1===(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"===typeof e);var t=e%26,n=(e-t)/26,i=1<>>26,s&=67108863,this.words[a]=s}return 0!==o&&(this.words[a]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this.strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:ie.length)return 1;if(this.length=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){ri&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new E(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var g={k256:null,p224:null,p192:null,p25519:null};function y(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function b(){y.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function w(){y.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function _(){y.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function M(){y.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function E(e){if("string"===typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function S(e){E.call(this,e),this.shift=this.m.bitLength(),this.shift%26!==0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}y.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},y.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},y.prototype.split=function(e,t){e.iushrn(this.n,0,t)},y.prototype.imulK=function(e){return e.imul(this.k)},i(b,y),b.prototype.split=function(e,t){for(var n=4194303,r=Math.min(e.length,9),i=0;i>>22,o=a}o>>>=22,e.words[i-10]=o,0===o&&e.length>10?e.length-=10:e.length-=9},b.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(g[e])return g[e];var t;if("k256"===e)t=new b;else if("p224"===e)t=new w;else if("p192"===e)t=new _;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new M}return g[e]=t,t},E.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},E.prototype._verify2=function(e,t){r(0===(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},E.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):e.umod(this.m)._forceRed(this)},E.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},E.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},E.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},E.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},E.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},E.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},E.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},E.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},E.prototype.isqr=function(e){return this.imul(e,e.clone())},E.prototype.sqr=function(e){return this.mul(e,e)},E.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2===1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),a=0;!i.isZero()&&0===i.andln(1);)a++,i.iushrn(1);r(!i.isZero());var s=new o(1).toRed(this),u=s.redNeg(),l=this.m.subn(1).iushrn(1),c=this.m.bitLength();for(c=new o(2*c*c).toRed(this);0!==this.pow(c,l).cmp(u);)c.redIAdd(u);for(var f=this.pow(c,i),h=this.pow(e,i.addn(1).iushrn(1)),d=this.pow(e,i),p=a;0!==d.cmp(s);){for(var m=d,v=0;0!==m.cmp(s);v++)m=m.redSqr();r(v=0;r--){for(var l=t.words[r],c=u-1;c>=0;c--){var f=l>>c&1;i!==n[0]&&(i=this.sqr(i)),0!==f||0!==a?(a<<=1,a|=f,(4===++s||0===r&&0===c)&&(i=this.mul(i,n[a]),s=0,a=0)):s=0}u=26}return i},E.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},E.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new S(e)},i(S,E),S.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},S.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},S.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},S.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},S.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(75)(e))},function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e,t){for(var n=0;n0)return this._typeStack[this._typeStack.length-1]},t.getParentType=function(){if(this._parentTypeStack.length>0)return this._parentTypeStack[this._parentTypeStack.length-1]},t.getInputType=function(){if(this._inputTypeStack.length>0)return this._inputTypeStack[this._inputTypeStack.length-1]},t.getParentInputType=function(){if(this._inputTypeStack.length>1)return this._inputTypeStack[this._inputTypeStack.length-2]},t.getFieldDef=function(){if(this._fieldDefStack.length>0)return this._fieldDefStack[this._fieldDefStack.length-1]},t.getDefaultValue=function(){if(this._defaultValueStack.length>0)return this._defaultValueStack[this._defaultValueStack.length-1]},t.getDirective=function(){return this._directive},t.getArgument=function(){return this._argument},t.getEnumValue=function(){return this._enumValue},t.enter=function(e){var t=this._schema;switch(e.kind){case i.a.SELECTION_SET:var n=Object(s.A)(this.getType());this._parentTypeStack.push(Object(s.D)(n)?n:void 0);break;case i.a.FIELD:var o,a,u=this.getParentType();u&&(o=this._getFieldDef(t,u,e))&&(a=o.type),this._fieldDefStack.push(o),this._typeStack.push(Object(s.O)(a)?a:void 0);break;case i.a.DIRECTIVE:this._directive=t.getDirective(e.name.value);break;case i.a.OPERATION_DEFINITION:var c;switch(e.operation){case"query":c=t.getQueryType();break;case"mutation":c=t.getMutationType();break;case"subscription":c=t.getSubscriptionType()}this._typeStack.push(Object(s.N)(c)?c:void 0);break;case i.a.INLINE_FRAGMENT:case i.a.FRAGMENT_DEFINITION:var f=e.typeCondition,h=f?Object(l.a)(t,f):Object(s.A)(this.getType());this._typeStack.push(Object(s.O)(h)?h:void 0);break;case i.a.VARIABLE_DEFINITION:var d=Object(l.a)(t,e.type);this._inputTypeStack.push(Object(s.G)(d)?d:void 0);break;case i.a.ARGUMENT:var p,m,v,g=null!==(p=this.getDirective())&&void 0!==p?p:this.getFieldDef();g&&(m=Object(r.a)(g.args,(function(t){return t.name===e.name.value})))&&(v=m.type),this._argument=m,this._defaultValueStack.push(m?m.defaultValue:void 0),this._inputTypeStack.push(Object(s.G)(v)?v:void 0);break;case i.a.LIST:var y=Object(s.B)(this.getInputType()),b=Object(s.J)(y)?y.ofType:y;this._defaultValueStack.push(void 0),this._inputTypeStack.push(Object(s.G)(b)?b:void 0);break;case i.a.OBJECT_FIELD:var w,_,M=Object(s.A)(this.getInputType());Object(s.F)(M)&&(_=M.getFields()[e.name.value])&&(w=_.type),this._defaultValueStack.push(_?_.defaultValue:void 0),this._inputTypeStack.push(Object(s.G)(w)?w:void 0);break;case i.a.ENUM:var E,S=Object(s.A)(this.getInputType());Object(s.E)(S)&&(E=S.getValue(e.value)),this._enumValue=E}},t.leave=function(e){switch(e.kind){case i.a.SELECTION_SET:this._parentTypeStack.pop();break;case i.a.FIELD:this._fieldDefStack.pop(),this._typeStack.pop();break;case i.a.DIRECTIVE:this._directive=null;break;case i.a.OPERATION_DEFINITION:case i.a.INLINE_FRAGMENT:case i.a.FRAGMENT_DEFINITION:this._typeStack.pop();break;case i.a.VARIABLE_DEFINITION:this._inputTypeStack.pop();break;case i.a.ARGUMENT:this._argument=null,this._defaultValueStack.pop(),this._inputTypeStack.pop();break;case i.a.LIST:case i.a.OBJECT_FIELD:this._defaultValueStack.pop(),this._inputTypeStack.pop();break;case i.a.ENUM:this._enumValue=null}},e}();function f(e,t,n){var r=n.name.value;return r===u.SchemaMetaFieldDef.name&&e.getQueryType()===t?u.SchemaMetaFieldDef:r===u.TypeMetaFieldDef.name&&e.getQueryType()===t?u.TypeMetaFieldDef:r===u.TypeNameMetaFieldDef.name&&Object(s.D)(t)?u.TypeNameMetaFieldDef:Object(s.N)(t)||Object(s.H)(t)?t.getFields()[r]:void 0}function h(e,t){return{enter:function(n){e.enter(n);var r=Object(a.b)(t,n.kind,!1);if(r){var i=r.apply(t,arguments);return void 0!==i&&(e.leave(n),Object(o.c)(i)&&e.enter(i)),i}},leave:function(n){var r,i=Object(a.b)(t,n.kind,!0);return i&&(r=i.apply(t,arguments)),e.leave(n),r}}}},function(e,t,n){var r=n(18).Buffer,i=n(426).Transform,o=n(88).StringDecoder;function a(e){i.call(this),this.hashMode="string"===typeof e,this.hashMode?this[e]=this._finalOrDigest:this.final=this._finalOrDigest,this._final&&(this.__final=this._final,this._final=null),this._decoder=null,this._encoding=null}n(11)(a,i),a.prototype.update=function(e,t,n){"string"===typeof e&&(e=r.from(e,t));var i=this._update(e);return this.hashMode?this:(n&&(i=this._toString(i,n)),i)},a.prototype.setAutoPadding=function(){},a.prototype.getAuthTag=function(){throw new Error("trying to get auth tag in unsupported state")},a.prototype.setAuthTag=function(){throw new Error("trying to set auth tag in unsupported state")},a.prototype.setAAD=function(){throw new Error("trying to set aad in unsupported state")},a.prototype._transform=function(e,t,n){var r;try{this.hashMode?this._update(e):this.push(this._update(e))}catch(i){r=i}finally{n(r)}},a.prototype._flush=function(e){var t;try{this.push(this.__final())}catch(n){t=n}e(t)},a.prototype._finalOrDigest=function(e){var t=this.__final()||r.alloc(0);return e&&(t=this._toString(t,e,!0)),t},a.prototype._toString=function(e,t,n){if(this._decoder||(this._decoder=new o(t),this._encoding=t),this._encoding!==t)throw new Error("can't switch encodings");var r=this._decoder.write(e);return n&&(r+=this._decoder.end()),r},e.exports=a},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){e.exports=!n(110)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(1),i=n(116),o=new(n.n(i).a);function a(e,t,r){var i,a;n(20).on(t,"select",(function(e,t){if(!i){var n,u=t.parentNode;(i=document.createElement("div")).className="CodeMirror-hint-information",u.appendChild(i),(a=document.createElement("div")).className="CodeMirror-hint-deprecation",u.appendChild(a),u.addEventListener("DOMNodeRemoved",n=function(e){e.target===u&&(u.removeEventListener("DOMNodeRemoved",n),i=null,a=null,n=null)})}var l=e.description?o.render(e.description):"Self descriptive.",c=e.type?''+s(e.type)+"":"";if(i.innerHTML='
'+("

"===l.slice(0,3)?"

"+c+l.slice(3):c+l)+"

",e&&a&&e.isDeprecated){var f=e.deprecationReason?o.render(e.deprecationReason):"";a.innerHTML='Deprecated'+f,a.style.display="block"}else a&&(a.style.display="none");r&&r(i)}))}function s(e){return e instanceof r.e?s(e.ofType)+"!":e instanceof r.d?"["+s(e.ofType)+"]":''+e.name+""}},function(e,t,n){"use strict";function r(e,t){for(var n=0,r=0;n0);var l=0;do{++r,l=10*l+s-i,s=t.charCodeAt(r)}while(o(s)&&l>0);if(ul)return 1}else{if(as)return 1;++n,++r}}return e.length-t.length}n.d(t,"a",(function(){return r}));var i=48;function o(e){return!isNaN(e)&&i<=e&&e<=57}},function(e,t,n){"use strict";n.d(t,"c",(function(){return c})),n.d(t,"a",(function(){return h})),n.d(t,"b",(function(){return d}));var r=n(9),i=n(3),o=n(35),a=n(115),s=n(73),u=n(227),l=n(235);function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.a,c=arguments.length>3&&void 0!==arguments[3]?arguments[3]:new s.a(e),f=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{maxErrors:void 0};t||Object(r.a)(0,"Must provide document."),Object(a.a)(e);var h=Object.freeze({}),d=[],p=new l.b(e,t,c,(function(e){if(null!=f.maxErrors&&d.length>=f.maxErrors)throw d.push(new i.a("Too many validation errors, error limit reached. Validation aborted.")),h;d.push(e)})),m=Object(o.d)(n.map((function(e){return e(p)})));try{Object(o.c)(t,Object(s.b)(c,m))}catch(v){if(v!==h)throw v}return d}function f(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.b,r=[],i=new l.a(e,t,(function(e){r.push(e)})),a=n.map((function(e){return e(i)}));return Object(o.c)(e,Object(o.d)(a)),r}function h(e){var t=f(e);if(0!==t.length)throw new Error(t.map((function(e){return e.message})).join("\n\n"))}function d(e,t){var n=f(e,t);if(0!==n.length)throw new Error(n.map((function(e){return e.message})).join("\n\n"))}},function(e,t,n){"use strict";var r,i=!1;"object"===typeof window&&(i="MacIntel"===window.navigator.platform);var o=((r={})[i?"Cmd-F":"Ctrl-F"]="findPersistent",r["Cmd-G"]="findPersistent",r["Ctrl-G"]="findPersistent",r["Ctrl-Left"]="goSubwordLeft",r["Ctrl-Right"]="goSubwordRight",r["Alt-Left"]="goGroupLeft",r["Alt-Right"]="goGroupRight",r);t.a=o},function(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(139);var i=n(369),o=n(171);function a(e){return function(e){if(Array.isArray(e))return Object(r.a)(e)}(e)||Object(i.a)(e)||Object(o.a)(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}},function(e,t,n){"use strict";n.d(t,"a",(function(){return h}));var r=n(97),i=n(16),o=n(4),a=n(15),s=n(31),u=n(114),l=n(2),c=n(13),f=n(1);function h(e,t){if(Object(f.L)(t)){var n=h(e,t.ofType);return(null===n||void 0===n?void 0:n.kind)===l.a.NULL?null:n}if(null===e)return{kind:l.a.NULL};if(void 0===e)return null;if(Object(f.J)(t)){var p=t.ofType,m=Object(u.a)(e);if(null!=m){for(var v=[],g=0;g0&&a.length>i&&!a.warned){a.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=a.length,s=u,console&&console.warn&&console.warn(s)}return e}function h(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function d(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=h.bind(r);return i.listener=n,r.wrapFn=i,i}function p(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];return void 0===i?[]:"function"===typeof i?n?[i.listener||i]:[i]:n?function(e){for(var t=new Array(e.length),n=0;n0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var u=i[e];if(void 0===u)return!1;if("function"===typeof u)o(u,this,t);else{var l=u.length,c=v(u,l);for(n=0;n=0;o--)if(n[o]===t||n[o].listener===t){a=n[o].listener,i=o;break}if(i<0)return this;0===i?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return p(this,e,!0)},s.prototype.rawListeners=function(e){return p(this,e,!1)},s.listenerCount=function(e,t){return"function"===typeof e.listenerCount?e.listenerCount(t):m.call(e,t)},s.prototype.listenerCount=m,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){"use strict";var r=n(18).Buffer,i=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!==typeof t&&(r.isEncoding===i||!i(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=l,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=c,this.end=f,t=3;break;default:return this.write=h,void(this.end=d)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5===6?2:e>>4===14?3:e>>3===30?4:e>>6===2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!==(192&t[0]))return e.lastNeed=0,"\ufffd";if(e.lastNeed>1&&t.length>1){if(128!==(192&t[1]))return e.lastNeed=1,"\ufffd";if(e.lastNeed>2&&t.length>2&&128!==(192&t[2]))return e.lastNeed=2,"\ufffd"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2===0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function l(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function c(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function d(e){return e&&e.length?this.write(e):""}t.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return i>0&&(e.lastNeed=i-1),i;if(--r=0)return i>0&&(e.lastNeed=i-2),i;if(--r=0)return i>0&&(2===i?i=0:e.lastNeed=i-3),i;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";var r=n(143),i=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var o=Object.create(n(125));o.inherits=n(11);var a=n(260),s=n(184);o.inherits(f,a);for(var u=i(s.prototype),l=0;lo)throw new RangeError("requested too many random bytes");var n=a.allocUnsafe(e);if(e>0)if(e>i)for(var u=0;u2?"one of ".concat(t," ").concat(e.slice(0,n-1).join(", "),", or ")+e[n-1]:2===n?"one of ".concat(t," ").concat(e[0]," or ").concat(e[1]):"of ".concat(t," ").concat(e[0])}return"of ".concat(t," ").concat(String(e))}i("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError),i("ERR_INVALID_ARG_TYPE",(function(e,t,n){var r,i,a,s;if("string"===typeof t&&(i="not ",t.substr(!a||a<0?0:+a,i.length)===i)?(r="must not be",t=t.replace(/^not /,"")):r="must be",function(e,t,n){return(void 0===n||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}(e," argument"))s="The ".concat(e," ").concat(r," ").concat(o(t,"type"));else{var u=function(e,t,n){return"number"!==typeof n&&(n=0),!(n+t.length>e.length)&&-1!==e.indexOf(t,n)}(e,".")?"property":"argument";s='The "'.concat(e,'" ').concat(u," ").concat(r," ").concat(o(t,"type"))}return s+=". Received type ".concat(typeof n)}),TypeError),i("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),i("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"})),i("ERR_STREAM_PREMATURE_CLOSE","Premature close"),i("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"})),i("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),i("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),i("ERR_STREAM_WRITE_AFTER_END","write after end"),i("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),i("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError),i("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),e.exports.codes=r},function(e,t,n){"use strict";(function(t){var r=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=l;var i=n(252),o=n(256);n(11)(l,i);for(var a=r(o.prototype),s=0;s=this._finalSize&&(this._update(this._block),this._block.fill(0));var n=8*this._len;if(n<=4294967295)this._block.writeUInt32BE(n,this._blockSize-4);else{var r=(4294967295&n)>>>0,i=(n-r)/4294967296;this._block.writeUInt32BE(i,this._blockSize-8),this._block.writeUInt32BE(r,this._blockSize-4)}this._update(this._block);var o=this._hash();return e?o.toString(e):o},i.prototype._update=function(){throw new Error("_update must be implemented by subclass")},e.exports=i},function(e,t,n){"use strict";var r={};function i(e,t,n){n||(n=Error);var i=function(e){var n,r;function i(n,r,i){return e.call(this,function(e,n,r){return"string"===typeof t?t:t(e,n,r)}(n,r,i))||this}return r=e,(n=i).prototype=Object.create(r.prototype),n.prototype.constructor=n,n.__proto__=r,i}(n);i.prototype.name=n.name,i.prototype.code=e,r[e]=i}function o(e,t){if(Array.isArray(e)){var n=e.length;return e=e.map((function(e){return String(e)})),n>2?"one of ".concat(t," ").concat(e.slice(0,n-1).join(", "),", or ")+e[n-1]:2===n?"one of ".concat(t," ").concat(e[0]," or ").concat(e[1]):"of ".concat(t," ").concat(e[0])}return"of ".concat(t," ").concat(String(e))}i("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError),i("ERR_INVALID_ARG_TYPE",(function(e,t,n){var r,i,a,s;if("string"===typeof t&&(i="not ",t.substr(!a||a<0?0:+a,i.length)===i)?(r="must not be",t=t.replace(/^not /,"")):r="must be",function(e,t,n){return(void 0===n||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}(e," argument"))s="The ".concat(e," ").concat(r," ").concat(o(t,"type"));else{var u=function(e,t,n){return"number"!==typeof n&&(n=0),!(n+t.length>e.length)&&-1!==e.indexOf(t,n)}(e,".")?"property":"argument";s='The "'.concat(e,'" ').concat(u," ").concat(r," ").concat(o(t,"type"))}return s+=". Received type ".concat(typeof n)}),TypeError),i("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),i("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"})),i("ERR_STREAM_PREMATURE_CLOSE","Premature close"),i("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"})),i("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),i("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),i("ERR_STREAM_WRITE_AFTER_END","write after end"),i("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),i("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError),i("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),e.exports.codes=r},function(e,t,n){"use strict";(function(t){var r=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=l;var i=n(282),o=n(286);n(11)(l,i);for(var a=r(o.prototype),s=0;sc);f++){var h=e.getLine(l++);i=null==i?h:i+"\n"+h}u*=2,t.lastIndex=n.ch;var d=t.exec(i);if(d){var p=i.slice(0,d.index).split("\n"),m=d[0].split("\n"),v=n.line+p.length-1,g=p[p.length-1].length;return{from:r(v,g),to:r(v+m.length-1,1==m.length?g+m[0].length:m[m.length-1].length),match:d}}}}function l(e,t,n){for(var r,i=0;i<=e.length;){t.lastIndex=i;var o=t.exec(e);if(!o)break;var a=o.index+o[0].length;if(a>e.length-n)break;(!r||a>r.index+r[0].length)&&(r=o),i=o.index+1}return r}function c(e,t,n){t=o(t,"g");for(var i=n.line,a=n.ch,s=e.firstLine();i>=s;i--,a=-1){var u=e.getLine(i),c=l(u,t,a<0?0:u.length-a);if(c)return{from:r(i,c.index),to:r(i,c.index+c[0].length),match:c}}}function f(e,t,n){if(!a(t))return c(e,t,n);t=o(t,"gm");for(var i,s=1,u=e.getLine(n.line).length-n.ch,f=n.line,h=e.firstLine();f>=h;){for(var d=0;d=h;d++){var p=e.getLine(f--);i=null==i?p:p+"\n"+i}s*=2;var m=l(i,t,u);if(m){var v=i.slice(0,m.index).split("\n"),g=m[0].split("\n"),y=f+v.length,b=v[v.length-1].length;return{from:r(y,b),to:r(y+g.length-1,1==g.length?b+g[0].length:g[g.length-1].length),match:m}}}}function h(e,t,n,r){if(e.length==t.length)return n;for(var i=0,o=n+Math.max(0,e.length-t.length);;){if(i==o)return i;var a=i+o>>1,s=r(e.slice(0,a)).length;if(s==n)return a;s>n?o=a:i=a+1}}function d(e,i,o,a){if(!i.length)return null;var s=a?t:n,u=s(i).split(/\r|\n\r?/);e:for(var l=o.line,c=o.ch,f=e.lastLine()+1-u.length;l<=f;l++,c=0){var d=e.getLine(l).slice(c),p=s(d);if(1==u.length){var m=p.indexOf(u[0]);if(-1==m)continue e;return o=h(d,p,m,s)+c,{from:r(l,h(d,p,m,s)+c),to:r(l,h(d,p,m+u[0].length,s)+c)}}var v=p.length-u[0].length;if(p.slice(v)==u[0]){for(var g=1;g=f;l--,c=-1){var d=e.getLine(l);c>-1&&(d=d.slice(0,c));var p=s(d);if(1==u.length){var m=p.lastIndexOf(u[0]);if(-1==m)continue e;return{from:r(l,h(d,p,m,s)),to:r(l,h(d,p,m+u[0].length,s))}}var v=u[u.length-1];if(p.slice(0,v.length)==v){var g=1;for(o=l-u.length+1;g0);)r.push({anchor:i.from(),head:i.to()});r.length&&this.setSelections(r,0)}))}(n(20))},function(e,t,n){!function(e){function t(t,n,r){var i,o=t.getWrapperElement();return(i=o.appendChild(document.createElement("div"))).className=r?"CodeMirror-dialog CodeMirror-dialog-bottom":"CodeMirror-dialog CodeMirror-dialog-top","string"==typeof n?i.innerHTML=n:i.appendChild(n),e.addClass(o,"dialog-opened"),i}function n(e,t){e.state.currentNotificationClose&&e.state.currentNotificationClose(),e.state.currentNotificationClose=t}e.defineExtension("openDialog",(function(r,i,o){o||(o={}),n(this,null);var a=t(this,r,o.bottom),s=!1,u=this;function l(t){if("string"==typeof t)f.value=t;else{if(s)return;s=!0,e.rmClass(a.parentNode,"dialog-opened"),a.parentNode.removeChild(a),u.focus(),o.onClose&&o.onClose(a)}}var c,f=a.getElementsByTagName("input")[0];return f?(f.focus(),o.value&&(f.value=o.value,!1!==o.selectValueOnOpen&&f.select()),o.onInput&&e.on(f,"input",(function(e){o.onInput(e,f.value,l)})),o.onKeyUp&&e.on(f,"keyup",(function(e){o.onKeyUp(e,f.value,l)})),e.on(f,"keydown",(function(t){o&&o.onKeyDown&&o.onKeyDown(t,f.value,l)||((27==t.keyCode||!1!==o.closeOnEnter&&13==t.keyCode)&&(f.blur(),e.e_stop(t),l()),13==t.keyCode&&i(f.value,t))})),!1!==o.closeOnBlur&&e.on(a,"focusout",(function(e){null!==e.relatedTarget&&l()}))):(c=a.getElementsByTagName("button")[0])&&(e.on(c,"click",(function(){l(),u.focus()})),!1!==o.closeOnBlur&&e.on(c,"blur",l),c.focus()),l})),e.defineExtension("openConfirm",(function(r,i,o){n(this,null);var a=t(this,r,o&&o.bottom),s=a.getElementsByTagName("button"),u=!1,l=this,c=1;function f(){u||(u=!0,e.rmClass(a.parentNode,"dialog-opened"),a.parentNode.removeChild(a),l.focus())}s[0].focus();for(var h=0;h1&&void 0!==arguments[1]?arguments[1]:function(e){return e};if(null==e||"object"!==i(e))return null;if(Array.isArray(e))return e.map(t);var n=e[r.b];if("function"===typeof n){for(var o,a=n.call(e),s=[],u=0;!(o=a.next()).done;++u)s.push(t(o.value,u));return s}var l=e.length;if("number"===typeof l&&l>=0&&l%1===0){for(var c=[],f=0;f1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"===typeof e||Object(o.a)(0,"Body must be a string. Received: ".concat(Object(i.a)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||Object(o.a)(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||Object(o.a)(0,"column in locationOffset is 1-indexed and must be positive.")}var t,n,a;return t=e,(n=[{key:r.c,get:function(){return"Source"}}])&&s(t.prototype,n),a&&s(t,a),e}();function l(e){return Object(a.a)(e,u)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return u}));var r=n(47),i=n(24),o=n(5),a=n(58),s=function(){function e(e){var t=new i.b(o.a.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e=this.token;if(e.kind!==o.a.EOF)do{var t;e=null!==(t=e.next)&&void 0!==t?t:e.next=c(this,e)}while(e.kind===o.a.COMMENT);return e},e}();function u(e){return e===o.a.BANG||e===o.a.DOLLAR||e===o.a.AMP||e===o.a.PAREN_L||e===o.a.PAREN_R||e===o.a.SPREAD||e===o.a.COLON||e===o.a.EQUALS||e===o.a.AT||e===o.a.BRACKET_L||e===o.a.BRACKET_R||e===o.a.BRACE_L||e===o.a.PIPE||e===o.a.BRACE_R}function l(e){return isNaN(e)?o.a.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function c(e,t){for(var n=e.source,a=n.body,s=a.length,u=t.end;u31||9===s));return new i.b(o.a.COMMENT,t,l,n,r,a,u.slice(t+1,l))}function d(e,t,n,a,s,u){var c=e.body,f=n,h=t,d=!1;if(45===f&&(f=c.charCodeAt(++h)),48===f){if((f=c.charCodeAt(++h))>=48&&f<=57)throw Object(r.a)(e,h,"Invalid number, unexpected digit after 0: ".concat(l(f),"."))}else h=p(e,h,f),f=c.charCodeAt(h);if(46===f&&(d=!0,f=c.charCodeAt(++h),h=p(e,h,f),f=c.charCodeAt(h)),69!==f&&101!==f||(d=!0,43!==(f=c.charCodeAt(++h))&&45!==f||(f=c.charCodeAt(++h)),h=p(e,h,f),f=c.charCodeAt(h)),46===f||function(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}(f))throw Object(r.a)(e,h,"Invalid number, expected digit but got: ".concat(l(f),"."));return new i.b(d?o.a.FLOAT:o.a.INT,t,h,a,s,u,c.slice(t,h))}function p(e,t,n){var i=e.body,o=t,a=n;if(a>=48&&a<=57){do{a=i.charCodeAt(++o)}while(a>=48&&a<=57);return o}throw Object(r.a)(e,o,"Invalid number, expected digit but got: ".concat(l(a),"."))}function m(e,t,n,a,s){for(var u,c,f,h,d=e.body,p=t+1,m=p,v=0,y="";p=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function y(e,t,n,r,a){for(var s=e.body,u=s.length,l=t+1,c=0;l!==u&&!isNaN(c=s.charCodeAt(l))&&(95===c||c>=48&&c<=57||c>=65&&c<=90||c>=97&&c<=122);)++l;return new i.b(o.a.NAME,t,l,n,r,a,s.slice(t,l))}},function(e,t,n){"use strict";function r(e,t){for(var n=0;n=this._delta8){var n=(e=this.pending).length%this._delta8;this.pending=e.slice(e.length-n,e.length),0===this.pending.length&&(this.pending=null),e=r.join32(e,0,e.length-n,this.endian);for(var i=0;i>>24&255,r[i++]=e>>>16&255,r[i++]=e>>>8&255,r[i++]=255&e}else for(r[i++]=255&e,r[i++]=e>>>8&255,r[i++]=e>>>16&255,r[i++]=e>>>24&255,r[i++]=0,r[i++]=0,r[i++]=0,r[i++]=0,o=8;o=65&&r<=90||!t.shiftKey&&r>=48&&r<=57||t.shiftKey&&189===r||t.shiftKey&&222===r)&&n.editor.execCommand("autocomplete")},n._onEdit=function(){n.editor&&(n.ignoreChangeEvent||(n.cachedValue=n.editor.getValue(),n.props.onEdit&&n.props.onEdit(n.cachedValue)))},n._onHasCompletion=function(e,t){Object(o.a)(e,t,n.props.onHintInformationRender)},n.cachedValue=t.value||"",n}return s(t,e),t.prototype.componentDidMount=function(){var e=this;this.CodeMirror=n(20),n(148),n(149),n(204),n(151),n(150),n(205),n(106),n(152),n(107),n(153),n(574),n(576),n(578);var t=this.editor=this.CodeMirror(this._node,{value:this.props.value||"",lineNumbers:!0,tabSize:2,mode:"graphql-variables",theme:this.props.editorTheme||"graphiql",keyMap:"sublime",autoCloseBrackets:!0,matchBrackets:!0,showCursorWhenSelecting:!0,readOnly:!!this.props.readOnly&&"nocursor",foldGutter:{minFoldSize:4},lint:{variableToType:this.props.variableToType},hintOptions:{variableToType:this.props.variableToType,closeOnUnfocus:!1,completeSingle:!1,container:this._node},gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],extraKeys:u({"Cmd-Space":function(){return e.editor.showHint({completeSingle:!1,container:e._node})},"Ctrl-Space":function(){return e.editor.showHint({completeSingle:!1,container:e._node})},"Alt-Space":function(){return e.editor.showHint({completeSingle:!1,container:e._node})},"Shift-Space":function(){return e.editor.showHint({completeSingle:!1,container:e._node})},"Cmd-Enter":function(){e.props.onRunQuery&&e.props.onRunQuery()},"Ctrl-Enter":function(){e.props.onRunQuery&&e.props.onRunQuery()},"Shift-Ctrl-P":function(){e.props.onPrettifyQuery&&e.props.onPrettifyQuery()},"Shift-Ctrl-M":function(){e.props.onMergeQuery&&e.props.onMergeQuery()}},a.a)});t.on("change",this._onEdit),t.on("keyup",this._onKeyUp),t.on("hasCompletion",this._onHasCompletion)},t.prototype.componentDidUpdate=function(e){if(this.CodeMirror=n(20),this.editor){if(this.ignoreChangeEvent=!0,this.props.variableToType!==e.variableToType&&(this.editor.options.lint.variableToType=this.props.variableToType,this.editor.options.hintOptions.variableToType=this.props.variableToType,this.CodeMirror.signal(this.editor,"change",this.editor)),this.props.value!==e.value&&this.props.value!==this.cachedValue){var t=this.props.value||"";this.cachedValue=t,this.editor.setValue(t)}this.ignoreChangeEvent=!1}},t.prototype.componentWillUnmount=function(){this.editor&&(this.editor.off("change",this._onEdit),this.editor.off("keyup",this._onKeyUp),this.editor.off("hasCompletion",this._onHasCompletion),this.editor=null)},t.prototype.render=function(){var e=this;return i.a.createElement("div",{className:"codemirrorWrap",style:{position:this.props.active?"relative":"absolute",visibility:this.props.active?"visible":"hidden"},ref:function(t){e._node=t}})},t.prototype.getCodeMirror=function(){return this.editor},t.prototype.getClientHeight=function(){return this._node&&this._node.clientHeight},t}(i.a.Component)},function(e,t,n){"use strict";function r(e,t,n){if(n&&!(n.length<1)){var r=n.map((function(e){return e.name&&e.name.value}));if(t&&-1!==r.indexOf(t))return t;if(t&&e){var i=e.map((function(e){return e.name&&e.name.value})).indexOf(t);if(-1!==i&&ie.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n>>24]^c[p>>>16&255]^f[m>>>8&255]^h[255&v]^t[g++],a=l[p>>>24]^c[m>>>16&255]^f[v>>>8&255]^h[255&d]^t[g++],s=l[m>>>24]^c[v>>>16&255]^f[d>>>8&255]^h[255&p]^t[g++],u=l[v>>>24]^c[d>>>16&255]^f[p>>>8&255]^h[255&m]^t[g++],d=o,p=a,m=s,v=u;return o=(r[d>>>24]<<24|r[p>>>16&255]<<16|r[m>>>8&255]<<8|r[255&v])^t[g++],a=(r[p>>>24]<<24|r[m>>>16&255]<<16|r[v>>>8&255]<<8|r[255&d])^t[g++],s=(r[m>>>24]<<24|r[v>>>16&255]<<16|r[d>>>8&255]<<8|r[255&p])^t[g++],u=(r[v>>>24]<<24|r[d>>>16&255]<<16|r[p>>>8&255]<<8|r[255&m])^t[g++],[o>>>=0,a>>>=0,s>>>=0,u>>>=0]}var s=[0,1,2,4,8,16,32,64,128,27,54],u=function(){for(var e=new Array(256),t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;for(var n=[],r=[],i=[[],[],[],[]],o=[[],[],[],[]],a=0,s=0,u=0;u<256;++u){var l=s^s<<1^s<<2^s<<3^s<<4;l=l>>>8^255&l^99,n[a]=l,r[l]=a;var c=e[a],f=e[c],h=e[f],d=257*e[l]^16843008*l;i[0][a]=d<<24|d>>>8,i[1][a]=d<<16|d>>>16,i[2][a]=d<<8|d>>>24,i[3][a]=d,d=16843009*h^65537*f^257*c^16843008*a,o[0][l]=d<<24|d>>>8,o[1][l]=d<<16|d>>>16,o[2][l]=d<<8|d>>>24,o[3][l]=d,0===a?a=s=1:(a=c^e[e[e[h^c]]],s^=e[e[s]])}return{SBOX:n,INV_SBOX:r,SUB_MIX:i,INV_SUB_MIX:o}}();function l(e){this._key=i(e),this._reset()}l.blockSize=16,l.keySize=32,l.prototype.blockSize=l.blockSize,l.prototype.keySize=l.keySize,l.prototype._reset=function(){for(var e=this._key,t=e.length,n=t+6,r=4*(n+1),i=[],o=0;o>>24,a=u.SBOX[a>>>24]<<24|u.SBOX[a>>>16&255]<<16|u.SBOX[a>>>8&255]<<8|u.SBOX[255&a],a^=s[o/t|0]<<24):t>6&&o%t===4&&(a=u.SBOX[a>>>24]<<24|u.SBOX[a>>>16&255]<<16|u.SBOX[a>>>8&255]<<8|u.SBOX[255&a]),i[o]=i[o-t]^a}for(var l=[],c=0;c>>24]]^u.INV_SUB_MIX[1][u.SBOX[h>>>16&255]]^u.INV_SUB_MIX[2][u.SBOX[h>>>8&255]]^u.INV_SUB_MIX[3][u.SBOX[255&h]]}this._nRounds=n,this._keySchedule=i,this._invKeySchedule=l},l.prototype.encryptBlockRaw=function(e){return a(e=i(e),this._keySchedule,u.SUB_MIX,u.SBOX,this._nRounds)},l.prototype.encryptBlock=function(e){var t=this.encryptBlockRaw(e),n=r.allocUnsafe(16);return n.writeUInt32BE(t[0],0),n.writeUInt32BE(t[1],4),n.writeUInt32BE(t[2],8),n.writeUInt32BE(t[3],12),n},l.prototype.decryptBlock=function(e){var t=(e=i(e))[1];e[1]=e[3],e[3]=t;var n=a(e,this._invKeySchedule,u.INV_SUB_MIX,u.INV_SBOX,this._nRounds),o=r.allocUnsafe(16);return o.writeUInt32BE(n[0],0),o.writeUInt32BE(n[3],4),o.writeUInt32BE(n[2],8),o.writeUInt32BE(n[1],12),o},l.prototype.scrub=function(){o(this._keySchedule),o(this._invKeySchedule),o(this._key)},e.exports.AES=l},function(e,t,n){var r=n(18).Buffer,i=n(178);e.exports=function(e,t,n,o){if(r.isBuffer(e)||(e=r.from(e,"binary")),t&&(r.isBuffer(t)||(t=r.from(t,"binary")),8!==t.length))throw new RangeError("salt should be Buffer with 8 byte length");for(var a=n/8,s=r.alloc(a),u=r.alloc(o||0),l=r.alloc(0);a>0||o>0;){var c=new i;c.update(l),c.update(e),t&&c.update(t),l=c.digest();var f=0;if(a>0){var h=s.length-a;f=Math.min(a,l.length),l.copy(s,h,0,f),a-=f}if(f0){var d=u.length-o,p=Math.min(o,l.length-f);l.copy(u,d,f,f+p),o-=p}}return l.fill(0),{key:s,iv:u}}},function(e,t,n){"use strict";var r=n(68),i=n(52),o=i.getNAF,a=i.getJSF,s=i.assert;function u(e,t){this.type=e,this.p=new r(t.p,16),this.red=t.prime?r.red(t.prime):r.mont(this.p),this.zero=new r(0).toRed(this.red),this.one=new r(1).toRed(this.red),this.two=new r(2).toRed(this.red),this.n=t.n&&new r(t.n,16),this.g=t.g&&this.pointFromJSON(t.g,t.gRed),this._wnafT1=new Array(4),this._wnafT2=new Array(4),this._wnafT3=new Array(4),this._wnafT4=new Array(4),this._bitLength=this.n?this.n.bitLength():0;var n=this.n&&this.p.div(this.n);!n||n.cmpn(100)>0?this.redN=null:(this._maxwellTrick=!0,this.redN=this.n.toRed(this.red))}function l(e,t){this.curve=e,this.type=t,this.precomputed=null}e.exports=u,u.prototype.point=function(){throw new Error("Not implemented")},u.prototype.validate=function(){throw new Error("Not implemented")},u.prototype._fixedNafMul=function(e,t){s(e.precomputed);var n=e._getDoubles(),r=o(t,1,this._bitLength),i=(1<=a;c--)u=(u<<1)+r[c];l.push(u)}for(var f=this.jpoint(null,null,null),h=this.jpoint(null,null,null),d=i;d>0;d--){for(a=0;a=0;l--){for(var c=0;l>=0&&0===a[l];l--)c++;if(l>=0&&c++,u=u.dblp(c),l<0)break;var f=a[l];s(0!==f),u="affine"===e.type?f>0?u.mixedAdd(i[f-1>>1]):u.mixedAdd(i[-f-1>>1].neg()):f>0?u.add(i[f-1>>1]):u.add(i[-f-1>>1].neg())}return"affine"===e.type?u.toP():u},u.prototype._wnafMulAdd=function(e,t,n,r,i){var s,u,l,c=this._wnafT1,f=this._wnafT2,h=this._wnafT3,d=0;for(s=0;s=1;s-=2){var m=s-1,v=s;if(1===c[m]&&1===c[v]){var g=[t[m],null,null,t[v]];0===t[m].y.cmp(t[v].y)?(g[1]=t[m].add(t[v]),g[2]=t[m].toJ().mixedAdd(t[v].neg())):0===t[m].y.cmp(t[v].y.redNeg())?(g[1]=t[m].toJ().mixedAdd(t[v]),g[2]=t[m].add(t[v].neg())):(g[1]=t[m].toJ().mixedAdd(t[v]),g[2]=t[m].toJ().mixedAdd(t[v].neg()));var y=[-3,-1,-5,-7,0,7,5,1,3],b=a(n[m],n[v]);for(d=Math.max(b[0].length,d),h[m]=new Array(d),h[v]=new Array(d),u=0;u=0;s--){for(var S=0;s>=0;){var x=!0;for(u=0;u=0&&S++,M=M.dblp(S),s<0)break;for(u=0;u0?l=f[u][k-1>>1]:k<0&&(l=f[u][-k-1>>1].neg()),M="affine"===l.type?M.mixedAdd(l):M.add(l))}}for(s=0;s=Math.ceil((e.bitLength()+1)/t.step)},l.prototype._getDoubles=function(e,t){if(this.precomputed&&this.precomputed.doubles)return this.precomputed.doubles;for(var n=[this],r=this,i=0;i1)){if(this.somethingSelected()){if(!t.hint.supportsSelection)return;for(var i=0;ih.clientHeight+1;if(setTimeout((function(){D=a.getScrollInfo()})),P.bottom-A>0){var N=P.bottom-P.top;if(w.top-(w.bottom-P.top)-N>0)h.style.top=(M=w.top-N-x)+"px",E=!1;else if(N>A){h.style.height=A-5+"px",h.style.top=(M=w.bottom-P.top-x)+"px";var R=a.getCursor();i.from.ch!=R.ch&&(w=a.cursorCoords(R),h.style.left=(_=w.left-S)+"px",P=h.getBoundingClientRect())}}var j,L=P.right-O;if(I&&(L+=a.display.nativeBarWidth),L>0&&(P.right-P.left>O&&(h.style.width=O-5+"px",L-=P.right-P.left-O),h.style.left=(_=w.left-L-S)+"px"),I)for(var F=h.firstChild;F;F=F.nextSibling)F.style.paddingRight=a.display.nativeBarWidth+"px";a.addKeyMap(this.keyMap=u(r,{moveFocus:function(e,t){o.changeActive(o.selectedHint+e,t)},setFocus:function(e){o.changeActive(e)},menuSize:function(){return o.screenAmount()},length:p.length,close:function(){r.close()},pick:function(){o.pick()},data:i})),r.options.closeOnUnfocus&&(a.on("blur",this.onBlur=function(){j=setTimeout((function(){r.close()}),100)}),a.on("focus",this.onFocus=function(){clearTimeout(j)})),a.on("scroll",this.onScroll=function(){var e=a.getScrollInfo(),t=a.getWrapperElement().getBoundingClientRect();D||(D=a.getScrollInfo());var n=M+D.top-e.top,i=n-(f.pageYOffset||(c.documentElement||c.body).scrollTop);if(E||(i+=h.offsetHeight),i<=t.top||i>=t.bottom)return r.close();h.style.top=n+"px",h.style.left=_+D.left-e.left+"px"}),e.on(h,"dblclick",(function(e){var t=l(h,e.target||e.srcElement);t&&null!=t.hintId&&(o.changeActive(t.hintId),o.pick())})),e.on(h,"click",(function(e){var t=l(h,e.target||e.srcElement);t&&null!=t.hintId&&(o.changeActive(t.hintId),r.options.completeOnSingleClick&&o.pick())})),e.on(h,"mousedown",(function(){setTimeout((function(){a.focus()}),20)}));var B=this.getSelectedHintRange();return 0===B.from&&0===B.to||this.scrollToActive(),e.signal(i,"select",p[this.selectedHint],h.childNodes[this.selectedHint]),!0}function f(e,t){if(!e.somethingSelected())return t;for(var n=[],r=0;r0?t(e):o(i+1)}))}o(0)};return o.async=!0,o.supportsSelection=!0,o}return(r=t.getHelper(t.getCursor(),"hintWords"))?function(t){return e.hint.fromList(t,{words:r})}:e.hint.anyword?function(t,n){return e.hint.anyword(t,n)}:function(){}}r.prototype={close:function(){this.active()&&(this.cm.state.completionActive=null,this.tick=null,this.options.updateOnCursorActivity&&this.cm.off("cursorActivity",this.activityFunc),this.widget&&this.data&&e.signal(this.data,"close"),this.widget&&this.widget.close(),e.signal(this.cm,"endCompletion",this.cm))},active:function(){return this.cm.state.completionActive==this},pick:function(t,n){var r=t.list[n],i=this;this.cm.operation((function(){r.hint?r.hint(i.cm,t,r):i.cm.replaceRange(s(r),r.from||t.from,r.to||t.to,"complete"),e.signal(t,"pick",r),i.cm.scrollIntoView()})),this.options.closeOnPick&&this.close()},cursorActivity:function(){this.debounce&&(o(this.debounce),this.debounce=0);var e=this.startPos;this.data&&(e=this.data.from);var t=this.cm.getCursor(),n=this.cm.getLine(t.line);if(t.line!=this.startPos.line||n.length-t.ch!=this.startLen-this.startPos.ch||t.ch=this.data.list.length?t=r?this.data.list.length-1:0:t<0&&(t=r?0:this.data.list.length-1),this.selectedHint!=t){var i=this.hints.childNodes[this.selectedHint];i&&(i.className=i.className.replace(" "+n,""),i.removeAttribute("aria-selected")),(i=this.hints.childNodes[this.selectedHint=t]).className+=" "+n,i.setAttribute("aria-selected","true"),this.completion.cm.getInputField().setAttribute("aria-activedescendant",i.id),this.scrollToActive(),e.signal(this.data,"select",this.data.list[this.selectedHint],i)}},scrollToActive:function(){var e=this.getSelectedHintRange(),t=this.hints.childNodes[e.from],n=this.hints.childNodes[e.to],r=this.hints.firstChild;t.offsetTopthis.hints.scrollTop+this.hints.clientHeight&&(this.hints.scrollTop=n.offsetTop+n.offsetHeight-this.hints.clientHeight+r.offsetTop)},screenAmount:function(){return Math.floor(this.hints.clientHeight/this.hints.firstChild.offsetHeight)||1},getSelectedHintRange:function(){var e=this.completion.options.scrollMargin||0;return{from:Math.max(0,this.selectedHint-e),to:Math.min(this.data.list.length-1,this.selectedHint+e)}}},e.registerHelper("hint","auto",{resolve:d}),e.registerHelper("hint","fromList",(function(t,n){var r,i=t.getCursor(),o=t.getTokenAt(i),a=e.Pos(i.line,o.start),s=i;o.start,]/,closeOnPick:!0,closeOnUnfocus:!0,updateOnCursorActivity:!0,completeOnSingleClick:!0,container:null,customKeys:null,extraKeys:null,paddingForScrollbar:!0,moveOnOverlap:!0};e.defineOption("hintOptions",null)}(n(20))},function(e,t,n){!function(e){var t=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),n=e.Pos,r={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<","<":">>",">":"<<"};function i(e){return e&&e.bracketRegex||/[(){}[\]]/}function o(e,t,o){var s=e.getLineHandle(t.line),u=t.ch-1,l=o&&o.afterCursor;null==l&&(l=/(^| )cm-fat-cursor($| )/.test(e.getWrapperElement().className));var c=i(o),f=!l&&u>=0&&c.test(s.text.charAt(u))&&r[s.text.charAt(u)]||c.test(s.text.charAt(u+1))&&r[s.text.charAt(++u)];if(!f)return null;var h=">"==f.charAt(1)?1:-1;if(o&&o.strict&&h>0!=(u==t.ch))return null;var d=e.getTokenTypeAt(n(t.line,u+1)),p=a(e,n(t.line,u+(h>0?1:0)),h,d,o);return null==p?null:{from:n(t.line,u),to:p&&p.pos,match:p&&p.ch==f.charAt(0),forward:h>0}}function a(e,t,o,a,s){for(var u=s&&s.maxScanLineLength||1e4,l=s&&s.maxScanLines||1e3,c=[],f=i(s),h=o>0?Math.min(t.line+l,e.lastLine()+1):Math.max(e.firstLine()-1,t.line-l),d=t.line;d!=h;d+=o){var p=e.getLine(d);if(p){var m=o>0?0:p.length-1,v=o>0?p.length:-1;if(!(p.length>u))for(d==t.line&&(m=t.ch-(o<0?1:0));m!=v;m+=o){var g=p.charAt(m);if(f.test(g)&&(void 0===a||(e.getTokenTypeAt(n(d,m+1))||"")==(a||""))){var y=r[g];if(y&&">"==y.charAt(1)==o>0)c.push(g);else{if(!c.length)return{pos:n(d,m),ch:g};c.pop()}}}}}return d-o!=(o>0?e.lastLine():e.firstLine())&&null}function s(e,r,i){for(var a=e.state.matchBrackets.maxHighlightLineLength||1e3,s=i&&i.highlightNonMatching,u=[],l=e.listSelections(),c=0;c=l){if(h&&s&&h.test(s.className))return;r=o(a.indicatorOpen)}}(r||s)&&e.setGutterMarker(n,a.gutter,r)}))}function s(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}function u(e){var t=e.getViewport(),n=e.state.foldGutter;n&&(e.operation((function(){a(e,t.from,t.to)})),n.from=t.from,n.to=t.to)}function l(e,n,r){var o=e.state.foldGutter;if(o){var a=o.options;if(r==a.gutter){var s=i(e,n);s?s.clear():e.foldCode(t(n,0),a)}}}function c(e){var t=e.state.foldGutter;if(t){var n=t.options;t.from=t.to=0,clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout((function(){u(e)}),n.foldOnChangeTimeSpan||600)}}function f(e){var t=e.state.foldGutter;if(t){var n=t.options;clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout((function(){var n=e.getViewport();t.from==t.to||n.from-t.to>20||t.from-n.to>20?u(e):e.operation((function(){n.fromt.to&&(a(e,t.to,n.to),t.to=n.to)}))}),n.updateViewportTimeSpan||400)}}function h(e,t){var n=e.state.foldGutter;if(n){var r=t.line;r>=n.from&&rc))l=c,s="{",u="}";else{if(null==f)return;l=f,s="[",u="]"}var h,d,p=1,m=t.lastLine();e:for(var v=i;v<=m;++v)for(var g=t.getLine(v),y=v==i?l:0;;){var b=g.indexOf(s,y),w=g.indexOf(u,y);if(b<0&&(b=g.length),w<0&&(w=g.length),(y=Math.min(b,w))==g.length)break;if(t.getTokenTypeAt(e.Pos(v,y+1))==r)if(y==b)++p;else if(!--p){h=v,d=y;break e}++y}if(null!=h&&i!=h)return{from:e.Pos(i,l),to:e.Pos(h,d)}})),e.registerHelper("fold","import",(function(t,n){function r(n){if(nt.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));if(/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"keyword"!=r.type||"import"!=r.string)return null;for(var i=n,o=Math.min(t.lastLine(),n+10);i<=o;++i){var a=t.getLine(i).indexOf(";");if(-1!=a)return{startCh:r.end,end:e.Pos(i,a)}}}var i,o=n.line,a=r(o);if(!a||r(o-1)||(i=r(o-2))&&i.end.line==o-1)return null;for(var s=a.end;;){var u=r(s.line+1);if(null==u)break;s=u.end}return{from:t.clipPos(e.Pos(o,a.startCh+1)),to:s}})),e.registerHelper("fold","include",(function(t,n){function r(n){if(nt.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));return/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"meta"==r.type&&"#include"==r.string.slice(0,8)?r.start+8:void 0}var i=n.line,o=r(i);if(null==o||null!=r(i-1))return null;for(var a=i;null!=r(a+1);)++a;return{from:e.Pos(i,o+1),to:t.clipPos(e.Pos(a))}}))}(n(20))},function(e,t,n){!function(e){"use strict";function t(e,t,n,r,i){e.openDialog?e.openDialog(t,i,{value:r,selectValueOnOpen:!0,bottom:e.options.search.bottom}):i(prompt(n,r))}function n(e){return e.phrase("Jump to line:")+' '+e.phrase("(Use line:column or scroll% syntax)")+""}function r(e,t){var n=Number(t);return/^[-+]/.test(t)?e.getCursor().line+n:n-1}e.defineOption("search",{bottom:!1}),e.commands.jumpToLine=function(e){var i=e.getCursor();t(e,n(e),e.phrase("Jump to line:"),i.line+1+":"+i.ch,(function(t){var n;if(t)if(n=/^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(t))e.setCursor(r(e,n[1]),Number(n[2]));else if(n=/^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(t)){var o=Math.round(e.lineCount()*Number(n[1])/100);/^[-+]/.test(n[1])&&(o=i.line+o+1),e.setCursor(o-1,i.ch)}else(n=/^\s*\:?\s*([\+\-]?\d+)\s*/.exec(t))&&e.setCursor(r(e,n[1]),i.ch)}))},e.keyMap.default["Alt-G"]="jumpToLine"}(n(20),n(107))},function(e,t,n){!function(e){"use strict";var t=e.commands,n=e.Pos;function r(t,r,i){if(i<0&&0==r.ch)return t.clipPos(n(r.line-1));var o=t.getLine(r.line);if(i>0&&r.ch>=o.length)return t.clipPos(n(r.line+1,0));for(var a,s="start",u=r.ch,l=u,c=i<0?0:o.length,f=0;l!=c;l+=i,f++){var h=o.charAt(i<0?l-1:l),d="_"!=h&&e.isWordChar(h)?"w":"o";if("w"==d&&h.toUpperCase()==h&&(d="W"),"start"==s)"o"!=d?(s="in",a=d):u=l+i;else if("in"==s&&a!=d){if("w"==a&&"W"==d&&i<0&&l--,"W"==a&&"w"==d&&i>0){if(l==u+1){a="w";continue}l--}break}}return n(r.line,l)}function i(e,t){e.extendSelectionsBy((function(n){return e.display.shift||e.doc.extend||n.empty()?r(e.doc,n.head,t):t<0?n.from():n.to()}))}function o(t,r){if(t.isReadOnly())return e.Pass;t.operation((function(){for(var e=t.listSelections().length,i=[],o=-1,a=0;a=n&&e.execCommand("goLineUp")}e.scrollTo(null,t.top-e.defaultTextHeight())},t.scrollLineDown=function(e){var t=e.getScrollInfo();if(!e.somethingSelected()){var n=e.lineAtHeight(t.top,"local")+1;e.getCursor().line<=n&&e.execCommand("goLineDown")}e.scrollTo(null,t.top+e.defaultTextHeight())},t.splitSelectionByLine=function(e){for(var t=e.listSelections(),r=[],i=0;io.line&&s==a.line&&0==a.ch||r.push({anchor:s==o.line?o:n(s,0),head:s==a.line?a:n(s)});e.setSelections(r,0)},t.singleSelectionTop=function(e){var t=e.listSelections()[0];e.setSelection(t.anchor,t.head,{scroll:!1})},t.selectLine=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;s--){var l=r[i[s]];if(!(u&&e.cmpPos(l.head,u)>0)){var c=a(t,l.head);u=c.from,t.replaceRange(n(c.word),c.from,c.to)}}}))}function p(t){var n=t.getCursor("from"),r=t.getCursor("to");if(0==e.cmpPos(n,r)){var i=a(t,n);if(!i.word)return;n=i.from,r=i.to}return{from:n,to:r,query:t.getRange(n,r),word:i}}function m(e,t){var r=p(e);if(r){var i=r.query,o=e.getSearchCursor(i,t?r.to:r.from);(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):(o=e.getSearchCursor(i,t?n(e.firstLine(),0):e.clipPos(n(e.lastLine()))),(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):r.word&&e.setSelection(r.from,r.to))}}t.selectScope=function(e){c(e)||e.execCommand("selectAll")},t.selectBetweenBrackets=function(t){if(!c(t))return e.Pass},t.goToBracket=function(t){t.extendSelectionsBy((function(r){var i=t.scanForBracket(r.head,1,f(t.getTokenTypeAt(r.head)));if(i&&0!=e.cmpPos(i.pos,r.head))return i.pos;var o=t.scanForBracket(r.head,-1,f(t.getTokenTypeAt(n(r.head.line,r.head.ch+1))));return o&&n(o.pos.line,o.pos.ch+1)||r.head}))},t.swapLineUp=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.firstLine()-1,a=[],s=0;so?i.push(l,c):i.length&&(i[i.length-1]=c),o=c}t.operation((function(){for(var e=0;et.lastLine()?t.replaceRange("\n"+s,n(t.lastLine()),null,"+swapLine"):t.replaceRange(s+"\n",n(o,0),null,"+swapLine")}t.setSelections(a),t.scrollIntoView()}))},t.swapLineDown=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.lastLine()+1,a=r.length-1;a>=0;a--){var s=r[a],u=s.to().line+1,l=s.from().line;0!=s.to().ch||s.empty()||u--,u=0;e-=2){var r=i[e],o=i[e+1],a=t.getLine(r);r==t.lastLine()?t.replaceRange("",n(r-1),n(r),"+swapLine"):t.replaceRange("",n(r,0),n(r+1,0),"+swapLine"),t.replaceRange(a+"\n",n(o,0),null,"+swapLine")}t.scrollIntoView()}))},t.toggleCommentIndented=function(e){e.toggleComment({indent:!0})},t.joinLines=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;o--){var a=r[o].head,s=t.getRange({line:a.line,ch:0},a),u=e.countColumn(s,null,t.getOption("tabSize")),l=t.findPosH(a,-1,"char",!1);if(s&&!/\S/.test(s)&&u%i==0){var c=new n(a.line,e.findColumn(s,u-i,i));c.ch!=a.ch&&(l=c)}t.replaceRange("",l,a,"+delete")}}))},t.delLineRight=function(e){e.operation((function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange("",t[r].anchor,n(t[r].to().line),"+delete");e.scrollIntoView()}))},t.upcaseAtCursor=function(e){d(e,(function(e){return e.toUpperCase()}))},t.downcaseAtCursor=function(e){d(e,(function(e){return e.toLowerCase()}))},t.setSublimeMark=function(e){e.state.sublimeMark&&e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor())},t.selectToSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&e.setSelection(e.getCursor(),t)},t.deleteToSublimeMark=function(t){var n=t.state.sublimeMark&&t.state.sublimeMark.find();if(n){var r=t.getCursor(),i=n;if(e.cmpPos(r,i)>0){var o=i;i=r,r=o}t.state.sublimeKilled=t.getRange(r,i),t.replaceRange("",r,i)}},t.swapWithSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&(e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor()),e.setCursor(t))},t.sublimeYank=function(e){null!=e.state.sublimeKilled&&e.replaceSelection(e.state.sublimeKilled,null,"paste")},t.showInCenter=function(e){var t=e.cursorCoords(null,"local");e.scrollTo(null,(t.top+t.bottom)/2-e.getScrollInfo().clientHeight/2)},t.findUnder=function(e){m(e,!0)},t.findUnderPrevious=function(e){m(e,!1)},t.findAllUnder=function(e){var t=p(e);if(t){for(var n=e.getSearchCursor(t.query),r=[],i=-1;n.findNext();)r.push({anchor:n.from(),head:n.to()}),n.from().line<=t.from.line&&n.from().ch<=t.from.ch&&i++;e.setSelections(r,i)}};var v=e.keyMap;v.macSublime={"Cmd-Left":"goLineStartSmart","Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-Left":"goSubwordLeft","Ctrl-Right":"goSubwordRight","Ctrl-Alt-Up":"scrollLineUp","Ctrl-Alt-Down":"scrollLineDown","Cmd-L":"selectLine","Shift-Cmd-L":"splitSelectionByLine",Esc:"singleSelectionTop","Cmd-Enter":"insertLineAfter","Shift-Cmd-Enter":"insertLineBefore","Cmd-D":"selectNextOccurrence","Shift-Cmd-Space":"selectScope","Shift-Cmd-M":"selectBetweenBrackets","Cmd-M":"goToBracket","Cmd-Ctrl-Up":"swapLineUp","Cmd-Ctrl-Down":"swapLineDown","Cmd-/":"toggleCommentIndented","Cmd-J":"joinLines","Shift-Cmd-D":"duplicateLine",F5:"sortLines","Shift-F5":"reverseSortLines","Cmd-F5":"sortLinesInsensitive","Shift-Cmd-F5":"reverseSortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Cmd-F2":"toggleBookmark","Shift-Cmd-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Cmd-K Cmd-D":"skipAndSelectNextOccurrence","Cmd-K Cmd-K":"delLineRight","Cmd-K Cmd-U":"upcaseAtCursor","Cmd-K Cmd-L":"downcaseAtCursor","Cmd-K Cmd-Space":"setSublimeMark","Cmd-K Cmd-A":"selectToSublimeMark","Cmd-K Cmd-W":"deleteToSublimeMark","Cmd-K Cmd-X":"swapWithSublimeMark","Cmd-K Cmd-Y":"sublimeYank","Cmd-K Cmd-C":"showInCenter","Cmd-K Cmd-G":"clearBookmarks","Cmd-K Cmd-Backspace":"delLineLeft","Cmd-K Cmd-1":"foldAll","Cmd-K Cmd-0":"unfoldAll","Cmd-K Cmd-J":"unfoldAll","Ctrl-Shift-Up":"addCursorToPrevLine","Ctrl-Shift-Down":"addCursorToNextLine","Cmd-F3":"findUnder","Shift-Cmd-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Cmd-[":"fold","Shift-Cmd-]":"unfold","Cmd-I":"findIncremental","Shift-Cmd-I":"findIncrementalReverse","Cmd-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"macDefault"},e.normalizeKeyMap(v.macSublime),v.pcSublime={"Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-T":"transposeChars","Alt-Left":"goSubwordLeft","Alt-Right":"goSubwordRight","Ctrl-Up":"scrollLineUp","Ctrl-Down":"scrollLineDown","Ctrl-L":"selectLine","Shift-Ctrl-L":"splitSelectionByLine",Esc:"singleSelectionTop","Ctrl-Enter":"insertLineAfter","Shift-Ctrl-Enter":"insertLineBefore","Ctrl-D":"selectNextOccurrence","Shift-Ctrl-Space":"selectScope","Shift-Ctrl-M":"selectBetweenBrackets","Ctrl-M":"goToBracket","Shift-Ctrl-Up":"swapLineUp","Shift-Ctrl-Down":"swapLineDown","Ctrl-/":"toggleCommentIndented","Ctrl-J":"joinLines","Shift-Ctrl-D":"duplicateLine",F9:"sortLines","Shift-F9":"reverseSortLines","Ctrl-F9":"sortLinesInsensitive","Shift-Ctrl-F9":"reverseSortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Ctrl-F2":"toggleBookmark","Shift-Ctrl-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Ctrl-K Ctrl-D":"skipAndSelectNextOccurrence","Ctrl-K Ctrl-K":"delLineRight","Ctrl-K Ctrl-U":"upcaseAtCursor","Ctrl-K Ctrl-L":"downcaseAtCursor","Ctrl-K Ctrl-Space":"setSublimeMark","Ctrl-K Ctrl-A":"selectToSublimeMark","Ctrl-K Ctrl-W":"deleteToSublimeMark","Ctrl-K Ctrl-X":"swapWithSublimeMark","Ctrl-K Ctrl-Y":"sublimeYank","Ctrl-K Ctrl-C":"showInCenter","Ctrl-K Ctrl-G":"clearBookmarks","Ctrl-K Ctrl-Backspace":"delLineLeft","Ctrl-K Ctrl-1":"foldAll","Ctrl-K Ctrl-0":"unfoldAll","Ctrl-K Ctrl-J":"unfoldAll","Ctrl-Alt-Up":"addCursorToPrevLine","Ctrl-Alt-Down":"addCursorToNextLine","Ctrl-F3":"findUnder","Shift-Ctrl-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Ctrl-[":"fold","Shift-Ctrl-]":"unfold","Ctrl-I":"findIncremental","Shift-Ctrl-I":"findIncrementalReverse","Ctrl-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"pcDefault"},e.normalizeKeyMap(v.pcSublime);var g=v.default==v.macDefault;v.sublime=g?v.macSublime:v.pcSublime}(n(20),n(106),n(149))},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){var r=n(320),i=n(214);e.exports=Object.keys||function(e){return r(e,i)}},function(e,t){e.exports=!0},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t,n){var r=n(210);e.exports=function(e){return Object(r(e))}},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(0),i=n.n(r);function o(e){var t=e.children;return i.a.createElement("div",{className:"toolbar-button-group"},t)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return u}));var r=n(54),i=n(73),o=n(35),a=n(17),s=n(1);function u(e,t,n){var s,u=[];if(!e||!t)return{insertions:u,result:t};try{s=Object(r.a)(t)}catch(p){return{insertions:u,result:t}}var h=n||l,d=new i.a(e);return Object(o.c)(s,{leave:function(e){d.leave(e)},enter:function(e){if(d.enter(e),"Field"===e.kind&&!e.selectionSet){var n=c(function(e){if(e)return e}(d.getType()),h);if(n&&e.loc){var r=function(e,t){var n=t,r=t;for(;n;){var i=e.charCodeAt(n-1);if(10===i||13===i||8232===i||8233===i)break;n--,9!==i&&11!==i&&12!==i&&32!==i&&160!==i&&(r=n)}return e.substring(n,r)}(t,e.loc.start);u.push({index:e.loc.end,string:" "+Object(a.a)(n).replace(/\n/g,"\n"+r)})}}}}),{insertions:u,result:f(t,u)}}function l(e){if(!("getFields"in e))return[];var t=e.getFields();if(t.id)return["id"];if(t.edges)return["edges"];if(t.node)return["node"];var n=[];return Object.keys(t).forEach((function(e){Object(s.I)(t[e].type)&&n.push(e)})),n}function c(e,t){var n=Object(s.A)(e);if(e&&!Object(s.I)(e)){var r=t(n);if(Array.isArray(r)&&0!==r.length&&"getFields"in n)return{kind:"SelectionSet",selections:r.map((function(e){var r=n.getFields()[e];return{kind:"Field",name:{kind:"Name",value:e},selectionSet:c(r?r.type:null,t)}}))}}}function f(e,t){if(0===t.length)return e;var n="",r=0;return t.forEach((function(t){var i=t.index,o=t.string;n+=e.slice(r,i)+o,r=i})),n+=e.slice(r)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return f}));var r=n(1),i=n(73),o=n(35),a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},u=function(e,t){var n="function"===typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(s){i={error:s}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a},l=function(){for(var e=[],t=0;t=0)continue;h.push(v)}var g=e[m.name.value];if(g)m={kind:"InlineFragment",typeCondition:g.typeCondition,directives:g.directives,selectionSet:g.selectionSet}}if("InlineFragment"===m.kind&&(!m.directives||0===(null===(a=m.directives)||void 0===a?void 0:a.length))){var y=m.typeCondition?m.typeCondition.name.value:null;if(!y||y===u){f.push.apply(f,l(c(e,m.selectionSet.selections,n)));continue}}f.push(m)}}catch(b){i={error:b}}finally{try{p&&!p.done&&(o=d.return)&&o.call(d)}finally{if(i)throw i.error}}return f}function f(e,t){var n,r,u=t?new i.a(t):null,f=Object.create(null);try{for(var h=s(e.definitions),d=h.next();!d.done;d=h.next()){var p=d.value;"FragmentDefinition"===p.kind&&(f[p.name.value]=p)}}catch(v){n={error:v}}finally{try{d&&!d.done&&(r=h.return)&&r.call(h)}finally{if(n)throw n.error}}var m={SelectionSet:function(e){var t=u?u.getParentType():null,n=e.selections;return n=function(e,t){var n,r,i=new Map,o=[];try{for(var u=s(e),c=u.next();!c.done;c=u.next()){var f=c.value;if("Field"===f.kind){var h=t(f),d=i.get(h);if(f.directives&&f.directives.length){var p=a({},f);o.push(p)}else d&&d.selectionSet&&f.selectionSet?d.selectionSet.selections=l(d.selectionSet.selections,f.selectionSet.selections):d||(p=a({},f),i.set(h,p),o.push(p))}else o.push(f)}}catch(m){n={error:m}}finally{try{c&&!c.done&&(r=u.return)&&r.call(u)}finally{if(n)throw n.error}}return o}(n=c(f,n,t),(function(e){return e.alias?e.alias.value:e.name.value})),a(a({},e),{selections:n})},FragmentDefinition:function(){return null}};return Object(o.c)(e,u?Object(i.b)(u,m):m)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return p}));var r=n(0),i=n(26),o=!0,a=!1,s=null,u={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function l(e){e.metaKey||e.altKey||e.ctrlKey||(o=!0)}function c(){o=!1}function f(){"hidden"===this.visibilityState&&a&&(o=!0)}function h(e){var t=e.target;try{return t.matches(":focus-visible")}catch(n){}return o||function(e){var t=e.type,n=e.tagName;return!("INPUT"!==n||!u[t]||e.readOnly)||"TEXTAREA"===n&&!e.readOnly||!!e.isContentEditable}(t)}function d(){a=!0,window.clearTimeout(s),s=window.setTimeout((function(){a=!1}),100)}function p(){return{isFocusVisible:h,onBlurVisible:d,ref:r.useCallback((function(e){var t,n=i.findDOMNode(e);null!=n&&((t=n.ownerDocument).addEventListener("keydown",l,!0),t.addEventListener("mousedown",c,!0),t.addEventListener("pointerdown",c,!0),t.addEventListener("touchstart",c,!0),t.addEventListener("visibilitychange",f,!0))}),[])}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=n(0);function i(e,t){return r.isValidElement(e)&&-1!==t.indexOf(e.type.muiName)}},function(e,t,n){"use strict";function r(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:166;function r(){for(var r=arguments.length,i=new Array(r),o=0;o0&&(t=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"arguments"),r.args.map((function(e){return i.a.createElement("div",{key:e.name,className:"doc-category-item"},i.a.createElement("div",null,i.a.createElement(f,{arg:e,onClickType:o})),i.a.createElement(m,{className:"doc-value-description",markdown:e.description}))})))),r&&r.astNode&&r.astNode.directives&&r.astNode.directives.length>0&&(n=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"directives"),r.astNode.directives.map((function(e){return i.a.createElement("div",{key:e.name.value,className:"doc-category-item"},i.a.createElement("div",null,i.a.createElement(h,{directive:e})))})))),i.a.createElement("div",null,i.a.createElement(m,{className:"doc-type-description",markdown:(null===r||void 0===r?void 0:r.description)||"No Description"}),r&&"deprecationReason"in r&&i.a.createElement(m,{className:"doc-deprecation",markdown:null===r||void 0===r?void 0:r.deprecationReason}),i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"type"),i.a.createElement(a,{type:null===r||void 0===r?void 0:r.type,onClick:o})),t,n)}function g(e){var t=e.schema,n=e.onClickType,r=t.getQueryType(),o=t.getMutationType&&t.getMutationType(),s=t.getSubscriptionType&&t.getSubscriptionType();return i.a.createElement("div",null,i.a.createElement(m,{className:"doc-type-description",markdown:t.description||"A GraphQL schema provides a root type for each kind of operation."}),i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"root types"),i.a.createElement("div",{className:"doc-category-item"},i.a.createElement("span",{className:"keyword"},"query"),": ",i.a.createElement(a,{type:r,onClick:n})),o&&i.a.createElement("div",{className:"doc-category-item"},i.a.createElement("span",{className:"keyword"},"mutation"),": ",i.a.createElement(a,{type:o,onClick:n})),s&&i.a.createElement("div",{className:"doc-category-item"},i.a.createElement("span",{className:"keyword"},"subscription"),": ",i.a.createElement(a,{type:s,onClick:n}))))}var y=n(56),b=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),w=function(e){function t(t){var n=e.call(this,t)||this;return n.handleChange=function(e){var t=e.currentTarget.value;n.setState({value:t}),n.debouncedOnSearch(t)},n.handleClear=function(){n.setState({value:""}),n.props.onSearch("")},n.state={value:t.value||""},n.debouncedOnSearch=Object(y.a)(200,n.props.onSearch),n}return b(t,e),t.prototype.render=function(){return i.a.createElement("label",{className:"search-box"},i.a.createElement("div",{className:"search-box-icon","aria-hidden":"true"},"\u26b2"),i.a.createElement("input",{value:this.state.value,onChange:this.handleChange,type:"text",placeholder:this.props.placeholder,"aria-label":this.props.placeholder}),this.state.value&&i.a.createElement("button",{className:"search-box-clear",onClick:this.handleClear,"aria-label":"Clear search input"},"\u2715"))},t}(i.a.Component),_=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),M=function(e){var t="function"===typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"===typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},E=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return _(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.schema!==e.schema||this.props.searchValue!==e.searchValue},t.prototype.render=function(){var e,t,n=this.props.searchValue,r=this.props.withinType,o=this.props.schema,s=this.props.onClickType,u=this.props.onClickField,l=[],c=[],h=[],d=o.getTypeMap(),p=Object.keys(d);r&&(p=p.filter((function(e){return e!==r.name}))).unshift(r.name);var m=function(e){if(l.length+c.length+h.length>=100)return"break";var t=d[e];if(r!==t&&S(e,n)&&c.push(i.a.createElement("div",{className:"doc-category-item",key:e},i.a.createElement(a,{type:t,onClick:s}))),t&&"getFields"in t){var o=t.getFields();Object.keys(o).forEach((function(c){var d,p=o[c];if(!S(c,n)){if(!("args"in p)||!p.args.length)return;if(0===(d=p.args.filter((function(e){return S(e.name,n)}))).length)return}var m=i.a.createElement("div",{className:"doc-category-item",key:e+"."+c},r!==t&&[i.a.createElement(a,{key:"type",type:t,onClick:s}),"."],i.a.createElement("a",{className:"field-name",onClick:function(e){return u(p,t,e)}},p.name),d&&["(",i.a.createElement("span",{key:"args"},d.map((function(e){return i.a.createElement(f,{key:e.name,arg:e,onClickType:s,showDefaultValue:!1})}))),")"]);r===t?l.push(m):h.push(m)}))}};try{for(var v=M(p),g=v.next();!g.done;g=v.next()){if("break"===m(g.value))break}}catch(y){e={error:y}}finally{try{g&&!g.done&&(t=v.return)&&t.call(v)}finally{if(e)throw e.error}}return l.length+c.length+h.length===0?i.a.createElement("span",{className:"doc-alert-text"},"No results found."):r&&c.length+h.length>0?i.a.createElement("div",null,l,i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"other results"),c,h)):i.a.createElement("div",{className:"doc-search-items"},l,c,h)},t}(i.a.Component);function S(e,t){try{var n=t.replace(/[^_0-9A-Za-z]/g,(function(e){return"\\"+e}));return-1!==e.search(new RegExp(n,"i"))}catch(r){return-1!==e.toLowerCase().indexOf(t.toLowerCase())}}var x=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),k=function(e){function t(t){var n=e.call(this,t)||this;return n.handleShowDeprecated=function(){return n.setState({showDeprecated:!0})},n.state={showDeprecated:!1},n}return x(t,e),t.prototype.shouldComponentUpdate=function(e,t){return this.props.type!==e.type||this.props.schema!==e.schema||this.state.showDeprecated!==t.showDeprecated},t.prototype.render=function(){var e,t,n,r,s,u=this.props.schema,l=this.props.type,c=this.props.onClickType,f=this.props.onClickField,h=null,d=[];if(l instanceof o.h?(h="possible types",d=u.getPossibleTypes(l)):l instanceof o.c?(h="implementations",d=u.getPossibleTypes(l)):l instanceof o.f&&(h="implements",d=l.getInterfaces()),d&&d.length>0&&(e=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},h),d.map((function(e){return i.a.createElement("div",{key:e.name,className:"doc-category-item"},i.a.createElement(a,{type:e,onClick:c}))})))),l&&"getFields"in l){var p=l.getFields(),v=Object.keys(p).map((function(e){return p[e]}));t=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"fields"),v.filter((function(e){return!("isDeprecated"in e)||!e.isDeprecated})).map((function(e){return i.a.createElement(T,{key:e.name,type:l,field:e,onClickType:c,onClickField:f})})));var g=v.filter((function(e){return"isDeprecated"in e&&e.isDeprecated}));g.length>0&&(n=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"deprecated fields"),this.state.showDeprecated?g.map((function(e){return i.a.createElement(T,{key:e.name,type:l,field:e,onClickType:c,onClickField:f})})):i.a.createElement("button",{className:"show-btn",onClick:this.handleShowDeprecated},"Show deprecated fields...")))}if(l instanceof o.a){var y=l.getValues();r=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"values"),y.filter((function(e){return!e.isDeprecated})).map((function(e){return i.a.createElement(C,{key:e.name,value:e})})));var b=y.filter((function(e){return e.isDeprecated}));b.length>0&&(s=i.a.createElement("div",{className:"doc-category"},i.a.createElement("div",{className:"doc-category-title"},"deprecated values"),this.state.showDeprecated?b.map((function(e){return i.a.createElement(C,{key:e.name,value:e})})):i.a.createElement("button",{className:"show-btn",onClick:this.handleShowDeprecated},"Show deprecated values...")))}return i.a.createElement("div",null,i.a.createElement(m,{className:"doc-type-description",markdown:"description"in l&&l.description||"No Description"}),l instanceof o.f&&e,t,n,r,s,!(l instanceof o.f)&&e)},t}(i.a.Component);function T(e){var t=e.type,n=e.field,r=e.onClickType,o=e.onClickField;return i.a.createElement("div",{className:"doc-category-item"},i.a.createElement("a",{className:"field-name",onClick:function(e){return o(n,t,e)}},n.name),"args"in n&&n.args&&n.args.length>0&&["(",i.a.createElement("span",{key:"args"},n.args.map((function(e){return i.a.createElement(f,{key:e.name,arg:e,onClickType:r})}))),")"],": ",i.a.createElement(a,{type:n.type,onClick:r}),i.a.createElement(c,{field:n}),n.description&&i.a.createElement(m,{className:"field-short-description",markdown:n.description}),"deprecationReason"in n&&n.deprecationReason&&i.a.createElement(m,{className:"doc-deprecation",markdown:n.deprecationReason}))}function C(e){var t=e.value;return i.a.createElement("div",{className:"doc-category-item"},i.a.createElement("div",{className:"enum-value"},t.name),i.a.createElement(m,{className:"doc-value-description",markdown:t.description}),t.deprecationReason&&i.a.createElement(m,{className:"doc-deprecation",markdown:t.deprecationReason}))}var O=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),A=function(){return(A=Object.assign||function(e){for(var t,n=1,r=arguments.length;n1&&n.setState({navStack:n.state.navStack.slice(0,-1)})},n.handleClickType=function(e){n.showDoc(e)},n.handleClickField=function(e){n.showDoc(e)},n.handleSearch=function(e){n.showSearch(e)},n.state={navStack:[D]},n}return O(t,e),t.prototype.shouldComponentUpdate=function(e,t){return this.props.schema!==e.schema||this.state.navStack!==t.navStack},t.prototype.render=function(){var e,t=this.props.schema,n=this.state.navStack,r=n[n.length-1];e=void 0===t?i.a.createElement("div",{className:"spinner-container"},i.a.createElement("div",{className:"spinner"})):t?r.search?i.a.createElement(E,{searchValue:r.search,withinType:r.def,schema:t,onClickType:this.handleClickType,onClickField:this.handleClickField}):1===n.length?i.a.createElement(g,{schema:t,onClickType:this.handleClickType}):Object(o.S)(r.def)?i.a.createElement(k,{schema:t,type:r.def,onClickType:this.handleClickType,onClickField:this.handleClickField}):i.a.createElement(v,{field:r.def,onClickType:this.handleClickType}):i.a.createElement("div",{className:"error-container"},"No Schema Available");var a,s=1===n.length||Object(o.S)(r.def)&&"getFields"in r.def;return n.length>1&&(a=n[n.length-2].name),i.a.createElement("section",{className:"doc-explorer",key:r.name,"aria-label":"Documentation Explorer"},i.a.createElement("div",{className:"doc-explorer-title-bar"},a&&i.a.createElement("button",{className:"doc-explorer-back",onClick:this.handleNavBackClick,"aria-label":"Go back to "+a},a),i.a.createElement("div",{className:"doc-explorer-title"},r.title||r.name),i.a.createElement("div",{className:"doc-explorer-rhs"},this.props.children)),i.a.createElement("div",{className:"doc-explorer-contents"},s&&i.a.createElement(w,{value:r.search,placeholder:"Search "+r.name+"...",onSearch:this.handleSearch}),e))},t.prototype.showDoc=function(e){var t=this.state.navStack;t[t.length-1].def!==e&&this.setState({navStack:t.concat([{name:e.name,def:e}])})},t.prototype.showDocForReference=function(e){e&&"Type"===e.kind?this.showDoc(e.type):"Field"===e.kind||"Argument"===e.kind&&e.field?this.showDoc(e.field):"EnumValue"===e.kind&&e.type&&this.showDoc(e.type)},t.prototype.showSearch=function(e){var t=this.state.navStack.slice(),n=t[t.length-1];t[t.length-1]=A(A({},n),{search:e}),this.setState({navStack:t})},t.prototype.reset=function(){this.setState({navStack:[D]})},t}(i.a.Component)},function(e,t,n){"use strict";n.d(t,"a",(function(){return h}));var r=n(6),i=n(0),o=n.n(i),a=n(10),s=(n(27),n(21)),u=n(29),l=n(45),c=i.forwardRef((function(e,t){var n=e.children,o=e.classes,u=e.className,c=e.color,f=void 0===c?"inherit":c,h=e.component,d=void 0===h?"svg":h,p=e.fontSize,m=void 0===p?"medium":p,v=e.htmlColor,g=e.titleAccess,y=e.viewBox,b=void 0===y?"0 0 24 24":y,w=Object(a.a)(e,["children","classes","className","color","component","fontSize","htmlColor","titleAccess","viewBox"]);return i.createElement(d,Object(r.a)({className:Object(s.a)(o.root,u,"inherit"!==f&&o["color".concat(Object(l.a)(f))],"default"!==m&&"medium"!==m&&o["fontSize".concat(Object(l.a)(m))]),focusable:"false",viewBox:b,color:v,"aria-hidden":!g||void 0,role:g?"img":void 0,ref:t},w),n,g?i.createElement("title",null,g):null)}));c.muiName="SvgIcon";var f=Object(u.a)((function(e){return{root:{userSelect:"none",width:"1em",height:"1em",display:"inline-block",fill:"currentColor",flexShrink:0,fontSize:e.typography.pxToRem(24),transition:e.transitions.create("fill",{duration:e.transitions.duration.shorter})},colorPrimary:{color:e.palette.primary.main},colorSecondary:{color:e.palette.secondary.main},colorAction:{color:e.palette.action.active},colorError:{color:e.palette.error.main},colorDisabled:{color:e.palette.action.disabled},fontSizeInherit:{fontSize:"inherit"},fontSizeSmall:{fontSize:e.typography.pxToRem(20)},fontSizeLarge:{fontSize:e.typography.pxToRem(35)}}}),{name:"MuiSvgIcon"})(c);function h(e,t){var n=function(t,n){return o.a.createElement(f,Object(r.a)({ref:n},t),e)};return n.muiName=f.muiName,o.a.memo(o.a.forwardRef(n))}},function(e,t,n){"use strict";var r=n(28),i=Array.from||function(e,t,n){if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var i=e[r.b];if("function"===typeof i){for(var o,a=i.call(e),s=[],u=0;!(o=a.next()).done;++u)if(s.push(t.call(n,o.value,u)),u>9999999)throw new TypeError("Near-infinite iteration.");return s}var l=e.length;if("number"===typeof l&&l>=0&&l%1===0){for(var c=[],f=0;f=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};r.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){u.headers[e]=r.merge(a)})),e.exports=u}).call(this,n(36))},function(e,t,n){"use strict";var r=n(11),i=n(251),o=n(18).Buffer,a=new Array(16);function s(){i.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878}function u(e,t){return e<>>32-t}function l(e,t,n,r,i,o,a){return u(e+(t&n|~t&r)+i+o|0,a)+t|0}function c(e,t,n,r,i,o,a){return u(e+(t&r|n&~r)+i+o|0,a)+t|0}function f(e,t,n,r,i,o,a){return u(e+(t^n^r)+i+o|0,a)+t|0}function h(e,t,n,r,i,o,a){return u(e+(n^(t|~r))+i+o|0,a)+t|0}r(s,i),s.prototype._update=function(){for(var e=a,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);var n=this._a,r=this._b,i=this._c,o=this._d;n=l(n,r,i,o,e[0],3614090360,7),o=l(o,n,r,i,e[1],3905402710,12),i=l(i,o,n,r,e[2],606105819,17),r=l(r,i,o,n,e[3],3250441966,22),n=l(n,r,i,o,e[4],4118548399,7),o=l(o,n,r,i,e[5],1200080426,12),i=l(i,o,n,r,e[6],2821735955,17),r=l(r,i,o,n,e[7],4249261313,22),n=l(n,r,i,o,e[8],1770035416,7),o=l(o,n,r,i,e[9],2336552879,12),i=l(i,o,n,r,e[10],4294925233,17),r=l(r,i,o,n,e[11],2304563134,22),n=l(n,r,i,o,e[12],1804603682,7),o=l(o,n,r,i,e[13],4254626195,12),i=l(i,o,n,r,e[14],2792965006,17),n=c(n,r=l(r,i,o,n,e[15],1236535329,22),i,o,e[1],4129170786,5),o=c(o,n,r,i,e[6],3225465664,9),i=c(i,o,n,r,e[11],643717713,14),r=c(r,i,o,n,e[0],3921069994,20),n=c(n,r,i,o,e[5],3593408605,5),o=c(o,n,r,i,e[10],38016083,9),i=c(i,o,n,r,e[15],3634488961,14),r=c(r,i,o,n,e[4],3889429448,20),n=c(n,r,i,o,e[9],568446438,5),o=c(o,n,r,i,e[14],3275163606,9),i=c(i,o,n,r,e[3],4107603335,14),r=c(r,i,o,n,e[8],1163531501,20),n=c(n,r,i,o,e[13],2850285829,5),o=c(o,n,r,i,e[2],4243563512,9),i=c(i,o,n,r,e[7],1735328473,14),n=f(n,r=c(r,i,o,n,e[12],2368359562,20),i,o,e[5],4294588738,4),o=f(o,n,r,i,e[8],2272392833,11),i=f(i,o,n,r,e[11],1839030562,16),r=f(r,i,o,n,e[14],4259657740,23),n=f(n,r,i,o,e[1],2763975236,4),o=f(o,n,r,i,e[4],1272893353,11),i=f(i,o,n,r,e[7],4139469664,16),r=f(r,i,o,n,e[10],3200236656,23),n=f(n,r,i,o,e[13],681279174,4),o=f(o,n,r,i,e[0],3936430074,11),i=f(i,o,n,r,e[3],3572445317,16),r=f(r,i,o,n,e[6],76029189,23),n=f(n,r,i,o,e[9],3654602809,4),o=f(o,n,r,i,e[12],3873151461,11),i=f(i,o,n,r,e[15],530742520,16),n=h(n,r=f(r,i,o,n,e[2],3299628645,23),i,o,e[0],4096336452,6),o=h(o,n,r,i,e[7],1126891415,10),i=h(i,o,n,r,e[14],2878612391,15),r=h(r,i,o,n,e[5],4237533241,21),n=h(n,r,i,o,e[12],1700485571,6),o=h(o,n,r,i,e[3],2399980690,10),i=h(i,o,n,r,e[10],4293915773,15),r=h(r,i,o,n,e[1],2240044497,21),n=h(n,r,i,o,e[8],1873313359,6),o=h(o,n,r,i,e[15],4264355552,10),i=h(i,o,n,r,e[6],2734768916,15),r=h(r,i,o,n,e[13],1309151649,21),n=h(n,r,i,o,e[4],4149444226,6),o=h(o,n,r,i,e[11],3174756917,10),i=h(i,o,n,r,e[2],718787259,15),r=h(r,i,o,n,e[9],3951481745,21),this._a=this._a+n|0,this._b=this._b+r|0,this._c=this._c+i|0,this._d=this._d+o|0},s.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var e=o.allocUnsafe(16);return e.writeInt32LE(this._a,0),e.writeInt32LE(this._b,4),e.writeInt32LE(this._c,8),e.writeInt32LE(this._d,12),e},e.exports=s},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(r){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(40))},function(e,t,n){"use strict";var r=n(101).codes.ERR_STREAM_PREMATURE_CLOSE;function i(){}e.exports=function e(t,n,o){if("function"===typeof n)return e(t,null,n);n||(n={}),o=function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,r=new Array(n),i=0;i>>32-t}function m(e,t,n,r,i,o,a,s){return p(e+(t^n^r)+o+a|0,s)+i|0}function v(e,t,n,r,i,o,a,s){return p(e+(t&n|~t&r)+o+a|0,s)+i|0}function g(e,t,n,r,i,o,a,s){return p(e+((t|~n)^r)+o+a|0,s)+i|0}function y(e,t,n,r,i,o,a,s){return p(e+(t&r|n&~r)+o+a|0,s)+i|0}function b(e,t,n,r,i,o,a,s){return p(e+(t^(n|~r))+o+a|0,s)+i|0}i(d,o),d.prototype._update=function(){for(var e=a,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);for(var n=0|this._a,r=0|this._b,i=0|this._c,o=0|this._d,d=0|this._e,w=0|this._a,_=0|this._b,M=0|this._c,E=0|this._d,S=0|this._e,x=0;x<80;x+=1){var k,T;x<16?(k=m(n,r,i,o,d,e[s[x]],f[0],l[x]),T=b(w,_,M,E,S,e[u[x]],h[0],c[x])):x<32?(k=v(n,r,i,o,d,e[s[x]],f[1],l[x]),T=y(w,_,M,E,S,e[u[x]],h[1],c[x])):x<48?(k=g(n,r,i,o,d,e[s[x]],f[2],l[x]),T=g(w,_,M,E,S,e[u[x]],h[2],c[x])):x<64?(k=y(n,r,i,o,d,e[s[x]],f[3],l[x]),T=v(w,_,M,E,S,e[u[x]],h[3],c[x])):(k=b(n,r,i,o,d,e[s[x]],f[4],l[x]),T=m(w,_,M,E,S,e[u[x]],h[4],c[x])),n=d,d=o,o=p(i,10),i=r,r=k,w=S,S=E,E=p(M,10),M=_,_=T}var C=this._b+i+E|0;this._b=this._c+o+S|0,this._c=this._d+d+w|0,this._d=this._e+n+_|0,this._e=this._a+r+M|0,this._a=C},d.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var e=r.alloc?r.alloc(20):new r(20);return e.writeInt32LE(this._a,0),e.writeInt32LE(this._b,4),e.writeInt32LE(this._c,8),e.writeInt32LE(this._d,12),e.writeInt32LE(this._e,16),e},e.exports=d},function(e,t,n){(t=e.exports=function(e){e=e.toLowerCase();var n=t[e];if(!n)throw new Error(e+" is not supported (we accept pull requests)");return new n}).sha=n(422),t.sha1=n(423),t.sha224=n(424),t.sha256=n(258),t.sha384=n(425),t.sha512=n(259)},function(e,t,n){(t=e.exports=n(260)).Stream=t,t.Readable=t,t.Writable=n(184),t.Duplex=n(89),t.Transform=n(263),t.PassThrough=n(432)},function(e,t,n){"use strict";(function(t,r,i){var o=n(143);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var i=r.callback;t.pendingcb--,i(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=y;var s,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:o.nextTick;y.WritableState=g;var l=Object.create(n(125));l.inherits=n(11);var c={deprecate:n(179)},f=n(261),h=n(18).Buffer,d=i.Uint8Array||function(){};var p,m=n(262);function v(){}function g(e,t){s=s||n(89),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var i=e.highWaterMark,l=e.writableHighWaterMark,c=this.objectMode?16:16384;this.highWaterMark=i||0===i?i:r&&(l||0===l)?l:c,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,i=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,i){--t.pendingcb,n?(o.nextTick(i,r),o.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(i(r),e._writableState.errorEmitted=!0,e.emit("error",r),S(e,t))}(e,n,r,t,i);else{var a=M(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||_(e,n),r?u(w,e,n,a,i):w(e,n,a,i)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function y(e){if(s=s||n(89),!p.call(y,this)&&!(this instanceof s))return new y(e);this._writableState=new g(e,this),this.writable=!0,e&&("function"===typeof e.write&&(this._write=e.write),"function"===typeof e.writev&&(this._writev=e.writev),"function"===typeof e.destroy&&(this._destroy=e.destroy),"function"===typeof e.final&&(this._final=e.final)),f.call(this)}function b(e,t,n,r,i,o,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),S(e,t)}function _(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,i=new Array(r),o=t.corkedRequestsFree;o.entry=n;for(var s=0,u=!0;n;)i[s]=n,n.isBuf||(u=!1),n=n.next,s+=1;i.allBuffers=u,b(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var l=n.chunk,c=n.encoding,f=n.callback;if(b(e,t,!1,t.objectMode?1:l.length,l,c,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function M(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function E(e,t){e._final((function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),S(e,t)}))}function S(e,t){var n=M(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"===typeof e._final?(t.pendingcb++,t.finalCalled=!0,o.nextTick(E,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}l.inherits(y,f),g.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(g.prototype,"buffer",{get:c.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"===typeof Symbol&&Symbol.hasInstance&&"function"===typeof Function.prototype[Symbol.hasInstance]?(p=Function.prototype[Symbol.hasInstance],Object.defineProperty(y,Symbol.hasInstance,{value:function(e){return!!p.call(this,e)||this===y&&(e&&e._writableState instanceof g)}})):p=function(e){return e instanceof this},y.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},y.prototype.write=function(e,t,n){var r,i=this._writableState,a=!1,s=!i.objectMode&&(r=e,h.isBuffer(r)||r instanceof d);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"===typeof t&&(n=t,t=null),s?t="buffer":t||(t=i.defaultEncoding),"function"!==typeof n&&(n=v),i.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),o.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var i=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"===typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),o.nextTick(r,a),i=!1),i}(this,i,e,n))&&(i.pendingcb++,a=function(e,t,n,r,i,o){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!==typeof t||(t=h.from(t,n));return t}(t,r,i);r!==a&&(n=!0,i="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var u=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(y.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),y.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},y.prototype._writev=null,y.prototype.end=function(e,t,n){var r=this._writableState;"function"===typeof e?(n=e,e=null,t=null):"function"===typeof t&&(n=t,t=null),null!==e&&void 0!==e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,S(e,t),n&&(t.finished?o.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),y.prototype.destroy=m.destroy,y.prototype._undestroy=m.undestroy,y.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(36),n(430).setImmediate,n(40))},function(e,t,n){"use strict";var r=n(51);function i(e){this.options=e,this.type=this.options.type,this.blockSize=8,this._init(),this.buffer=new Array(this.blockSize),this.bufferOff=0}e.exports=i,i.prototype._init=function(){},i.prototype.update=function(e){return 0===e.length?[]:"decrypt"===this.type?this._updateDecrypt(e):this._updateEncrypt(e)},i.prototype._buffer=function(e,t){for(var n=Math.min(this.buffer.length-this.bufferOff,e.length-t),r=0;r0;r--)t+=this._buffer(e,t),n+=this._flushBuffer(i,n);return t+=this._buffer(e,t),i},i.prototype.final=function(e){var t,n;return e&&(t=this.update(e)),n="encrypt"===this.type?this._finalEncrypt():this._finalDecrypt(),t?t.concat(n):n},i.prototype._pad=function(e,t){if(0===t)return!1;for(;t=0||!t.umod(e.prime1)||!t.umod(e.prime2));return t}function a(e,n){var i=function(e){var t=o(e);return{blinder:t.toRed(r.mont(e.modulus)).redPow(new r(e.publicExponent)).fromRed(),unblinder:t.invm(e.modulus)}}(n),a=n.modulus.byteLength(),s=new r(e).mul(i.blinder).umod(n.modulus),u=s.toRed(r.mont(n.prime1)),l=s.toRed(r.mont(n.prime2)),c=n.coefficient,f=n.prime1,h=n.prime2,d=u.redPow(n.exponent1).fromRed(),p=l.redPow(n.exponent2).fromRed(),m=d.isub(p).imul(c).umod(f).imul(h);return p.iadd(m).imul(i.unblinder).umod(n.modulus).toArrayLike(t,"be",a)}a.getr=o,e.exports=a}).call(this,n(33).Buffer)},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var a;"object"===typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{a="undefined"!==typeof window&&"undefined"!==typeof window.Buffer?window.Buffer:n(472).Buffer}catch(C){}function s(e,t){var n=e.charCodeAt(t);return n>=48&&n<=57?n-48:n>=65&&n<=70?n-55:n>=97&&n<=102?n-87:void r(!1,"Invalid character in "+e)}function u(e,t,n){var r=s(e,n);return n-1>=t&&(r|=s(e,n-1)<<4),r}function l(e,t,n,i){for(var o=0,a=0,s=Math.min(e.length,n),u=t;u=49?l-49+10:l>=17?l-17+10:l,r(l>=0&&a0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"===typeof e)return this._initNumber(e,t,n);if("object"===typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&(i++,this.negative=1),i=0;i-=3)a=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=a<>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);else if("le"===n)for(i=0,o=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);return this._strip()},o.prototype._parseHex=function(e,t,n){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var r=0;r=t;r-=2)i=u(e,t,r)<=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;else for(r=(e.length-t)%2===0?t+1:t;r=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;this._strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,a=o%r,s=Math.min(o,o-a)+n,u=0,c=n;c1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},"undefined"!==typeof Symbol&&"function"===typeof Symbol.for)try{o.prototype[Symbol.for("nodejs.util.inspect.custom")]=f}catch(C){o.prototype.inspect=f}else o.prototype.inspect=f;function f(){return(this.red?""}var h=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],d=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],p=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,a=0;a>>24-i&16777215)||a!==this.length-1?h[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,a--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var l=d[e],c=p[e];n="";var f=this.clone();for(f.negative=0;!f.isZero();){var m=f.modrn(c).toString(e);n=(f=f.idivn(c)).isZero()?m+n:h[l-m.length]+m+n}for(this.isZero()&&(n="0"+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16,2)},a&&(o.prototype.toBuffer=function(e,t){return this.toArrayLike(a,e,t)}),o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)};function m(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],a=i*o,s=67108863&a,u=a/67108864|0;n.words[0]=s;for(var l=1;l>>26,f=67108863&u,h=Math.min(l,t.length-1),d=Math.max(0,l-e.length+1);d<=h;d++){var p=l-d|0;c+=(a=(i=0|e.words[p])*(o=0|t.words[d])+f)/67108864|0,f=67108863&a}n.words[l]=0|f,u=0|c}return 0!==u?n.words[l]=0|u:n.length--,n._strip()}o.prototype.toArrayLike=function(e,t,n){this._strip();var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0");var a=function(e,t){return e.allocUnsafe?e.allocUnsafe(t):new e(t)}(e,o);return this["_toArrayLike"+("le"===t?"LE":"BE")](a,i),a},o.prototype._toArrayLikeLE=function(e,t){for(var n=0,r=0,i=0,o=0;i>8&255),n>16&255),6===o?(n>24&255),r=0,o=0):(r=a>>>24,o+=2)}if(n=0&&(e[n--]=a>>8&255),n>=0&&(e[n--]=a>>16&255),6===o?(n>=0&&(e[n--]=a>>24&255),r=0,o=0):(r=a>>>24,o+=2)}if(n>=0)for(e[n--]=r;n>=0;)e[n--]=0},Math.clz32?o.prototype._countBits=function(e){return 32-Math.clz32(e)}:o.prototype._countBits=function(e){var t=e,n=0;return t>=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0===(8191&t)&&(n+=13,t>>>=13),0===(127&t)&&(n+=7,t>>>=7),0===(15&t)&&(n+=4,t>>>=4),0===(3&t)&&(n+=2,t>>>=2),0===(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;te.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;ne.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;re.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"===typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-n),this._strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"===typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o>>26;for(;0!==i&&o>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;oe.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,a=0;a>26,this.words[a]=67108863&t;for(;0!==o&&a>26,this.words[a]=67108863&t;if(0===o&&a>>13,d=0|a[1],p=8191&d,m=d>>>13,v=0|a[2],g=8191&v,y=v>>>13,b=0|a[3],w=8191&b,_=b>>>13,M=0|a[4],E=8191&M,S=M>>>13,x=0|a[5],k=8191&x,T=x>>>13,C=0|a[6],O=8191&C,A=C>>>13,D=0|a[7],P=8191&D,I=D>>>13,N=0|a[8],R=8191&N,j=N>>>13,L=0|a[9],F=8191&L,B=L>>>13,V=0|s[0],z=8191&V,U=V>>>13,q=0|s[1],H=8191&q,G=q>>>13,W=0|s[2],K=8191&W,Y=W>>>13,Q=0|s[3],Z=8191&Q,$=Q>>>13,J=0|s[4],X=8191&J,ee=J>>>13,te=0|s[5],ne=8191&te,re=te>>>13,ie=0|s[6],oe=8191&ie,ae=ie>>>13,se=0|s[7],ue=8191&se,le=se>>>13,ce=0|s[8],fe=8191&ce,he=ce>>>13,de=0|s[9],pe=8191&de,me=de>>>13;n.negative=e.negative^t.negative,n.length=19;var ve=(l+(r=Math.imul(f,z))|0)+((8191&(i=(i=Math.imul(f,U))+Math.imul(h,z)|0))<<13)|0;l=((o=Math.imul(h,U))+(i>>>13)|0)+(ve>>>26)|0,ve&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,U))+Math.imul(m,z)|0,o=Math.imul(m,U);var ge=(l+(r=r+Math.imul(f,H)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,H)|0))<<13)|0;l=((o=o+Math.imul(h,G)|0)+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(g,z),i=(i=Math.imul(g,U))+Math.imul(y,z)|0,o=Math.imul(y,U),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,G)|0)+Math.imul(m,H)|0,o=o+Math.imul(m,G)|0;var ye=(l+(r=r+Math.imul(f,K)|0)|0)+((8191&(i=(i=i+Math.imul(f,Y)|0)+Math.imul(h,K)|0))<<13)|0;l=((o=o+Math.imul(h,Y)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,U))+Math.imul(_,z)|0,o=Math.imul(_,U),r=r+Math.imul(g,H)|0,i=(i=i+Math.imul(g,G)|0)+Math.imul(y,H)|0,o=o+Math.imul(y,G)|0,r=r+Math.imul(p,K)|0,i=(i=i+Math.imul(p,Y)|0)+Math.imul(m,K)|0,o=o+Math.imul(m,Y)|0;var be=(l+(r=r+Math.imul(f,Z)|0)|0)+((8191&(i=(i=i+Math.imul(f,$)|0)+Math.imul(h,Z)|0))<<13)|0;l=((o=o+Math.imul(h,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,U))+Math.imul(S,z)|0,o=Math.imul(S,U),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,G)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,G)|0,r=r+Math.imul(g,K)|0,i=(i=i+Math.imul(g,Y)|0)+Math.imul(y,K)|0,o=o+Math.imul(y,Y)|0,r=r+Math.imul(p,Z)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(m,Z)|0,o=o+Math.imul(m,$)|0;var we=(l+(r=r+Math.imul(f,X)|0)|0)+((8191&(i=(i=i+Math.imul(f,ee)|0)+Math.imul(h,X)|0))<<13)|0;l=((o=o+Math.imul(h,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(k,z),i=(i=Math.imul(k,U))+Math.imul(T,z)|0,o=Math.imul(T,U),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,G)|0)+Math.imul(S,H)|0,o=o+Math.imul(S,G)|0,r=r+Math.imul(w,K)|0,i=(i=i+Math.imul(w,Y)|0)+Math.imul(_,K)|0,o=o+Math.imul(_,Y)|0,r=r+Math.imul(g,Z)|0,i=(i=i+Math.imul(g,$)|0)+Math.imul(y,Z)|0,o=o+Math.imul(y,$)|0,r=r+Math.imul(p,X)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(m,X)|0,o=o+Math.imul(m,ee)|0;var _e=(l+(r=r+Math.imul(f,ne)|0)|0)+((8191&(i=(i=i+Math.imul(f,re)|0)+Math.imul(h,ne)|0))<<13)|0;l=((o=o+Math.imul(h,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(O,z),i=(i=Math.imul(O,U))+Math.imul(A,z)|0,o=Math.imul(A,U),r=r+Math.imul(k,H)|0,i=(i=i+Math.imul(k,G)|0)+Math.imul(T,H)|0,o=o+Math.imul(T,G)|0,r=r+Math.imul(E,K)|0,i=(i=i+Math.imul(E,Y)|0)+Math.imul(S,K)|0,o=o+Math.imul(S,Y)|0,r=r+Math.imul(w,Z)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,Z)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(g,X)|0,i=(i=i+Math.imul(g,ee)|0)+Math.imul(y,X)|0,o=o+Math.imul(y,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(m,ne)|0,o=o+Math.imul(m,re)|0;var Me=(l+(r=r+Math.imul(f,oe)|0)|0)+((8191&(i=(i=i+Math.imul(f,ae)|0)+Math.imul(h,oe)|0))<<13)|0;l=((o=o+Math.imul(h,ae)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,U))+Math.imul(I,z)|0,o=Math.imul(I,U),r=r+Math.imul(O,H)|0,i=(i=i+Math.imul(O,G)|0)+Math.imul(A,H)|0,o=o+Math.imul(A,G)|0,r=r+Math.imul(k,K)|0,i=(i=i+Math.imul(k,Y)|0)+Math.imul(T,K)|0,o=o+Math.imul(T,Y)|0,r=r+Math.imul(E,Z)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(S,Z)|0,o=o+Math.imul(S,$)|0,r=r+Math.imul(w,X)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,X)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(g,ne)|0,i=(i=i+Math.imul(g,re)|0)+Math.imul(y,ne)|0,o=o+Math.imul(y,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,ae)|0)+Math.imul(m,oe)|0,o=o+Math.imul(m,ae)|0;var Ee=(l+(r=r+Math.imul(f,ue)|0)|0)+((8191&(i=(i=i+Math.imul(f,le)|0)+Math.imul(h,ue)|0))<<13)|0;l=((o=o+Math.imul(h,le)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(R,z),i=(i=Math.imul(R,U))+Math.imul(j,z)|0,o=Math.imul(j,U),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,G)|0)+Math.imul(I,H)|0,o=o+Math.imul(I,G)|0,r=r+Math.imul(O,K)|0,i=(i=i+Math.imul(O,Y)|0)+Math.imul(A,K)|0,o=o+Math.imul(A,Y)|0,r=r+Math.imul(k,Z)|0,i=(i=i+Math.imul(k,$)|0)+Math.imul(T,Z)|0,o=o+Math.imul(T,$)|0,r=r+Math.imul(E,X)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(S,X)|0,o=o+Math.imul(S,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(g,oe)|0,i=(i=i+Math.imul(g,ae)|0)+Math.imul(y,oe)|0,o=o+Math.imul(y,ae)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,le)|0)+Math.imul(m,ue)|0,o=o+Math.imul(m,le)|0;var Se=(l+(r=r+Math.imul(f,fe)|0)|0)+((8191&(i=(i=i+Math.imul(f,he)|0)+Math.imul(h,fe)|0))<<13)|0;l=((o=o+Math.imul(h,he)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(F,z),i=(i=Math.imul(F,U))+Math.imul(B,z)|0,o=Math.imul(B,U),r=r+Math.imul(R,H)|0,i=(i=i+Math.imul(R,G)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,G)|0,r=r+Math.imul(P,K)|0,i=(i=i+Math.imul(P,Y)|0)+Math.imul(I,K)|0,o=o+Math.imul(I,Y)|0,r=r+Math.imul(O,Z)|0,i=(i=i+Math.imul(O,$)|0)+Math.imul(A,Z)|0,o=o+Math.imul(A,$)|0,r=r+Math.imul(k,X)|0,i=(i=i+Math.imul(k,ee)|0)+Math.imul(T,X)|0,o=o+Math.imul(T,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(S,ne)|0,o=o+Math.imul(S,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,ae)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,ae)|0,r=r+Math.imul(g,ue)|0,i=(i=i+Math.imul(g,le)|0)+Math.imul(y,ue)|0,o=o+Math.imul(y,le)|0,r=r+Math.imul(p,fe)|0,i=(i=i+Math.imul(p,he)|0)+Math.imul(m,fe)|0,o=o+Math.imul(m,he)|0;var xe=(l+(r=r+Math.imul(f,pe)|0)|0)+((8191&(i=(i=i+Math.imul(f,me)|0)+Math.imul(h,pe)|0))<<13)|0;l=((o=o+Math.imul(h,me)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(F,H),i=(i=Math.imul(F,G))+Math.imul(B,H)|0,o=Math.imul(B,G),r=r+Math.imul(R,K)|0,i=(i=i+Math.imul(R,Y)|0)+Math.imul(j,K)|0,o=o+Math.imul(j,Y)|0,r=r+Math.imul(P,Z)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(I,Z)|0,o=o+Math.imul(I,$)|0,r=r+Math.imul(O,X)|0,i=(i=i+Math.imul(O,ee)|0)+Math.imul(A,X)|0,o=o+Math.imul(A,ee)|0,r=r+Math.imul(k,ne)|0,i=(i=i+Math.imul(k,re)|0)+Math.imul(T,ne)|0,o=o+Math.imul(T,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,ae)|0)+Math.imul(S,oe)|0,o=o+Math.imul(S,ae)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,le)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,le)|0,r=r+Math.imul(g,fe)|0,i=(i=i+Math.imul(g,he)|0)+Math.imul(y,fe)|0,o=o+Math.imul(y,he)|0;var ke=(l+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,me)|0)+Math.imul(m,pe)|0))<<13)|0;l=((o=o+Math.imul(m,me)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(F,K),i=(i=Math.imul(F,Y))+Math.imul(B,K)|0,o=Math.imul(B,Y),r=r+Math.imul(R,Z)|0,i=(i=i+Math.imul(R,$)|0)+Math.imul(j,Z)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,X)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(I,X)|0,o=o+Math.imul(I,ee)|0,r=r+Math.imul(O,ne)|0,i=(i=i+Math.imul(O,re)|0)+Math.imul(A,ne)|0,o=o+Math.imul(A,re)|0,r=r+Math.imul(k,oe)|0,i=(i=i+Math.imul(k,ae)|0)+Math.imul(T,oe)|0,o=o+Math.imul(T,ae)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,le)|0)+Math.imul(S,ue)|0,o=o+Math.imul(S,le)|0,r=r+Math.imul(w,fe)|0,i=(i=i+Math.imul(w,he)|0)+Math.imul(_,fe)|0,o=o+Math.imul(_,he)|0;var Te=(l+(r=r+Math.imul(g,pe)|0)|0)+((8191&(i=(i=i+Math.imul(g,me)|0)+Math.imul(y,pe)|0))<<13)|0;l=((o=o+Math.imul(y,me)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(F,Z),i=(i=Math.imul(F,$))+Math.imul(B,Z)|0,o=Math.imul(B,$),r=r+Math.imul(R,X)|0,i=(i=i+Math.imul(R,ee)|0)+Math.imul(j,X)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(I,ne)|0,o=o+Math.imul(I,re)|0,r=r+Math.imul(O,oe)|0,i=(i=i+Math.imul(O,ae)|0)+Math.imul(A,oe)|0,o=o+Math.imul(A,ae)|0,r=r+Math.imul(k,ue)|0,i=(i=i+Math.imul(k,le)|0)+Math.imul(T,ue)|0,o=o+Math.imul(T,le)|0,r=r+Math.imul(E,fe)|0,i=(i=i+Math.imul(E,he)|0)+Math.imul(S,fe)|0,o=o+Math.imul(S,he)|0;var Ce=(l+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,me)|0)+Math.imul(_,pe)|0))<<13)|0;l=((o=o+Math.imul(_,me)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(F,X),i=(i=Math.imul(F,ee))+Math.imul(B,X)|0,o=Math.imul(B,ee),r=r+Math.imul(R,ne)|0,i=(i=i+Math.imul(R,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,ae)|0)+Math.imul(I,oe)|0,o=o+Math.imul(I,ae)|0,r=r+Math.imul(O,ue)|0,i=(i=i+Math.imul(O,le)|0)+Math.imul(A,ue)|0,o=o+Math.imul(A,le)|0,r=r+Math.imul(k,fe)|0,i=(i=i+Math.imul(k,he)|0)+Math.imul(T,fe)|0,o=o+Math.imul(T,he)|0;var Oe=(l+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,me)|0)+Math.imul(S,pe)|0))<<13)|0;l=((o=o+Math.imul(S,me)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(F,ne),i=(i=Math.imul(F,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(R,oe)|0,i=(i=i+Math.imul(R,ae)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,ae)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,le)|0)+Math.imul(I,ue)|0,o=o+Math.imul(I,le)|0,r=r+Math.imul(O,fe)|0,i=(i=i+Math.imul(O,he)|0)+Math.imul(A,fe)|0,o=o+Math.imul(A,he)|0;var Ae=(l+(r=r+Math.imul(k,pe)|0)|0)+((8191&(i=(i=i+Math.imul(k,me)|0)+Math.imul(T,pe)|0))<<13)|0;l=((o=o+Math.imul(T,me)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(F,oe),i=(i=Math.imul(F,ae))+Math.imul(B,oe)|0,o=Math.imul(B,ae),r=r+Math.imul(R,ue)|0,i=(i=i+Math.imul(R,le)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,le)|0,r=r+Math.imul(P,fe)|0,i=(i=i+Math.imul(P,he)|0)+Math.imul(I,fe)|0,o=o+Math.imul(I,he)|0;var De=(l+(r=r+Math.imul(O,pe)|0)|0)+((8191&(i=(i=i+Math.imul(O,me)|0)+Math.imul(A,pe)|0))<<13)|0;l=((o=o+Math.imul(A,me)|0)+(i>>>13)|0)+(De>>>26)|0,De&=67108863,r=Math.imul(F,ue),i=(i=Math.imul(F,le))+Math.imul(B,ue)|0,o=Math.imul(B,le),r=r+Math.imul(R,fe)|0,i=(i=i+Math.imul(R,he)|0)+Math.imul(j,fe)|0,o=o+Math.imul(j,he)|0;var Pe=(l+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,me)|0)+Math.imul(I,pe)|0))<<13)|0;l=((o=o+Math.imul(I,me)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(F,fe),i=(i=Math.imul(F,he))+Math.imul(B,fe)|0,o=Math.imul(B,he);var Ie=(l+(r=r+Math.imul(R,pe)|0)|0)+((8191&(i=(i=i+Math.imul(R,me)|0)+Math.imul(j,pe)|0))<<13)|0;l=((o=o+Math.imul(j,me)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863;var Ne=(l+(r=Math.imul(F,pe))|0)+((8191&(i=(i=Math.imul(F,me))+Math.imul(B,pe)|0))<<13)|0;return l=((o=Math.imul(B,me))+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863,u[0]=ve,u[1]=ge,u[2]=ye,u[3]=be,u[4]=we,u[5]=_e,u[6]=Me,u[7]=Ee,u[8]=Se,u[9]=xe,u[10]=ke,u[11]=Te,u[12]=Ce,u[13]=Oe,u[14]=Ae,u[15]=De,u[16]=Pe,u[17]=Ie,u[18]=Ne,0!==l&&(u[19]=l,n.length++),n};function g(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o>>26)|0)>>>26,a&=67108863}n.words[o]=s,r=a,a=i}return 0!==r?n.words[o]=r:n.length--,n._strip()}function y(e,t,n){return g(e,t,n)}function b(e,t){this.x=e,this.y=t}Math.imul||(v=m),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?v(this,e,t):n<63?m(this,e,t):n<1024?g(this,e,t):y(this,e,t)},b.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r>=1;return r},b.prototype.permute=function(e,t,n,r,i,o){for(var a=0;a>>=1)i++;return 1<>>=13,n[2*a+1]=8191&o,o>>>=13;for(a=2*t;a>=26,n+=o/67108864|0,n+=a>>>26,this.words[i]=67108863&a}return 0!==n&&(this.words[i]=n,this.length++),t?this.ineg():this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n>>i&1}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var a=0;for(t=0;t>>26-n}a&&(this.words[t]=a,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t=0),i=t?(t-t%26)/26:0;var o=e%26,a=Math.min((e-o)/26,this.length),s=67108863^67108863>>>o<a)for(this.length-=a,l=0;l=0&&(0!==c||l>=i);l--){var f=0|this.words[l];this.words[l]=c<<26-o|f>>>o,c=f&s}return u&&0!==c&&(u.words[u.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this._strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"===typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"===typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i>26,this.words[i+n]=67108863&o;if(0===s)return this._strip();for(r(-1===s),s=0,i=0;i>26,this.words[i]=67108863&o;return this.negative=1,this._strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,a=0|i.words[i.length-1];0!==(n=26-this._countBits(a))&&(i=i.ushln(n),r.iushln(n),a=0|i.words[i.length-1]);var s,u=r.length-i.length;if("mod"!==t){(s=new o(null)).length=u+1,s.words=new Array(s.length);for(var l=0;l=0;f--){var h=67108864*(0|r.words[i.length+f])+(0|r.words[i.length+f-1]);for(h=Math.min(h/a|0,67108863),r._ishlnsubmul(i,h,f);0!==r.negative;)h--,r.negative=0,r._ishlnsubmul(i,1,f),r.isZero()||(r.negative^=1);s&&(s.words[f]=h)}return s&&s._strip(),r._strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:s||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(s=this.neg().divmod(e,t),"mod"!==t&&(i=s.div.neg()),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.iadd(e)),{div:i,mod:a}):0===this.negative&&0!==e.negative?(s=this.divmod(e.neg(),t),"mod"!==t&&(i=s.div.neg()),{div:i,mod:s.mod}):0!==(this.negative&e.negative)?(s=this.neg().divmod(e.neg(),t),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.isub(e)),{div:s.div,mod:a}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modrn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modrn(e.words[0]))}:this._wordDiv(e,t);var i,a,s},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modrn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=(1<<26)%e,i=0,o=this.length-1;o>=0;o--)i=(n*i+(0|this.words[o]))%e;return t?-i:i},o.prototype.modn=function(e){return this.modrn(e)},o.prototype.idivn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=0,i=this.length-1;i>=0;i--){var o=(0|this.words[i])+67108864*n;this.words[i]=o/e|0,n=o%e}return this._strip(),t?this.ineg():this},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),a=new o(0),s=new o(0),u=new o(1),l=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++l;for(var c=n.clone(),f=t.clone();!t.isZero();){for(var h=0,d=1;0===(t.words[0]&d)&&h<26;++h,d<<=1);if(h>0)for(t.iushrn(h);h-- >0;)(i.isOdd()||a.isOdd())&&(i.iadd(c),a.isub(f)),i.iushrn(1),a.iushrn(1);for(var p=0,m=1;0===(n.words[0]&m)&&p<26;++p,m<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(s.isOdd()||u.isOdd())&&(s.iadd(c),u.isub(f)),s.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(s),a.isub(u)):(n.isub(t),s.isub(i),u.isub(a))}return{a:s,b:u,gcd:n.iushln(l)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,a=new o(1),s=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var l=0,c=1;0===(t.words[0]&c)&&l<26;++l,c<<=1);if(l>0)for(t.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);for(var f=0,h=1;0===(n.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(n.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);t.cmp(n)>=0?(t.isub(n),a.isub(s)):(n.isub(t),s.isub(a))}return(i=0===t.cmpn(1)?a:s).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0===(1&this.words[0])},o.prototype.isOdd=function(){return 1===(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"===typeof e);var t=e%26,n=(e-t)/26,i=1<>>26,s&=67108863,this.words[a]=s}return 0!==o&&(this.words[a]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this._strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:ie.length)return 1;if(this.length=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){ri&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new k(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var w={k256:null,p224:null,p192:null,p25519:null};function _(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function M(){_.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function E(){_.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function S(){_.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function x(){_.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function k(e){if("string"===typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function T(e){k.call(this,e),this.shift=this.m.bitLength(),this.shift%26!==0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}_.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},_.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},_.prototype.split=function(e,t){e.iushrn(this.n,0,t)},_.prototype.imulK=function(e){return e.imul(this.k)},i(M,_),M.prototype.split=function(e,t){for(var n=4194303,r=Math.min(e.length,9),i=0;i>>22,o=a}o>>>=22,e.words[i-10]=o,0===o&&e.length>10?e.length-=10:e.length-=9},M.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(w[e])return w[e];var t;if("k256"===e)t=new M;else if("p224"===e)t=new E;else if("p192"===e)t=new S;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new x}return w[e]=t,t},k.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},k.prototype._verify2=function(e,t){r(0===(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},k.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):(c(e,e.umod(this.m)._forceRed(this)),e)},k.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},k.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},k.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},k.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},k.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},k.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},k.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},k.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},k.prototype.isqr=function(e){return this.imul(e,e.clone())},k.prototype.sqr=function(e){return this.mul(e,e)},k.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2===1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),a=0;!i.isZero()&&0===i.andln(1);)a++,i.iushrn(1);r(!i.isZero());var s=new o(1).toRed(this),u=s.redNeg(),l=this.m.subn(1).iushrn(1),c=this.m.bitLength();for(c=new o(2*c*c).toRed(this);0!==this.pow(c,l).cmp(u);)c.redIAdd(u);for(var f=this.pow(c,i),h=this.pow(e,i.addn(1).iushrn(1)),d=this.pow(e,i),p=a;0!==d.cmp(s);){for(var m=d,v=0;0!==m.cmp(s);v++)m=m.redSqr();r(v=0;r--){for(var l=t.words[r],c=u-1;c>=0;c--){var f=l>>c&1;i!==n[0]&&(i=this.sqr(i)),0!==f||0!==a?(a<<=1,a|=f,(4===++s||0===r&&0===c)&&(i=this.mul(i,n[a]),s=0,a=0)):s=0}u=26}return i},k.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},k.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new T(e)},i(T,k),T.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},T.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},T.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},T.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},T.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(75)(e))},function(e,t,n){"use strict";var r=t;r.version=n(473).version,r.utils=n(52),r.rand=n(188),r.curve=n(289),r.curves=n(194),r.ec=n(485),r.eddsa=n(489)},function(e,t,n){"use strict";var r,i=t,o=n(195),a=n(289),s=n(52).assert;function u(e){"short"===e.type?this.curve=new a.short(e):"edwards"===e.type?this.curve=new a.edwards(e):this.curve=new a.mont(e),this.g=this.curve.g,this.n=this.curve.n,this.hash=e.hash,s(this.g.validate(),"Invalid curve"),s(this.g.mul(this.n).isInfinity(),"Invalid curve, G*N != O")}function l(e,t){Object.defineProperty(i,e,{configurable:!0,enumerable:!0,get:function(){var n=new u(t);return Object.defineProperty(i,e,{configurable:!0,enumerable:!0,value:n}),n}})}i.PresetCurve=u,l("p192",{type:"short",prime:"p192",p:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff",a:"ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc",b:"64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1",n:"ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831",hash:o.sha256,gRed:!1,g:["188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012","07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811"]}),l("p224",{type:"short",prime:"p224",p:"ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001",a:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe",b:"b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4",n:"ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d",hash:o.sha256,gRed:!1,g:["b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21","bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34"]}),l("p256",{type:"short",prime:null,p:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff",a:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc",b:"5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b",n:"ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551",hash:o.sha256,gRed:!1,g:["6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296","4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5"]}),l("p384",{type:"short",prime:null,p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 ffffffff",a:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 fffffffc",b:"b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef",n:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973",hash:o.sha384,gRed:!1,g:["aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7","3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f"]}),l("p521",{type:"short",prime:null,p:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff",a:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffc",b:"00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00",n:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409",hash:o.sha512,gRed:!1,g:["000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66","00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650"]}),l("curve25519",{type:"mont",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"76d06",b:"1",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:o.sha256,gRed:!1,g:["9"]}),l("ed25519",{type:"edwards",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"-1",c:"1",d:"52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:o.sha256,gRed:!1,g:["216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a","6666666666666666666666666666666666666666666666666666666666666658"]});try{r=n(484)}catch(c){r=void 0}l("secp256k1",{type:"short",prime:"k256",p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f",a:"0",b:"7",n:"ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141",h:"1",hash:o.sha256,beta:"7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee",lambda:"5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72",basis:[{a:"3086d221a7d46bcde86c90e49284eb15",b:"-e4437ed6010e88286f547fa90abfe4c3"},{a:"114ca50f7a8e2f3f657c1108d9d44cfd8",b:"3086d221a7d46bcde86c90e49284eb15"}],gRed:!1,g:["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",r]})},function(e,t,n){var r=t;r.utils=n(64),r.common=n(127),r.sha=n(478),r.ripemd=n(482),r.hmac=n(483),r.sha1=r.sha.sha1,r.sha256=r.sha.sha256,r.sha224=r.sha.sha224,r.sha384=r.sha.sha384,r.sha512=r.sha.sha512,r.ripemd160=r.ripemd.ripemd160},function(e,t,n){"use strict";(function(t){var r,i=n(33),o=i.Buffer,a={};for(r in i)i.hasOwnProperty(r)&&"SlowBuffer"!==r&&"Buffer"!==r&&(a[r]=i[r]);var s=a.Buffer={};for(r in o)o.hasOwnProperty(r)&&"allocUnsafe"!==r&&"allocUnsafeSlow"!==r&&(s[r]=o[r]);if(a.Buffer.prototype=o.prototype,s.from&&s.from!==Uint8Array.from||(s.from=function(e,t,n){if("number"===typeof e)throw new TypeError('The "value" argument must not be of type number. Received type '+typeof e);if(e&&"undefined"===typeof e.length)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);return o(e,t,n)}),s.alloc||(s.alloc=function(e,t,n){if("number"!==typeof e)throw new TypeError('The "size" argument must be of type number. Received type '+typeof e);if(e<0||e>=2*(1<<30))throw new RangeError('The value "'+e+'" is invalid for option "size"');var r=o(e);return t&&0!==t.length?"string"===typeof n?r.fill(t,n):r.fill(t):r.fill(0),r}),!a.kStringMaxLength)try{a.kStringMaxLength=t.binding("buffer").kStringMaxLength}catch(u){}a.constants||(a.constants={MAX_LENGTH:a.kMaxLength},a.kStringMaxLength&&(a.constants.MAX_STRING_LENGTH=a.kStringMaxLength)),e.exports=a}).call(this,n(36))},function(e,t,n){"use strict";var r=n(198).Reporter,i=n(128).EncoderBuffer,o=n(128).DecoderBuffer,a=n(51),s=["seq","seqof","set","setof","objid","bool","gentime","utctime","null_","enum","int","objDesc","bitstr","bmpstr","charstr","genstr","graphstr","ia5str","iso646str","numstr","octstr","printstr","t61str","unistr","utf8str","videostr"],u=["key","obj","use","optional","explicit","implicit","def","choice","any","contains"].concat(s);function l(e,t,n){var r={};this._baseState=r,r.name=n,r.enc=e,r.parent=t||null,r.children=null,r.tag=null,r.args=null,r.reverseArgs=null,r.choice=null,r.optional=!1,r.any=!1,r.obj=!1,r.use=null,r.useDecoder=null,r.key=null,r.default=null,r.explicit=null,r.implicit=null,r.contains=null,r.parent||(r.children=[],this._wrap())}e.exports=l;var c=["enc","parent","children","tag","args","reverseArgs","choice","optional","any","obj","use","alteredUse","key","default","explicit","implicit","contains"];l.prototype.clone=function(){var e=this._baseState,t={};c.forEach((function(n){t[n]=e[n]}));var n=new this.constructor(t.parent);return n._baseState=t,n},l.prototype._wrap=function(){var e=this._baseState;u.forEach((function(t){this[t]=function(){var n=new this.constructor(this);return e.children.push(n),n[t].apply(n,arguments)}}),this)},l.prototype._init=function(e){var t=this._baseState;a(null===t.parent),e.call(this),t.children=t.children.filter((function(e){return e._baseState.parent===this}),this),a.equal(t.children.length,1,"Root node can have only one child")},l.prototype._useArgs=function(e){var t=this._baseState,n=e.filter((function(e){return e instanceof this.constructor}),this);e=e.filter((function(e){return!(e instanceof this.constructor)}),this),0!==n.length&&(a(null===t.children),t.children=n,n.forEach((function(e){e._baseState.parent=this}),this)),0!==e.length&&(a(null===t.args),t.args=e,t.reverseArgs=e.map((function(e){if("object"!==typeof e||e.constructor!==Object)return e;var t={};return Object.keys(e).forEach((function(n){n==(0|n)&&(n|=0);var r=e[n];t[r]=n})),t})))},["_peekTag","_decodeTag","_use","_decodeStr","_decodeObjid","_decodeTime","_decodeNull","_decodeInt","_decodeBool","_decodeList","_encodeComposite","_encodeStr","_encodeObjid","_encodeTime","_encodeNull","_encodeInt","_encodeBool"].forEach((function(e){l.prototype[e]=function(){var t=this._baseState;throw new Error(e+" not implemented for encoding: "+t.enc)}})),s.forEach((function(e){l.prototype[e]=function(){var t=this._baseState,n=Array.prototype.slice.call(arguments);return a(null===t.tag),t.tag=e,this._useArgs(n),this}})),l.prototype.use=function(e){a(e);var t=this._baseState;return a(null===t.use),t.use=e,this},l.prototype.optional=function(){return this._baseState.optional=!0,this},l.prototype.def=function(e){var t=this._baseState;return a(null===t.default),t.default=e,t.optional=!0,this},l.prototype.explicit=function(e){var t=this._baseState;return a(null===t.explicit&&null===t.implicit),t.explicit=e,this},l.prototype.implicit=function(e){var t=this._baseState;return a(null===t.explicit&&null===t.implicit),t.implicit=e,this},l.prototype.obj=function(){var e=this._baseState,t=Array.prototype.slice.call(arguments);return e.obj=!0,0!==t.length&&this._useArgs(t),this},l.prototype.key=function(e){var t=this._baseState;return a(null===t.key),t.key=e,this},l.prototype.any=function(){return this._baseState.any=!0,this},l.prototype.choice=function(e){var t=this._baseState;return a(null===t.choice),t.choice=e,this._useArgs(Object.keys(e).map((function(t){return e[t]}))),this},l.prototype.contains=function(e){var t=this._baseState;return a(null===t.use),t.contains=e,this},l.prototype._decode=function(e,t){var n=this._baseState;if(null===n.parent)return e.wrapResult(n.children[0]._decode(e,t));var r,i=n.default,a=!0,s=null;if(null!==n.key&&(s=e.enterKey(n.key)),n.optional){var u=null;if(null!==n.explicit?u=n.explicit:null!==n.implicit?u=n.implicit:null!==n.tag&&(u=n.tag),null!==u||n.any){if(a=this._peekTag(e,u,n.any),e.isError(a))return a}else{var l=e.save();try{null===n.choice?this._decodeGeneric(n.tag,e,t):this._decodeChoice(e,t),a=!0}catch(m){a=!1}e.restore(l)}}if(n.obj&&a&&(r=e.enterObject()),a){if(null!==n.explicit){var c=this._decodeTag(e,n.explicit);if(e.isError(c))return c;e=c}var f=e.offset;if(null===n.use&&null===n.choice){var h;n.any&&(h=e.save());var d=this._decodeTag(e,null!==n.implicit?n.implicit:n.tag,n.any);if(e.isError(d))return d;n.any?i=e.raw(h):e=d}if(t&&t.track&&null!==n.tag&&t.track(e.path(),f,e.length,"tagged"),t&&t.track&&null!==n.tag&&t.track(e.path(),e.offset,e.length,"content"),n.any||(i=null===n.choice?this._decodeGeneric(n.tag,e,t):this._decodeChoice(e,t)),e.isError(i))return i;if(n.any||null!==n.choice||null===n.children||n.children.forEach((function(n){n._decode(e,t)})),n.contains&&("octstr"===n.tag||"bitstr"===n.tag)){var p=new o(i);i=this._getUse(n.contains,e._reporterState.obj)._decode(p,t)}}return n.obj&&a&&(i=e.leaveObject(r)),null===n.key||null===i&&!0!==a?null!==s&&e.exitKey(s):e.leaveKey(s,n.key,i),i},l.prototype._decodeGeneric=function(e,t,n){var r=this._baseState;return"seq"===e||"set"===e?null:"seqof"===e||"setof"===e?this._decodeList(t,e,r.args[0],n):/str$/.test(e)?this._decodeStr(t,e,n):"objid"===e&&r.args?this._decodeObjid(t,r.args[0],r.args[1],n):"objid"===e?this._decodeObjid(t,null,null,n):"gentime"===e||"utctime"===e?this._decodeTime(t,e,n):"null_"===e?this._decodeNull(t,n):"bool"===e?this._decodeBool(t,n):"objDesc"===e?this._decodeStr(t,e,n):"int"===e||"enum"===e?this._decodeInt(t,r.args&&r.args[0],n):null!==r.use?this._getUse(r.use,t._reporterState.obj)._decode(t,n):t.error("unknown tag: "+e)},l.prototype._getUse=function(e,t){var n=this._baseState;return n.useDecoder=this._use(e,t),a(null===n.useDecoder._baseState.parent),n.useDecoder=n.useDecoder._baseState.children[0],n.implicit!==n.useDecoder._baseState.implicit&&(n.useDecoder=n.useDecoder.clone(),n.useDecoder._baseState.implicit=n.implicit),n.useDecoder},l.prototype._decodeChoice=function(e,t){var n=this._baseState,r=null,i=!1;return Object.keys(n.choice).some((function(o){var a=e.save(),s=n.choice[o];try{var u=s._decode(e,t);if(e.isError(u))return!1;r={type:o,value:u},i=!0}catch(l){return e.restore(a),!1}return!0}),this),i?r:e.error("Choice not matched")},l.prototype._createEncoderBuffer=function(e){return new i(e,this.reporter)},l.prototype._encode=function(e,t,n){var r=this._baseState;if(null===r.default||r.default!==e){var i=this._encodeValue(e,t,n);if(void 0!==i&&!this._skipDefault(i,t,n))return i}},l.prototype._encodeValue=function(e,t,n){var i=this._baseState;if(null===i.parent)return i.children[0]._encode(e,t||new r);var o=null;if(this.reporter=t,i.optional&&void 0===e){if(null===i.default)return;e=i.default}var a=null,s=!1;if(i.any)o=this._createEncoderBuffer(e);else if(i.choice)o=this._encodeChoice(e,t);else if(i.contains)a=this._getUse(i.contains,n)._encode(e,t),s=!0;else if(i.children)a=i.children.map((function(n){if("null_"===n._baseState.tag)return n._encode(null,t,e);if(null===n._baseState.key)return t.error("Child should have a key");var r=t.enterKey(n._baseState.key);if("object"!==typeof e)return t.error("Child expected, but input is not object");var i=n._encode(e[n._baseState.key],t,e);return t.leaveKey(r),i}),this).filter((function(e){return e})),a=this._createEncoderBuffer(a);else if("seqof"===i.tag||"setof"===i.tag){if(!i.args||1!==i.args.length)return t.error("Too many args for : "+i.tag);if(!Array.isArray(e))return t.error("seqof/setof, but data is not Array");var u=this.clone();u._baseState.implicit=null,a=this._createEncoderBuffer(e.map((function(n){var r=this._baseState;return this._getUse(r.args[0],e)._encode(n,t)}),u))}else null!==i.use?o=this._getUse(i.use,n)._encode(e,t):(a=this._encodePrimitive(i.tag,e),s=!0);if(!i.any&&null===i.choice){var l=null!==i.implicit?i.implicit:i.tag,c=null===i.implicit?"universal":"context";null===l?null===i.use&&t.error("Tag could be omitted only for .use()"):null===i.use&&(o=this._encodeComposite(l,s,c,a))}return null!==i.explicit&&(o=this._encodeComposite(i.explicit,!1,"context",o)),o},l.prototype._encodeChoice=function(e,t){var n=this._baseState,r=n.choice[e.type];return r||a(!1,e.type+" not found in "+JSON.stringify(Object.keys(n.choice))),r._encode(e.value,t)},l.prototype._encodePrimitive=function(e,t){var n=this._baseState;if(/str$/.test(e))return this._encodeStr(t,e);if("objid"===e&&n.args)return this._encodeObjid(t,n.reverseArgs[0],n.args[1]);if("objid"===e)return this._encodeObjid(t,null,null);if("gentime"===e||"utctime"===e)return this._encodeTime(t,e);if("null_"===e)return this._encodeNull();if("int"===e||"enum"===e)return this._encodeInt(t,n.args&&n.reverseArgs[0]);if("bool"===e)return this._encodeBool(t);if("objDesc"===e)return this._encodeStr(t,e);throw new Error("Unsupported tag: "+e)},l.prototype._isNumstr=function(e){return/^[0-9 ]*$/.test(e)},l.prototype._isPrintstr=function(e){return/^[A-Za-z0-9 '()+,-./:=?]*$/.test(e)}},function(e,t,n){"use strict";var r=n(11);function i(e){this._reporterState={obj:null,path:[],options:e||{},errors:[]}}function o(e,t){this.path=e,this.rethrow(t)}t.Reporter=i,i.prototype.isError=function(e){return e instanceof o},i.prototype.save=function(){var e=this._reporterState;return{obj:e.obj,pathLen:e.path.length}},i.prototype.restore=function(e){var t=this._reporterState;t.obj=e.obj,t.path=t.path.slice(0,e.pathLen)},i.prototype.enterKey=function(e){return this._reporterState.path.push(e)},i.prototype.exitKey=function(e){var t=this._reporterState;t.path=t.path.slice(0,e-1)},i.prototype.leaveKey=function(e,t,n){var r=this._reporterState;this.exitKey(e),null!==r.obj&&(r.obj[t]=n)},i.prototype.path=function(){return this._reporterState.path.join("/")},i.prototype.enterObject=function(){var e=this._reporterState,t=e.obj;return e.obj={},t},i.prototype.leaveObject=function(e){var t=this._reporterState,n=t.obj;return t.obj=e,n},i.prototype.error=function(e){var t,n=this._reporterState,r=e instanceof o;if(t=r?e:new o(n.path.map((function(e){return"["+JSON.stringify(e)+"]"})).join(""),e.message||e,e.stack),!n.options.partial)throw t;return r||n.errors.push(t),t},i.prototype.wrapResult=function(e){var t=this._reporterState;return t.options.partial?{result:this.isError(e)?null:e,errors:t.errors}:e},r(o,Error),o.prototype.rethrow=function(e){if(this.message=e+" at: "+(this.path||"(shallow)"),Error.captureStackTrace&&Error.captureStackTrace(this,o),!this.stack)try{throw new Error(this.message)}catch(t){this.stack=t.stack}return this}},function(e,t,n){"use strict";function r(e){var t={};return Object.keys(e).forEach((function(n){(0|n)==n&&(n|=0);var r=e[n];t[r]=n})),t}t.tagClass={0:"universal",1:"application",2:"context",3:"private"},t.tagClassByName=r(t.tagClass),t.tag={0:"end",1:"bool",2:"int",3:"bitstr",4:"octstr",5:"null_",6:"objid",7:"objDesc",8:"external",9:"real",10:"enum",11:"embed",12:"utf8str",13:"relativeOid",16:"seq",17:"set",18:"numstr",19:"printstr",20:"t61str",21:"videostr",22:"ia5str",23:"utctime",24:"gentime",25:"graphstr",26:"iso646str",27:"genstr",28:"unistr",29:"charstr",30:"bmpstr"},t.tagByName=r(t.tag)},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var a;"object"===typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{a="undefined"!==typeof window&&"undefined"!==typeof window.Buffer?window.Buffer:n(508).Buffer}catch(x){}function s(e,t){var n=e.charCodeAt(t);return n>=65&&n<=70?n-55:n>=97&&n<=102?n-87:n-48&15}function u(e,t,n){var r=s(e,n);return n-1>=t&&(r|=s(e,n-1)<<4),r}function l(e,t,n,r){for(var i=0,o=Math.min(e.length,n),a=t;a=49?s-49+10:s>=17?s-17+10:s}return i}o.isBN=function(e){return e instanceof o||null!==e&&"object"===typeof e&&e.constructor.wordSize===o.wordSize&&Array.isArray(e.words)},o.max=function(e,t){return e.cmp(t)>0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"===typeof e)return this._initNumber(e,t,n);if("object"===typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&(i++,this.negative=1),i=0;i-=3)a=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=a<>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);else if("le"===n)for(i=0,o=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,o++);return this.strip()},o.prototype._parseHex=function(e,t,n){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var r=0;r=t;r-=2)i=u(e,t,r)<=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;else for(r=(e.length-t)%2===0?t+1:t;r=18?(o-=18,a+=1,this.words[a]|=i>>>26):o+=8;this.strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,a=o%r,s=Math.min(o,o-a)+n,u=0,c=n;c1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},o.prototype.inspect=function(){return(this.red?""};var c=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],f=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],h=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function d(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],a=i*o,s=67108863&a,u=a/67108864|0;n.words[0]=s;for(var l=1;l>>26,f=67108863&u,h=Math.min(l,t.length-1),d=Math.max(0,l-e.length+1);d<=h;d++){var p=l-d|0;c+=(a=(i=0|e.words[p])*(o=0|t.words[d])+f)/67108864|0,f=67108863&a}n.words[l]=0|f,u=0|c}return 0!==u?n.words[l]=0|u:n.length--,n.strip()}o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,a=0;a>>24-i&16777215)||a!==this.length-1?c[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,a--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var l=f[e],d=h[e];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var m=p.modn(d).toString(e);n=(p=p.idivn(d)).isZero()?m+n:c[l-m.length]+m+n}for(this.isZero()&&(n="0"+n);n.length%t!==0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16)},o.prototype.toBuffer=function(e,t){return r("undefined"!==typeof a),this.toArrayLike(a,e,t)},o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)},o.prototype.toArrayLike=function(e,t,n){var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0"),this.strip();var a,s,u="le"===t,l=new e(o),c=this.clone();if(u){for(s=0;!c.isZero();s++)a=c.andln(255),c.iushrn(8),l[s]=a;for(;s=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0===(8191&t)&&(n+=13,t>>>=13),0===(127&t)&&(n+=7,t>>>=7),0===(15&t)&&(n+=4,t>>>=4),0===(3&t)&&(n+=2,t>>>=2),0===(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;te.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;ne.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;re.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"===typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-n),this.strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"===typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o>>26;for(;0!==i&&o>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;oe.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,a=0;a>26,this.words[a]=67108863&t;for(;0!==o&&a>26,this.words[a]=67108863&t;if(0===o&&a>>13,d=0|a[1],p=8191&d,m=d>>>13,v=0|a[2],g=8191&v,y=v>>>13,b=0|a[3],w=8191&b,_=b>>>13,M=0|a[4],E=8191&M,S=M>>>13,x=0|a[5],k=8191&x,T=x>>>13,C=0|a[6],O=8191&C,A=C>>>13,D=0|a[7],P=8191&D,I=D>>>13,N=0|a[8],R=8191&N,j=N>>>13,L=0|a[9],F=8191&L,B=L>>>13,V=0|s[0],z=8191&V,U=V>>>13,q=0|s[1],H=8191&q,G=q>>>13,W=0|s[2],K=8191&W,Y=W>>>13,Q=0|s[3],Z=8191&Q,$=Q>>>13,J=0|s[4],X=8191&J,ee=J>>>13,te=0|s[5],ne=8191&te,re=te>>>13,ie=0|s[6],oe=8191&ie,ae=ie>>>13,se=0|s[7],ue=8191&se,le=se>>>13,ce=0|s[8],fe=8191&ce,he=ce>>>13,de=0|s[9],pe=8191&de,me=de>>>13;n.negative=e.negative^t.negative,n.length=19;var ve=(l+(r=Math.imul(f,z))|0)+((8191&(i=(i=Math.imul(f,U))+Math.imul(h,z)|0))<<13)|0;l=((o=Math.imul(h,U))+(i>>>13)|0)+(ve>>>26)|0,ve&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,U))+Math.imul(m,z)|0,o=Math.imul(m,U);var ge=(l+(r=r+Math.imul(f,H)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,H)|0))<<13)|0;l=((o=o+Math.imul(h,G)|0)+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(g,z),i=(i=Math.imul(g,U))+Math.imul(y,z)|0,o=Math.imul(y,U),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,G)|0)+Math.imul(m,H)|0,o=o+Math.imul(m,G)|0;var ye=(l+(r=r+Math.imul(f,K)|0)|0)+((8191&(i=(i=i+Math.imul(f,Y)|0)+Math.imul(h,K)|0))<<13)|0;l=((o=o+Math.imul(h,Y)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,U))+Math.imul(_,z)|0,o=Math.imul(_,U),r=r+Math.imul(g,H)|0,i=(i=i+Math.imul(g,G)|0)+Math.imul(y,H)|0,o=o+Math.imul(y,G)|0,r=r+Math.imul(p,K)|0,i=(i=i+Math.imul(p,Y)|0)+Math.imul(m,K)|0,o=o+Math.imul(m,Y)|0;var be=(l+(r=r+Math.imul(f,Z)|0)|0)+((8191&(i=(i=i+Math.imul(f,$)|0)+Math.imul(h,Z)|0))<<13)|0;l=((o=o+Math.imul(h,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,U))+Math.imul(S,z)|0,o=Math.imul(S,U),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,G)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,G)|0,r=r+Math.imul(g,K)|0,i=(i=i+Math.imul(g,Y)|0)+Math.imul(y,K)|0,o=o+Math.imul(y,Y)|0,r=r+Math.imul(p,Z)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(m,Z)|0,o=o+Math.imul(m,$)|0;var we=(l+(r=r+Math.imul(f,X)|0)|0)+((8191&(i=(i=i+Math.imul(f,ee)|0)+Math.imul(h,X)|0))<<13)|0;l=((o=o+Math.imul(h,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(k,z),i=(i=Math.imul(k,U))+Math.imul(T,z)|0,o=Math.imul(T,U),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,G)|0)+Math.imul(S,H)|0,o=o+Math.imul(S,G)|0,r=r+Math.imul(w,K)|0,i=(i=i+Math.imul(w,Y)|0)+Math.imul(_,K)|0,o=o+Math.imul(_,Y)|0,r=r+Math.imul(g,Z)|0,i=(i=i+Math.imul(g,$)|0)+Math.imul(y,Z)|0,o=o+Math.imul(y,$)|0,r=r+Math.imul(p,X)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(m,X)|0,o=o+Math.imul(m,ee)|0;var _e=(l+(r=r+Math.imul(f,ne)|0)|0)+((8191&(i=(i=i+Math.imul(f,re)|0)+Math.imul(h,ne)|0))<<13)|0;l=((o=o+Math.imul(h,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(O,z),i=(i=Math.imul(O,U))+Math.imul(A,z)|0,o=Math.imul(A,U),r=r+Math.imul(k,H)|0,i=(i=i+Math.imul(k,G)|0)+Math.imul(T,H)|0,o=o+Math.imul(T,G)|0,r=r+Math.imul(E,K)|0,i=(i=i+Math.imul(E,Y)|0)+Math.imul(S,K)|0,o=o+Math.imul(S,Y)|0,r=r+Math.imul(w,Z)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,Z)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(g,X)|0,i=(i=i+Math.imul(g,ee)|0)+Math.imul(y,X)|0,o=o+Math.imul(y,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(m,ne)|0,o=o+Math.imul(m,re)|0;var Me=(l+(r=r+Math.imul(f,oe)|0)|0)+((8191&(i=(i=i+Math.imul(f,ae)|0)+Math.imul(h,oe)|0))<<13)|0;l=((o=o+Math.imul(h,ae)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,U))+Math.imul(I,z)|0,o=Math.imul(I,U),r=r+Math.imul(O,H)|0,i=(i=i+Math.imul(O,G)|0)+Math.imul(A,H)|0,o=o+Math.imul(A,G)|0,r=r+Math.imul(k,K)|0,i=(i=i+Math.imul(k,Y)|0)+Math.imul(T,K)|0,o=o+Math.imul(T,Y)|0,r=r+Math.imul(E,Z)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(S,Z)|0,o=o+Math.imul(S,$)|0,r=r+Math.imul(w,X)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,X)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(g,ne)|0,i=(i=i+Math.imul(g,re)|0)+Math.imul(y,ne)|0,o=o+Math.imul(y,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,ae)|0)+Math.imul(m,oe)|0,o=o+Math.imul(m,ae)|0;var Ee=(l+(r=r+Math.imul(f,ue)|0)|0)+((8191&(i=(i=i+Math.imul(f,le)|0)+Math.imul(h,ue)|0))<<13)|0;l=((o=o+Math.imul(h,le)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(R,z),i=(i=Math.imul(R,U))+Math.imul(j,z)|0,o=Math.imul(j,U),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,G)|0)+Math.imul(I,H)|0,o=o+Math.imul(I,G)|0,r=r+Math.imul(O,K)|0,i=(i=i+Math.imul(O,Y)|0)+Math.imul(A,K)|0,o=o+Math.imul(A,Y)|0,r=r+Math.imul(k,Z)|0,i=(i=i+Math.imul(k,$)|0)+Math.imul(T,Z)|0,o=o+Math.imul(T,$)|0,r=r+Math.imul(E,X)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(S,X)|0,o=o+Math.imul(S,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(g,oe)|0,i=(i=i+Math.imul(g,ae)|0)+Math.imul(y,oe)|0,o=o+Math.imul(y,ae)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,le)|0)+Math.imul(m,ue)|0,o=o+Math.imul(m,le)|0;var Se=(l+(r=r+Math.imul(f,fe)|0)|0)+((8191&(i=(i=i+Math.imul(f,he)|0)+Math.imul(h,fe)|0))<<13)|0;l=((o=o+Math.imul(h,he)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(F,z),i=(i=Math.imul(F,U))+Math.imul(B,z)|0,o=Math.imul(B,U),r=r+Math.imul(R,H)|0,i=(i=i+Math.imul(R,G)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,G)|0,r=r+Math.imul(P,K)|0,i=(i=i+Math.imul(P,Y)|0)+Math.imul(I,K)|0,o=o+Math.imul(I,Y)|0,r=r+Math.imul(O,Z)|0,i=(i=i+Math.imul(O,$)|0)+Math.imul(A,Z)|0,o=o+Math.imul(A,$)|0,r=r+Math.imul(k,X)|0,i=(i=i+Math.imul(k,ee)|0)+Math.imul(T,X)|0,o=o+Math.imul(T,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(S,ne)|0,o=o+Math.imul(S,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,ae)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,ae)|0,r=r+Math.imul(g,ue)|0,i=(i=i+Math.imul(g,le)|0)+Math.imul(y,ue)|0,o=o+Math.imul(y,le)|0,r=r+Math.imul(p,fe)|0,i=(i=i+Math.imul(p,he)|0)+Math.imul(m,fe)|0,o=o+Math.imul(m,he)|0;var xe=(l+(r=r+Math.imul(f,pe)|0)|0)+((8191&(i=(i=i+Math.imul(f,me)|0)+Math.imul(h,pe)|0))<<13)|0;l=((o=o+Math.imul(h,me)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(F,H),i=(i=Math.imul(F,G))+Math.imul(B,H)|0,o=Math.imul(B,G),r=r+Math.imul(R,K)|0,i=(i=i+Math.imul(R,Y)|0)+Math.imul(j,K)|0,o=o+Math.imul(j,Y)|0,r=r+Math.imul(P,Z)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(I,Z)|0,o=o+Math.imul(I,$)|0,r=r+Math.imul(O,X)|0,i=(i=i+Math.imul(O,ee)|0)+Math.imul(A,X)|0,o=o+Math.imul(A,ee)|0,r=r+Math.imul(k,ne)|0,i=(i=i+Math.imul(k,re)|0)+Math.imul(T,ne)|0,o=o+Math.imul(T,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,ae)|0)+Math.imul(S,oe)|0,o=o+Math.imul(S,ae)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,le)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,le)|0,r=r+Math.imul(g,fe)|0,i=(i=i+Math.imul(g,he)|0)+Math.imul(y,fe)|0,o=o+Math.imul(y,he)|0;var ke=(l+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,me)|0)+Math.imul(m,pe)|0))<<13)|0;l=((o=o+Math.imul(m,me)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(F,K),i=(i=Math.imul(F,Y))+Math.imul(B,K)|0,o=Math.imul(B,Y),r=r+Math.imul(R,Z)|0,i=(i=i+Math.imul(R,$)|0)+Math.imul(j,Z)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,X)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(I,X)|0,o=o+Math.imul(I,ee)|0,r=r+Math.imul(O,ne)|0,i=(i=i+Math.imul(O,re)|0)+Math.imul(A,ne)|0,o=o+Math.imul(A,re)|0,r=r+Math.imul(k,oe)|0,i=(i=i+Math.imul(k,ae)|0)+Math.imul(T,oe)|0,o=o+Math.imul(T,ae)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,le)|0)+Math.imul(S,ue)|0,o=o+Math.imul(S,le)|0,r=r+Math.imul(w,fe)|0,i=(i=i+Math.imul(w,he)|0)+Math.imul(_,fe)|0,o=o+Math.imul(_,he)|0;var Te=(l+(r=r+Math.imul(g,pe)|0)|0)+((8191&(i=(i=i+Math.imul(g,me)|0)+Math.imul(y,pe)|0))<<13)|0;l=((o=o+Math.imul(y,me)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(F,Z),i=(i=Math.imul(F,$))+Math.imul(B,Z)|0,o=Math.imul(B,$),r=r+Math.imul(R,X)|0,i=(i=i+Math.imul(R,ee)|0)+Math.imul(j,X)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(I,ne)|0,o=o+Math.imul(I,re)|0,r=r+Math.imul(O,oe)|0,i=(i=i+Math.imul(O,ae)|0)+Math.imul(A,oe)|0,o=o+Math.imul(A,ae)|0,r=r+Math.imul(k,ue)|0,i=(i=i+Math.imul(k,le)|0)+Math.imul(T,ue)|0,o=o+Math.imul(T,le)|0,r=r+Math.imul(E,fe)|0,i=(i=i+Math.imul(E,he)|0)+Math.imul(S,fe)|0,o=o+Math.imul(S,he)|0;var Ce=(l+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,me)|0)+Math.imul(_,pe)|0))<<13)|0;l=((o=o+Math.imul(_,me)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(F,X),i=(i=Math.imul(F,ee))+Math.imul(B,X)|0,o=Math.imul(B,ee),r=r+Math.imul(R,ne)|0,i=(i=i+Math.imul(R,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,ae)|0)+Math.imul(I,oe)|0,o=o+Math.imul(I,ae)|0,r=r+Math.imul(O,ue)|0,i=(i=i+Math.imul(O,le)|0)+Math.imul(A,ue)|0,o=o+Math.imul(A,le)|0,r=r+Math.imul(k,fe)|0,i=(i=i+Math.imul(k,he)|0)+Math.imul(T,fe)|0,o=o+Math.imul(T,he)|0;var Oe=(l+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,me)|0)+Math.imul(S,pe)|0))<<13)|0;l=((o=o+Math.imul(S,me)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(F,ne),i=(i=Math.imul(F,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(R,oe)|0,i=(i=i+Math.imul(R,ae)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,ae)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,le)|0)+Math.imul(I,ue)|0,o=o+Math.imul(I,le)|0,r=r+Math.imul(O,fe)|0,i=(i=i+Math.imul(O,he)|0)+Math.imul(A,fe)|0,o=o+Math.imul(A,he)|0;var Ae=(l+(r=r+Math.imul(k,pe)|0)|0)+((8191&(i=(i=i+Math.imul(k,me)|0)+Math.imul(T,pe)|0))<<13)|0;l=((o=o+Math.imul(T,me)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(F,oe),i=(i=Math.imul(F,ae))+Math.imul(B,oe)|0,o=Math.imul(B,ae),r=r+Math.imul(R,ue)|0,i=(i=i+Math.imul(R,le)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,le)|0,r=r+Math.imul(P,fe)|0,i=(i=i+Math.imul(P,he)|0)+Math.imul(I,fe)|0,o=o+Math.imul(I,he)|0;var De=(l+(r=r+Math.imul(O,pe)|0)|0)+((8191&(i=(i=i+Math.imul(O,me)|0)+Math.imul(A,pe)|0))<<13)|0;l=((o=o+Math.imul(A,me)|0)+(i>>>13)|0)+(De>>>26)|0,De&=67108863,r=Math.imul(F,ue),i=(i=Math.imul(F,le))+Math.imul(B,ue)|0,o=Math.imul(B,le),r=r+Math.imul(R,fe)|0,i=(i=i+Math.imul(R,he)|0)+Math.imul(j,fe)|0,o=o+Math.imul(j,he)|0;var Pe=(l+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,me)|0)+Math.imul(I,pe)|0))<<13)|0;l=((o=o+Math.imul(I,me)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(F,fe),i=(i=Math.imul(F,he))+Math.imul(B,fe)|0,o=Math.imul(B,he);var Ie=(l+(r=r+Math.imul(R,pe)|0)|0)+((8191&(i=(i=i+Math.imul(R,me)|0)+Math.imul(j,pe)|0))<<13)|0;l=((o=o+Math.imul(j,me)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863;var Ne=(l+(r=Math.imul(F,pe))|0)+((8191&(i=(i=Math.imul(F,me))+Math.imul(B,pe)|0))<<13)|0;return l=((o=Math.imul(B,me))+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863,u[0]=ve,u[1]=ge,u[2]=ye,u[3]=be,u[4]=we,u[5]=_e,u[6]=Me,u[7]=Ee,u[8]=Se,u[9]=xe,u[10]=ke,u[11]=Te,u[12]=Ce,u[13]=Oe,u[14]=Ae,u[15]=De,u[16]=Pe,u[17]=Ie,u[18]=Ne,0!==l&&(u[19]=l,n.length++),n};function m(e,t,n){return(new v).mulp(e,t,n)}function v(e,t){this.x=e,this.y=t}Math.imul||(p=d),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?p(this,e,t):n<63?d(this,e,t):n<1024?function(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o>>26)|0)>>>26,a&=67108863}n.words[o]=s,r=a,a=i}return 0!==r?n.words[o]=r:n.length--,n.strip()}(this,e,t):m(this,e,t)},v.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r>=1;return r},v.prototype.permute=function(e,t,n,r,i,o){for(var a=0;a>>=1)i++;return 1<>>=13,n[2*a+1]=8191&o,o>>>=13;for(a=2*t;a>=26,t+=i/67108864|0,t+=o>>>26,this.words[n]=67108863&o}return 0!==t&&(this.words[n]=t,this.length++),this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n>>i}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var a=0;for(t=0;t>>26-n}a&&(this.words[t]=a,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t=0),i=t?(t-t%26)/26:0;var o=e%26,a=Math.min((e-o)/26,this.length),s=67108863^67108863>>>o<a)for(this.length-=a,l=0;l=0&&(0!==c||l>=i);l--){var f=0|this.words[l];this.words[l]=c<<26-o|f>>>o,c=f&s}return u&&0!==c&&(u.words[u.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"===typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"===typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i>26,this.words[i+n]=67108863&o;if(0===s)return this.strip();for(r(-1===s),s=0,i=0;i>26,this.words[i]=67108863&o;return this.negative=1,this.strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,a=0|i.words[i.length-1];0!==(n=26-this._countBits(a))&&(i=i.ushln(n),r.iushln(n),a=0|i.words[i.length-1]);var s,u=r.length-i.length;if("mod"!==t){(s=new o(null)).length=u+1,s.words=new Array(s.length);for(var l=0;l=0;f--){var h=67108864*(0|r.words[i.length+f])+(0|r.words[i.length+f-1]);for(h=Math.min(h/a|0,67108863),r._ishlnsubmul(i,h,f);0!==r.negative;)h--,r.negative=0,r._ishlnsubmul(i,1,f),r.isZero()||(r.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),r.strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:s||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(s=this.neg().divmod(e,t),"mod"!==t&&(i=s.div.neg()),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.iadd(e)),{div:i,mod:a}):0===this.negative&&0!==e.negative?(s=this.divmod(e.neg(),t),"mod"!==t&&(i=s.div.neg()),{div:i,mod:s.mod}):0!==(this.negative&e.negative)?(s=this.neg().divmod(e.neg(),t),"div"!==t&&(a=s.mod.neg(),n&&0!==a.negative&&a.isub(e)),{div:s.div,mod:a}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modn(e.words[0]))}:this._wordDiv(e,t);var i,a,s},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modn=function(e){r(e<=67108863);for(var t=(1<<26)%e,n=0,i=this.length-1;i>=0;i--)n=(t*n+(0|this.words[i]))%e;return n},o.prototype.idivn=function(e){r(e<=67108863);for(var t=0,n=this.length-1;n>=0;n--){var i=(0|this.words[n])+67108864*t;this.words[n]=i/e|0,t=i%e}return this.strip()},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),a=new o(0),s=new o(0),u=new o(1),l=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++l;for(var c=n.clone(),f=t.clone();!t.isZero();){for(var h=0,d=1;0===(t.words[0]&d)&&h<26;++h,d<<=1);if(h>0)for(t.iushrn(h);h-- >0;)(i.isOdd()||a.isOdd())&&(i.iadd(c),a.isub(f)),i.iushrn(1),a.iushrn(1);for(var p=0,m=1;0===(n.words[0]&m)&&p<26;++p,m<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(s.isOdd()||u.isOdd())&&(s.iadd(c),u.isub(f)),s.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(s),a.isub(u)):(n.isub(t),s.isub(i),u.isub(a))}return{a:s,b:u,gcd:n.iushln(l)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,a=new o(1),s=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var l=0,c=1;0===(t.words[0]&c)&&l<26;++l,c<<=1);if(l>0)for(t.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);for(var f=0,h=1;0===(n.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(n.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);t.cmp(n)>=0?(t.isub(n),a.isub(s)):(n.isub(t),s.isub(a))}return(i=0===t.cmpn(1)?a:s).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0===(1&this.words[0])},o.prototype.isOdd=function(){return 1===(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"===typeof e);var t=e%26,n=(e-t)/26,i=1<>>26,s&=67108863,this.words[a]=s}return 0!==o&&(this.words[a]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this.strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:ie.length)return 1;if(this.length=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){ri&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new E(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var g={k256:null,p224:null,p192:null,p25519:null};function y(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function b(){y.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function w(){y.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function _(){y.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function M(){y.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function E(e){if("string"===typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function S(e){E.call(this,e),this.shift=this.m.bitLength(),this.shift%26!==0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}y.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},y.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},y.prototype.split=function(e,t){e.iushrn(this.n,0,t)},y.prototype.imulK=function(e){return e.imul(this.k)},i(b,y),b.prototype.split=function(e,t){for(var n=4194303,r=Math.min(e.length,9),i=0;i>>22,o=a}o>>>=22,e.words[i-10]=o,0===o&&e.length>10?e.length-=10:e.length-=9},b.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(g[e])return g[e];var t;if("k256"===e)t=new b;else if("p224"===e)t=new w;else if("p192"===e)t=new _;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new M}return g[e]=t,t},E.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},E.prototype._verify2=function(e,t){r(0===(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},E.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):e.umod(this.m)._forceRed(this)},E.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},E.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},E.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},E.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},E.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},E.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},E.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},E.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},E.prototype.isqr=function(e){return this.imul(e,e.clone())},E.prototype.sqr=function(e){return this.mul(e,e)},E.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2===1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),a=0;!i.isZero()&&0===i.andln(1);)a++,i.iushrn(1);r(!i.isZero());var s=new o(1).toRed(this),u=s.redNeg(),l=this.m.subn(1).iushrn(1),c=this.m.bitLength();for(c=new o(2*c*c).toRed(this);0!==this.pow(c,l).cmp(u);)c.redIAdd(u);for(var f=this.pow(c,i),h=this.pow(e,i.addn(1).iushrn(1)),d=this.pow(e,i),p=a;0!==d.cmp(s);){for(var m=d,v=0;0!==m.cmp(s);v++)m=m.redSqr();r(v=0;r--){for(var l=t.words[r],c=u-1;c>=0;c--){var f=l>>c&1;i!==n[0]&&(i=this.sqr(i)),0!==f||0!==a?(a<<=1,a|=f,(4===++s||0===r&&0===c)&&(i=this.mul(i,n[a]),s=0,a=0)):s=0}u=26}return i},E.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},E.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new S(e)},i(S,E),S.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},S.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},S.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},S.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},S.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(75)(e))},function(e,t){e.exports=/[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4E\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/},function(e,t,n){"use strict";function r(){this.__rules__=[],this.__cache__=null}r.prototype.__find__=function(e){for(var t=0;t=0&&(n=this.attrs[t][1]),n},r.prototype.attrJoin=function(e,t){var n=this.attrIndex(e);n<0?this.attrPush([e,t]):this.attrs[n][1]=this.attrs[n][1]+" "+t},e.exports=r},function(e,t,n){!function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function r(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,(function(t,n,a){a&&a!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(o(r(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))}));var i={Backspace:u,Enter:l};function o(e){for(var t=0;t=0;u--){var c=a[u].head;t.replaceRange("",n(c.line,c.ch-1),n(c.line,c.ch+1),"+delete")}}function l(t){var n=s(t),i=n&&r(n,"explode");if(!i||t.getOption("disableInput"))return e.Pass;for(var o=t.listSelections(),a=0;a0?{line:a.head.line,ch:a.head.ch+t}:{line:a.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function f(t){var r=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(r?-1:1)),head:new n(t.head.line,t.head.ch+(r?1:-1))}}function h(t,i){var o=s(t);if(!o||t.getOption("disableInput"))return e.Pass;var a=r(o,"pairs"),u=a.indexOf(i);if(-1==u)return e.Pass;for(var l,h=r(o,"closeBefore"),d=r(o,"triples"),m=a.charAt(u+1)==i,v=t.listSelections(),g=u%2==0,y=0;y1&&d.indexOf(i)>=0&&t.getRange(n(_.line,_.ch-2),_)==i+i){if(_.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(_.line,_.ch-2))))return e.Pass;b="addFour"}else if(m){var E=0==_.ch?" ":t.getRange(n(_.line,_.ch-1),_);if(e.isWordChar(M)||E==i||e.isWordChar(E))return e.Pass;b="both"}else{if(!g||!(0===M.length||/\s/.test(M)||h.indexOf(M)>-1))return e.Pass;b="both"}else b=m&&p(t,_)?"both":d.indexOf(i)>=0&&t.getRange(_,n(_.line,_.ch+3))==i+i+i?"skipThree":"skip";if(l){if(l!=b)return e.Pass}else l=b}var S=u%2?a.charAt(u-1):i,x=u%2?i:a.charAt(u+1);t.operation((function(){if("skip"==l)c(t,1);else if("skipThree"==l)c(t,3);else if("surround"==l){for(var e=t.getSelections(),n=0;n-1)&&c.push(e.message)}));for(var m=null,v=i.hasGutter&&document.createDocumentFragment(),g=0;g1,o.tooltips)),o.highlightLines&&e.addLineClass(s,"wrap",n+m)}}o.onUpdateLinting&&o.onUpdateLinting(r,a,e)}}function y(e){var t=e.state.lint;t&&(clearTimeout(t.timeout),t.timeout=setTimeout((function(){v(e)}),t.options.delay))}function b(e,t,n){for(var r=n.target||n.srcElement,i=document.createDocumentFragment(),o=0;o1&&"boolean"!==typeof t)throw new a('"allowMissing" argument must be a boolean');var n=k(e),r=n.length>0?n[0]:"",o=T("%"+r+"%",t),s=o.name,l=o.value,c=!1,f=o.alias;f&&(r=f[0],_(n,w([0,1],f)));for(var h=1,d=!0;h=n.length){var y=u(l,p);l=(d=!!y)&&"get"in y&&!("originalValue"in y.get)?y.get:l[p]}else d=b(l,p),l=l[p];d&&!c&&(m[s]=l)}}return l}},function(e,t,n){"use strict";var r=n(585);e.exports=Function.prototype.bind||r},function(e,t,n){"use strict";var r=String.prototype.replace,i=/%20/g,o="RFC1738",a="RFC3986";e.exports={default:a,formatters:{RFC1738:function(e){return r.call(e,i,"+")},RFC3986:function(e){return String(e)}},RFC1738:o,RFC3986:a}},function(e,t,n){var r=n(109);e.exports=function(e,t){if(!r(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!r(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")}},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},function(e,t,n){var r=n(213)("keys"),i=n(157);e.exports=function(e){return r[e]||(r[e]=i(e))}},function(e,t,n){var r=n(65),i=n(76),o="__core-js_shared__",a=i[o]||(i[o]={});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:r.version,mode:n(156)?"pure":"global",copyright:"\xa9 2020 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t){e.exports={}},function(e,t,n){var r=n(129),i=n(617),o=n(214),a=n(212)("IE_PROTO"),s=function(){},u=function(){var e,t=n(319)("iframe"),r=o.length;for(t.style.display="none",n(618).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write(" + + + +Redirecting... + + diff --git a/observability/root-cause-analysis/index.html b/observability/root-cause-analysis/index.html new file mode 100644 index 000000000..80ba06a26 --- /dev/null +++ b/observability/root-cause-analysis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/choreo-insights-api/index.html b/observe-and-analyze/analyze/choreo-insights-api/index.html new file mode 100644 index 000000000..9347b189d --- /dev/null +++ b/observe-and-analyze/analyze/choreo-insights-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/configure-alerts/index.html b/observe-and-analyze/analyze/configure-alerts/index.html new file mode 100644 index 000000000..17db144ab --- /dev/null +++ b/observe-and-analyze/analyze/configure-alerts/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/dora-metrics/configure-cio-dashboard/index.html b/observe-and-analyze/analyze/dora-metrics/configure-cio-dashboard/index.html new file mode 100644 index 000000000..649f91f47 --- /dev/null +++ b/observe-and-analyze/analyze/dora-metrics/configure-cio-dashboard/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/dora-metrics/view-dora-metrics/index.html b/observe-and-analyze/analyze/dora-metrics/view-dora-metrics/index.html new file mode 100644 index 000000000..7974d4a0b --- /dev/null +++ b/observe-and-analyze/analyze/dora-metrics/view-dora-metrics/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/generate-custom-reports/index.html b/observe-and-analyze/analyze/generate-custom-reports/index.html new file mode 100644 index 000000000..25ca54f22 --- /dev/null +++ b/observe-and-analyze/analyze/generate-custom-reports/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/programmatic-access-choreo-insights-api/index.html b/observe-and-analyze/analyze/programmatic-access-choreo-insights-api/index.html new file mode 100644 index 000000000..a524c8f81 --- /dev/null +++ b/observe-and-analyze/analyze/programmatic-access-choreo-insights-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/analyze/view-api-insights/index.html b/observe-and-analyze/analyze/view-api-insights/index.html new file mode 100644 index 000000000..9023b18e2 --- /dev/null +++ b/observe-and-analyze/analyze/view-api-insights/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/observe/observability-overview/index.html b/observe-and-analyze/observe/observability-overview/index.html new file mode 100644 index 000000000..5bf45b44e --- /dev/null +++ b/observe-and-analyze/observe/observability-overview/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/observe-and-analyze/observe/root-cause-analysis/index.html b/observe-and-analyze/observe/root-cause-analysis/index.html new file mode 100644 index 000000000..01f424356 --- /dev/null +++ b/observe-and-analyze/observe/root-cause-analysis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/page-not-found/index.html b/page-not-found/index.html new file mode 100644 index 000000000..d62af1af8 --- /dev/null +++ b/page-not-found/index.html @@ -0,0 +1,3408 @@ + + + + + + + + + + + + + + + + + + + + + + + + Page not found - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Page not found

+ + + +

Try one of the navigation links above or use the search engine in the top right corner. 

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick-start-guides/build-your-first-cloud-native-application-with-choreo/index.html b/quick-start-guides/build-your-first-cloud-native-application-with-choreo/index.html new file mode 100644 index 000000000..1bab0eb3b --- /dev/null +++ b/quick-start-guides/build-your-first-cloud-native-application-with-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/quick-start-guides/build-your-first-integration-with-choreo-ipaas/index.html b/quick-start-guides/build-your-first-integration-with-choreo-ipaas/index.html new file mode 100644 index 000000000..1379409c4 --- /dev/null +++ b/quick-start-guides/build-your-first-integration-with-choreo-ipaas/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/index.html b/quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/index.html new file mode 100644 index 000000000..4430f9eb6 --- /dev/null +++ b/quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/index.html @@ -0,0 +1,4165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy a Web Application that Consumes a Backend Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deploy a Web Application that Consumes a Backend Service

+

Choreo is an Internal Developer Platform (IDevP) that streamlines the entire process of building, deploying, monitoring, and managing your cloud-native applications easily.

+

In this quick start guide, you will explore how to expose a service endpoint via Choreo and securely consume the service from a web application. You will use a simple reading list web application with a sign-in page and functionality to interact with a secure backend service. You will also use Choreo's managed authentication to easily set up authentication for your web application without having to dive into the details of security protocols. The application will allow users to sign in and view their reading lists, add books to a reading list, delete books from the reading list, and sign out of the application effortlessly.

+

This guide walks you through the following steps:

+
    +
  • Deploy and test a service component.
  • +
  • Create a web application to consume the exposed service.
  • +
  • Create a connection to the deployed service.
  • +
  • Enable managed authentication and deploy the web application.
  • +
  • Consume the deployed service via the web application.
  • +
+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  1. +

    Create a GitHub repository to save the service implementation. For this guide, you can fork the Choreo sample book list app repository.

    +
  2. +
  3. +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the organization home page.

    +
  4. +
+

Step 1: Create a project

+

Follow the steps given below to create a project:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. +
  3. On the organization home page, click + Create Project.
  4. +
  5. +

    Enter a display name, unique name, and description for the project. You can enter the values given below:

    +
    +

    Tip

    +

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Display NameSample project
    Namesample-project
    Project DescriptionMy sample project
    +
  6. +
  7. +

    Click Create. This creates the project and opens the project home page.

    +
  8. +
+

Step 2: Connect your sample repository and configure the sample service

+

To connect to the repository you forked in the prerequisites and configure the sample service, follow the steps given below:

+
    +
  1. On the project home page, click Start under Create Multiple Components.
  2. +
  3. Go to the GitHub tab.
  4. +
  5. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo sample book list app repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  6. +
  7. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    Repositorychoreo-sample-book-list-app
    Branchmain
    +
  8. +
  9. +

    In the Add Component Directories pane under Configure Components, click the + icon corresponding to reading-list-service.

    +
  10. +
  11. +

    In the Component Configuration dialog that opens, specify values as follows for each of the fields:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameReading List Service
    Component Namereading-list-service
    Pathreading-list-service
    Component TypeService
    BuildpackNodeJS
    Language Version20.x.x
    +
  12. +
  13. +

    Click Save. This adds the Reading List Service component to the Configured Components pane.

    +
  14. +
  15. +

    Click Finish. This initializes the service with the implementation from your GitHub repository and takes you to the project home page.

    +

    You can see the Reading List Service component listed under Component Listing on the project home page.

    +
  16. +
+

Step 3: Build the service

+

To build the service, follow the steps given below:

+
    +
  1. On the project home page, click the Reading List Service component listed under Component Listing. This takes you to the component overview page.
  2. +
  3. In the left navigation menu, click Build.
  4. +
  5. In the Builds pane, click Build Latest.
  6. +
+

!!! note + Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

+

Step 4: Deploy the service

+

For the REST endpoint of the service to be invokable, you need to deploy it. To deploy the service, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane that opens, click Next to skip the configuration.
  6. +
  7. In the File Mount pane that opens, click Next to skip the configuration.
  8. +
  9. In the Endpoint Details pane that opens, verify that the Network Visibility is set to Public. This setting securely exposes the endpoint for consumption.
  10. +
  11. Click Deploy. This deploys the service to the development environment and lists the service in the Choreo Marketplace.
  12. +
+

Step 5: Test the service

+

To test the endpoint via the integrated OpenAPI Console in Choreo, follow the steps given below:

+
    +
  1. In the Choreo Console left navigation menu, click Test and then click Console.
  2. +
  3. In the OpenAPI Console that opens, select Development from the environment drop-down list.
  4. +
  5. In the Endpoint list, select Books REST Endpoint.
  6. +
  7. Expand the GET/books method, click Try it out, then click Execute.
  8. +
  9. Click .
  10. +
  11. Check the Server Response section. You will see an empty response. You can add an entry using the POST method and retry the GET/books method again.
  12. +
  13. Expand the POST/books method and click Try it out.
  14. +
  15. +

    Update the request body so that the parameters have the values given below:

    + + + + + + + + + + + + + + + + + + + + + +
    ParameterValue
    authorBram Stoker
    statusto_read
    titleDracula
    +

    The request body should look as follows:

    +

      {
    +    "author": "Bram Stoker",
    +    "status": "to_read",
    +    "title": "Dracula"
    +  }
    +
    +9. Click Execute.

    +

    Check the Server Response section. On successful invocation, you will receive the 201 HTTP code.

    +
  16. +
+

Similarly, you can expand and try out the GET and DELETE methods.

+

Step 6: Consume the service

+

Now that the Reading List Service is deployed and available in the Choreo Marketplace, application developers can discover the service via the Marketplace and consume it.

+

In this section of the guide, you will deploy a sample front-end application to consume the service. This application will serve as the interface for users to interact with the reading list. The sample application used in this guide is designed to personalize the book lists based on the user ID that it obtains from its identity provider.

+

To host the front-end application in Choreo, you will create a web application component, set up authentication for it, and deploy it. To establish a connection between your web application and the deployed service, you will create a Connection.

+

Step 6.1: Create a web application to consume the service

+

To create a web application component, follow the steps given below:

+
    +
  1. In the Choreo Console header, click the Project list and select the project that you created in step 1.
  2. +
  3. On the project home page, click + Create under Component Listing.
  4. +
  5. Click the Web Application card.
  6. +
  7. +

    Enter a display name, unique name, and a description to create the web application. You can enter the values given below:

    +
    +

    Info

    +

    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameReading List Web App
    Component Namereading-list-web-app
    DescriptionFront-end application for the reading list service
    +
  8. +
  9. +

    Go to the GitHub tab.

    +
  10. +
  11. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo sample Book List Service repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-sample-book-list-app
    Branchmain
    +
  14. +
  15. +

    Select React as the buildpack because the sample front-end application is a React application built with Vite.

    +
  16. +
  17. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Directory/choreo-sample-book-list-app/reading-list-front-end-with-managed-auth
    Build Commandnpm install && npm run build
    Build Pathdist
    Node Version18
    +
  18. +
  19. +

    Click Create. This initializes the component with the implementation from your GitHub repository and takes you to the Overview page of the component.

    +
  20. +
+

Step 6.2: Create a connection between the web application and the deployed service

+

A connection allows you to integrate the service you intend to deploy on Choreo with other services on Choreo or external resources. For more information on Choreo Connections refer to the Connection documentation.

+

To establish a connection between the web application you created and the deployed service, follow the steps given below:

+
    +
  1. In the left navigation menu, click Dependencies and then click Connections.
  2. +
  3. Click + Create.
  4. +
  5. In the Select a Service pane, click Reading List Service.`
  6. +
  7. +

    Specify values as follows for each of the fields:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    NameReading List Connection
    DescriptionConnection to the reading list
    +
  8. +
  9. +

    Click Create. This creates the connection and displays the service URL of the connection for +each environment the service is deployed in. In this guide, you will see the service URL for the Development environment. You can copy the service URL to use when you configure the web application before deploying it.

    +
  10. +
+

Step 6.3: Build the web application component

+

To build the web application, follow the steps given below:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. In the Builds pane, click Build Latest.
  4. +
+

!!! note + Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

+

Step 6.4: Configure and deploy the web application

+

In this step, you will configure managed authentication, create a user to access the web application, and then deploy the web application. For more information on Choreo's managed authentication capability, see the Managed Authentication documentation.

+

To configure managed authentication, follow the steps given below:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can specify values for the mount file.
  4. +
  5. +

    Specify the following in the config.js file mount.

    +
      +
    • +

      You must replace <Service URL> with the value that you copied when creating a connection to the Reading List Service in step 6.2.

      +
      window.configs = {
      +    apiUrl: '<Service URL>',
      +};
      +
      + +
    • +
    +
    +

    Tip

    +

    You can refer to the configuration file mounted at /app/public as ./public/config.js within your web application.

    +
    +
  6. +
  7. +

    Click Next. This opens the Authentication pane.

    +
  8. +
  9. +

    Under Authentication Settings, make sure that you have the Managed authentication with Choreo toggle enabled.

    +
    +

    Tip

    +

    Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks.

    +
    +
  10. +
  11. +

    Specify values as follows for each of the fields:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Post Login Path/
    Post Logout Path/
    Error Path/
    +
  12. +
+

Next, you can create a user to access the web application.

+

To create a user to access the readingListApp application, follow the steps given below:

+
    +
  1. Under Manage Users, click + Create.
  2. +
  3. +

    To proceed with creating a user with the populated username and password, click Create. Make sure you copy the populated username and password to use when you test the front-end application.

    +
    +

    Tip

    + +
    +
  4. +
+

Now, you can deploy the web application.

+

To deploy the web application and obtain the URL to access it, follow the steps given below:

+
    +
  1. In the Authentication pane, click Deploy. The deployment may take a few minutes to complete.
  2. +
  3. Once you deploy the web application, copy the Web App URL from the development environment card.
  4. +
  5. Navigate to the web app URL. You can verify that you have successfully hosted the web application.
  6. +
+

Step 7: Test the front-end application

+

To test the front-end application and send requests to the Reading List Service via it, follow the steps given below:

+
    +
  1. Access the front-end application via its web URL that you copied in the above step.
  2. +
  3. +

    Click Login, and sign in with the credentials of the user that you created.

    +

    The application opens as follows.

    +

    Front-end application

    +
  4. +
  5. +

    Add three new reading items with different statuses.

    +

    For example, the details can be as follows:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    TitleAuthorStatus
    The Museum of InnocenceOrhan Pamukreading
    The Remains of the DayKazuo Ishiguroto_read
    David CopperfieldCharles Dickensread
    +

    To add each record, follow the steps given below:

    +
      +
    1. Click + Add New.
    2. +
    3. Enter values for the Name, Author, and Status fields.
    4. +
    5. Click Save.
    6. +
    +

    Three tabs open for each status. To delete a reading list item, you can click Delete.

    +
  6. +
+

To verify whether the reading list is personalized for each user, you can sign in as a different user. The reading list items you entered above will not appear for the other user.

+

Congratulations! You have successfully exposed a service endpoint via Choreo and securely consumed it from a web application.

+

After you have successfully tested your service and web application, you can now try out various other Choreo features such as managing, observing, DevOps, etc., similar to any other component type within Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick-start-guides/deploy-your-first-service/index.html b/quick-start-guides/deploy-your-first-service/index.html new file mode 100644 index 000000000..0250a92fc --- /dev/null +++ b/quick-start-guides/deploy-your-first-service/index.html @@ -0,0 +1,3838 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy Your First Service - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deploy Your First Service

+

Choreo, an Internal Developer Platform (IDevP), simplifies the deployment, monitoring, and management of your cloud-native services, allowing you to focus on innovation and implementation.

+

Choreo allows you to easily deploy services you've created in your preferred programming language in just a few steps.

+

In this guide, you will:

+
    +
  • Use a pre-implemented service that has resources to maintain a book list.
  • +
  • Build and deploy the service in Choreo using the Nodejs buildpack. It runs on port 8080.
  • +
  • Test the service.
  • +
+

For a video tutorial that walks you through these steps, see Deploy Your First Service with Choreo.

+

Prerequisites

+
    +
  1. +

    You must have a GitHub account with a repository that contains your service implementation. To proceed with the steps in this guide, you can fork the Choreo sample book list service repository, which contains the sample for this guide.

    +
  2. +
  3. +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the organization home page.

    +
  4. +
+

Learn the repository file structure

+

Let's familiarize ourselves with the key files in this sample application. The below table gives a brief overview of the important files in the sample book list service.

+
+

Note

+

The following file paths are relative to the path <choreo-sample-book-list-service>/.

+
+ + + + + + + + + + + + + + + + + + + + + +
FilepathDescription
app.mjsThe Node.js (JavaScript) based service code.
.choreo/component.yamlChoreo-specific configuration that provides information about how Choreo exposes the service.
openapi.yamlOpenAPI contract of the service. This is required to publish our service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml.
+

Let's get started!

+

Step 1: Create a project

+

Follow the steps given below to create a project:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. +
  3. On the organization home page, click + Create Project.
  4. +
  5. +

    Enter a display name, unique name, and description for the project. You can enter the values given below:

    +
    +

    Info

    +

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Display NameBook List Project
    Namebook-list-project
    Project DescriptionMy sample project
    +
  6. +
  7. +

    Click Create. This creates the project and takes you to the project home page.

    +
  8. +
+

Step 2: Create a service component

+

Let's create a service component by following these steps:

+
    +
  1. On the project home page, click Service under Create a Component.
  2. +
  3. +

    Enter a unique name and a description for the service. For this guide, let's enter the following values:

    + + + + + + + + + + + + + + + + + +
    FieldValue
    Component Display NameBook List
    DescriptionGets the book list
    +
  4. +
  5. +

    Go to the GitHub tab.

    +
  6. +
  7. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the Choreo sample Book List Service repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  8. +
  9. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    OrganizationYour GitHub account
    Repositorychoreo-sample-book-list-service
    Branchmain
    +
  10. +
  11. +

    Select the NodeJS buildpack.

    +
  12. +
  13. +

    Enter the following information.

    + + + + + + + + + + + + + + + + + +
    FieldDescription
    NodeJS Project Directory/
    Language Version20.x.x
    +
  14. +
  15. +

    Click Create.

    +
  16. +
+

You have successfully created a Service component with the NodeJS buildpack. Now let's build and deploy the service.

+

Step 3: Build and deploy

+

Now that the source repository is connected and Choreo has set up the endpoints based on the repository's configuration, it's time to proceed with building the service. Choreo will create a Docker image in the build process. You can then deploy the built Docker image and test the book list service.

+

Step 3.1: Build

+

To build the service, follow these steps:

+
    +
  1. On the project home page, click the Book List component listed under Component Listing. This takes you to the component overview page.
  2. +
  3. In the left navigation, click Build.
  4. +
  5. Click Build Latest.
  6. +
+

!!! note + Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

+

Step 3.2: Deploy

+

Now you are ready to deploy the service. Follow these steps:

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. On the Set Up card, click Configure & Deploy.
  4. +
  5. In the Environment Configurations pane, click Next.
  6. +
  7. In the File Mount pane, click Next.
  8. +
  9. +

    Review the Endpoint Details and click Deploy.

    +
    +

    Note

    +

    Deploying the service component may take a while. You can track the progress by observing the logs. Once the deployment is complete, the build status changes to Active on the Development environment card.

    +
    +
  10. +
+

Step 4: Test the service

+

To test the Book List service via the integrated OpenAPI Console in Choreo, follow the steps given below:

+
    +
  1. In the Choreo Console left navigation menu, click Test and then click Console.
  2. +
  3. In the OpenAPI Console that opens, select Development from the environment drop-down list.
  4. +
  5. In the Endpoint list, select Books REST Endpoint.
  6. +
  7. Expand the GET /books method and click Try it out.
  8. +
  9. Click Execute.
  10. +
  11. Check the Server Response section.
  12. +
+

Similarly, you can expand and try out the other methods.

+

After you have successfully tested your service, you can now try out various other Choreo features such as managing, observing, DevOps, etc., similar to any other component type within Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick-start-guides/deploy-your-first-static-web-application/index.html b/quick-start-guides/deploy-your-first-static-web-application/index.html new file mode 100644 index 000000000..28a4af4ca --- /dev/null +++ b/quick-start-guides/deploy-your-first-static-web-application/index.html @@ -0,0 +1,3709 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy Your First Static Web Application - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Deploy Your First Static Web Application

+

Choreo is an internal developer platform as a service that takes care of the complexities of building platforms, allowing application developers to focus on innovation and implementation. Choreo streamlines the entire process of building, deploying, monitoring, and managing your cloud-native applications.

+

In this quick start guide, you will explore how easy it is to deploy a web application using Choreo. Here, you will use a simple web application designed to add tasks to a to-do list.

+

This guide walks you through the following steps:

+
    +
  • Create a project.
  • +
  • Create a Web Application component and connect it to the GitHub repository that includes the web application implementation.
  • +
  • Build the web application.
  • +
  • Deploy the web application and access it.
  • +
+

For a video tutorial that walks you through these steps, see Deploy a Static Web App on Choreo.

+

Prerequisites

+

Before you try out this guide, complete the following:

+
    +
  1. Fork the choreo-sample-todo-list-app + repository, which contains the sample for this guide.
  2. +
  3. +

    If you are signing in to the Choreo Console for the first time, create an organization as follows:

    +
      +
    1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
    2. +
    3. Enter a unique organization name. For example, Stark Industries.
    4. +
    5. Read and accept the privacy policy and terms of use.
    6. +
    7. Click Create.
    8. +
    +

    This creates the organization and opens the organization home page.

    +
  4. +
+

Step 1: Create a project

+

Follow the steps given below to create a project:

+
    +
  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. +
  3. On the organization home page, click + Create Project.
  4. +
  5. +

    Enter a display name, unique name, and description for the project. You can enter the values given below:

    +
    +

    Tip

    +

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    +
    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    Project Display NameSample project
    Namesample-project
    Project DescriptionMy sample project
    +
  6. +
  7. +

    Click Create. This creates the project and opens the project home page.

    +
  8. +
+

Step 2: Create a Web Application component

+

To create a Web Application component, follow the steps given below:

+
    +
  1. On the project home page, click Web Application under Create a Component.
  2. +
  3. Enter a unique name and a description for the web application.
  4. +
  5. Go to the GitHub tab.
  6. +
  7. +

    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

    +

    Alternatively, you can paste the choreo-sample-todo-list-app repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

    +
    +

    Note

    +

    The Choreo GitHub App requires the following permissions:

    +
      +
    • Read and write access to code and pull requests.
    • +
    • Read access to issues and metadata.
    • +
    +

    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    +
    +
  8. +
  9. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    OrganizationYour GitHub account
    Repositorychoreo-sample-todo-list-app
    Branchmain
    +
  10. +
  11. +

    Select NodeJS as the Buildpack

    +
  12. +
  13. +

    Enter the following information:

    + + + + + + + + + + + + + + + + + + + + + +
    FieldValue
    NodeJS Project Directory/
    Language Version20.x.x
    Port8080
    +
  14. +
  15. +

    Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    +
  16. +
+

Now let's build and deploy the web application.

+

Step 3: Build your web application

+

To build the web application, follow the steps given below:

+
    +
  1. In the left navigation menu, click Build.
  2. +
  3. +

    In the Builds pane, click Build Latest.

    +
    +

    Note

    +

    Building the component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    +
    +
  4. +
+

Now you can proceed to deploy your web application.

+

Step 4: Deploy and access your web application

+
    +
  1. In the left navigation menu, click Deploy.
  2. +
  3. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can add a file mount if necessary. In this guide you will not add a file mount.
  4. +
  5. Click Deploy. The deployment to the Development environment may take a few minutes to complete. On successful deployment, you will see the Deployment Status as Active in the Development card.
  6. +
  7. To verify that you have successfully hosted the web application, click the Web App URL on the Development card. This takes you to the web application. You can try creating one or more new tasks by specifying an appropriate task ID and task label.
  8. +
+

After you have successfully tested your web application, you can now try out various other Choreo features such as observability, DevOps, etc., similar to any other component type within Choreo.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quick-start-guides/expose-a-service-as-a-managed-api-with-choreo-api-manager/index.html b/quick-start-guides/expose-a-service-as-a-managed-api-with-choreo-api-manager/index.html new file mode 100644 index 000000000..91cc4aadf --- /dev/null +++ b/quick-start-guides/expose-a-service-as-a-managed-api-with-choreo-api-manager/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/reference/connect-with-protected-third-party-applications/index.html b/reference/connect-with-protected-third-party-applications/index.html new file mode 100644 index 000000000..618e92ae7 --- /dev/null +++ b/reference/connect-with-protected-third-party-applications/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/alerting/index.html b/references/alerting/index.html new file mode 100644 index 000000000..b0b2e108a --- /dev/null +++ b/references/alerting/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/choreo-limitations/index.html b/references/choreo-limitations/index.html new file mode 100644 index 000000000..d9e1e6c2a --- /dev/null +++ b/references/choreo-limitations/index.html @@ -0,0 +1,3582 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo Limitations - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Limitations

+

Explore key limitations in Choreo, covering areas like HTTP request parameters, components, applications, and API definition files. You can gain insights into the limitations to enhance your understanding and optimize your use of Choreo effectively.

+

API management limits

+

Below are key limitations when working with APIs in Choreo:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResourceLimit
Maximum request payload10 MB
URL size2 KB
Request header
  • Request Headers total: 40 KB
  • Max Single Request header: 10 KB
Total request duration
  • Minimum: 10 seconds
  • Default: 1 minute
  • Maximum: 5 minutes
Maximum connection duration (WebSocket APIs)15 minutes
Connection idle timeout (WebSocket APIs)5 minutes
Size for API definition (OpenAPI document)10 Mb
Number of APIs for PDP1000 API deployments
Number of APIs per organization (free tier)5 APIs for free users
Number of Developer Portal applications per organization (free tier)10 applications for free users
+

Choreo cloud data plane limits

+

Below are key limitations when working with web applications in the Choreo cloud data plane:

+ + + + + + + + + + + + + + + + + + + + + +
ResourceLimit
Request size limit (including headers, cookies, and payloads)256 KB
Response body size limit20 MB
Number of open ports permitted per web application1
While it is possible to have multiple ports open for project-level communication within a data plane, incoming internet traffic can only be directed to a single port. This contrasts with Service-type components, which allow for multiple endpoints.
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/references/choreo-platform-services-billing/index.html b/references/choreo-platform-services-billing/index.html new file mode 100644 index 000000000..538c8cf9c --- /dev/null +++ b/references/choreo-platform-services-billing/index.html @@ -0,0 +1,3438 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Choreo Platform Services Billing - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Platform Services Billing

+

The platform services you create in your Choreo Organization, such as databases, caches, or Kafka services are billed as part of your existing Choreo subscription. The cost is determined by the usage and service plan of each resource you create.

+

Key billing information:

+
    +
  • Hourly billing: Usage is billed based on the number of hours a resource is active. For example, if you create a database, cache, or Kafka service and remove it within the same month, you only pay for the number of hours it was active.
  • +
  • Fixed pricing: Pricing is based on the selected service plan. Choreo does not charge extra for network bandwidth usage.
  • +
+
+

Try out the free trial

+

Choreo provides a 7-day free trial for all database types on the 'Hobbyist' service plan, available to free-tier users.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/references/connect-with-protected-third-party-applications/index.html b/references/connect-with-protected-third-party-applications/index.html new file mode 100644 index 000000000..a296aff39 --- /dev/null +++ b/references/connect-with-protected-third-party-applications/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/define-configurable-variables/index.html b/references/define-configurable-variables/index.html new file mode 100644 index 000000000..181da5513 --- /dev/null +++ b/references/define-configurable-variables/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/faq/index.html b/references/faq/index.html new file mode 100644 index 000000000..56397d957 --- /dev/null +++ b/references/faq/index.html @@ -0,0 +1,4837 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + FAQ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Frequently Asked Questions

+

General

+

Q: What is Choreo?

+

Choreo is an internal developer platform designed to accelerate the creation of digital experiences. With Choreo, you can effortlessly build, deploy, monitor, and manage your cloud native applications. Our goal is to enhance developer productivity and enable innovation.

+

Q: What is an organization in Choreo?

+

An organization is a logical grouping of users and their resources. It may represent a company, community, or a single user. Users can belong to multiple organizations, and each organization can have different roles assigned to its users to control access to Choreo features.

+

Q: What is a project in Choreo?

+

A project is a logical grouping of related components to help you organize your work. Each project provides runtime isolation through namespaces when you deploy components.

+

Q: What is a component in Choreo?

+

A component is a workload designed to run on Choreo. Examples of components include integrations, APIs, microservices, manual/scheduled jobs, web apps, and triggers.

+

Q: What is the difference between an internal and external API?

+

In Choreo, you can publish an API as an internal or an external API. A user or an application can access an external API publicly over the internet, whereas an internal API is only accessible through other components within the same organization.

+

Q: What is a connector in Choreo Marketplace?

+

A connector is a reusable Ballerina package that simplifies connecting to external or internal systems and APIs, such as Salesforce, SAP, GitHub, and Twilio. You can use the connectors available in the Choreo marketplace to implement your integration use cases. Connectors can be created and published by both WSO2 and Choreo users.

+

Q: What is a trigger in Choreo Marketplace?

+

A trigger is a construct that enables users to receive known event payloads from external systems, facilitating event-driven programming.

+

Q: What is a sample/template in Choreo?

+

A sample or template is a prebuilt Ballerina program that covers a popular integration use case or pattern. Examples include connecting Salesforce to Slack or implementing content-based routing.

+

Q: What are the support options in Choreo?

+

You can find information about our support plans, including free, basic, and enterprise options at https://wso2.com/choreo/customer-support/.

+

Q: How can I perform log monitoring or analytics for the Azure environment?

+

If you have a log monitoring product or service, such as Azure Monitor, you can use it together with Choreo. Note: The log monitoring tool is not included in the infrastructure cost.

+

Q: What is the maximum request payload size supported by Choreo?

+

Choreo allows a maximum request payload size of 10 MB.

+

Q: What source control software does Choreo support?

+

Choreo now supports GitHub, Bitbucket and GitLab.

+

Q: Why don't I see the undeployed builds for my component in Choreo?

+

You are allowed to build your component any number of times. However, Choreo has a limit on retaining undeployed builds. For users on the free-tier, Choreo will retain only one undeployed build. For those on any other tier, Choreo will retain the latest five undeployed builds.

+

Q: What is Ballerina?

+

Ballerina is an open-source programming language designed for the cloud. It simplifies the process of using, combining, and creating network services. When you use Ballerina to write integrations in Choreo, you can save time and deliver 2-3x faster. To learn more, check out https://ballerina.io/.

+

Q: What is Asgardeo?

+

Asgardeo is an identity provider (IdP) that allows developers to secure access for consumers, business partners, employees, and APIs. Asgardeo is Choreo’s default IDP. To learn more, visit https://wso2.com/asgardeo/.

+

Q: Why don’t I see the region selector on the project creation page?

+

If you are a Choreo cloud data plane user, you can create projects in multiple regions only if you have a paid subscription in Choreo. Otherwise, your projects will be created in the same region you selected when onboarding the organization.

+

If you are a private data plane user, there will be no region selector in project creation at all.

+

Q: As a Cloud Data Plane user, how can I create components in multiple data planes?

+

When an organization admin onboards a new organization in Choreo, they can choose the preferred data plane. Choreo then sets the selected data plane as the default for the entire organization. Subsequently, users within the free tier of the cloud data plane can create components only in the set default data plane. If a free-tier user needs to create components in a different data plane, the user must get a paid subscription.

+

Security and data protection

+

Q: How is data managed in Choreo?

+

Choreo manages data using WSO2 containers and Kubernetes clusters, which provide scalability, resilience, and security. Find out more here.

+

Q: What is the WSO2 Subprocessor list?

+

This is a detailed list of all subprocessors used by WSO2, including their name, location, and purpose. This information is updated frequently to ensure compliance with data protection regulations and is found here.

+

Q: How do we secure WSO2 Private and Public Clouds?

+

WSO2 uses a range of security controls and design patterns to protect against several threats, including internal attacks, software supply chain attacks, service and platform attacks, and more. Find out more regarding this here.

+

Q: How can I connect a Choreo component with a protected third-party application?

+

To connect a Choreo component with a third-party application, it is necessary to establish seamless communication between the component and the protected third-party application, especially when connecting to external databases like MySQL, MSSQL, PGSQL, Oracle DB, etc. +To ensure this, the requests coming from the Choreo data plane must be allowed by adding the specific data plane IP ranges to your allowlist.

+
    +
  • +

    If your component is deployed in the Choreo US data plane, add the following IP range to your allowlist:

    +
      +
    • 20.22.170.144/28
    • +
    +
  • +
  • +

    If your component is deployed in the Choreo EU data plane, add the following IP range to your allowlist:

    +
      +
    • 20.166.183.112/28
    • +
    +
  • +
  • +

    If you are working on the Cybertruck Challenge, add the following IP range to your allowlist:

    +
      +
    • 20.190.30.48/28
    • +
    +
  • +
+

Data planes

+

Q: What is a Choreo control plane?

+

The Choreo control plane is a centralized management component that oversees and coordinates the workloads deployed by customers. It provides a unified point of control and visibility for the organization, allowing administrators to manage, monitor, and orchestrate the organization’s resources efficiently.

+

Q: What is a data plane?

+

A data plane in Choreo is a computing environment designed for running customer workloads. These environments are hosted in either a dedicated cloud infrastructure owned by the customer (private data planes) or on public cloud infrastructure owned by WSO2, also known as the Choreo data plane.

+

Q: Which regions support the Choreo data plane(CDP)?

+

The Choreo data plane is currently supported in the US East 2 and North Europe. However, WSO2 is planning to add support for additional regions as needed.

+

Q: Which regions support private data planes(PDPs)?

+

Private data planes can be deployed in any region where Azure and AWS are available and meet the requirements for PDPs.

+

Q: If I want to use my Azure AKS instances as the private data plane, what are the minimum requirements I should meet?

+

We recommend using a minimum of two (2) workload nodes to ensure high availability.

+

Q: Are the Choreo control plane and data planes highly available? Are they running on multiple clusters?

+

The Choreo control plane and data plane are designed for high availability using Azure components like AKS, MSSQL, ACR, KV, Service Bus, and so on, with a high availability of 99.99%, which allows at least three workload nodes. In the event of a node failure or upgrade, this setup provides reliable failover. WSO2 also has a backup and recovery strategy in place, including continuous restore drills. If you require AKS cluster-level redundancy, we can consider multiple zones. In this case, the cost will include an additional infrastructure cost.

+

Environments

+

Q: As a Choreo cloud data plane user, why can't I create environments?

+

You can create environments only if you have a paid subscription in Choreo. It can be either Pay-as-you-Go (PAYG) or an Enterprise plan.

+

Q: I am a Pay-As-You-Go (PAYG) customer using the Choreo cloud data plane. How many environments can I create?

+

You can create up to 5 environments at the organization level, including the existing Development & Production environments by default. If you have projects in both data planes (US & EU), there will be 4 environments already created in total, and you will only be allowed to create one additional environment either in the US or EU data plane.

+

Q: I am an Enterprise subscription customer using the Choreo private data plane. How many environments do I get?

+

As an Enterprise subscription customer, the number of environments you can use is not limited. However, the more environments you use, the more resources you will consume in the data plane for the workload you deploy. This may result in higher infrastructure costs for the private data plane.

+

Q: As a Choreo cloud data plane user, why don’t I see both US & EU data planes in the data plane selector when creating an environment?

+

You will see both US & EU data planes only if you have a paid subscription and have created projects in both US & EU data planes.

+

Q: I am a customer who use Choreo in a private data plane. How many environments can I create?

+

Initially, you will receive the requested number of environments when establishing your private data plane. Subsequently, you can create additional environments as needed.

+

Billing and support

+

Q: Whom do I reach out to if I have a billing question?

+

You can reach out to cloud-billing-support@wso2.com or create a support ticket via our support portal.

+

Q: What's a Developer plan?

+

A Developer plan allows you to try out Choreo’s capabilities at no cost. It’s ideal for proof of concept (PoC) tasks or workloads with limited transactions. This plan allows you to experiment with up to 5 components and provides US$1,000/year of Choreo data plane (CDP) credits.

+

Q: How do I calculate the infrastructure costs?

+

Calculating infrastructure costs depends on the type of workload you want to manage. Here are a few examples:

+
    +
  • Example 1: Managing existing APIs as an API proxy with simple mediation; no additional infrastructure costs.
  • +
  • Example 2: Managing existing APIs as an API proxy with complex mediation and policies; Choreo will deploy 1 x container to handle these mediation and policies at approximately US$57.25 per month per API.
  • +
  • Example 3: Creating, deploying, and managing a new API or integration within Choreo; pay for 1 x component + infrastructure cost. Each container deployed will be approximately US$57.25 per month on the default configuration provided by Choreo. Additional resources will be charged based on the type of resource required.
  • +
  • Example 4: Creating, deploying, and managing a microservice; the same approach as example 3.
  • +
+

Q: What are the component limitations?

+
    +
  • Developer plan: Allows up to a maximum of five free components and unlimited paid components.
  • +
  • PAYG plan: Allows unlimited paid components.
  • +
  • Enterprise plan: Allows unlimited paid components.
  • +
+

Q: How do I read the bill?

+

Your bill will detail the number of components used, infrastructure consumed, support plans used, and any additional services you may have purchased. If you are unsure about any charges on your bill, reach out to choreo-support@wso2.com for clarification.

+

Q: Is support included in the Choreo Enterprise plan?

+

The Choreo Enterprise plan does not automatically include support; however, you can purchase support plans in addition to the Enterprise plan at any time. Find out more at https://wso2.com/choreo/customer-support/.

+

Q: I am an Enterprise subscription customer who wants to use the Choreo private data plane. What costs will I incur in addition to the subscription and support plan?

+

You can start by using a basic plan or contact us for an Enterprise support plan.

+

Q: I want to upgrade from PAYG to an Enterprise subscription. Will there be an outage during the upgrade?

+

No, there are no outages when upgrading a plan.

+

Choreo CLI

+

Q: How do I uninstall the CLI?

+

If you didn't download the binary directly, you can uninstall the CLI by deleting the .choreo directory in the +home directory of your operating system.

+

Q: How do I update the CLI?

+

You can update the CLI by running the following command: +

curl -o- https://cli.choreo.dev/install.sh | bash
+

+

Q: What are the supported component types in the CLI?

+

The Choreo CLI currently supports the following component types: +- Service +- Web Application +- Webhook +- Scheduled Task +- Manual Task

+

Q: How do I get help with a specific command in the CLI?

+

You can get help with a specific command by running the following command: +

choreo <command> --help
+

+

Q: What are the build configurations required when creating components using the CLI?

+

You can configure the component build configurations depending on the component type as follows:

+
choreo create component <name> --project <name> --build-configs='key1=value1,key2=value2'
+choreo create component <name> --project <name> --build-configs='key1=value1' --build-configs='key2=value2'
+
+ +

The build configurations required for existing buildpacks are as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Component TypeBuildpackRequired Configurations
ServicePython +
    +
  • buildPackLangVersion: Language Version
  • +
+
Node.js +
    +
  • buildPackLangVersion: Language Version
  • +
+
Java +
    +
  • buildPackLangVersion: Language Version
  • +
+
Go +
    +
  • buildPackLangVersion: Language Version
  • +
+
PHP +
    +
  • buildPackLangVersion: Language Version
  • +
+
Ruby +
    +
  • buildPackLangVersion: Language Version
  • +
+
Docker +
    +
  • dockerFilePath: Path to the docker file
  • +
+
Ballerina +
    +
  • Not Applicable
  • +
      +
WSO2 MI +
    +
  • Not Applicable
  • +
      +
.Net +
    +
  • buildPackLangVersion: Language Version
  • +
      +
WebappPython +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
Node.js +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
Go +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
PHP +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
Ruby +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
.Net +
    +
  • buildPackLangVersion: Language Version
  • +
  • port: Port
  • +
+
Docker +
    +
  • dockerFilePath: Path to the docker file
  • +
  • port: Port
  • +
+
Static website +
    +
  • Not Applicable
  • +
      +
React +
    +
  • buildCommand: Command to be used for building the component
  • +
  • outputDirectory: Output directory for the component build artifacts
  • +
  • nodeVersion: Node.js version used
  • +
+
Angular +
    +
  • buildCommand: Command to be used for building the component
  • +
  • outputDirectory: Output directory for the component build artifacts
  • +
  • nodeVersion: Node.js version used
  • +
+
Vue +
    +
  • buildCommand: Command to be used for building the component
  • +
  • outputDirectory: Output directory for the component build artifacts
  • +
  • nodeVersion: Node.js version used
  • +
+
WebhookPython +
    +
  • buildPackLangVersion: Language Version
  • +
+
Node.js +
    +
  • buildPackLangVersion: Language Version
  • +
+
Java +
    +
  • buildPackLangVersion: Language Version
  • +
+
Go +
    +
  • buildPackLangVersion: Language Version
  • +
+
PHP +
    +
  • buildPackLangVersion: Language Version
  • +
+
Ruby +
    +
  • buildPackLangVersion: Language Version
  • +
+
Docker +
    +
  • dockerFilePath: Path to the docker file
  • +
+
Ballerina +
    +
  • Not Applicable
  • +
      +
WSO2 MI +
    +
  • Not Applicable
  • +
      +
Scheduled TaskPython +
    +
  • buildPackLangVersion: Language Version
  • +
+
Node.js +
    +
  • buildPackLangVersion: Language Version
  • +
+
Java +
    +
  • buildPackLangVersion: Language Version
  • +
+
Go +
    +
  • buildPackLangVersion: Language Version
  • +
+
.Net +
    +
  • buildPackLangVersion: Language Version
  • +
+
PHP +
    +
  • buildPackLangVersion: Language Version
  • +
+
Ruby +
    +
  • buildPackLangVersion: Language Version
  • +
+
Docker +
    +
  • dockerFilePath: Path to the docker file
  • +
+
Ballerina +
    +
  • Not Applicable
  • +
      +
WSO2 MI +
    +
  • Not Applicable
  • +
      +
Manual TaskPython +
    +
  • buildPackLangVersion: Language Version
  • +
+
Node.JS +
    +
  • buildPackLangVersion: Language Version
  • +
+
Java +
    +
  • buildPackLangVersion: Language Version
  • +
+
Go +
    +
  • buildPackLangVersion: Language Version
  • +
+
.Net +
    +
  • buildPackLangVersion: Language Version
  • +
+
PHP +
    +
  • buildPackLangVersion: Language Version
  • +
+
Ruby +
    +
  • buildPackLangVersion: Language Version
  • +
+
Docker +
    +
  • dockerFilePath: Path to the docker file
  • +
+
Ballerina +
    +
  • Not Applicable
  • +
      +
WSO2 MI +
    +
  • Not Applicable
  • +
      +
+ + + + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/references/handle-non-ballerina-files-in-choreo/index.html b/references/handle-non-ballerina-files-in-choreo/index.html new file mode 100644 index 000000000..e0f627126 --- /dev/null +++ b/references/handle-non-ballerina-files-in-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/manage-connectors/index.html b/references/manage-connectors/index.html new file mode 100644 index 000000000..30c9cc46b --- /dev/null +++ b/references/manage-connectors/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/performance-analysis/index.html b/references/performance-analysis/index.html new file mode 100644 index 000000000..134164328 --- /dev/null +++ b/references/performance-analysis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/references/private-data-plane-management-models/index.html b/references/private-data-plane-management-models/index.html new file mode 100644 index 000000000..a2d8a0277 --- /dev/null +++ b/references/private-data-plane-management-models/index.html @@ -0,0 +1,4009 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Private Data Plane Management Models - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Private Data Plane Management Models

+

Choreo supports various management models for private data planes (PDPs), fostering collaboration between WSO2 and customers across diverse scenarios. The following sections provide insights into WSO2's fully managed solutions and shared responsibility models, allowing you to make informed decisions regarding cloud-based operations and security.

+

WSO2 fully managed (infrastructure and PDP in WSO2 subscription) model

+

WSO2 fully managed private data planes are supported only on Azure, AWS, and GCP cloud providers.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TaskTask descriptionResponsible partyAccountableConsultedInformed
Subscription prerequisites- Create subscriptions
+ - Check quota and service limits
+ - Run the Choreo compatibility prerequisite script
WSO2WSO2Customer (If required)Customer (If required)
Remote access for installationProvide owner accessWSO2WSO2WSO2WSO2
Network management- Obtain customers backend CIDR in case of VPN/peering
+ - Check end-to-end connectivity (primary and failover)
WSO2/CustomerWSO2/CustomerCustomerCustomer
Firewall rules/access controlSet up firewall and required rules depending on the security tierWSO2WSO2CustomerCustomer
Infrastructure provisioning- Provision Bastion
+ - Provision Kubernetes clusters
WSO2WSO2-Customer(If required)
Kubernetes cluster management- Manage Kubernetes versions
+ - Increase node pool size
WSO2WSO2CustomerCustomer
Infrastructure monitoringSet up alertsWSO2WSO2-Customer(If required)
DNS management for Choreo system- Manage DNS infrastructure
+ - Manage SSL certificates for Choreo system components
WSO2/CustomerWSO2/CustomerCustomerCustomer
Choreo system components deploymentSet up PDP agents via HelmWSO2WSO2--
Choreo system components managementUpgrade/patch/debug versionsWSO2WSO2-Customer(If required)
Choreo system components monitoring- Set up continuous monitoring 24x7
+ - Provide monthly uptime reports
WSO2WSO2-Customer
Choreo system security monitoringIf basic tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security (Image scanning, SAST)
+ - Manage security incidents
+ If standard tier/premium tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security
+ - Monitor runtime security alerts (Azure Defender)
+ - Monitor security incident and event management (SIEM) alerts
+ - Manage security incidents
+ - Adhere to compliance standards
WSO2/CustomerWSO2/CustomerWSO2/CustomerWSO2/Customer
Choreo application creation/deploymentCustomerCustomerCustomerCustomer
Choreo application managementCustomerCustomerCustomerCustomer
Choreo application monitoringCustomerCustomerCustomerCustomer
Choreo application logsCustomerCustomerCustomerCustomer
+ +

WSO2 fully managed (infrastructure and PDP in customer subscription) model

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TaskTask descriptionResponsible partyAccountableConsultedInformed
Subscription prerequisites- Create subscriptions
+ - Check quota and service limits
+ - Run the Choreo compatibility prerequisite script
CustomerCustomerWSO2-
Remote access for installationProvide accessCustomerCustomerWSO2WSO2
Network management- Obtain customers backend CIDR in case of VPN/peering
+ - Check end-to-end connectivity (primary and failover)
WSO2/CustomerWSO2/CustomerCustomerCustomer
Firewall rules/access controlSet up firewall and required rules depending on the security tierWSO2/CustomerWSO2/CustomerCustomerCustomer
Infrastructure provisioning- Provision Bastion
+ - Provision Kubernetes clusters
WSO2WSO2CustomerCustomer
Kubernetes cluster management- Manage Kubernetes versions
+ - Increase node pool size
WSO2WSO2CustomerCustomer
Infrastructure monitoringSet up alertsWSO2WSO2-Customer(If required)
DNS management for Choreo system- Manage DNS infrastructure
+ - Manage SSL certificates for Choreo system components
WSO2/CustomerWSO2/CustomerCustomerCustomer
Choreo system components deploymentSet up PDP agents via HelmWSO2WSO2Customer-
Choreo system components managementUpgrade/patch/debug versionsWSO2WSO2-Customer(If required)
Choreo system components monitoring- Set up continuous monitoring 24x7
+ - Provide monthly uptime reports
WSO2WSO2-Customer
Choreo system security monitoringIf basic tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security (Image scanning, SAST)
+ - Manage security incidents
+ If standard tier/premium tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security
+ - Monitor runtime security alerts (Azure Defender)
+ - Monitor security incident and event management (SIEM) alerts
+ - Manage security incidents
+ - Adhere to compliance standards
WSO2/CustomerWSO2/CustomerWSO2/CustomerWSO2/Customer
Choreo application creation/deploymentCustomerCustomerCustomerCustomer
Choreo application managementCustomerCustomerCustomerCustomer
Choreo application monitoringCustomerCustomerCustomerCustomer
Choreo application logsCustomerCustomerCustomerCustomer
+ +

Customer self-managed (WSO2 provides installation script and updates) model

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TaskTask descriptionResponsible partyAccountableConsultedInformed
Subscription prerequisites- Create subscriptions
+ - Check quota and service limits
+ - Run the Choreo compatibility prerequisite script
CustomerCustomerWSO2WSO2
Remote access for installationProvide owner accessCustomerCustomerWSO2-
Network management- Obtain customers backend CIDR in case of VPN/peering
+ - Check end-to-end connectivity (primary and failover)
CustomerCustomerWSO2WSO2
Firewall rules/access controlSet up firewall and required rules depending on the security tierCustomerCustomerWSO2WSO2
Infrastructure provisioning- Provision Bastion
+ - Provision Kubernetes clusters
CustomerCustomerWSO2WSO2(If required)
Kubernetes cluster management- Manage Kubernetes versions
+ - Increase node pool size
CustomerCustomerWSO2WSO2(If required)
Infrastructure monitoringSet up alertsCustomerCustomerWSO2-
DNS management for Choreo system- Manage DNS infrastructure
+ - Manage SSL certificates for Choreo system components
CustomerCustomerWSO2-
Choreo system components deploymentSet up PDP agents via HelmCustomerCustomerWSO2-
Choreo system components managementUpgrade/patch/debug versionsCustomerCustomerWSO2-
Choreo system components monitoring- Set up continuous monitoring 24x7
+ - Provide monthly uptime reports
CustomerCustomerWSO2-
Choreo system security monitoringIf basic tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security (Image scanning, SAST)
+ - Manage security incidents
+ If standard tier/premium tier
+ - CSPM
+ - Apply security patches
+ - Manage supply chain security
+ - Monitor runtime security alerts (Azure Defender)
+ - Monitor security incident and event management (SIEM) alerts
+ - Manage security incidents
+ - Adhere to compliance standards
WSO2/CustomerWSO2/CustomerWSO2/CustomerWSO2/Customer
Choreo application creation/deploymentCustomerCustomerCustomerCustomer
Choreo application managementCustomerCustomerCustomerCustomer
Choreo application monitoringCustomerCustomerCustomerCustomer
Choreo application logsCustomerCustomerCustomerCustomer
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/references/private-data-plane-security-levels/index.html b/references/private-data-plane-security-levels/index.html new file mode 100644 index 000000000..dfbb16020 --- /dev/null +++ b/references/private-data-plane-security-levels/index.html @@ -0,0 +1,3530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Private Data Plane Security Levels - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Private Data Plane Security Levels

+

The following table outlines the private data plane security levels supported in Choreo:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Basic tierStandard tierPremium tier
Distributed denial-of-service (DDoS) protection basic *Distributed denial-of-service (DDoS) protection basic *Distributed denial-of-service (DDoS) protection premium *
Controlled admin access *Controlled admin access *Controlled admin access *
End-to-end data encryption in transitEnd-to-end data encryption in transitEnd-to-end data encryption in transit
Data encryption at rest *Data encryption at rest *Data encryption at rest *
Secret managementSecret managementSecret management
Foundational CSPM *Foundational CSPM *Premium CSPM *
Static application security testing (SAST)Static application security testing (SAST)Static application security testing (SAST)
Infrastructure as code (IaC) scanningInfrastructure as code (IaC) scanningInfrastructure as code (IaC) scanning
Software composition analysisSoftware composition analysisSoftware composition analysis
Docker image security scanningDocker image security scanningDocker image security scanning
N/AKubernetes runtime protection *Kubernetes runtime protection *
N/AWeb application firewall (WAF) *Web application firewall (WAF) *
N/AN/ANetwork firewall *
+ +

* Not available in the on-premises private data plane.

+
+

Tip

+

Available add-ons:
+ - Security incident and event management (SIEM).
+ - 24/7 security operation center.

+
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/references/troubleshoot-choreo/index.html b/references/troubleshoot-choreo/index.html new file mode 100644 index 000000000..10e2bb965 --- /dev/null +++ b/references/troubleshoot-choreo/index.html @@ -0,0 +1,3890 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Troubleshoot Choreo - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Troubleshoot Choreo

+

This page walks you through common problems you may encounter when building and deploying components with Choreo, along with the recommended solutions to resolve each issue.

+

Troubleshoot component build errors

+
    +
  • +

    Deploying an Angular web application displays the Nginx welcome page instead of the application's homepage.

    +

    This occurs due to specifying an incorrect build output directory when you set up your Angular application in Choreo. +To resolve the issue, follow the guidelines given below:

    +
      +
    • Ensure that the build output directory correctly points to where your Angular build script outputs the files. The deafult output directory is dist/<project-name>.
    • +
    • Make sure to reconfigure the build settings if the current configuration is incorrect.
    • +
    +
  • +
  • +

    An error occurs in the container Trivy scan when building a BYOC component.

    +

    The recommended approach to address this issue is to fix the identified vulnerability and rebuild the component.

    +

    However, if you want to add a .trivyignore file to overcome the issue, ensure to add it to the Docker build context path specified when creating the component. For example, {buildContextPath}./trivyignore.

    +
  • +
  • +

    The config.js file is not properly mounted in a web application.

    +

    To resolve this issue, follow the steps given below:

    +
      +
    1. Add the config.js file to the app/public directory in your repository.
    2. +
    3. +

      Reference it from the index.html file by adding a script tag as follows:

      +

      <script src="public/config.js"></script>

      +
    4. +
    +
  • +
+

Troubleshoot component deployment errors

+
    +
  • +

    The config.js file is not properly integrated during the deployment of a React application, causing it to render with unexpected HTML instead of the expected JavaScript configuration.

    +

    To ensure correct loading of the config.js file, follow the steps given below:

    +
      +
    • +

      Reference the config.js file from the index.html file of your application by adding a script tag as follows:

      +

      <script src="public/config.js"></script>

      +
    • +
    • +

      Verify that the path in the script tag matches the location where the config.js file is stored in your repository.

      +
    • +
    • Make sure the script tag is placed within the <body> tag in your index.html file. You must ensure that it is not mistakenly placed within another HTML element.
    • +
    +
  • +
  • +

    I'm not aware of the commits that can trigger an automatic build in Choreo.

    +

    Merge commits and commits pushed directly to the branch can trigger a build in Choreo.

    +
  • +
+

Troubleshoot web application issues

+
    +
  • +

    After building a web application, the Nginx welcome page is displayed instead of the web application home page.

    +

    This can happen if an incorrect build output directory is specified during component creation.

    +

    During the build process, output files including the index.html are copied to the Nginx root directory. To ensure that the correct files are copied during the build process, you must check the Docker build logs.

    +
  • +
  • +

    The language I prefer to use is not available as a buildpack.

    +

    In such scenarios, you can use the Dockerfile buildpack to create the component.

    +
  • +
  • +

    I mistakenly used an incorrect build command when creating a web application. How can I update it before triggering a build?

    +

    You can go to the build page of the component and update the build command in the build configurations section.

    +
  • +
+

Troubleshoot managed-authentication issues

+
    +
  • +

    After securing a web application with managed authentication, I’m not able to add users who can sign in to the application.

    +

    For step-by-step instructions on how to manage users with Choreo's built-in identity provider (IdP), see Configure a User Store with the Built-In IdP.

    +

    For details on setting up other OpenID Connect (OIDC) supported IdPs, see Manage OAuth Keys.

    +
  • +
+

Troubleshoot Tailscale proxy issues

+
    +
  • +

    Where can I find logs to troubleshoot Tailscale proxy issues?

    +

    To troubleshoot Tailscale proxy issues, you can view the Runtime Logs of the running container for your Tailscale proxy deployment. These logs can help you diagnose most of the issues. + You can also view real-time container logs via the Runtime page under DevOps. For more details, see Observe real-time container logs.

    +
  • +
  • +

    I'm not able to connect the Tailscale proxy node to my Tailscale network due to an authentication failure.

    +
      +
    • +

      If you encounter the following log lines in your Tailscale proxy deployment, it indicates a misconfiguration of the TS_AUTH_KEY:

      +

      2024-06-04T10:38:53.885800940Z To authenticate, visit:
      +2024-06-04T10:38:53.885802684Z 
      +2024-06-04T10:38:53.885815708Z https://login.tailscale.com/a/696841f011517
      +2024-06-04T10:38:53.885817457Z 
      +2024-06-04T10:38:55.194344862Z Waiting for tailscale up to complete...
      +2024-06-04T10:38:57.198970796Z Waiting for tailscale up to complete...
      +2024-06-04T10:38:59.203265659Z Waiting for tailscale up to complete...
      +
      +To resolve this, you must re-check your authentication key and ensure you have entered the correct key.

      +
    • +
    • +

      If you encounter the following log lines in your Tailscale proxy deployment, it indicates that your authentication key is invalid or expired. +

      2024-06-04T11:33:58.762363181Z 2024/06/04 11:33:58 Received error: invalid key: unable to validate API key
      +2024-06-04T11:33:58.762458209Z backend error: invalid key: unable to validate API key
      +

      +

      To resolve this, you must verify the correctness of your authentication key. If the key has expired, you must generate a new key from Tailscale admin console.

      +
    • +
    +
  • +
  • +

    I'm not able to access private endpoints although the Tailscale proxy is properly connected to my Tailscale network.

    +

    To resolve this, do the following:

    +
      +
    • Ensure your on-premises setup is properly connected to the Tailscale network and that specific services, database servers, etc., are running as expected in your on-premises setup.
    • +
    • Verify that the IP addresses and ports specified in your Config.yaml file (mounted to Tailscale proxy during deployment) match the IP addresses in your Tailscale network.
    • +
    • Cross-check the ports defined in the endpoints.yaml file with the port mappings in the Config.yaml file.
    • +
    +
  • +
+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/kubernetes-upgrade-notice/index.html b/resources/kubernetes-upgrade-notice/index.html new file mode 100644 index 000000000..609de44df --- /dev/null +++ b/resources/kubernetes-upgrade-notice/index.html @@ -0,0 +1,3477 @@ + + + + + + + + + + + + + + + + + + + + + + + + Choreo Kubernetes Infrastructure Upgrade Notice - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
+ + +
+ +
+ + + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +

Choreo Kubernetes Infrastructure Upgrade Notice

+

Upgrade Date: September 4, 2023, from 3:00 a.m. to 6:00 a.m. UTC

+

An upcoming upgrade to the Choreo Kubernetes infrastructure is scheduled to take place on September 4, 2023.

+

Impact on Java-based Components

+

This upgrade is geared towards enhancing the performance and capabilities of our platform. However, it's important to note that there might be an impact on Java-based components in terms of memory usage. Specifically, applications relying on Java Runtime versions older than jdk8u372 or 11.0.16 could experience out-of-memory errors due to potential memory consumption increases resulting from the upgrade.

+

Affected Component Types

+

The following Choreo component types could be affected:

+
    +
  • Components created using the Ballerina preset (For example, Service, Webhook, Scheduled trigger, Manual Trigger components).
  • +
  • Integration components created using the WSO2 Micro Integrator preset (For example, Integration as an API, Event-triggered integration, Manually-triggered integration, and Scheduled integration components).
  • +
  • REST API Proxies that include mediation policies.
  • +
  • Components created using the Dockerfile preset (Components created with containerized applications utilizing the Java Runtime).
  • +
+

Action Required

+

Recommended action date: Before September 4, 2023, 3:00 a.m. UTC

+

To ensure a smooth transition and compatibility with the updated Java Runtime version, follow the steps below:

+
    +
  • +

    Ballerina or Micro Integrator-based components: If you have created components using the Ballerina preset or the MI preset, we strongly advise you to redeploy your components before we initiate the upgrade. In the deployment pipeline, we will build your component using the latest Java version.

    +
  • +
  • +

    REST API Proxy components that include mediation policies: If you have created REST API Proxy components and attached a mediation policy, we strongly advise you to redeploy your components before we initiate the upgrade. In the deployment pipeline, we will build your component using the latest Java version.

    +
  • +
  • +

    Other Java-based containerized components: If you have components created using the Dockerfile preset that includes containerized applications utilizing the Java Runtime, follow the steps below:

    +
      +
    1. Upgrade your Java version to OpenJDK / HotSpot - jdk8u372, 11.0.16, 15, or later.
    2. +
    3. Rebuild your containerized application.
    4. +
    5. Redeploy your containerized component.
    6. +
    +
  • +
+

Redeploy a component in Choreo

+

To redeploy your component, follow the steps given below:

+
    +
  1. Go to https://console.choreo.dev/, and sign in using your preferred login method.
  2. +
  3. Select your component from Components Listing. This will open the overview page of your component.
  4. +
  5. In the left navigation menu, click Deploy.
  6. +
  7. Deploy your component via the Build Area card.
  8. +
+

For more information, refer to this document.

+ + + + + + +
+
+ + +
+ + + +
+ + +
+ + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rest-api/index.html b/rest-api/index.html new file mode 100644 index 000000000..3702b71cb --- /dev/null +++ b/rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/scheduled-tasks/index.html b/scheduled-tasks/index.html new file mode 100644 index 000000000..1e3d20c85 --- /dev/null +++ b/scheduled-tasks/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/search-results.html b/search-results.html new file mode 100644 index 000000000..3e756c53b --- /dev/null +++ b/search-results.html @@ -0,0 +1,289 @@ + + + + + + + + + + + + Search Results + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + +
+ +
+ + +
+
+ + +
+
+
+ +
+ +
+
+
+ + + + + + + + diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 000000000..70ed08cb6 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"Welcome to the Choreo Learning Portal

NoteThe Home page will be designed to provide a guided experience to any user coming to docs with a valid Choreo use case. We intend to ONLY INCLUDE conceptual information in the documentation for the relevant topics and **NOT INCLUDE** any how to guides, or instructions with the exception of Tutorials.

"},{"location":"page-not-found/","title":"Page not found","text":"

Try one of the navigation links above or use the search engine in the top right corner.\u00a0

"},{"location":"what-is-choreo/","title":"What is Choreo?","text":"

Choreo is an internal developer platform that redefines how you create digital experiences. Choreo empowers you to seamlessly design, develop, deploy, and govern your cloud native applications, unlocking innovation while reducing time-to-market.

The following are some of the cutting-edge capabilities of Choreo:

  • Design that leads to end-to-end security, governance, and operational efficiency:

    • Domain-driven design: Organize your enterprise systems into domains, exposing managed APIs, events, and data through projects., A project consists of components representing units of deployment.
    • Application security design: Cell-based architecture, where projects become governable units from development to deployment, ensuring managed access via APIs, events, and data.
  • Efficient and effective development:

    • Code in any language: Develop applications in your team's preferred programming language, harnessing existing skill sets to build powerful polyglot APIs, services, events, tasks, and more.
    • Native support for VS Code: Seamlessly collaborate and manage code using VS Code in a feature-rich, visually-enhanced development environment.
    • Git repository integration: Effortlessly connect to Git-based platforms like GitHub, Bitbucket, or GitLab to develop components by linking an existing repository.
  • Seamless deployment:

    • CI/CD: Eliminate manual builds and unreliable deployments with Choreo's industry-standard CI/CD tooling, providing complete control and flexibility.
    • Multi-cloud Kubernetes: Easily deliver cloud native applications across Azure, AWS, GCP, or your Kubernetes clusters.
    • Configuration management: Centralize configuration parameters, sensitive credentials, and secrets across deployment environments via an intuitive interface.
  • Effortless management of APIs, integrations, microservices, and web applications:

    • Enable security: Empower security teams to manage data flows, ensuring seamless control over sensitive information like access credentials.
    • Scale up or down: Kubernetes handles scaling automatically, optimizing costs by scaling services based on demand.
    • Ensure reliability: DevOps and SRE teams can easily manage deployed components with built-in insights and observability.
  • Reusable digital assets:

    • Control visibility and sharing: Publish your digital assets to a shared marketplace for consumption by internal or external stakeholders, managed by role-based access control.
    • Internal Marketplace: Choreo's secure internal marketplace fosters transparency and efficiency with granular access control for publishers and consumers.
  • Comprehensive observability:

    • Anomaly detection: Stay ahead of issues with prompt notifications, ensuring balanced scaling and immediate action during unexpected mishaps.
    • Troubleshoot and debug: Quickly pinpoint and address root causes using detailed logs and data aligned in the same timeline, down to the machine-level details.
  • Robust governance:

    • DORA metrics: Monitor your DevOps efficiency with Choreo DORA metrics, experiencing rapid improvements in time from deployment to production safely and robustly.
    • Engineering insights: Gain visibility into engineering insights and advanced data analytics to make data-driven decisions, optimize processes, and improve efficiency.
    • API analytics: Understand API performance and adoption patterns to identify and resolve operational bottlenecks.
"},{"location":"administer/configure-a-custom-domain-for-your-organization/","title":"Configure a Custom Domain for Your Organization","text":"

A custom domain is essential for effective branding, discoverability, and credibility of a website. Choreo allows you to easily configure custom domains for your organization, enabling developers to utilize it to configure custom URLs for their components such as API proxies, services, web applications, and webhooks.

This section provides an overview of Choreo\u2019s custom domain configuration model and guides you through configuring a custom domain for your organization. It also walks you through utilizing a custom domain to configure a custom URL for a component.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#choreo-custom-domain-configuration-model","title":"Choreo custom domain configuration model","text":"

Choreo allows organization administrators to add custom domains for their organizations. When an administrator adds custom domains to an organization, component developers can submit requests to utilize the custom domains for their respective components. These requests require approval from the organization administrator. Upon approval, the custom domain and the relevant URL customization become available to the component.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#configure-a-custom-domain-for-an-organization","title":"Configure a custom domain for an organization","text":""},{"location":"administer/configure-a-custom-domain-for-your-organization/#prerequisites","title":"Prerequisites","text":"
  1. Sign in to the Choreo Console.
  2. Create an organization in Choreo.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#add-a-custom-domain","title":"Add a custom domain","text":"

To add a custom domain for your organization, follow the steps given below:

Note

To add a custom domain, you must have organization administrator privileges.

  1. Sign in to the Choreo Console.
  2. In the Choreo Console header, click the Organization list.
  3. In the left navigation menu, click Settings. This opens the organization-level settings page.
  4. Click the URL Settings tab and then click the Active Domains tab.
  5. Click + Add Domains.
  6. In the Add a Custom Domain pane, do the following:

    1. Enter your domain name.
    2. Select the environment to apply the domain name.
    3. Select the entity type to apply the domain name.

      Tip

      In this context:

      • The API entity type represents Choreo components exposed via an endpoint, including API Proxy, Service, and Webhook components.
      • The Web App entity type represents the Web Application component.
  7. Take a look at the generated CNAME target value displayed and create a DNS record associating the domain name to the CNAME target value with your DNS provider.

    Info

    When you select Developer Portal as the type, the environment is not applicable, and the CNAME alias will be displayed as follows:

  8. Once the CNAME type DNS record is created, click Verify.

    Note

    If the CNAME mapping is correct, the verification completes successfully. It can take some time for the configured CNAME mapping to be globally available.

  9. On successful verification of the custom domain, click Next.

  10. Select a TLS certificate provider depending on your preference. You can either import the TLS certificates you created for the custom domain or click Let's Encrypt to allow Choreo to generate and manage the certificates for you.

    If you want to import your own certificate, it should adhere to specific guidelines

    • TLS certificate guidelines:
      • It should be issued by a certificate authority (CA) and should contain the domain's public key along with additional information such as the domain name, the company that owns the domain, the certificate's expiration date, and the digital signature of the issuing CA.
      • It should be an X509 certificate.
      • It should be in the PEM format.
      • It should be issued directly or through a wildcard entry for\u00a0the provided custom URL. For example,
        • For direct issuance, the SSL file must include the exact domain name. For example, if the domain is apis.choreo.dev, the SSL file must include apis.choreo.com.
        • For wildcard entries, the SSL file should use a wildcard notation to cover all subdomains under the provided URL. For example, if the CNAME is apis.choreo.dev, the SSL file should use *.choreo.dev.
    • TLS key file guidelines:
      • It should be in the PEM format.
      • It must be encrypted using RSA encryption.
    • Certificate chain file guidelines:
      • The chain file, which is essential for some clients to verify the authenticity of a server's SSL/TLS certificate, should contain your domain's SSL/TLS certificate (optional, as this can be provided via the certificate itself) and one or more intermediate certificates in the correct order, leading back to a root certificate.
      • All certificates in the chain should be X509 certificates in PEM format.

    To proceed with this step in this guide, click Let's Encrypt.

  11. To save the custom domain, click Add.

Now, you have successfully added a custom domain for your organization.

You can see the added custom domain listed in the Active Domains tab under the URL Settings tab.

The custom domain you added will be available to the entity types in the specified environment. You can request the custom domain when configuring a custom URL for a component.

Note

If you add a custom domain for the Developer Portal type, the customization is applied immediately, and you can access the organization\u2019s Developer Portal via the added domain.

If you want to view the entity types that use a particular custom domain, click the specific custom domain listed in the Active Domains tab under URL Settings.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#configure-a-custom-url-for-a-component","title":"Configure a custom URL for a component","text":"

When an organization administrator adds custom domains for specific environments, developers can request any available custom domain to configure a custom URL for a component in a specific environment.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#request-a-custom-url-for-a-component","title":"Request a custom URL for a component","text":"

To request a custom URL for your component, follow the steps given below:

Note

Before you request a custom domain for a specific environment, ensure that the component is deployed to that environment.

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the component for which you want to customize the URL.
  3. In the left navigation menu, click Settings. This opens the component-level settings page.
  4. Click the URL Settings tab. This displays the active deployments of the component across different environments and indicates whether a custom URL is configured. If an active custom domain is available to configure a custom URL for a component in a specific environment, the Edit URL Mapping icon in the corresponding Action column becomes enabled.

  5. To configure a custom URL for a component in a specific environment, click the Edit URL Mapping icon under the Action column corresponding to the respective environment. This opens the URL Settings dialog, where you can specify values to request for a custom URL.

  6. In the URL Settings dialog, select a domain to configure a custom URL.

    Tip

    • The Domain drop-down lists the available domains for the component. You can request for any listed domain.
    • If you want to request a custom URL for an API, you must specify an appropriate context path in the Path field. The Path field displays the default context path for the API. You can edit the path depending on your preference.
  7. Click Configure. This creates the custom URL mapping, which you can see under the URL Settings tab. The custom URL request will be in the Pending status until an organization administrator approves the request.

"},{"location":"administer/configure-a-custom-domain-for-your-organization/#approve-a-custom-url-request","title":"Approve a custom URL request","text":"

When a developer requests a custom URL, the request will be listed in the organization-level settings page under the URL Settings tab.

To approve a custom URL mapping, follow the steps given below:

Note

To approve custom URL requests, you must have organization administrator privileges.

  1. Sign in to the Choreo Console.
  2. In the Choreo Console header, click the Organization list.
  3. In the left navigation menu, click Settings. This opens the organization-level settings page.
  4. Click the URL Settings tab and then click the Pending URL Requests tab. You will see all the pending URL mapping requests sent by developers.

  5. Go to the custom URL you want to approve and click the corresponding Approve URL Mapping icon under the Action column.

  6. Review the details and click Approve.

Once approved, the invoke URL of the component gets replaced with the configured custom URL.

Now you have successfully utilized the configured custom domain to set up a custom URL for a component.

"},{"location":"administer/configure-a-user-store-with-built-in-idp/","title":"Configure a User Store with the Built-In Identity Provider","text":"

Developers looking to experiment with a complete application development process that includes user authentication and authorization can utilize Choreo's built-in identity provider (IdP). Choreo's built-in identity provider allows you to seamlessly test your application's authentication by setting up test users and groups within Choreo.

Note

Although the built-in IdP facilitates user management support, it is limited to adding users with attributes and groups. Therefore, the built-in IdP user management capabilities are not recommended for use in production.

"},{"location":"administer/configure-a-user-store-with-built-in-idp/#prerequisites","title":"Prerequisites","text":"

Before you try out the steps in this guide, be sure you have administrator rights to your Choreo organization. This permission is essential to configure a user store with the built-in IdP.

"},{"location":"administer/configure-a-user-store-with-built-in-idp/#configure-a-choreo-built-in-idp-user-store","title":"Configure a Choreo built-in IdP user store","text":"

Follow the steps given below to configure a Choreo built-in IdP user store for an environment:

  1. Go to https://console.choreo.dev/ and sign in.
  2. In the Choreo Console top navigation menu, click the Organization list and then click on your organization.
  3. In the left navigation menu, click Settings. This takes you to your organization settings.
  4. Click the Application Security tab and then click the Identity Providers tab.
  5. On the Identity Providers tab, click Manage in the Choreo Built-in Identity Provider pane.
  6. In the Manage IdP pane, click on a specific environment tab depending on where you want to configure the built-in IdP user store.
  7. You can download the sample User store template file(.csv ) from the User Store section. The template file content is similar to the following:
username,password,groups,first_name,last_name,email\n\"demouser\",\"password1\",\"[manager, engineering]\",\"John\",\"Doe\",\"john@acme.org\"\n

Note

The provided template file includes a sample user with associated attributes. To add new users, insert additional rows in the .csv file. To include more user attributes, add columns as required in the .csv file.

  1. Specify appropriate user details in the template file and save it.
  2. Select the template file that you saved and click Upload. A successful upload creates the user store and displays the configured users in the Users section.
"},{"location":"administer/configure-approvals-for-choreo-workflows/","title":"Configure Approvals for Choreo Workflows","text":"

Choreo allows you to configure approval processes for specific workflows within the platform. An approval process for a workflow ensures that critical or sensitive changes are properly managed and controlled.

Choreo currently allows you to configure approvals for environment promotion workflows, with support for API subscription approvals coming soon.

"},{"location":"administer/configure-approvals-for-choreo-workflows/#permissions-to-review-and-respond-to-approval-requests","title":"Permissions to review and respond to approval requests","text":"

To review and respond to approval requests, a user must have the following permissions. Administrators must ensure that users designated to review and respond to approval requests have these permissions:

  • WORKFLOW-MANAGEMENT: Grants access to view and approve workflow requests. Each workflow type has a separate permission.
  • PROJECT-MANAGEMENT: Grants access to view and approve workflow requests. This is the same permission used to update or delete projects.
"},{"location":"administer/configure-approvals-for-choreo-workflows/#set-up-an-approval-process-for-a-workflow","title":"Set up an approval process for a workflow","text":"

To set up an approval process for a workflow, follow these steps:

Note

  • You must have administrator privileges in Choreo to configure workflow approvals.
  • Administrators can designate specific roles and assignees to review and respond to requests associated with each workflow.
  1. Sign in to the Choreo Console.
  2. In the Choreo Console header, go to the Organization list and select your organization.
  3. In the left navigation menu, click Settings. This opens the organization-level settings page.
  4. Click the Workflows tab.
  5. Click the edit icon corresponding to the workflow for which you want to configure an approval.
  6. In the Configure Workflow dialog that opens, select roles and assignees to review and respond to workflow approval requests.

    • In the Roles field, select one or more roles depending on your preference. Any user assigned to these roles can review and respond to requests.
    • In the Assignees field, select specific users who can review and approve workflow requests. Assignees can be any Choreo user, even if they are not assigned to a selected role.

    Important

    Currently, there is no validation to ensure that the specified roles and assignees have the necessary permissions to review and respond to requests. If the required permissions are not correctly configured, some users may receive email notifications but will be unable to review the requests.

  7. Click Save. This configures and enables the approval process for the workflow.

Once you configure an approval process for a workflow, developers must submit a request for approval to use the workflow. An authorized assignee must then review and approve the request for a developer to proceed with the task related to the workflow. Depending on the workflow, there can be tasks where the execution may occur automatically upon approval.

"},{"location":"administer/configure-enterprise-login/","title":"Configure Enterprise Login","text":"

With Choreo, you can configure enterprise login to allow users from an external identity provider (IdP) to sign in to Choreo seamlessly without changing their credentials.

This guide walks you through the steps to configure enterprise login for your organization in Choreo.

"},{"location":"administer/configure-enterprise-login/#prerequisites","title":"Prerequisites","text":"

Before you proceed with the configuration, set up the following:

  • A valid email domain for your organization.
  • Access the Choreo Console at https://console.choreo.dev/ via your Google, GitHub, or Microsoft account. If you are a new user, create an organization with a unique organization name. For example, \"Stark Industries\".
"},{"location":"administer/configure-enterprise-login/#configure-enterprise-login-for-your-choreo-organization","title":"Configure enterprise login for your Choreo organization","text":"

To configure enterprise login for your Choreo organization, follow the steps given below:

  • If you already have a support account with us, send us your organization name/handle and the email domains specific to your organization through our support portal.

  • If you do not have a support account with us yet, send an email to choreo-help@wso2.com requesting to enable enterprise login for your organization.

    Tip

    Ensure you include the following information in the request:

    • Organization name or handle. For example, \u201cStark Industries\u201d or \u201cstarkindustries\u201d.
    • Email domains specific to your organization. For example, \u201c@stark.com\u201d, \u201c@starkindustries.com\u201d, and \u201c@stark.eu.

    Sample email

    Subject : [Stark Industries] Configure enterprise login

    Hi CS team,

    I need to configure enterprise login for my organization. Can you please do the necessary configurations to proceed?

    My organization details are as follows:

    • Organization name: Stark Industries
    • Organization handle: starkindustries
    • Email domains specific to my organization: \u201c@stark.com\u201d, \u201c@starkindustries.com\u201d, and \u201c@stark.eu\u201d

    Thank you.

    The Choreo support team will perform the necessary configurations and respond to you with a verification code. You must sign in to your domain host account and configure the DNS record for your email domain with the following values:

    Field Value Name/Host/Alias Specify @ or leave it blank Time to Live (TTL) Keep the default value or use 86400 Value/Answer/Destination wso2-domain-verification:<verification_code>

Now, you are ready to bring your own identity to Choreo.

"},{"location":"administer/configure-enterprise-login/#bring-your-own-identity-to-choreo","title":"Bring your own identity to Choreo","text":"

When you create an organization in Choreo, an organization with the same name is provisioned for you in Asgardeo. To bring your own identity to Choreo, you must configure a federated enterprise IdP on Asgardeo in the organization that is provisioned for you.

Follow the steps given below to configure the federated IdP:

  1. Sign in to Asgardeo.
  2. To configure a federated enterprise identity provider for your Asgardeo organization, follow the steps in Asgardeo documentation - Add Standard-Based Login.
  3. In the Asgardeo Console left navigation menu, click Applications. You will see an application named WSO2_LOGIN_FOR_CHOREO_CONSOLE.
  4. Click on the application to edit it.
  5. Click the Sign-in Method tab. You can observe the configured connection.

Now, users in your enterprise IdP can sign in to the Choreo Console using their enterprise IDs.

"},{"location":"administer/configure-enterprise-login/#configure-role-based-access-control-for-enterprise-login","title":"Configure role-based access control for enterprise login","text":"

To streamline the enterprise login process and grant appropriate permission, Choreo provides the flexibility to configure role-based access control for users who reside in an external IdP.

To set up role-based access control for enterprise login within Choreo, follow the steps given below:

"},{"location":"administer/configure-enterprise-login/#prerequisites_1","title":"Prerequisites","text":"

Before you proceed with the configuration, make sure you complete the following:

  1. Configure enterprise login for your organization. For instructions, see Configure enterprise login for your Choreo organization.
  2. Ensure your enterprise identity provider includes the group/role attributes in tokens it sends to Asgardeo via the respective protocol.
  3. Be sure you have administrator privileges in Choreo.
"},{"location":"administer/configure-enterprise-login/#step-1-configure-asgardeo","title":"Step 1: Configure Asgardeo","text":"
  1. Sign in to Asgardeo.
  2. Configure your IdP as an external IdP in Asgardeo. Depending on your IdP, you can select OpenID Connect or SAML as the protocol between Asgardeo and your IdP.

    Note

    If you are using OpenID Connect, configure the requested scopes accordingly for Asgardeo to get the relevant group/role details from the external IdP.

  3. To configure the application, follow the steps given below:

    1. In the Asgardeo Console left navigation menu, click Applications. You will see an application named WSO2_LOGIN_FOR_CHOREO_CONSOLE.
    2. Click on the application to edit it.
    3. Click the Sign-in Method tab.
    4. Configure the IdP for login depending on the protocol you selected:

      • For OpenID Connect, follow the instructions in Enable the OIDC IdP for login.
      • For SAML, follow the instructions in Enable the SAML IdP for login.
    5. Click the User Attributes tab.

    6. Select the Groups attribute and click the arrow to expand the section. Then, select the Requested checkbox.
    7. Click Update.
  4. To add the user attributes as OpenID Connect scopes, follow the steps given below:

    1. In the Asgardeo Console left navigation menu, click Scopes.
    2. In the OpenID Connect Scopes pane, click OpenID to edit it.
    3. Click New Attribute and select the Groups attribute.
    4. Click Save and then click Save Changes.
"},{"location":"administer/configure-enterprise-login/#step-2-map-choreo-groups-to-enterprise-idp-groups-via-the-choreo-console","title":"Step 2: Map Choreo groups to enterprise IdP groups via the Choreo Console","text":"

Note

Before you map Choreo groups to enterprise IdP groups, ensure you meet the following criteria:

  • Asgardeo is your key manager.
  • You have permission to perform actions of the organization administrator role.
  1. Sign in to the Choreo Console.
  2. In the Choreo Console, go to the top navigation menu and click Organization. This takes you to the organization's home page.
  3. In the left navigation menu, click Settings. This opens the organization-level settings page.
  4. In the Access Control tab, click Groups.
  5. Click Manage IdP Group Mapping.

  6. Click the edit icon corresponding to the Choreo group you want to map to the enterprise IdP group.

  7. In the IdP Group Name field, specify the exact name you configured in the enterprise IdP and enter to add it.

    Tip

    If there is a change to the IdP group mapping, it takes effect from the next login session onwards.

  8. Click Save.

By following these steps, you have successfully configured role-based access control for enterprise login in Choreo, allowing users from the external IdP to have the appropriate permission.

"},{"location":"administer/configure-self-sign-up/","title":"Configure Self-Sign-Up","text":"

With Choreo, you can set up a self-sign-up page for your Developer Portal. The self-sign-up page allows users to easily access your Developer Portal and subscribe to APIs. When you configure self-sign-up, users can create their accounts and access your Developer Portal without any manual intervention from you.

This page walks you through the steps to configure self-sign-up for your Developer Portal.

"},{"location":"administer/configure-self-sign-up/#prerequisites","title":"Prerequisites","text":"
  1. Sign in to the Choreo Console at https://console.choreo.dev/ using your Google, GitHub, or Microsoft account.
  2. If you are a new user, create an organization with a unique organization name. For example, \"Stark Industries\".
"},{"location":"administer/configure-self-sign-up/#configure-developer-portal-self-sign-up","title":"Configure Developer Portal self-sign-up","text":"

To configure self-sign-up, follow the steps given below:

  1. Send an email to choreo-help@wso2.com requesting to configure enterprise IdP for the Developer Portal of your organization.

    Tip

    Ensure you include the organization name or handle in the request.

    Sample email

    Subject : [Stark Industries] Configure enterprise IdP for Developer Portal

    Hi CS team,

    I need to configure enterprise IdP for my organization\u2019s Developer Portal to enable self-sign-up. Can you please do the necessary configurations to proceed?

    My organization details are as follows:

    • Organization name: Stark Industries
    • Organization handle: starkindustries

    Thank you

    The Choreo support team will perform the necessary configurations and respond to your request.

  2. When you receive a response, sign in to Asgardeo using the same credentials that you used to sign in to Choreo.

  3. In the Asgardeo Console, click View all applications.

    You will see an application named WSO2_LOGIN_FOR_CHOREO_DEV_PORTAL.

  4. Click on the application to edit it and enter your organization\u2019s Developer Portal URL as the Access URL of the application. For example, https://devportal.choreo.dev/starkindustries.

  5. Click Update.
  6. To add user attributes, follow these steps:

    Note

    If you have enabled enterprise login and you want to add the Groups attribute during self-sign-up configuration, avoid making it mandatory. This ensures proper access control and prevents unauthorized privileges. If you make the Groups attribute mandatory, it allows self-signed-up users to specify a group and assume roles associated with it.

    1. Click the User Attributes tab.
    2. To add the email as a mandatory user attribute, select Email and click the arrow to expand the section. Then, select the Requested and Mandatory checkboxes.

    3. To add the first name and last name as optional attributes, select Profile and click the arrow to expand the section. Then, select the Requested checkbox for the First Name and the Last Name attributes.

    4. Click Update.

  7. To add the user attributes as OpenID Connect scopes, follow these steps:

    1. In the Asgardeo Console left navigation menu, click Scopes.
    2. In the OpenID Connect Scopes pane, click OpenID to edit it.
    3. Click + New Attribute.
    4. Select Email, First Name, and Last Name as the attributes to associate with the OpenID scope.
    5. Click Save and then click Save Changes.

  8. To configure basic authentication as the sign-in method, follow these steps:

    1. In the Asgardeo Console left navigation menu, click Applications.
    2. In the Applications pane, click the WSO2_LOGIN_FOR_CHOREO_DEV_PORTAL application to edit it.
    3. Click the Sign-in Method tab and then click Start with default configuration.

    4. Click Update.

  9. To configure self-registration, follow these steps:

    1. In the Asgardeo Console left navigation menu, click Self Registration.
    2. In the Self Registration pane, click Configure.
    3. To enable self-registration, turn on the toggle.
    4. Select Account verification. This displays a confirmation message to enable account verification.
    5. Click Continue.
    6. Specify an appropriate value in the Account verification link expiry time field.
    7. Click Update.

Once you complete these steps, you will see a sign up link similar to the following in your Developer Portal:

Users can click LOGIN/SIGN UP and then click Create an account to sign up to access your Developer Portal.

"},{"location":"administer/configure-self-sign-up/#manage-new-users","title":"Manage new users","text":"

To manage users who want to access your Developer Portal via self-sign-up, you have two possible approaches:

  • Enable auto-approval for new user registrations: This approach automates the user approval process. When you enable auto-approval, each user who creates an account and signs up to your Developer Portal can access it by default.
  • Manually approve or reject user accounts: This allows you to review the list of user registrations and manually approve or reject each registration as needed.
"},{"location":"administer/configure-self-sign-up/#enable-auto-approval-for-new-user-registrations","title":"Enable auto-approval for new user registrations","text":"

To automatically approve each new user account registered on your Developer Portal, follow the steps given below:

  1. In the Choreo Console, click your username in the top right corner.
  2. In the drop-down menu, click Settings. This opens the Organization pane, where you can make necessary changes to organization settings.
  3. In the Organization pane, click Self Signups.
  4. To enable auto-approval, turn on the toggle.

Once you enable auto-approval, users can sign in to your Developer Portal and view your APIs and applications immediately after creating an account.

"},{"location":"administer/configure-self-sign-up/#manually-approve-or-reject-user-accounts","title":"Manually approve or reject user accounts","text":"

If you have not enabled auto-approval, you can manually approve or reject new user registrations. Once a user creates an account, Choreo sends an email to ask the user to confirm the account. To manually approve or reject user accounts, follow the steps given below:

  1. In the Choreo Console, click your username in the top right corner.
  2. In the drop-down menu, click Settings. This opens the Organization pane, where you can make necessary changes to organization settings.
  3. In the Organization pane, click Self Signups. You will see the user accounts listed for approval.
  4. To approve a user account, click Approve. To reject an account, click Reject.

    • If you approve an account, the user will receive an email confirming the approval.
    • If you reject an account, the user will receive an email mentioning that their account is rejected.

      Note

      A rejected user cannot sign up to your Developer Portal using the same account again.

"},{"location":"administer/control-access-in-the-choreo-console/","title":"Control Access in the Choreo Console","text":"

In the Choreo Console, you have the ability to manage access to projects and the actions that can be performed within them. Administrators have the capability to restrict project access to specific user groups. This feature is useful when you need certain user groups to have access to particular projects or for a set of projects.

Choreo uses Roles, Groups, and a Mapping level to control access to the Choreo Console as follows:

  • Role : Role is a collection of permissions. Choreo has a predefined set of roles with permissions assigned to them. Learn more
  • Group : Group is a collection of users. A user group requires a role or multiple roles to be assigned to it so that the users in those groups get the relevant permissions via the assigned roles. Learn more

  • Mapping level : A mapping level defines the extent at which a role-group mapping can be done. Choreo has two defined resource levels.

    • Organization : You can assign a role to a group or associate a group with a role within the organization. This ensures that all users in a group inherit the permissions granted by that role across all organizational resources. For example, if a user has edit_project permission at the organization mapping level, that user can edit all the projects in the organization.
    • Project : You can assign a role to a group or associate a group with a role within a specific project resource. This ensures that users in the group inherit the permissions granted by that role only within the context of the specified project. For example, If a user has edit_project permission at the project mapping level, that user can only edit the specified project.

In Choreo, authorization operates by assigning a role to a group at a specified level. The level at which the role is assigned determines the extent of permissions granted to users.

Important

Avoid assigning multiple roles to a single user across different projects or levels (organization and project). Such assignments can grant users unintended permission to some projects, allowing them to perform tasks they shouldn't have access to. Therefore, it is recommended to assign only one role to a user across projects or levels to ensure proper access control.

Info

In Choreo, organization-level permissions take precedence over project-level permissions.

To elaborate further, refer to the following diagram.

The following diagram depicts a role-group assignment at a specific resource level. In the diagram, an admin user has assigned the Developer role to all members of the Engineering group within the Engineering Project. This grants users in the Engineering group the ability to perform all actions allowed by the Developer role within the Engineering Project.

"},{"location":"administer/control-access-in-the-choreo-console/#sample-scenario","title":"Sample scenario","text":"

Now that you understand the basic concepts of access control within the Choreo Console, let\u2019s try out a sample scenario to manage access within a project.

Assume you are overseeing the Engineering Project within your organization and you need to grant development access to specific users solely within this project. Here's a step-by-step guide on how to achieve this:

"},{"location":"administer/control-access-in-the-choreo-console/#step-1-create-a-project","title":"Step 1: Create a project","text":"

Follow the steps given below to create a project:

  1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
  2. On the organization home page, click + Create Project.
  3. Enter a display name, unique name, and description for the project. You can enter the values given below:

    Info

    In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

    Field Value Project Display Name Engineering Project Name engineering-project Project Description My sample project
  4. Click Create. This creates the project and takes you to the project home page.

"},{"location":"administer/control-access-in-the-choreo-console/#step-2-create-a-new-group","title":"Step 2: Create a new group","text":"

Follow the steps given below to create a group with the name Engineering Project Developer:

  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your project.
  2. In the left navigation menu, click Settings.
  3. Click the Access Control tab and then click the Groups tab.
  4. Click + Create Group.
  5. Enter a group name and group description. You can enter the values given below:

    Field Value Group Name Engineering Project Developer Group Description Users with development access within the engineering project
  6. Click Create.

"},{"location":"administer/control-access-in-the-choreo-console/#step-3-assign-roles-to-the-group","title":"Step 3: Assign roles to the group","text":"

Follow the steps given below to assign the Developer role to the Engineering Project Developer group that you created:

  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the Engineering Project that you created.
  2. In the left navigation menu, click Settings.
  3. Click the Access Control tab and then click the Groups tab.
  4. On the Groups tab, search for the Engineering Project Developer group and click the corresponding edit icon.
  5. Click +Add Roles.
  6. In the Add Roles to Group in Project dialog that opens, click the Roles list and select Developer.
  7. Click Add. This assigns the Developer role to the group. You should see the mapping level as Project (Engineering Project) as follows, indicating the scope of the mapping:

This means that you have granted developer access to users in the Engineering Project Developer group in the scope of the Engineering Project.

Now that you have set up access control, you can proceed to add users to the new group.

"},{"location":"administer/control-access-in-the-choreo-console/#step-4-add-users-to-the-group","title":"Step 4: Add users to the group","text":"

There are two approaches you can follow to add users to the group.

Add a new user as a project developer

Follow the steps given below to add a new user as a project developer:

  1. In the Choreo Console, go to the top navigation menu, click the\u00a0Organization\u00a0list, and select the organization where you created your project.
  2. In the left navigation menu, click Settings.
  3. Click the Access Control tab and then click the Users tab.
  4. Click +Invite Users.
  5. In the Invite Users dialog,
  6. Specify the email addresses of the users in the Emails field.
  7. Click the Groups list and select Engineering Project Developer.
  8. Click Invite.
Add an existing user as a project developer

Follow the steps given below to add an existing user as a project developer:

  1. In the Choreo Console, go to the top navigation menu, click the\u00a0Organization\u00a0list, and select the organization where you created your project.
  2. In the left navigation menu, click Settings.
  3. Click the Access Control tab and then click the Users tab.
  4. Search for the existing user you want to add to the Engineering Project Developer group.
  5. Click the edit icon corresponding to the user.
  6. Click +Assign Groups.
  7. In the Add Groups to User dialog, click the Groups list and select Engineering Project Developer.
  8. Click Add.

Tip

Make sure to remove the user from any other groups to avoid granting organization-level access unintentionally.

Note

  • Existing groups are already mapped to similar roles at the organization level. Therefore, adding users to those groups or keeping users in them, will give organization-level access to the users.
  • When users are added to the Engineering Project Developer group, they will only have developer access to the Engineering Project.
  • You can invite new users or add existing users to new groups within the Engineering Project, and based on their requirements, assign roles like Developer, API Publisher, etc.

Now you have successfully set up access control within your project.

"},{"location":"administer/create-api-subscription-plans/","title":"Create API Subscription Plans","text":"

API subscription plans are essential to control and manage access to APIs. These plans define the rules and limitations on how clients can interact with APIs, ensuring efficient resource utilization and robust security. With the option to set rate limits and burst control, subscription plans allow API providers to manage traffic, prevent misuse, and offer tiered service levels. Organizations can implement subscription plans to provide varying levels of API access, accommodating different user needs and business models, while ensuring optimal performance and security.

In Choreo, users with the administrator role can create, update, and delete subscription plans at the organization level.

Tip

Deleting a subscription plan is only possible if there are no active subscriptions associated with it.

To create an organization-level subscription plan, follow the steps given below:

  1. Sign in to the Choreo Console.
  2. In the Choreo Console header, go to the Organization list and select your organization.
  3. In the left navigation menu, click Settings. This opens the organization-level settings page.
  4. Click the API Management tab and then click Subscription Plans.
  5. Click + Add Subscription Plan.
  6. In the Create Subscription Plan pane, enter the appropriate values for each field:

    Note

    • In the Name field, you must specify a name to uniquely identify the subscription plan in various contexts. The value is editable only at the time you create the subscription plan. You cannot change the name after you create it.
    • The Stop on Quota Reach checkbox is selected by default when creating a subscription plan. When selected, requests return an HTTP 429 response if the request count exceeds the limit. If you clear the checkbox, requests are allowed even if the quota is exceeded.
    • Burst control protects your backend from sudden request spikes and manages API usage. It\u2019s especially useful for subscription plans where the request count is enforced over a long period, to prevent consumers from using their entire quota too quickly. Ensure you select the Burst Control checkbox when the Request Count Time Unit is selected as Hour or Day.

  7. Click Create. This creates the subscription plan and lists it under Subscription Plans.

After creating subscription plans, users with the API publisher role can assign subscription plans to APIs. API consumers can then choose the appropriate subscription plan during the subscription process depending on their requirements.

"},{"location":"administer/customize-the-developer-portal/","title":"Customize the Developer Portal","text":"

The Developer Portal allows API consumers to find and consume APIs with ease. You can change the look and feel of your Developer Portal by changing the theme to match your brand. Doing so will help you give a better developer experience to your users.

To customize the Developer Portal theme, follow the steps given below:

Note

  • To customize the Developer Portal theme for an organization, you need to be an admin user of that organization.
  • You cannot undo a change and restore or revert to a previous version of the theme. However, you can reset it to the default theme.
  1. Sign in to the Choreo Console at https://console.choreo.dev/ using a Google/ GitHub/ Microsoft account.

  2. In the left pane, click Settings.

  3. In the header, click the Organization list. This will open the organization level settings page.

  4. In the API Management tab, click Devportal Theme.

    Once you access the theme, you can customize the Home page, color theme, font, header and footer, logos, etc., by expanding the relevant sections.

  5. Make a change to the theme. For example, let's change the title on the Home page and the color theme.

    1. To update the title on the Home page, expand the Home Page section, and in the Title field, change the default text (for example, to Try our APIs!).

    2. To update the color theme, expand the Color Palette section, and change the colors as required (for example, change the background color to #C3C5CD and the primary color of the buttons to #086634).

    3. Click Preview to view a preview of the Developer Portal with the changes you made. Based on the changes given in the examples, the preview appears as follows.

    4. Click Save to save your changes as a draft theme.

    5. To apply the changes to the Developer Portal, toggle the Go Live switch. To confirm that you want to go live with the changes, click Enable in the message that appears.

  6. Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.

The Home page will appear as it did in the preview.

"},{"location":"administer/customize-the-developer-portal/#reset-the-developer-portal-theme","title":"Reset the Developer Portal theme","text":"

To reset the Developer Portal theme to the default theme, follow the steps given below:

  1. Sign in to the Choreo Console at https://console.choreo.dev/ using a Google, GitHub, or Microsoft account.

  2. In the left pane, click Settings.

  3. In the header, click the Organization list. This will open the organization level settings page.

  4. In the Organization tab, click Devportal Theme, and then click Reset to Default.

"},{"location":"administer/inviting-members/","title":"Inviting members","text":""},{"location":"administer/inviting-members/#inviting-users","title":"Inviting users","text":"

An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

"},{"location":"administer/manage-members-of-an-organization/","title":"Manage Members of an Organization","text":"

An organization in Choreo is a logical grouping of users and user resources. A first-time user must create an organization and be a user of it when signing in to Choreo. Users and resources in an organization cannot access resources in another organization unless an admin of the other organization invites them and adds them as a user of that organization.

"},{"location":"administer/manage-members-of-an-organization/#inviting-users","title":"Inviting users","text":"

An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

"},{"location":"administer/manage-members-of-an-organization/#manage-user-permission","title":"Manage user permission","text":"

For details on how Choreo manages user permission, see Manage user permission.

"},{"location":"administer/review-workflow-approval-requests/","title":"Review Workflow Approval Requests","text":"

In Choreo, administrators can configure approvals for workflows and assign specific users as approvers.

If you are assigned as an authorized reviewer for a particular workflow approval request, you will receive an email notification when a request is submitted for approval. The email includes a summary of the request and a link to the Approvals page in the Choreo Console, where you can review the details and either approve or reject the request.

Note

  • Workflow approvals are managed at the project level. If a role with the necessary permissions is assigned in a project context, only members of the user group bound to that role within the specific project will receive notifications for requests made in that project. For example, if you are assigned the Project Admin role (which includes the necessary permissions) for project A, you will only be notified of workflow requests within project A.
  • Users with organization-level permissions will receive notifications for all workflow requests across any project in the organization.

Other approvers within your organization will also receive notifications for workflow requests and may review a request before you. If a request has already been reviewed, it will appear under the Past tab on the Approvals page.

Approval requests are submitted on behalf of the team. Once approved, any authorized team member can execute the task. For certain tasks, execution may occur automatically upon approval.

"},{"location":"administer/review-workflow-approval-requests/#view-workflow-approval-requests","title":"View workflow approval requests","text":"

To view workflow approval requests assigned to you, follow these steps:

  1. Sign in to the Choreo Console.
  2. In the Choreo Console header, go to the Organization list and select your organization.
  3. In the left navigation menu, click Approvals. This opens the Approvals page where you can see all approval requests assigned to you. The Pending tab lists requests that are yet to be reviewed. The Past tab displays requests already reviewed by you or other approvers, as well as requests canceled by the requester.
  4. To view details of a specific request, click Review corresponding to it.
"},{"location":"administer/review-workflow-approval-requests/#approve-or-reject-an-approval-request","title":"Approve or reject an approval request","text":"

To approve or reject a request, follow these steps:

  1. Follow the instructions in the View workflow approval requests section above to see details of the workflow you want to review. Alternatively, click the Choreo Console link in the approval request email notification you received. This takes you to the request details in the Choreo Console.
  2. Review the request and click Approve or Reject based on your decision.
"},{"location":"administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/","title":"Configure Asgardeo as an External Identity Provider (IdP)","text":"

Asgardeo is an identity-as-a-service (IDaaS) solution designed to create seamless login experiences for your applications. Asgardeo seamlessly integrates with Choreo, providing powerful API access control through the use of API scopes. This enables restricting API access to designated user groups. By configuring Asgardeo as an external IdP in Choreo, you can leverage your Asgardeo user stores to manage API access control effectively. This guide walks you through the steps to set up Asgardeo as your external IdP.

"},{"location":"administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/#prerequisites","title":"Prerequisites","text":"

Before you proceed, be sure to complete the following:

  • Create an Asgardeo application. You can follow the Asgardeo guide to register a standard-based application.

  • Find the well-known URL: Go to the info tab of the Asgardeo application to view the endpoints and copy the Discovery endpoint.

  • Find the Client ID: Go to the Protocol tab of the Asgardeo application and copy the Client ID.

"},{"location":"administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/#add-asgardeo-as-an-external-idp-in-choreo","title":"Add Asgardeo as an external IdP in Choreo","text":"

Follow the steps below to add Asgardeo as an external IdP in Choreo:

  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. In the left navigation menu, click Settings.
  3. In the header, click the Organization list. This opens the organization-level settings page.
  4. Click the Application Security tab and then click the Identity Providers tab.
  5. To add an identity provider, click + Identity Provider.
  6. Click Asgardeo.
  7. In the Asgardeo dialog that opens, specify a name and a description for the IdP.
  8. In the Well-Known URL field, paste the well-known URL that you copied from your Asgardeo instance by following the prerequisites.
  9. Leave the Apply to all environments checkbox selected. This allows you to use the tokens generated via this IdP to invoke APIs across all environments.

    Note

    If you want to restrict the use of tokens generated via this IdP to invoke APIs in specific environments, clear the Apply to all environments checkbox and select the necessary environments from the Environments list.

  10. Click Next. This displays the server endpoints that are useful to implement and configure authentication for your application.

  11. Click Add.

Now you have configured Asgardeo as an external IdP in Choreo.

"},{"location":"administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/","title":"Configure Azure Active Directory (Azure AD) as an External Identity Provider (IdP)","text":"

In organizations leveraging Microsoft Azure Active Directory (Azure AD) for identity and access management (IAM), integrating it with Choreo offers powerful API access control. This control hinges on the use of API scopes. That is, it enables the restriction of access to a designated group of users. This document guide you step-by-step to configure Azure AD as your external IdP.

"},{"location":"administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/#prerequisites","title":"Prerequisites","text":"

Before you try out this guide, be sure you have the following:

  • An Azure Active Directory account: If you don\u2019t already have one, setup an Azure Active Directory account at https://azure.microsoft.com/en-gb/.
  • Administrator rights to your Choreo organization: You need this to configure the Azure AD account in your organization.
"},{"location":"administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/#add-azure-active-directory-as-an-external-idp-in-choreo","title":"Add Azure Active Directory as an external IdP in Choreo","text":"

Follow the steps below to add Azure AD as an IdP in Choreo:

  1. Sign in to the Choreo Console at https://console.choreo.dev/.
  2. In the left navigation menu, click Settings.
  3. In the header, click the Organization list. This will open the organization level settings page.
  4. On the Application Security tab, click Identity Providers and then click + Identity Provider.
  5. Select Microsoft Entra ID (Azure AD) as the Identity Provider.
  6. Provide a name and a description for the IdP.
  7. To obtain the Well-Known URL of your Azure AD instance, on your Azure account, under Azure Active Directory go to App registrations, and then Endpoints. Copy the URI underOpenID Connect metadata document.

    Info

    • In azure, there are two versions of access tokens available. By default, the IDP applications you create use the v1 access token. Therefore, if you intend to use the v1 access token, when providing the Well-Known URL, omit the v2.0 path segment from the URL. Learn more For example, convert https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration-> https://login.microsoftonline.com/<tenant-id>/.well-known/openid-configuration
    • If you intend to work with v2.0, then the IDP application's manifest should be changed as explained in the access tokendocumentation.
  8. Leave the Apply to all environments checkbox selected. However, if you want to restrict the use of the external IdP to a certain environment, you can select them from the Environments list.

  9. Review the endpoints and click Next.
"},{"location":"api-management/api-rate-limiting/","title":"API Rate Limiting","text":"

API rate limiting is a technique that allows you to control the rate of requests made to an API. Rate limiting helps prevent system overload and enhances API performance. When you limit the number of requests that can be made in a specific time frame, you can ensure that your API is available and responsive to all users while protecting it from malicious attacks.

This page walks you through the steps to enable rate limiting for your APIs via Choreo and also provides information on the rate-limiting options supported by Choreo.

"},{"location":"api-management/api-rate-limiting/#enable-rate-limiting-for-an-api","title":"Enable rate limiting for an API","text":"

To enable rate limiting for an API, follow the steps given below:

Note

You can apply rate-limiting settings separately for each environment.

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the component for which you want to apply rate limiting.
  3. In the left navigation menu, click Deploy.
  4. Go to the required environment card and click the view icon corresponding to the endpoint for which you want to apply rate limiting.

    Info

    If you are applying rate limiting for an API Proxy component, go to the required environment card, click the setting icon corresponding to API Configuration, and proceed to step 6.

  5. In the Endpoint Details pane that opens, click the settings icon.

  6. In the Manage section, click Rate Limiting to expand it.
  7. Select a Rate Limiting Level depending on your requirement and click Apply.
"},{"location":"api-management/api-rate-limiting/#api-level-rate-limiting","title":"API-level rate limiting","text":"

API-level rate limiting applies the allocated request count for the specified time unit to all operations in the API.

"},{"location":"api-management/api-rate-limiting/#operation-level-rate-limiting","title":"Operation-level rate limiting","text":"

Operation-level rate limiting allows you to configure different rate-limiting values for each operation. You can use this option to define specific rate-limiting values for critical API operations that require an extra layer of protection.

"},{"location":"api-management/api-rate-limiting/#rate-limiting-response-headers","title":"Rate-limiting response headers","text":"

The following table lists the response headers available when you enable rate limiting for your APIs. You can implement necessary rate-limiting scenarios depending on the response header values.

Header Name Description x-ratelimit-limit Denotes the request count allocated for the specified time unit. x-ratelimit-reset Provides the time remaining to start the next rate-limiting time unit. x-ratelimit-remaining Denotes the remaining request count for the specified time unit. x-ratelimit-enforced Visible after exceeding the allocated request count."},{"location":"api-management/control-api-visibility/","title":"Control API Visibility","text":"

By default, the APIs published in Choreo are visible to anyone who visits the Choreo Developer Portal. By default, Choreo sets the visibility of the API to Public. However, developers can control the visibility of their APIs by changing the default option to Private or Restricted.

Visibility settings control users from viewing and modifying APIs. API visibility can be one of the following options:

  • Public : The API is visible to all in the developer portal.

  • Private : The API is visible to the users who only sign in to the Developer Portal.

  • Restricted: The API is visible to only the user that has the roles that you specify. This option helps developers to enforce fine-grained access control to the API.

"},{"location":"api-management/control-api-visibility/#change-api-visibility","title":"Change API visibility","text":"
  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the REST API (Service) for which you want to control API visibility.
  3. In the left navigation menu, click Manage and then click API Info.
  4. On the API Info page that opens, click the Developer Portal tab.
  5. Under General Details, select the required visibility setting from the Visibility list.

    Enable fine-grained role-based access control to the API

    1. To enable fine-grained role-based access control to an API in the Developer Portal, select Restricted from the API visibility list. Once selected, you will see the roles available in your organization in the Visible Roles list.
    2. Select any combination of roles. Only the users with the given roles can access the APIs through the Dev Portal.
    3. Alternatively, You can create a new role and assign it to an API by following the steps below:
      1. Click + Create New Role in the list.
      2. Add the role name and description.
      3. Click Next.
      4. Assign the relevant permissions to the new role.
      5. Click Create.
      6. Select the newly created role from the Visible Roles list.
  6. Click Save.

"},{"location":"api-management/documents/","title":"Documents","text":"

When an API consumer signs in to the Choreo Developer Portal to browse APIs, it is not sufficient to just have an API thumbnail along with the name and version of the API. An API consumer would expect to see more details about the API, such as the following:

  • A brief description of the API.
  • How to invoke the API.
  • The limitations/restrictions of the API.
  • Version history.

To provide such information that improves the overall visibility of the API, an API developer can add such documentation to an API before publishing it to the Developer Portal.

"},{"location":"api-management/documents/#add-documents-to-an-api","title":"Add documents to an API","text":"

To add documentation for an API, follow the steps given below.

  1. Sign in to the Choreo Console.

  2. In the Component Listing pane, click on the component for which you want to add documents.

  3. In the left navigation menu, click Manage and then click Documents.

  4. Specify a title for the document and provide the content in markdown syntax.

  5. Click Add to save the document.

Depending on the information you need to add to the API, you can add one or more documents.

You can also edit existing documents and delete documents if necessary.

"},{"location":"api-management/lifecycle-management/","title":"Lifecycle Management","text":"

API lifecycle management is an important aspect of API management. The API lifecycle consists of various states that an API passes through, from creation to retirement. In Choreo, there are six distinct lifecycle states: created, pre-released, published, blocked, deprecated, and retired.

By leveraging the various lifecycle states, API managers can optimize the development process and ensure that subscribers have access to the latest and most reliable APIs.

"},{"location":"api-management/lifecycle-management/#api-lifecycle-states","title":"API lifecycle states","text":"

The following lifecycle states are applicable to APIs in Choreo:

API lifecycle state Use case Corresponding action CREATED The API is created but is not ready for consumption. The API is not visible to subscribers in the Developer Portal. PRE-RELEASED A prototype is created for early promotion and consumer testing. You can deploy a new API or a new version of an existing API as a prototype to provide subscribers with an early implementation of the API. The API is published to the Developer Portal as a pre-release. PUBLISHED The API is ready for subscribers to view and subscribe to via the Developer Portal The API is visible in the Developer Portal and is available for subscription. BLOCKED Access to the API is temporarily blocked. Runtime calls are blocked, and the API is not visible in the Developer Portal. DEPRECATED The old version of an API is moved to this state when a newer version of the API is PUBLISHED. The API is deployed and is available to existing subscribers. New subscriptions are disabled. Existing subscribers can continue to use it as usual until the API is retired. RETIRED The API is no longer in use when it is in this state. The API is unpublished and deleted from the Developer Portal."},{"location":"api-management/lifecycle-management/#manage-the-lifecycle-of-an-api","title":"Manage the lifecycle of an API","text":"

To change the lifecycle state of an API via the Choreo Console, follow the instructions given below:

Tip

You must have publishing privileges to manage the lifecycle states of a component.

  1. Sign in to the\u00a0Choreo Console.
  2. In the Component Listing pane, click on the component for which you want to manage the lifecycle.
  3. In the left navigation menu, click\u00a0Manage, and then click Lifecycle.
  4. In the Lifecycle Management pane, you will see the lifecycle state transition diagram indicating the current lifecycle state of the component. Just above the lifecycle state transition diagram, The possible lifecycle states you can apply to the component are displayed just above the lifecycle state transition diagram. Click on a required lifecycle state to apply it to the component. For example, if a component is in the Created state, you can click either Pre-release or Publish.
"},{"location":"api-management/rename-api-display-name/","title":"Rename API Display Name","text":"

Choreo allows you to make one or more endpoints accessible through its service and integration components. These endpoints are published as individual APIs in Choreo, accessible via the Choreo Developer Portal. By default, Choreo assigns an API name by combining the component name and the endpoint name, resulting in the following format: <component name>-<endpoint name>. For example, if you create a component named Ballerina Reading List, the API is displayed as Ballerina Reading List - GraphQL Reading List 591.

Choreo provides you with the flexibility to personalize the display name of the API, enhancing its user-friendliness and readability. Once you modify the API display name within the Choreo Console, Choreo applies the change immediately. From there onwards, Choreo displays the published API by this name in the Choreo Developer Portal.

Follow the steps below to rename the API display name:

  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
  2. In the Component Listing pane, click on the component for which you want to rename the API display name. This opens the Overview page of the component.
  3. In the left navigation menu, click Manage and then click API Info.
  4. On the API Info page that opens, click the Developer Portal tab.
  5. Under General Details, specify an appropriate API display name in the Name field.
  6. Click Save.

Now, you can view the updated API display name in the Choreo Developer Portal.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/","title":"OWASP Top 10","text":"

A set of rules enforcing OWASP security guidelines to prevent common vulnerabilities and ensure secure coding practices.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi12023-no-numeric-ids","title":"\u274c owasp:api1:2023-no-numeric-ids","text":"

Use random IDs that cannot be guessed. UUIDs are preferred but any other random string will do.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-no-http-basic","title":"\u274c owasp:api2:2023-no-http-basic","text":"

Basic authentication credentials transported over network are more susceptible to interception than other forms of authentication, and as they are not encrypted it means passwords and tokens are more easily leaked.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-no-api-keys-in-url","title":"\u274c owasp:api2:2023-no-api-keys-in-url","text":"

API Keys are passed in headers, cookies, or query parameters to access APIs. Those keys can be eavesdropped, especially when they are passed in the URL, as logging or history tools will keep track of them and potentially expose them.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-no-credentials-in-url","title":"\u274c owasp:api2:2023-no-credentials-in-url","text":"

URL parameters MUST NOT contain credentials such as API key, password, or secret.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-auth-insecure-schemes","title":"\u274c owasp:api2:2023-auth-insecure-schemes","text":"

There are many HTTP authorization schemes but some of them are now considered insecure, such as negotiating authentication using specifications like NTLM or OAuth v1.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-jwt-best-practices","title":"\u274c owasp:api2:2023-jwt-best-practices","text":"

JSON Web Tokens RFC7519 is a compact, URL-safe, means of representing claims to be transferred between two parties. JWT can be enclosed in encrypted or signed tokens like JWS and JWE.

The JOSE IANA registry provides algorithms information.

RFC8725 describes common pitfalls in the JWx specifications and in their implementations, such as: - the ability to ignore algorithms, eg. {\"alg\": \"none\"}; - using insecure algorithms like RSASSA-PKCS1-v1_5 eg. {\"alg\": \"RS256\"}. An API using JWT should explicit in the description that the implementation conforms to RFC8725.

components:\n  securitySchemes:\n    JWTBearer:\n      type: http\n      scheme: bearer\n      bearerFormat: JWT\n      description: |-\n        A bearer token in the format of a JWS and conformato\n        to the specifications included in RFC8725.\n

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi22023-short-lived-access-tokens","title":"\u274c owasp:api2:2023-short-lived-access-tokens","text":"

Using short-lived access tokens is a good practice, and when using OAuth 2 this is done by using refresh tokens. If a malicious actor is able to get hold of an access token then rotation means that token might not work by the time they try to use it, or it could at least reduce how long they are able to perform malicious requests.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-rate-limit","title":"\u274c owasp:api4:2023-rate-limit","text":"

Define proper rate limiting to avoid attackers overloading the API. There are many ways to implement rate-limiting, but most of them involve using HTTP headers, and there are two popular ways to do that:

IETF Draft HTTP RateLimit Headers:. https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers//

Customer headers like X-Rate-Limit-Limit (Twitter: https://developer.twitter.com/en/docs/twitter-api/rate-limits or X-RateLimit-Limit (GitHub: https://docs.github.com/en/rest/overview/resources-in-the-rest-api)

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-rate-limit-retry-after","title":"\u274c owasp:api4:2023-rate-limit-retry-after","text":"

Define proper rate limiting to avoid attackers overloading the API. Part of that involves setting a Retry-After header so well meaning consumers are not polling and potentially exacerbating problems.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-array-limit","title":"\u274c owasp:api4:2023-array-limit","text":"

Array size should be limited to mitigate resource exhaustion attacks. This can be done using maxItems. You should ensure that the subschema in items is constrained too.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-string-limit","title":"\u274c owasp:api4:2023-string-limit","text":"

String size should be limited to mitigate resource exhaustion attacks. This can be done using maxLength, enum or const.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-integer-limit","title":"\u274c owasp:api4:2023-integer-limit","text":"

Integers should be limited to mitigate resource exhaustion attacks. This can be done using minimum and maximum, which can with e.g.: avoiding negative numbers when positive are expected, or reducing unreasonable iterations like doing something 1000 times when 10 is expected.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-integer-limit-legacy","title":"\u274c owasp:api4:2023-integer-limit-legacy","text":"

Integers should be limited to mitigate resource exhaustion attacks. This can be done using minimum and maximum, which can with e.g.: avoiding negative numbers when positive are expected, or reducing unreasonable iterations like doing something 1000 times when 10 is expected.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-integer-format","title":"\u274c owasp:api4:2023-integer-format","text":"

Integers should be limited to mitigate resource exhaustion attacks. Specifying whether int32 or int64 is expected via format.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-define-cors-origin","title":"\u274c owasp:api8:2023-define-cors-origin","text":"

Setting up CORS headers will control which websites can make browser-based HTTP requests to your API, using either the wildcard \"*\" to allow any origin, or \"null\" to disable any origin. Alternatively you can use \"Access-Control-Allow-Origin: https://example.com\" to indicate that only requests originating from the specified domain (https://example.com) are allowed to access its resources.

More about CORS here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-no-scheme-http","title":"\u274c owasp:api8:2023-no-scheme-http","text":"

Server interactions must use the http protocol as it's inherently insecure and can lead to PII and other sensitive information being leaked through traffic sniffing or man-in-the-middle attacks. Use the https or wss schemes instead.

Learn more about the importance of TLS (over SSL) here: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-no-server-http","title":"\u274c owasp:api8:2023-no-server-http","text":"

Server interactions must not use the http:// as it's inherently insecure and can lead to PII and other sensitive information being leaked through traffic sniffing or man-in-the-middle attacks. Use https:// or wss:// protocols instead.

Learn more about the importance of TLS (over SSL) here: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi92023-inventory-access","title":"\u274c owasp:api9:2023-inventory-access","text":"

Servers are required to use vendor extension x-internal set to true or false to explicitly explain the audience for the API, which will be picked up by most documentation tools.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi92023-inventory-environment","title":"\u274c owasp:api9:2023-inventory-environment","text":"

Make it clear which servers are expected to run as which environment to avoid unexpected problems, exposing test data to the public, or letting bad actors bypass security measures to get to production-like environments.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi32023-no-additionalproperties","title":"\u26a0\ufe0f owasp:api3:2023-no-additionalProperties","text":"

By default JSON Schema allows additional properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with additionalProperties: false or add maxProperties.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi32023-constrained-additionalproperties","title":"\u26a0\ufe0f owasp:api3:2023-constrained-additionalProperties","text":"

By default JSON Schema allows additional properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with additionalProperties: false or add maxProperties

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi32023-no-unevaluatedproperties","title":"\u26a0\ufe0f owasp:api3:2023-no-unevaluatedProperties","text":"

By default JSON Schema allows unevaluated properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with unevaluatedProperties: false or add maxProperties.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi32023-constrained-unevaluatedproperties","title":"\u26a0\ufe0f owasp:api3:2023-constrained-unevaluatedProperties","text":"

By default JSON Schema allows unevaluated properties, which can potentially lead to mass assignment issues, where unspecified fields are passed to the API without validation. Disable them with unevaluatedProperties: false or add maxProperties

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-rate-limit-responses-429","title":"\u26a0\ufe0f owasp:api4:2023-rate-limit-responses-429","text":"

OWASP API Security recommends defining schemas for all responses, even errors. A HTTP 429 response signals the API client is making too many requests, and will supply information about when to retry so that the client can back off calmly without everything breaking. Defining this response is important not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces. It also ensures your API/framework/gateway actually has rate limiting set up.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi42023-string-restricted","title":"\u26a0\ufe0f owasp:api4:2023-string-restricted","text":"

To avoid unexpected values being sent or leaked, strings should have a format, RegEx pattern, enum, or const.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-define-error-validation","title":"\u26a0\ufe0f owasp:api8:2023-define-error-validation","text":"

Carefully define schemas for all the API responses, including either 400, 422 or 4XX responses which describe errors caused by invalid requests.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-define-error-responses-401","title":"\u26a0\ufe0f owasp:api8:2023-define-error-responses-401","text":"

OWASP API Security recommends defining schemas for all responses, even errors. The 401 describes what happens when a request is unauthorized, so its important to define this not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#owaspapi82023-define-error-responses-500","title":"\u26a0\ufe0f owasp:api8:2023-define-error-responses-500","text":"

OWASP API Security recommends defining schemas for all responses, even errors. The 500 describes what happens when a request fails with an internal server error, so its important to define this not just for documentation, but to empower contract testing to make sure the proper JSON structure is being returned instead of leaking implementation details in backtraces.

"},{"location":"api-management/api-governance/default-rulesets/owasp_top_10_doc/#i-owaspapi72023-concerning-url-parameter","title":"\u2139\ufe0f owasp:api7:2023-concerning-url-parameter","text":"

Using external resources based on user input for webhooks, file fetching from URLs, custom SSO, URL previews, or redirects can lead to a wide variety of security issues.

Learn more about Server Side Request Forgery https://owasp.org/API-Security/editions/2023/en/0xa7-server-side-request-forgery/.

"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/","title":"WSO2 API Design Guidelines","text":"

A guide detailing best practices for creating robust, scalable, and secure APIs, ensuring alignment with industry standards for optimal design.

"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#path-casing","title":"\u274c path-casing","text":"

Paths must be kebab-case, with hyphens separating words.

Invalid Example

userInfo must be separated with a hyphen.

{\n\"/userInfo\": {\n\"post: }\n       ....\n}\n

Valid Example

{\n\"/user-info\": {\n\"post: }\n       ....\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#paths-no-file-extensions","title":"\u274c paths-no-file-extensions","text":"

Paths must not include json or xml file extensions.

Invalid Example

The path contains a .json extension.

{\n\"/user.json\": {\n\"post: }\n       ....\n}\n

Valid Example

{\n\"/user\": {\n\"post: }\n       ....\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#paths-no-http-verbs","title":"\u274c paths-no-http-verbs","text":"

Verbs such as get, delete, and put must not be included in paths because this information is conveyed by the HTTP method.

Invalid Example

The path contains the verb get.

{\n\"/getUsers\": {\n\"post: }\n       ....\n}\n

Valid Example

{\n\"/user\": {\n\"post: }\n       ....\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#path-parameters-snake-case","title":"\u274c path-parameters-snake-case","text":"

Path parameters must be snake_case, with each word separated by an underscore character and the first letter of each word lowercase. Also, the path parameter must not contain digits.

Invalid Example

The name property on line 9 (userId) must be separated by an underscore character and the I must be lowercase.

{\n\"paths\": {\n\"/users/{userId}\": {\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"integer\"\n},\n\"name\": \"userId\",\n\"in\": \"path\"\n}\n]\n}\n}\n}\n

Valid Example

{\n\"paths\": {\n\"/users/{userId}\": {\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"integer\"\n},\n\"name\": \"user_id\",\n\"in\": \"path\"\n}\n]\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#query-parameters-snake-case","title":"\u274c query-parameters-snake-case","text":"

Query parameters must be snake_case, with each word separated by an underscore character and the first letter of each word lowercase. Also, the query parameter must not contain digits.

Invalid Example

The name property on line 8 (user-Id) must be separated by an underscore character and the I must be lowercase.

{\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"string\"\n},\n\"in\": \"query\",\n\"name\": \"user-Id\"\n}\n]\n}\n

Valid Example

{\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"string\"\n},\n\"in\": \"query\",\n\"name\": \"user_id\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#resource-names-plural","title":"\u26a0\ufe0f resource-names-plural","text":"

Resource names should generally be plural.

Invalid Example

{\n\"paths\": {\n\"/user\": }\n}\n

Valid Example

{\n\"paths\": {\n\"/users\": }\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#paths-avoid-special-characters","title":"\u26a0\ufe0f paths-avoid-special-characters","text":"

Paths should not contain special characters, such as $ & + , ; = ? and @%.

Invalid Example

The path contains an ampersand.

{\n\"/user&info\": {\n\"post: }\n       ....\n}\n

Valid Example

{\n\"/user\": {\n\"post: }\n       ....\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/#i-server-has-api","title":"\u2139\ufe0f server-has-api","text":"

Server must have /api

"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/","title":"WSO2 Style Guidelines","text":"

A set of guidelines focused on enforcing uniformity in API style, including naming conventions, formatting, and documentation to ensure clarity and maintainability across all APIs.

"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#operation-operationid-valid-in-url","title":"\u274c operation-operationId-valid-in-url","text":"

Operation IDs must not contain characters that are invalid for URLs.

Invalid Example

The operationId in this example includes a pipe and space, which are invalid for URLs.

{\n\"/users\": {\n\"get\": {\n\"operationId\": \"invalid|operationID\"\n}\n}\n}\n

Valid Example

This operationId is valid for URLs.

{\n\"/users\": {\n\"get\": {\n\"operationId\": \"this-must-be-unique\"\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#path-declarations-must-exist","title":"\u274c path-declarations-must-exist","text":"

Path parameter declarations must not be empty.

Invalid Example

/users/{}

Valid Example

/users/{userId}

"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#paths-no-trailing-slash","title":"\u274c paths-no-trailing-slash","text":"

Paths must not end with a trailing slash.

/users and /users/ are separate paths. It's considered bad practice for them to differ based only on a trailing slash. It's usually preferred to not have a trailing slash.

Invalid Example

The users path ends with a slash.

{\n\"/users/\": {\n\"post\": {}\n}\n}\n

Valid Example

{\n\"/user\": {\n\"post\": {}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#server-lowercase","title":"\u274c server-lowercase","text":"

Server URLs must be lowercase. This standard helps meet industry best practices.

Invalid Example

The url property uses uppercase letters.

{\n\"servers\": [\n{\n\"url\": \"https://ACME.com/api\"\n}\n]\n}\n

Valid Example

The url property is fully lowercase.

{\n\"servers\": [\n{\n\"url\": \"https://acme.com/api\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#oas2-api-schemes","title":"\u274c oas2-api-schemes","text":"

OpenAPI 2 host schemes reflect the transfer protocol of the API. Host schemes must be present and an array with one or more of these values: http, https, ws, or wss.

Valid Example

This example shows that host schemes are http and https.

{\n\"schemes\": [\n\"http\",\n\"https\"\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#array-items","title":"\u274c array-items","text":"

Schemas with type: array, require a sibling items field.

Recommended: Yes

Good Example

TheGoodModel:\ntype: object\nproperties:\nfavoriteColorSets:\ntype: array\nitems:\ntype: array\nitems: {}\n

Bad Example

TheBadModel:\ntype: object\nproperties:\nfavoriteColorSets:\ntype: array\nitems:\ntype: array\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#contact-url","title":"\u26a0\ufe0f contact-url","text":"

The contact object should have a valid organization URL.

Valid Example

{\n\"contact\": {\n... ,\n\"url\": \"https://acme.com\",\n... },\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#contact-email","title":"\u26a0\ufe0f contact-email","text":"

The contact object should have a valid email.

Valid Example

{\n\"contact\": {\n... ,\n\"email\": \"support.contact@acme.com\"\n},\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#info-contact","title":"\u26a0\ufe0f info-contact","text":"

The info object should include a contact object.

Valid Example

{\n\"info\": {\n... ,\n\"contact\": {\n\"name\": \"ACME Corporation\",\n\"url\": \"https://acme.com\",\n\"email\": \"support.contact@acme.com\"\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#info-description","title":"\u26a0\ufe0f info-description","text":"

The info object should have a description object.

Valid Example

{\n\"info\": {\n... ,\n\"description\": \"This describes my API.\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#info-license","title":"\u26a0\ufe0f info-license","text":"

The info object should have a license object.

Valid Example

{\n\"info\": {\n... ,\n\"license\": {\n\"name\": \"Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)\",\n\"url\": \"https://creativecommons.org/licenses/by-sa/4.0/\"\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#license-url","title":"\u26a0\ufe0f license-url","text":"

The license object should include a valid url.

Valid Example

{\n\"license\": {\n\"name\": \"Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)\",\n\"url\": \"https://creativecommons.org/licenses/by-sa/4.0/\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#no-eval-in-markdown","title":"\u26a0\ufe0f no-eval-in-markdown","text":"

Markdown descriptions should not contain eval() functions, which pose a security risk.

Invalid Example

{\n\"info\": {\n... ,\n\"description\": \"API for users. eval()\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#no-script-tags-in-markdown","title":"\u26a0\ufe0f no-script-tags-in-markdown","text":"

Markdown descriptions should not contain script tags, which pose a security risk.

Invalid Example

{\n\"info\": {\n... ,\n\"description\": \"API for users. <script>alert(\\\"You are Hacked\\\");</script>\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#openapi-tags-alphabetical","title":"\u26a0\ufe0f openapi-tags-alphabetical","text":"

Global tags specified at the root OpenAPI Document level should be in alphabetical order based on the name property.

Invalid Example

{\n\"tags\":[\n{\n\"name\":\"Z Global Tag\"\n},\n{\n\"name\":\"A Global Tag\"\n}\n]\n}\n

Valid Example

{\n\"tags\":[\n{\n\"name\":\"A Global Tag\"\n},\n{\n\"name\":\"Z Global Tag\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#openapi-tags","title":"\u26a0\ufe0f openapi-tags","text":"

At least one global tag should be specified at the root OpenAPI Document level.

Valid Example

{\n\"tags\":[\n{\n\"name\":\"Global Tag #1\"\n},\n{\n\"name\":\"Global Tag #2\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#operation-description","title":"\u26a0\ufe0f operation-description","text":"

Each operation should have a description.

Valid Example

{\n\"get\": {\n\"description\": \"Get a list of users.\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#operation-operationid","title":"\u26a0\ufe0f operation-operationId","text":"

All operations should have an operationId.

Valid Example

{\n\"get\": {\n\"summary\": \"Get users\",\n\"operationId\": \"get-users\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#operation-tags","title":"\u26a0\ufe0f operation-tags","text":"

At least one tag should be defined for each operation.

Valid Example

{\n\"get\": {\n\"tags\": [\"Users\"]\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#contact-name","title":"\u26a0\ufe0f contact-name","text":"

The contact object should have an organization name.

Valid Example

{\n\"contact\": {\n\"name\": \"ACME Corporation\"\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#path-keys-no-trailing-slash","title":"\u26a0\ufe0f path-keys-no-trailing-slash","text":"

Path keys should not end in forward slashes. This is a best practice for working with web tooling, such as mock servers, code generators, application frameworks, and more.

Invalid Example

{\n\"/users/\": {\n}\n}\n

Valid Example

{\n\"/users\": {\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#path-not-include-query","title":"\u26a0\ufe0f path-not-include-query","text":"

Paths should not include query string items. Instead, add them as parameters with in: query.

Invalid Example

{\n\"/users/{?id}\": {\n}\n}\n

Valid Example

{\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"string\"\n},\n\"name\": \"id\",\n\"in\": \"path\",\n\"required\": true,\n\"description\": \"User's ID\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#tag-description","title":"\u26a0\ufe0f tag-description","text":"

Tags defined at the global level should have a description.

Valid Example

{\n\"tags\": [\n{\n\"name\": \"Users\",\n\"description\": \"End-user information\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#api-servers","title":"\u26a0\ufe0f api-servers","text":"

A server should be defined at the root document level. This can be localhost, a development server, or a production server.

Valid OpenAPI V3 Example

{\n\"servers\": [\n{\n\"url\": \"https://staging.myprodserver.com/v1\",\n\"description\": \"Staging server\"\n},\n{\n\"url\": \"https://myprodserver.com/v1\",\n\"description\": \"Production server\"\n}\n]\n}\n

Valid OpenAPI V2 Example

{\n\"host\": \"myprodserver.com\",\n\"basePath\": \"/v2\",\n\"schemes\": [\n\"https\"\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#server-trailing-slash","title":"\u26a0\ufe0f server-trailing-slash","text":"

Server URLs should not end in forward slashes. This is a best practice for working with web tooling, such as mock servers, code generators, application frameworks, and more.

Invalid Example

{\n\"servers\": [\n{\n\"url\": \"https://api.openweathermap.org/data/2.5/\"\n}\n]\n}\n

Valid Example

{\n\"servers\": [\n{\n\"url\": \"https://api.openweathermap.org/data/2.5\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#server-not-example","title":"\u26a0\ufe0f server-not-example","text":"

Server URLs must not direct to example.com. This helps ensure URLs are valid before you distribute your API document.

Invalid Example

{\n\"servers\": [\n{\n... ,\n\"url\": \"https://example.com\"\n}\n]\n}\n

Valid Example

{\n\"servers\": [\n{\n... ,\n\"url\": \"https://api.openweathermap.org/data/2.5\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#parameter-description","title":"\u26a0\ufe0f parameter-description","text":"

All parameter objects should have a description.

Valid Example

{\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"integer\"\n},\n... ,\n... ,\n\"description\": \"The number of days to include in the response.\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#oas2-anyof","title":"\u26a0\ufe0f oas2-anyOf","text":"

The anyOf keyword is not supported in OAS2. Only allOf is supported.

Invalid Example

{\n\"schema\": {\n\"anyOf\": [\n{\n\"properties\": {\n\"firstName\": {\n\"type\": \"string\"\n},\n\"lastName\": {\n\"type\": \"string\"\n}\n}\n},\n{}\n]\n}\n}\n

Valid Example

{\n\"schema\": {\n\"type\": \"object\",\n\"properties\": {\n\"firstName\": {\n\"type\": \"string\"\n},\n\"lastName\": {\n\"type\": \"string\"\n}\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#oas2-oneof","title":"\u26a0\ufe0f oas2-oneOf","text":"

The oneOf keyword is not supported in OAS2. Only allOf is supported.

Invalid Example

{\n\"schema\": {\n\"oneOf\": [\n{\n\"properties\": {\n\"firstName\": {\n\"type\": \"string\"\n},\n\"lastName\": {\n\"type\": \"string\"\n}\n}\n},\n{}\n]\n}\n}\n

Valid Example

{\n\"schema\": {\n\"type\": \"object\",\n\"properties\": {\n\"firstName\": {\n\"type\": \"string\"\n},\n\"lastName\": {\n\"type\": \"string\"\n}\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#oas3-examples-value-or-externalvalue","title":"\u26a0\ufe0f oas3-examples-value-or-externalValue","text":"

The examples object should include a value or externalValue field, but cannot include both.

Invalid Example

This example includes both a value field and an externalValue field.

{\n\"examples\": {\n\"example-1\": {\n\"value\": {\n\"id\": \"string\",\n\"name\": \"string\"\n},\n\"externalValue\": {\n\"id\": \"string\",\n\"name\": \"string\"\n}\n}\n}\n}\n

Valid Example

This example includes only a value field.

{\n\"examples\": {\n\"example-1\": {\n\"value\": {\n\"id\": \"string\",\n\"name\": \"string\"\n}\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#path-parameters-on-path-only","title":"\u26a0\ufe0f path-parameters-on-path-only","text":"

Path parameters should be defined on the path level instead of the operation level.

Invalid Example

The user_id path parameter on line 8 should not be included with the patch operation.

{      \"patch\": {\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"integer\"\n},\n\"name\": \"user_id\",\n\"in\": \"path\"\n}\n]\n}\n}\n

Valid Example

The user-id path parameter is correctly located at the path level.

{\n\"paths\": {\n\"/users/{userId}\": {\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"integer\"\n},\n\"name\": \"user_id\",\n\"in\": \"path\"\n}\n]\n}\n}\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#paths-no-query-params","title":"\u26a0\ufe0f paths-no-query-params","text":"

Paths should not have query parameters in them. They should be defined separately in the OpenAPI.

Invalid Example

{\n\"/users/{?id}\": {\n

Valid Example

{\n\"parameters\": [\n{\n\"schema\": {\n\"type\": \"string\"\n},\n\"name\": \"id\",\n\"in\": \"path\",\n\"required\": true,\n\"description\": \"User's ID\"\n}\n]\n}\n
"},{"location":"api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/#i-operation-singular-tag","title":"\u2139\ufe0f operation-singular-tag","text":"

Operation should not have more than a single tag.

"},{"location":"api-management/api-policies/about-api-policies/","title":"About API Policies","text":"

API policies are units of business logic that you can apply to modify the flow of API invocations.

You can apply a policy to alter the Request, Response, or Error flow of an API invocation before it reaches the backend or the client. For example, you can add a policy to the response flow to transform the payload from JSON to XML and add a header to the response.

"},{"location":"api-management/api-policies/about-api-policies/#inbuilt-mediation-policies","title":"Inbuilt mediation policies","text":"

Choreo supports a set of inbuilt mediation policies that can handle common API transformation and mediation tasks. These policies run within a single mediation service, making it straightforward to implement and manage complex mediation logic. The following inbuilt policies are available in Choreo:

  • JSON to XML: Transforms a JSON payload in a request or response into XML format. This policy is applicable only to JSON payloads in mediation flows. Applying it to a non-JSON payload terminates the flow. This policy cannot be used more than once on the same resource because the payload will already be converted to XML.
  • XML to JSON: Converts an XML payload in a request or response into JSON format. This policy is applicable only to XML payloads in mediation flows. Applying it to a non-XML payload terminates the flow. This policy cannot be used more than once on the same resource because the payload will already be converted to JSON.
  • Remove Query Parameter: Removes specified query parameters from a request. You can use this policy multiple times to remove different parameters. Attempting to remove a non-existent parameter has no effect. If the parameter exists, it will be removed; otherwise, the request proceeds as usual.
  • Remove Header: Removes specified headers from a request or response. You can attach this policy multiple times to remove multiple headers. The header name must be static, but you can use placeholders to configure different values for different environments. For example, ${headerName}.
  • Add Query Parameter: Adds query parameters to a request. You can attach this policy multiple times to add various parameters. Adding the same parameter multiple times creates an array of values. The parameter name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${fooValue}.
  • Add Header: Adds headers to a request or response. If the same header is added multiple times, values are appended rather than overwritten. The header name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${authzHeaderValue}.
  • Set Header: Sets headers in a request or response, overwriting any existing values. You can attach this policy multiple times to set multiple headers. Each time the same header is set, it replaces the previous value. The header name and value must be static, but you can use placeholders to configure different values for different environments. For example, ${authzHeaderValue}.
  • Rewrite Resource Path: Modifies the resource path of an HTTP request by replacing the original path with a new relative path. You can apply this policy multiple times, but only the last instance will take effect. The new path must be static, but you can use placeholders to configure different values for different environments. For example, ${myResourcePath}.
  • Log Message: Logs the payload and headers of a request or response. Attaching this policy multiple times results in duplicate log entries. By default, headers and payloads are not logged. To log them, you can enable Log Headers and Log Payload parameters. To exclude specific headers when logging, you can use the Excluded Headers parameter, which takes a comma-separated list of header names. An error will occur if payload logging is enabled but the payload cannot be read.

These inbuilt mediation policies provide flexibility to manage API requests and responses, allowing for custom transformations and logic without requiring custom code.

For details on attaching and managing one or more policies to an API proxy component implementation via the Choreo Console, see Attach and Manage Policies.

For details on applying advanced settings on mediation policies, see Apply Advanced Settings on Mediation Policies.

"},{"location":"api-management/api-policies/apply-advanced-settings-on-mediation-policies/","title":"Apply Advanced Settings on Mediation Policies","text":"

Advanced settings for mediation policies are available for proxy components with an attached mediation policy. For details on attaching a mediation policy to a proxy component, see Attach and Manage Policies.

The approach to applying advanced settings depends on whether the proxy component is deployed or not.

"},{"location":"api-management/api-policies/apply-advanced-settings-on-mediation-policies/#mediation-policy-advanced-settings","title":"Mediation policy advanced settings","text":"Setting Purpose How to apply Impact HTTP version By default, Choreo supports HTTP 1.1. If necessary, you can change to HTTP 1.0 or HTTP 2.0. Specify the required HTTP version in the Advanced Settings field. The mediation application will use the specified HTTP version when interacting with backend services. Hostname verification Choreo enables hostname verification by default when using mTLS. You can disable it if necessary. Set the verifyHostname parameter to false in the Advanced Settings field. Hostname verification will be skipped during mTLS interactions. Minimum evictable idle time Determines how long (in seconds) an outgoing connection remains idle before eviction. The default is 300 seconds. Set the required idle time in the Advanced Settings field. Idle connections will be closed and evicted after the defined period. Detailed access log By default, logs related to the mediation application are generated and can be viewed as runtime logs. You can disable these logs if necessary. Set the detailedAccessLog parameter in the Advanced Settings field. Logs related to the mediation application will not be generated."},{"location":"api-management/api-policies/apply-advanced-settings-on-mediation-policies/#configure-advanced-settings-for-a-proxy-component","title":"Configure advanced settings for a proxy component","text":"

To configure advanced settings for a proxy component with an attached mediation policy, follow these steps:

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the REST API Proxy component for which you want to configure advanced settings.
  3. In the left navigation menu, click Deploy.
  4. Depending on the deployment status of the proxy component, follow one of these steps:
  5. If the proxy component is not deployed, go to the Set Up card and click Configure & Deploy.
  6. If the proxy component is already deployed, go to the respective environment card depending on the environment you want to apply advanced settings, and then click the Environment Variables icon.
  7. In the Configurations pane that opens, expand the Defaultable Configurables section.
  8. In the Advanced Settings field, configure the necessary settings as described in the Mediation policy advanced settings section.
  9. Click Save & Deploy.
"},{"location":"api-management/api-policies/attach-and-manage-policies/","title":"Attach and Manage Policies","text":"

You can easily attach one or more policies to an API proxy component implementation via the Choreo Console. If necessary, you can also rearrange or swap the policies you attach.

In Choreo, when you attach a mediation policy to a proxy, the deployment is a two-step process.

  1. Deployment initiation:

    If the component to which you want to attach the mediation policy is new, the system creates and commits a new repository with the mediation service code based on the attached policy. This new service is called the mediation application.

  2. Deploying the API:

    Once the deployment initiation is complete, you can specify configuration values if any, and proceed to deploy. Choreo builds the generated mediation application and pushes the Docker image to the Docker registry. Finally, Choreo deploys the mediation application with the API Proxy.

When a mediation policy is attached to a specific flow, the API invocation undergoes the following behavioral modification:

  • In the request path, the requests that pass through the gateway reach the relevant component, and Choreo executes any attached policies to the resource's request path before sending it to the backend.

  • In the response path, the mediation component receives response messages from the backend, and Choreo executes any mediation policies attached to the Response flow or the Error flow. Then the response is forwarded to the client.

  • If an error occurs during the execution of policies or due to an internal error, Choreo executes the Error flow and sends an error response to the client.

"},{"location":"api-management/api-policies/attach-and-manage-policies/#attach-a-policy","title":"Attach a policy","text":"

To attach a policy to the Request, Response, or Error flow of a REST API proxy, follow the steps given below:

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the REST API Proxy component for which you want to attach a policy.
  3. In the left navigation menu, click Develop and then click Policies.
  4. From the list of resources, expand the resource to which you want to attach the policy.
  5. Click Attach Mediation Policy in the respective flow for which you want to attach a policy.
  6. In the Policy List pane that opens, click on a required policy to view its details.
  7. If the attached policy requires parameter configuration, on the policy pane enter the appropriate values and configure the parameters. To make a parameter a configurable variable, input the value in the ${<variableName>} format. For example, you can use ${name} as an example.

  8. To attach the policy, click Add.

After attaching an API Policy, it is necessary to deploy the API for the policy to become active within its corresponding flow. To deploy the API follow the steps below:

  1. In the left navigation menu, click Deploy and then click Configure & Deploy. Choreo performs the mediation application generation step and opens the Configure & Deploy pane.

  2. In the Configure & Deploy pane, if you have any configurable variables that require values, specify appropriate values for them.

  3. Click Save & Deploy.

"},{"location":"api-management/api-policies/attach-and-manage-policies/#refresh-mediation-policies","title":"Refresh mediation policies","text":"

Choreo selectively generates and builds the mediation application code during component deployment depending on specific changes. These changes include:

  • Addition, deletion, or modification of API resources.
  • Attachment, removal, or editing of API mediation policies.
  • Endpoint modifications via the Develop page.
  • Initial configuration or removal of backend endpoints or mutual TLS certificates.

If none of the above changes occur during deployment, Choreo skips the code generation and build process of the mediation application.

Info

  • If you want to enforce the code generation and build process of the mediation application in instances where the specified changes do not take place, you must turn on the Refresh Mediation Policies toggle when you configure and deploy the component.
  • It is useful to enable Refresh Mediation Policies when you want to incorporate the latest Ballerina patches for your generated mediation application. However, this can result in longer deployment times.
"},{"location":"api-management/api-policies/attach-and-manage-policies/#implement-an-api-policy","title":"Implement an API policy","text":"

Choreo allows you to implement an API policy as a Ballerina project and attach it to an API proxy component.

Info

Supported Ballerina version: 2201.5.5

To implement a policy, follow the steps given below:

"},{"location":"api-management/api-policies/attach-and-manage-policies/#prerequisites","title":"Prerequisites","text":"
  1. Set up Ballerina 2201.5.5.
  2. Open the ~/.ballerina/settings.toml file and ensure you have configured an access token to Ballerina Central. If you have not configured an access token, follow the steps given below to configure one:
    1. Generate a token via https://central.ballerina.io/dashboard?tab=token.
    2. Download the generated Settings.toml file and copy it to your local ~/.ballerina directory.

Alternatively, you can set the access token via the BALLERINA_CENTRAL_ACCESS_TOKEN environment variable.

export BALLERINA_CENTRAL_ACCESS_TOKEN=<access-token> \n
"},{"location":"api-management/api-policies/attach-and-manage-policies/#step-1-initialize-a-ballerina-project","title":"Step 1: Initialize a Ballerina project","text":"

Choreo provides a template to initialize a mediation policy project with all the required configurations. The mediation policy project will be created as a Ballerina project.

To create a Ballerina project for the mediation policy using mediation.template as the project template, issue the following command:

Format:

    bal new -t choreo/mediation.template:1.0.0 <policy-name> \n

Example:

    bal new -t choreo/mediation.template:1.0.0 validateHeader \n
The Ballerina project that is created should have the following content:

Depending on your requirement, you can modify the Ballerina.toml and the Package.md files of the generated project. For example, you can update the org, package, package version, API documentation content, keywords, etc.

Note

To successfully publish to Ballerina Central, make sure you update the org value to your organization name.

     [package]\n        org = \"starkindustries\"\n        name = \"validateHeader\"\n        version = \"1.0.0\"\n        export = [\"validateHeader\"]\n        distribution = \"2201.5.5\"\n        keywords = [\"choreo-apim-mediation-policy\",\"choreo-apim-mediation-request-flow\",\"choreo-apim-mediation-response-flow\",\"choreo-apim-mediation-fault-flow\"]\n
"},{"location":"api-management/api-policies/attach-and-manage-policies/#step-2-implement-the-policy","title":"Step 2: Implement the policy","text":"

In this step, you will implement the policy.

Let's assume you want to implement a policy to validate an incoming header in the request and the response.

  • Request path: If the request header is not present or if the validation fails, you want to log an error and return a 403 Bad Request response to the client.
  • Response path: You want to log a message to indicate whether the request is valid or not.

To implement the policy, open the policy.bal file in the Ballerina project and update the generated policy stubs(i.e., request, response, or fault) appropriately.

The following sections walk you through sample implementations for the Request and Response stubs:

Request flow

The following is a sample implementation for the request flow:

@mediation:RequestFlow\npublic function validateRequestHeader(mediation:Context ctx, http:Request req, string headerName, string headerValue) returns http:Response|false|error|() {\n   string|http:HeaderNotFoundError header = req.getHeader(headerName);\n   if (header is http:HeaderNotFoundError) {\n    string message = string `Header ${headerName} is not found`;\n    log:printError(message);\n    return generateResponse(message, http:STATUS_BAD_REQUEST);\n   }\n   if (header != headerValue) {\n    string validationFailedMessage = string `Header validation failed. Expected ${headerValue} but found ${header}`;\n    log:printError(validationFailedMessage);\n    return generateResponse(validationFailedMessage, http:STATUS_BAD_REQUEST);\n    }\n    log:printInfo(\"Header validation successful\");\n    return ();\n};\n\nfunction generateResponse(string message, int statusCode) returns http:Response {\n    http:Response response = new();\n    response.setTextPayload(message); \n    response.statusCode = statusCode;\n    return response;\n}\n
Response flow

The following is a sample implementation for the response flow:

@mediation:ResponseFlow\npublic function validateResponseHeader(mediation:Context ctx, http:Request req, http:Response res, string headerName, string headerValue) returns http:Response|false|error|() { \n   string|http:HeaderNotFoundError header = res.getHeader(headerName);\n   if (header is http:HeaderNotFoundError) {\n    string message = string `Header ${headerName} is not found`;\n    log:printError(message);\n    return ();\n   }\n   if (header != headerValue) {\n    string validationFailedMessage = string `Header validation failed. Expected ${headerValue} but found ${header}`;\n    log:printError(validationFailedMessage);\n    return ();\n   }\n   return ();\n}\n
Fault flow

In this guide, you are not going to make any changes to the Fault flow. Therefore, you can remove the Fault flow stub from the policy.bal file.

Note

The @mediation:RequestFlow, @mediation:ResponseFlow, and @mediation:FaultFlow annotations are bound with the keywords in the Ballerina.toml. Therefore, the changes you make to the policy stubs should reflect in the Ballerina.toml file. For example, if the policy is applicable only on the request and response paths, you can remove the @mediation:FaultFlow annotation from the policy. Then, you MUST also remove the choreo-apim-mediation-fault-flow keyword from the generated Ballerina.toml file. If you do not do so, the Ballerina compiler will show an error at compile time.

Publish as a private custom policy

Choreo supports publishing a policy as a private custom policy. Publishing a policy as a private custom policy makes the policy inaccessible outside of the organization. To publish a policy as a private custom policy, change the visibility to private prior to pushing the package to Ballerina Central as follows:

  1. Open the Ballerina.toml file of your policy.
  2. Set the visibility to private by adding the configuration visibility=\"private\". For example:

    [package]\n   org = \"orgName\"\n   name = \"packageName\"\n   version = \"1.0.2\"\n   export = [\"packageName\"]\n   distribution = \"2201.5.5\"\n   keywords = [\"choreo-apim-mediation-policy\",\"choreo-apim-mediation-request-flow\",\"choreo-apim-mediation-response-flow\",\"choreo-apim-mediation-fault-flow\"]\n   visibility = \"private\"\n
  3. Package and publish your policy to Ballerina Central.

Best practices

When implementing a policy, it is essential to follow best practices to ensure efficiency and maintainability. Here are some recommended best practices to follow:

  • Organize the source code within the default module of the package. Do not add any additional modules.
  • A policy implementation can contain any combination of flows. A generated project contains stubs for all three flows: Request, Response, and Fault. You can remove any stub that you do not require. For example, when you create a policy that re-writes the resource paths, you can remove the Response and fault stubs.
  • The HTTP request/response objects and context record parameters gets passed as references to the policy functions. Therefore, the changes you make to these values persist throughout the policy execution and are propagated to subsequent policies. This behavior allows the request and response objects to accumulate transformations applied by attached policies.
  • Familiarize yourself with the different return types of policy flows. The following return types are unmodifiable:
    • http:Response - Returns an HTTP response when you terminate the mediation flow prematurely. For example, in the in-flow sequence, the mediation sequence terminates before calling the backend. The mediation policy then sends an HTTP response to the client.
    • false - Returns false if you want to terminate the mediation sequence with a predefined response (on the Choreo side).
    • error - Returns an error if you want to terminate the mediation flow and transfer control to the fault flow. The fault flow would then construct an error response and send it to the client.
    • () - Returns () to signal the successful completion of the policy. Once the proxy has completed executing the policy, it starts to execute the next policy in the sequence.
"},{"location":"api-management/api-policies/attach-and-manage-policies/#step-3-publish-the-policy","title":"Step 3: Publish the policy","text":"

Once you implement a policy, you must publish it to Ballerina Central.

When you attach a policy and deploy an API, Choreo pulls the necessary packages from Ballerina Central and bundles them into the mediation application under the hood. Therefore to use policies in your APIs, you must publish them as public packages.

To publish the policy, follow the steps given below:

  1. To package the policy before you publish it to Ballerina Central, issue the following command:
        bal pack \n
  2. To publish the package to Ballerina Central, issue the following command:

        bal push \n

Once you publish the package, it will appear as follows in the policy list:

"},{"location":"api-management/api-policies/attach-and-manage-policies/#write-unit-tests","title":"Write unit tests","text":"

You can write unit tests to test policy functions in a manner similar to how you write unit tests for a regular Ballerina function.

The following is a sample unit test for the validateRequestHeader function:

import ballerina/http;\nimport choreo/mediation;\nimport ballerina/test;\n\n@test:Config {}\npublic function testRequestHeaderValidationFailure() {\n  http:Request req = new;\n  http:Response|false|error|() result = validateRequestHeader(createContext(\"get\", \"/test\"), req, \"testHeader\", \"test\");\n\n  if !(result is http:Response) {\n    test:assertFail(\"Expected http:Response, found \" + (typeof result).toString());\n  }\n\n  test:assertEquals(result.statusCode, http:STATUS_BAD_REQUEST, \"Status code mismatch\");\n}\n\nfunction createContext(string httpMethod, string resPath) returns mediation:Context {\n   mediation:ResourcePath originalPath = checkpanic mediation:createImmutableResourcePath(resPath);\n   mediation:Context originalCtx =\n               mediation:createImmutableMediationContext(httpMethod, originalPath.pathSegments(), {}, {});\n   mediation:ResourcePath mutableResPath = checkpanic mediation:createMutableResourcePath(resPath);\n   return mediation:createMutableMediationContext(originalCtx, mutableResPath.pathSegments(), {}, {});\n}\n

The policy function modifies the same request/response/context instance that you pass to it. You can check the request/response/context instance after calling the policy function to verify changes.

"},{"location":"api-management/api-policies/attach-and-manage-policies/#glossary","title":"Glossary","text":"

Here are some of the common terms used when working with policies in Choreo:

mediation:Context

The mediation context is used to pass parameters between policies. It is created per request and you can access it in any of the flows. For example, if a correlation ID needs to be set to the request, you can set it in the context of the request flow and access it in the response or fault flow.

The mediation context can include the following functions:

# Retrieves the value for the specified key.   \npublic function get(string name) returns anydata;\n\n# Stores the provided key-value pair. If a mapping exists for the key, the value is overwritten.\npublic function put(string name, anydata value);\n\n# Removes the entry mapped by the specified key and returns the removed value.\npublic function remove(string name) returns anydata;\n\n# Retrieves the value for the specified key. If there is no mapping for the key, return the specified\npublic function getOrDefault(string name, anydata default) returns anydata;\n\n# Checks whether a mapping exists for the specified key.\npublic function hasKey(string name) returns boolean;\n\n# Returns the `mediation:Context` instance which captured the initial contextual information of the resource,\n# before the mediation flow was invoked. Calling this on an original `mediation:Context` object will return itself.\npublic function originalContext() returns Context;\n\n# The HTTP method of the resource method\npublic function httpMethod() returns string;\n\n# Retrieves an instance of `mediation:ResourcePath` which is an API for contextual information on the resource path\n# of this resource. It also contains methods for modifying the resource path as the user sees fit. This resource\n# path is the same path used by the mediation service for deriving the backend endpoint's resource to invoke.\n# Therefore, the default behavior of the mediation service is to invoke a resource in the backend endpoint which\n# has the same relative resource path as the corresponding mediation service resource.\npublic function resourcePath() returns ResourcePath;\n\n# Sets the given `mediation:ResourcePath` instance as the resource path of this context.\npublic function setResourcePath(ResourcePath path);\n\n# Adds a mapping between a path param name and a resolved value for it. There need not be a path parameter in the\n# resource path by the name specified in `name` for one to use this method. On its own, the path param values have\n# no bearing on the resource path.\npublic function addPathParamValue(string name, PathParamValue value);\n\n# Returns the collection of resolved values for the path parameters in this particular context, mapped\n# by the parameter name.\npublic function resolvedPathParams() returns map<PathParamValue> & readonly;\n\n# Removes the resolved path parameter value which maps to the specified name.\npublic function removePathParamValue(string name);\n\n# Adds a query parameter to the request to be sent to the backend. If there is already a query parameter by\n# with the same name, the new value will be appended to it, making it an array.\npublic function addQueryParam(string name, string value);\n\n# Removes the specified query parameter from the request. If the value of the parameter is an array, the whole\n# array will be removed.\npublic function removeQueryParam(string name);\n\n# Retrieves a map of all the query parameters in the current request context. The returned map is a read-only snapshot\n# of the map of query parameters in the context at the time this method was called.\npublic function queryParams() returns map<string[]> & readonly;\n
"},{"location":"api-management/api-policies/attach-and-manage-policies/#keywords","title":"Keywords","text":"

The Ballerina.toml file needs to include the following keywords for the mediation policies to work:

  • choreo-apim-mediation-policy: This keyword is a mandatory keyword that is required to identify that the package is a mediation policy type.
  • choreo-apim-mediation-request-flow: Specifies whether the policy applies to the request flow.
  • choreo-apim-mediation-response-flow: Specifies whether the policy applies to the response flow.
  • choreo-apim-mediation-fault-flow: Specifies whether the policy is applicable for the fault flow.
Policy name and description

The Package.md file contains information about the policy. Choreo uses this information to render the policy configuring UI. This file is written in Markdown format and should be structured as follows.

Format:

# <policy-name>\n\n## Overview\n\n<policy description>\n

Example:

# ValidateHeader\n\n## Overview\n\nThis policy validates the request and response headers with the configured values.\n
Policy versioning

When it comes to policy versioning in Choreo or mediation dependencies, it is important to consider the major version changes in the Ballerina language. For example, transitioning from update 1 to update 2 requires a major version increment, which can introduce significant incompatibilities.

Therefore, to ensure compatibility, the recommended approach is to version the policy package in a manner that the major version gets upgraded when the Choreo/mediation dependency version is upgraded to a major version.

"},{"location":"api-management/manage-api-traffic/assign-subscription-plans-to-apis/","title":"Assign Subscription Plans to APIs","text":"

API subscription plans allow API publishers to control and manage access to APIs. These plans define the rules and limitations on how clients can interact with APIs, ensuring efficient resource utilization and robust security.

Choreo allows users with the administrator role to create, update, and delete subscription plans at the organization level. For instructions on creating subscription plans, see Create API Subscription Plans.

Once created, Choreo allows API publishers to assign subscription plans to APIs, providing different levels of access based on user needs.

To assign subscription plans to an API, follow the steps given below:

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the component for which you want to assign subscription plans.
  3. In the left navigation menu, click Manage and then click Subscription Plans. This displays the subscription plans available for the component.
  4. Enable the Subscription Plan Status toggle corresponding to the subscription plans you want to assign to the API.

  5. Click Save.

When an API has subscription plans assigned to it, API consumers can select the plan that best fits their requirements during the subscription process. For details, see Subscribe to an API with a Subscription Plan

"},{"location":"api-management/manage-api-traffic/subscribe-to-an-api-with-a-subscription-plan/","title":"Subscribe to an API with a Subscription Plan","text":"

If an API has subscription plans assigned to it, API consumers can select the subscription plan that best fits their requirements at the time of subscribing to the API.

To subscribe to an API with a subscription plan, follow the steps given below:

  1. Sign in to the Choreo Developer Portal.
  2. In the Developer Portal header, click Applications.
  3. On the My Applications page, click on the application you want to use to subscribe to an API.
  4. In the left navigation menu, click Subscriptions.
  5. In the Subscription Management pane that opens, click + Add APIs.
  6. In the Add APIs pane that opens, select the API, API version, and subscription plan with which you want to subscribe to the API.
  7. Click Add Subscription.

To verify that the subscription plan works as expected, follow the steps given below:

  1. In the Developer Portal header, click APIs.
  2. Search for the API you subscribed to and click Try Out.
  3. Invoke the API until you exceed the request limit set in the subscription plan. You will see that the API throttles further requests once the limit is reached.

"},{"location":"authentication-and-authorization/configure-mutual-tls-between-components/","title":"Configure Mutual TLS Between Components","text":"

Mutual transport layer security (mutual TLS) is a protocol that ensures privacy, integrity, and authentication of the data transmitted between two endpoints. In mutual TLS, the client and the server authenticate each other using digital certificates, establishing trust and verifying identities. Upon successful authentication, mutual TLS encrypts the data exchanged between the client and the server, preventing unauthorized access.

In Choreo, you can use mutual TLS to establish secure connections between components within a project.

Note

If mutual TLS is not required, you can configure TLS instead. TLS provides a secure communication channel between a client and server but does not require the client to present a certificate to the server. This results in the absence of mutual authentication between the client and the server. While TLS ensures the confidentiality of data transmitted between the client and server, preventing unauthorized tampering, mutual TLS enhances TLS by introducing client-side authentication and facilitating mutual verification of identities between the client and server.

To configure TLS, you can follow the same steps as for mutual TLS as mentioned below, without having to generate a client certificate. The client only needs the root certificate to verify the server's identity.

"},{"location":"authentication-and-authorization/configure-mutual-tls-between-components/#generate-certificates-to-establish-mutual-tls","title":"Generate certificates to establish mutual TLS","text":"
  • Root certificate: Trusted by both the client and the server, this certificate is used to verify the authenticity of other certificates presented during the mutual TLS handshake process and to issue certificates for clients and servers. For a specific project, you can generate a single root certificate using a tool like OpenSSL.

  • Client certificate: Contains the client\u2019s identity for authentication. The common name (CN) in the certificate identifies the client. The generated client certificate must be signed by the root certificate.

  • Server certificate: Clients use the server certificate to verify the trustworthiness of the server and establish a secure and authenticated connection. Similar to the client certificates, the server certificate must also be signed by the root certificate. When generating the server certificate, you must specify the server's hostname for the subject alternative name (SAN). You can obtain the hostname for the specific version of a service component from any project endpoint on the Overview page.

For example, if your project endpoint is http://my-service-3781140846:7080/todos, the hostname will be my-service-3781140846.

"},{"location":"authentication-and-authorization/configure-mutual-tls-between-components/#read-mutual-tls-certificates-from-your-component","title":"Read mutual TLS certificates from your component","text":"

The approach to read mutual TLS certificates from a component can vary depending on its implementation. Typically, a component can read the certificate data from the file system or via an environment variable. For detailed instructions on adding environment variables and file mounts to your application, see Manage Configurations and Secrets.

Info

When you specify a private key, ensure you save it as a secret.

"},{"location":"authentication-and-authorization/configure-mutual-tls-between-components/#sample-for-mutual-tls-communication","title":"Sample for mutual TLS communication","text":"

For a sample that demonstrates how you can deploy services that communicate using mutual TLS, see service-to-service-mtls.

"},{"location":"authentication-and-authorization/pass-end-user-attributes-to-upstream-services/","title":"Pass End-User Attributes to Upstream Services","text":"

There are scenarios where a backend service needs to apply specific logic or make decisions depending on the user consuming an API. In such scenarios, you must pass end-user attributes to the backend during an API call.

Choreo provides a method to send user information to a backend service through a JSON Web Token (JWT) in an HTTP header of an API request.

"},{"location":"authentication-and-authorization/pass-end-user-attributes-to-upstream-services/#how-it-works","title":"How it works","text":"

The backend JWT contains claims transferred between the parties, such as the user and the backend. A claim can be metadata of the request or data about the user. A set of claims is called a dialect, for example, http://wso2.org/claims.

For each API request, a digitally signed JWT is carried to the backend service in the following format to ensure that the authenticity of the claims list is verified:

{token header}.{claims list}.{signature}

When a request goes through Choreo, the backend JWT is appended as the\u00a0X-JWT-Assertion\u00a0header in the outgoing message. The backend service fetches the JWT and retrieves the required information about the user, application, or token.

"},{"location":"authentication-and-authorization/pass-end-user-attributes-to-upstream-services/#claims","title":"Claims","text":"

Claims are fragments of information included in the JWT.

The following is a sample claim set added to the end-user token for an access token generated via the authorization code:

Tip

This access token is generated via Asgardeo using the authorization code grant type. Here, the Asgardeo application is configured to include the email claim in the token.

{\n\"sub\": \"11f53c32-f8ac-4810-bb79-615b2184baf5\",\n\"http://wso2.org/claims/apiname\": \"JWT Test - Endpoint 9090 803\",\n\"http://wso2.org/claims/applicationtier\": \"Unlimited\",\n\"http://wso2.org/claims/version\": \"1.0.0\",\n\"http://wso2.org/claims/keytype\": \"PRODUCTION\",\n\"iss\": \"wso2.org/products/am\",\n\"http://wso2.org/claims/applicationname\": \"jwtTest2\",\n\"http://wso2.org/claims/enduserTenantId\": \"0\",\n\"http://wso2.org/claims/applicationUUId\": \"45101ccb-865f-4f48-b7ac-18e43b07edd3\",\n\"client_id\": \"IMJB5ZiR1dHQYBdiMIRAGis1WToa\",\n\"http://wso2.org/claims/subscriber\": \"5f4a7105-a889-4f92-9612-eef5bafe4eec\",\n\"azp\": \"IMJB5ZiR1dHQYBdiMIRAGis1WToa\",\n\"org_id\": \"b554e001-761c-4d3a-a7a6-a61d73d34221\",\n\"http://wso2.org/claims/tier\": \"Unlimited\",\n\"scope\": \"email openid profile\",\n\"exp\": 1690537362,\n\"http://wso2.org/claims/applicationid\": \"45101ccb-865f-4f48-b7ac-18e43b07edd3\",\n\"http://wso2.org/claims/usertype\": \"Application_User\",\n\"org_name\": \"test\",\n\"iat\": 1690533762,\n\"email\": \"testmail@gmail.com\",\n\"jti\": \"69558555-d386-4a81-9ca0-0a23f809cd3c\",\n\"http://wso2.org/claims/apicontext\": \"/b554e001-761c-4d3a-a7a6-a61d73d34221/swog/jwt-test/endpoint-9090-803/1.0.0\"\n}\n

The following table describes the information contained in the sample JWT claims set given above:

Claim Name Description Mandatory/Optional iat The time the token was issued. Mandatory jti The unique token identifier. Mandatory exp The token expiry time. Mandatory iss The issuer of the token. Mandatory http://wso2.org/claims/apiname The name of the API in Choreo. Optional http://wso2.org/claims/version The API version. Optional http://wso2.org/claims/keytype The environment in Choreo that the API is in (Development or production). Optional http://wso2.org/claims/apicontext The API context in Choreo. Optional http://wso2.org/claims/subscriber The subscriber to the API, usually the app developer. Optional http://wso2.org/claims/applicationname The application through which the API invocation is done. Optional http://wso2.org/claims/applicationid The ID of the application through which the API invocation is done. Optional http://wso2.org/claims/applicationUUId The UUID of the application. Optional client_id The client identifier. This is copied from the original token. Optional azp The authorized party (the party to which the ID token was issued). This is copied from the original token. Optional org_id The organization ID. This is copied from the original token. Optional org_name The organization name. This is copied from the original token. Optional http://wso2.org/claims/tier The tier/price band for the subscription. Optional scope The scope of the token. This is copied from the original token. Optional http://wso2.org/claims/usertype The type of application user whose action invoked the API. Optional email The email address of the user. This is copied from the original token. Optional

Note

The claims that get added to the end-user token can vary depending on the grant type used when generating the access token. For example, if you use the client-credentials grant type to generate the access token, the generated backend JWT would contain the following information:

{ \"http://wso2.org/claims/apiname\": \"DefaultAPI\", \"http://wso2.org/claims/version\": \"1.0.0\", \"http://wso2.org/claims/keytype\": \"PRODUCTION\", \"iss\": \"wso2.org/products/am\", \"http://wso2.org/claims/enduserTenantId\": \"0\", \"exp\": 1673245727, \"http://wso2.org/claims/usertype\": \"Application_User\", \"iat\": 1673242127, \"jti\": \"6e3f4392-8bd9-4900-9d08-eaab7429c510\", \"http://wso2.org/claims/apicontext\": \"/9e71ab5e-6df5-4727-92d2-80ecf1a6218d/qbky/default/1.0.0\" }\n

To verify the authenticity of claims in a JWT, the claims must be validated using the public key corresponding to the private key used to sign the JWT.

JSON web key set (JWKS) is a set of keys to validate a JWT. It contains a collection of JSON web keys, which are public keys used to verify the signature of a JWT.

Typically, when a third party (such as an identity provider)issues a JWT and the recipient needs to verify its signature, they can use a JWKS. JWKS allows the issuer to rotate keys dynamically rather than hard-coding the public key in the application. The recipient can obtain the public key by accessing the JWKS endpoint.

"},{"location":"authentication-and-authorization/pass-end-user-attributes-to-upstream-services/#jwks-support-in-choreo-to-validate-the-jwt","title":"JWKS support in Choreo to validate the JWT","text":"

Choreo provides an endpoint to specify the public keys for backend JWT validation. Here are the endpoint URLs for the US East and EU regions:

  • https://gateway.e1-us-east-azure.choreoapis.dev/.wellknown/jwks
  • https://gateway.e1-eu-north-azure.choreoapis.dev/.wellknown/jwks

Note

For private data planes (PDPs), use the following JWKS endpoint URL template:

https://<PDP_GATEWAY_DOMAIN>/.wellknown/jwks

Be sure to replace <PDP-GATEWAY-DOMAIN> with the default domain configured to access the PDP APIs.

The endpoint provides one or more signing keys to validate the JWT. The JSON web keys have a kid identifier that can be matched with the same property on the JWT to decide which key to use when validating.

The following is a sample JWKS response:

{\n\"keys\": [\n{\n\"kty\": \"RSA\",\n\"e\": \"AQAB\",\n\"use\": \"sig\",\n\"kid\": \"ZjcwNmI2ZDJmNWQ0M2I5YzZiYzJmZmM4YjMwMDFlOTA4MGE3ZWZjZTMzNjU3YWU1MzViYjZkOTkzZjYzOGYyNg\",\n\"alg\": \"RS256\",\n\"n\": \"8vjeHzRhvpfMystncPnLBWy_t5F3eCxbcLbdugWnzfnIgaV6TWnqPBUagJBKpzRZs4A9Qja_ZrSVJjYsbARzCS_qiWp0Cdwkqn6ZCXpmbpfjYnKORq8N8M-zWaSZYbNvWJ5oSO4kH-LKWzODaFebwTJBpsR1vChHH95doxFuUjiZaisVaQgUJ6drRdlDtImp9r9EAX36YROuYFPoEJcvsH4_uuAR6ClJ12RE3M-YN4NTi1waVNvGbz43oNrpPy7SXgpizingxSGMqI6WU2ysRmk_f9ALgiPIpFDpufiCTYaIcRT-YcUyp9nMDlTRskMuD-dQ1sdJOa11P_yMs-glfQ\"\n}\n]\n}\n

The following table describes the information contained in the JWKS response:

Property Description kty The cryptographic family to which the key belongs. Choreo only supports RSA. e The exponent value of the public key. use The purpose of the key. For example, whether it is for signing or encryption. kid The identification parameter to match a specific key. alg The algorithm to use with the key. n The modulus value of the public key."},{"location":"authentication-and-authorization/pass-end-user-attributes-to-upstream-services/#enable-passing-end-user-attributes-to-the-backend","title":"Enable passing end-user attributes to the backend","text":"

To enable passing end-user attributes to the backend through API calls via Choreo, follow the steps given below:

  1. Sign in to the Choreo Console.
  2. In the Components Listing\u00a0pane, click on the component for which you want to pass end-user attributes to the backend.
  3. In the left navigation menu, click\u00a0Deploy.
  4. Go to the Set Up card and click Endpoint Configurations. This opens the Endpoint Configurations pane.

    Note

    If the component is an API Proxy, go to the Build Area card and click Security Settings. This opens the Security Settings pane.

  5. Select the\u00a0Pass Security Context To Backend checkbox.

  6. Optionally, specify appropriate audience values in the End User Token Audiences field. Specifying values restricts the JWT to the respective audiences, enabling the backend service to validate and confirm the intended recipients, including itself.

    Note

    The backend JWT does not include the audience field (aud) by default.

  7. Click\u00a0Apply.

  8. To redeploy the component with the applied setting, go to the Set Up card and click Deploy.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/","title":"Secure API Access with Asgardeo","text":"

API security refers to the measures and practices used to protect Application Programming Interfaces (APIs) from potential threats and vulnerabilities. APIs are essential for enabling communication and data exchange between different software applications and services, making them a critical component in modern software development. However, their openness and accessibility can also make them targets for various security risks. Authentication and authorization are key aspects of API security. Authentication is ensuring that only authorized users or applications can access the API. This can involve using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization is controlling what authenticated users or applications are allowed to do within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

Organizations using Asgardeo for identity and access management (IAM) can seamlessly integrate it with Choreo as an external Identity Provider (IdP). This guide will walk you through setting up Choreo to authenticate API invocations through Asgardeo which is configured as an external IdP.

This guide walks you through the following steps:

  • Assign scopes to an API in Choreo.
  • Create an API in Asgardeo.
  • Create an application in Asgardeo and consume the Asgardeo API.
  • Create an application in Choreo and enable external IdP authentication.
  • Invoke the API with scopes.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/#prerequisites","title":"Prerequisites","text":"

To follow this guide, you need to satisfy the following prerequisites:

  • Configured Asgardeo as an external IdP
  • If you don't already have a service in Choreo, develop a service or an API Proxy.
  • Deploy and publish your API.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/#step-1-assign-scopes-to-an-api-in-choreo","title":"Step 1: Assign scopes to an API in Choreo","text":"

You can provide fine-grained access control to your API resources with scopes. Follow the steps below to assign a scope to the resources in the API:

  1. In the Component Listing pane, click on the component you want to attach scopes to.
  2. In the left navigation menu, click Manage and then Permissions.
  3. Click + Add Permission (Scope).
  4. In the Permission List pane, enter the permission value and click + Add New.
  5. Click the copy icon in front of the added scope to copy the fully qualified name of the scope. Save this value for future reference.
  6. To attach a scope to a resource, click the Select Permissions list under the respective resource, and select the scopes you wish to attach.
  7. Click Save and Deploy.
  8. In the left navigation, click Manage and then Lifecycle.
  9. Click Publish and continue to publish your API to the Choreo Developer Portal.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/#step-2-create-an-api-and-an-application-in-asgardeo","title":"Step 2: Create an API and an application in Asgardeo","text":"

Follow the Asgardeo API Authorization guide to create an application and an API in Asgardeo and to enable API authorization.

Note

  • Use the fully qualified name of the scope when adding scopes.
  • Do the following under the protocol tab:
    • Select JWT as the Access Token.
    • Select the appropriate grant types.
    • Copy the client ID and client secret of the application for future reference.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/#step-3-create-an-application-in-choreo-and-enable-external-idp-authentication","title":"Step 3: Create an application in Choreo and enable external IdP authentication","text":"

Follow the steps below to consume the Choreo API and use an external IdP for authentication:

  1. Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.
  2. Click Applications. and then click +Create.
  3. Enter a name and description for the application.
  4. Click Create.
  5. In the left navigation, under Credentials and click Production.
  6. Select the Identity Provider as Asgardeo.
  7. Enter the Client ID you copied in step 2.
  8. Click +Add.

    Note

    • You can only use the Client ID in one application.
    • The Identity Provider dropdown is visible only to organizations where you have configured external IdPs.
  9. In the left navigation menu, click Subscriptions.

  10. In the Subscription Management pane that opens, click + Add APIs.
  11. Select the API you assigned scopes to in step 1 and click Add.
"},{"location":"authentication-and-authorization/secure-api-access-with-asgardeo/#step-4-invoke-the-choreo-api-with-scopes","title":"Step 4: Invoke the Choreo API with scopes","text":"
  1. On the Choreo Developer Portal, go to your application.
  2. In the left navigation menu, under Credentials and click Production.
  3. Under Endpoints, copy the Token Endpoint URL.
  4. Obtain an access token by invoking the token endpoint as follows:

    Note

    • If you are using the production credentials, you need to deploy your component(endpoint) to the production environment by promoting it from the development environment.
    • If you are using the sandbox credentials, you can use the endpoints deployed in the development environment.
    FormatExample
    curl -X POST '<TOKEN_ENDPOINT>?grant_type=password&scope=<REQUIRED_SCOPES>&username=<USER_NAME>&password=<USER_PASSWORD>' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--header 'Authorization: Basic <BASE64-ENCODED ASGARDEO_APP_CLIENT_ID:ASGARDEO_APP_CLIENT_SECRET>'\n
    curl -X POST 'https://dev.api.asgardeo.io/t/orgHandle/oauth2/token?grant_type=password&scope=<REQUIRED_SCOPES>&username=<USER_NAME>&password=<USER_PASSWORD>' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--header 'Authorization: Basic <BASE64-ENCODED CLIENT_ID:CLIENT_SECRET>'\n
  5. Once you receive the access token, you can test invoking the resource using the OpenAPI console in Choreo by specifying the scope.

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/","title":"Secure API Access with Microsoft Azure Active Directory (Azure AD)","text":"

API security refers to the measures and practices used to protect Application Programming Interfaces (APIs) from potential threats and vulnerabilities. Authentication and authorization are key aspects of API security. Authentication is ensuring that only authorized users or applications can access the API. This can involve using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization is controlling what authenticated users or applications are allowed to do within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

Organizations using Microsoft Azure AD for identity and access management (IAM) can seamlessly integrate it with Choreo as an external Identity Provider (IdP). This guide will walk you through setting up Choreo to authenticate API invocations through Azure AD which is configured as an external IdP.

This guide walks you through the following steps:

  • Assign scopes to an API in Choreo.
  • Create an API in Azure AD.
  • Create an application in Azure AD and consume the Azure API.
  • Create an application in Choreo and enable external IdP authentication.
  • Invoke the API with scopes.
"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#prerequisites","title":"Prerequisites","text":"

To follow this guide, you need to satisfy the following prerequisites:

  • Configure Azure AD as an external IdP.
  • An API: If you don't already have a service in Choreo, develop a service or an API Proxy.
  • Deploy and publish your API.
  • An Azure Active Directory account: If you don\u2019t already have one, set up an Azure Active Directory account at https://azure.microsoft.com/en-gb/.
  • Administrator rights to your Choreo organization: You need this to configure the Azure AD account in your organization.
  • To create applications, the Application Developer role is required. Learn more
"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-1-assign-scopes-to-an-api-in-choreo","title":"Step 1: Assign scopes to an API in Choreo","text":"

You can provide fine-grained access control to your API resources with scopes. Follow the steps below to assign a scope to the resources in the API:

  1. In the Component Listing pane, click on the component you want to attach scopes to.
  2. In the left navigation menu, click Manage and then Permissions.
  3. Click + Add Permission (Scope).
  4. In the Permission List pane, enter the permission value and click + Add New.
  5. Click the copy icon in front of the added scope to copy the fully qualified name of the scope. Save this value for future reference.
  6. To attach a scope to a resource, click the Select Permissions list under the respective resource, and select the scopes you wish to attach.
  7. Click Save and Deploy.
  8. In the left navigation menu, click Manage and then Lifecycle.
  9. Click Publish and continue to publish your API to the Choreo Developer Portal.
"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-2-create-a-web-api-on-azure-ad","title":"Step 2: Create a web API on Azure AD","text":"

To enable external IdP authentication for APIs, create an API on Azure AD that represents the API on Choreo. Follow the steps below:

  1. Sign in to the Azure console.
  2. Follow the Azure guide to create a Web API that represents your API on Choreo.
  3. In the left navigation menu, under Manage, select Expose an API.
  4. Add the default Application ID URI and click Save and Continue.
  5. Under Scopes defined by this API, select Add a scope.
  6. Enter the fully qualified name as the scope name.
  7. Define who can consent. You can alternatively add a scope requiring admin consent.
  8. Enter appropriate values and click Add Scope.

For more information, refer to the Azure documentation:

  • Quickstart: Register an application with the Microsoft identity platform
  • Quickstart: Configure an application to expose a web API
"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-21-assign-users-to-the-web-api","title":"Step 2.1: Assign users to the web API","text":"

You can restrict users to the API as follows:

  1. Go to your Azure AD main menu.
  2. Under Manage, click on Enterprise Applications. Alternatively, on Microsoft Entra, under Applications, click Enterprise Applications.
  3. Select your API.
  4. Under Manage, select the Users and groups then select + Add user/group.
  5. Select the users and groups and click Select.

For more information, refer to the Azure documentation: Assign the app to users and groups to restrict access

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-3-create-a-client-application-on-azure-ad-and-invoke-the-azure-web-api","title":"Step 3: Create a client application on Azure AD and invoke the Azure web API","text":"

To expose the API to application developers, create an application in Azure AD. This application provides you with a client-id and client-secret that your application needs to use to invoke the API.

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-31-create-a-client-application","title":"Step 3.1: Create a client application","text":"

Follow the steps below to create the application:

  1. Follow the steps in Register an application on Azure to create an application.
  2. Configure the platform settings. Enter your client application's redirect URI in the process.

    Note

    OAuth2 Authorization Grant flow applies to Web Applications.

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-32-consume-the-azure-ad-web-api-from-the-azure-ad-application","title":"Step 3.2: Consume the Azure AD web API from the Azure AD application","text":"

Once you create the application, select the API and the scopes you want the application to consume. Follow the steps below:

  1. Go to Azure Active Directory and then click App registrations.
  2. Select your client application (not your web API).
  3. In the left navigation menu, click API permissions.
  4. Click + Add a permission and select My APIs.
  5. Select the API and the required scopes and click Add Permissions.
  6. Once you add the scope, click on the scope and copy the scope name and keep it for future reference. Use this as the scope when you invoke the authorize and token endpoint in step 5.

For more information, refer to the Azure documentation: Add permissions to access your web API

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-33-create-secrets-for-the-azure-web-application","title":"Step 3.3: Create secrets for the Azure web application","text":"

To invoke the application, provide client secrets to the consuming application. Follow the steps below to generate the credentials:

  1. In the left navigation menu, click Certificates & Secrets.
  2. Click + New client secret.
  3. Provide a meaningful description and the required expiration.
  4. Click Add.
  5. Copy the created Secret ID and Value for future reference.
  6. In the left navigation menu, click Overview and open the overview page of the API.
  7. Copy the Application (client) ID and save it for future reference.

For more information, refer to the Azure documentation: Add a Client Secret

"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-4-create-an-application-in-choreo-and-enable-external-idp-authentication","title":"Step 4: Create an application in Choreo and enable external IdP authentication.","text":"

Follow the steps below to consume the Choreo API and use an external IdP for authentication:

  1. Sign in to the Choreo Developer Portal at https://devportal.choreo.dev.
  2. Click Applications. and then click +Create.
  3. Enter a name and description for the application.
  4. Click Create.
  5. In the left navigation menu, under Credentials and click Production.
  6. Select your AzureAD (Microsoft) configuration as the Identity Provider.
  7. Enter the Application (client) ID you copied in at Step 3.2 as the Client ID.
  8. Click +Add.

    Note

    • You can only use the Client ID in one application.
    • The Identity Provider dropdown is visible only to organizations where you have configured external IdPs.
  9. In the left navigation menu, click Subscriptions.

  10. In the Subscription Management pane that opens, click + Add APIs.
  11. Select the API you assigned scopes to in step 1 and click Add.
"},{"location":"authentication-and-authorization/secure-api-access-with-azure-ad/#step-5-invoke-the-api-with-scopes","title":"Step 5: Invoke the API with scopes","text":"

You can now invoke the Choreo API using the authorization code grant. Choreo will authenticate the user with Azure AD and provide access to the resource.

  1. On the Choreo Developer Portal, go to your application.
  2. In the left navigation menu, under Credentials and click Production.
  3. Under Endpoints, copy the Authorize Endpoint URL.
  4. Invoke the authorization endpoint as follows:

    FormatExample
    {authorize_url}?client_id={client_id}&redirect_uri={redirect_url}&scope={scopes}&response_mode=query&response_type=code\n
    https://login.microsoftonline.com/dd912d48-b0be-401f-b18c-8ca89e9c0b6c/oauth2/authorize?client_id=5eb1de74-e449-4973-a620-52c4dc9157a9&redirect_uri=https://localhost:9000&scope=api://580b40b7-5513-4714-a4e0-8d4e784f7dc6/urn:taylordean:books:books_addt&response_mode=query&response_type=code\n
    1. Review the consent in the login screens that prompt and continue.
    2. After you log in, you will receive an authorization code in the URL. Copy the authorization code and use it to get an access token from Azure AD by following the next steps.
    3. On the Choreo Developer Portal, go to your application.
    4. In the left navigation menu, under Credentials and click Production.
    5. Under Endpoints, copy the Token Endpoint URL.
    6. Invoke the token endpoint as follows:
    FormatExample
    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \\\n{token_endpoint} \\\n-d 'client_id={client_id}' \\\n-d 'scope={scopes}' \\\n-d 'code={authorization_code}' \\\n-d 'redirect_uri={redirect_url}' \\\n-d 'client_secret={The client_secret value you copied from the Azure Application}'\n-d 'grant_type=authorization_code' \\    \n
    curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \\\nhttps://login.microsoftonline.com/dd912d48-b0be-401f-b18c-8ca89e9c0b6c/oauth2/v2.0/token \\\n-d 'client_id=5eb1de74-e449-4973-a620-52c4dc9157a9' \\\n-d 'scope=api://580b40b7-5513-4714-a4e0-8d4e784f7dc6/urn:taylordean:books:books_add' \\\n-d 'code=0.AXAASC\u2026zZUzKYm18yM_5-SXz1uvRbbGYF7F32hE9zIQFRQY35haD' \\\n-d 'redirect_uri=https://localhost:9000' \\\n-d 'grant_type=authorization_code' \\\n-d 'state=111' \\\n-d 'client_secret=l4Q8Q~4WKiRXYSQZly5E6Ess.fKf__U1yJR3IaMd'\n
  5. Once you receive the access token, you can test invoking the resource using the OpenAPI console in Choreo by specifying the scope.

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/","title":"Secure Communication Between the Choreo Gateway and Your Backend with Mutual TLS","text":"

To establish secure communication between the Choreo Gateway and your backend, you can configure mutual TLS.

Mutual TLS authentication involves both the client and server validating each other\u2019s certificates before establishing a connection. The following diagram depicts this scenario:

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#configure-mutual-tls-to-establish-secure-connectivity","title":"Configure mutual TLS to establish secure connectivity","text":"

To establish secure connectivity between the Choreo Gateway and your backend using mutual TLS, you must add the certificate of the backend (server certificate) to Choreo and add the certificate of Choreo (client certificate) as a trusted certificate in the backend.

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#step-1-configure-the-backend-certificate","title":"Step 1: Configure the backend certificate","text":"Prerequisites
  • The endpoint must be protected with TLS.
  • The public certificate of the backend server should be extracted in PEM format and saved on the disk with the .pem extension.

To configure the backend certificate, follow the steps given below:

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the API proxy for which you want to configure TLS. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  3. In the left navigation menu, click Develop and then click Endpoints.
  4. On the Endpoints page, click Configure corresponding to the endpoint.
  5. Click Upload Endpoint Certificate, and select the certificate file that you extracted in the prerequisites section to add it. This adds the certificate to all the environments as the default certificate for the endpoint. You can override this certificate if necessary when you deploy or promote the API.
"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#step-2-configure-mutual-tls-with-the-backend-service","title":"Step 2: Configure mutual TLS with the backend service","text":"

There are two approaches you can take to configure mutual TLS.

  • Generate a key pair with a self-signed certificate from Choreo, download the public certificate, and subsequently add and configure it in the backend.
  • Upload your own public or private certificate pair to Choreo. Subsequently, add and configure the public certificate of this key pair in your backend.

Follow the step-by-step instructions below depending on how you want to establish mutual TLS with the backend service:

Generate a key pair through ChoreoUse your own certificate pair

When you follow these steps, Choreo generates a key pair with a self-signed certificate. You can attach this key pair to any API proxy created within the same project.

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the API proxy for which you want to generate a key pair. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  3. In the left navigation menu, click Develop and then click Endpoints.
  4. On the Endpoints page, click Configure corresponding to the endpoint.
  5. If your backend does not use a CA-signed certificate and you have not already added the backend certificate, click Upload Endpoint Certificate and add the backend certificate.
  6. To enable mutual SSL, turn on the Mutual SSL toggle.
  7. Click Add Client Certificate.
  8. In the Add Client Certificate Pair dialog, select Generate new key pair and specify a value as the common name for the certificate pair. This value will be used to identify the certificate.

  9. Optionally, click Show advanced options to expand the section and specify appropriate values for each of the fields.

  10. Click Generate. This generates the certificate and lists it under Existing Certificates.
  11. Click the more options icon corresponding to the certificate and then click View and Download.

    This opens the certificate for you to view and download.

  12. To download the certificate in PEM format, click Download. You can add this certificate as a trusted certificate in the API backend server.

Now you can associate the certificate with the API and deploy the API.

Here, you can use your own public certificate and private certificate as client certificates.

  1. Sign in to the Choreo Console.
  2. In the Component Listing pane, click on the API proxy for which you want to generate a key pair. For instructions on how to create an API proxy component, see Develop an API Proxy: Step 1.
  3. In the left navigation menu, click Develop and then click Endpoints.
  4. On the Endpoints page, click Configure corresponding to the endpoint.
  5. If your backend does not use a CA-signed certificate and you have not already added the backend certificate, click Upload Endpoint Certificate and add the backend certificate.
  6. To enable mutual SSL, turn on the Mutual SSL toggle.
  7. Click Add Client Certificate.
  8. In the Add Client Certificate Pair dialog, select Use my own key pair.

  9. Upload the private key and public certificate in PEM format or copy and paste the content of the private key and public certificate.

  10. Click Add. This generates the certificate and lists it under Existing Certificates.
  11. Click the more options icon corresponding to the certificate and then click View and Download.

    This opens the certificate for you to view and download.

  12. To download the certificate in PEM format, click Download. You can add this certificate as a trusted certificate in the API backend server.

Now you can associate the certificate with the API and deploy the API.

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#step-3-associate-the-certificate-with-the-api","title":"Step 3: Associate the certificate with the API","text":"

To associate a certificate with the API, follow the steps given below:

  1. On the Endpoints page, go to the Existing Certificates section.
  2. Select the certificate you want to associate with the API.

  3. Click Save.

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#step-4-deploy-the-api","title":"Step 4: Deploy the API","text":"

To deploy the API, follow the steps given below:

  1. In the left navigation menu, click Deploy.
  2. In the Build Area card, click Configure & Deploy.
  3. Once the mediation application generation phase is complete, verify the endpoint URL populated for the environment and then click Save & Deploy.

Once the deployment is complete, you can test the API.

"},{"location":"authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/#change-the-certificate-for-the-production-environment","title":"Change the certificate for the production environment","text":"

If the API backend changes depending on the environment, the respective certificate must be updated for each environment.

Here, let's take a look at the steps to update the certificate for the production environment:

  1. On the Deploy page, go to the Development card and click Promote.
  2. In the Configurations pane that opens, click Endpoint Configuration. You will see all applicable certificates listed in the Mutual TLS list.
  3. Select the certificate applicable to the production environment and click Promote. This promotes the component to the production environment with the selected certificate.
"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/","title":"Secure Web Applications with Managed Authentication","text":"

The managed authentication capability of Choreo simplifies adding authentication and authorization to a single-page web application.

As a developer, you can easily set up Choreo's managed authentication to seamlessly integrate authentication into your web application. You just need to enable Choreo\u2019s managed authentication, configure the built-in identity provider, and connect to Choreo without having to deal with the complexities of underlying OIDC/OAuth2.0 protocols.

Choreo's managed authentication follows the backend for frontend (BFF) architecture, which is a secure pattern recommended for browser-based applications that utilize OIDC/OAuth2.0 for authentication and authorization. This architecture ensures that OAuth tokens remain secure from browser-side code, making them immune to potential attacks like cross-site scripting (XSS).

Note

Choreo's managed authentication is currently available only for web applications created with React, Angular, or Vue.js buildpacks.

Warning

Managed authentication uses the 'SAMESITE' cookie attribute to prevent CSRF attacks. Therefore, it is recommended to use managed authentication with modern browsers that support the 'SAMESITE' attribute.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-1-set-up-managed-authentication-for-your-web-application","title":"Step 1: Set up managed authentication for your web application","text":"

To secure your web application, you must implement authentication and authorization for it.

To easily set up authentication for your web application with Choreo's managed authentication, follow the steps given below. Before you move on to the next section, see Develop Web Applications Locally with Choreo\u2019s Managed Authentication to ensure a seamless authentication experience when developing your web application on your local machine. You can also refer to the sample\u00a0React app with managed authentication.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-11-implement-the-sign-in-functionality","title":"Step 1.1: Implement the sign-in functionality","text":"

To allow Choreo to manage the sign-in functionality for your web application, you must implement a sign-in button that redirects users to the /auth/login path on click. You can use the following code snippet or any custom button component from a preferred UI component library:

<button onClick={() => {window.location.href=\"/auth/login\"}}>Login</button>\n

This code snippet works as follows:

When a user clicks sign in on your web application, Choreo will redirect the user to the configured identity provider and handle the authentication process, conforming to the OICD/OAuth2.0 protocols. On successful sign-in, Choreo will set the relevant session cookies and redirect the user to the post-sign-in path (default is /). The user can then invoke any Choreo-deployed APIs depending on the permission granted.

Note

Refer to configure the identity provider section for details on configuring an identity provider for the web application.

Optional: Pass additional query parameters to the identity provider

If you want to pass additional query parameters to the identity provider, include them in the /auth/login request. Choreo appends these parameters to the authorize request sent to the identity provider.

For example,

<button onClick={() => {window.location.href=\"/auth/login?fidp=myfederatedidp\"}}>Login</button>\n
"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-12-obtain-user-information-claims","title":"Step 1.2: Obtain user information claims","text":"

Choreo's managed authentication allows you to access user information claims that the identity provider returns post-sign-in, either via a cookie or by invoking a GET resource.

Obtain user information via the userinfo cookie

Upon successful sign-in, Choreo's managed authentication establishes a userinfo cookie that is accessible from the post-sign-in path you configured (by default, set to /). This userinfo cookie, provided by the identity provider, contains encoded user information claims.

Note

  • The userinfo cookie is intentionally set to have a short lifespan of only 2 minutes.
  • As a developer, you can decide how to utilize the user information that you retrieve. You must securely store the user information because the stored information can also serve as a means to verify the logged-in state of a user.
  • The following example uses the js-cookie library for cookie parsing. You can use any cookie-parsing library of your choice.\u00a0

The recommended approach is to retrieve user information from the cookie and subsequently clear the cookie. The following is a sample code snippet that you can include in your post-sign-in path to retrieve user information from the cookie and subsequently clear the cookie:

    import Cookies from 'js-cookie';\n// Read userinfo cookie value.\nconst encodedUserInfo = Cookies.get('userinfo')\n// Decode the value. \nconst userInfo = JSON.parse(atob(encodedUserInfo))\n// Store the value in a preferred browser-based storage if needed.\n// Clear the cookie.\nCookies.remove('userinfo', { path: <post-login-path> })\n
Obtain user information via a GET endpoint

Choreo's managed authentication provides the GET endpoint /auth/userinfo in addition to the userinfo cookie that it sets after successful sign-in. You can use this endpoint to query information about users who have signed in. It also serves as a mechanism to check the state of a user who has signed in.

The following is an example of a request to this endpoint:

const response = await fetch('/auth/userinfo')\n

If a user has signed in, the server sends a 200 OK response with the user information in JSON format in the response body. However, if the user is not signed in, the server sends a 401 Unauthorized response.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-13-implement-the-sign-out-functionality","title":"Step 1.3: Implement the sign-out functionality","text":"

To allow Choreo to manage the sign-out functionality of your web application, you can implement a sign-out button to redirect users to the /auth/logout path along with the session_hint cookie value on click. You can use the following code snippet or any custom button component from a preferred UI component library:

Note

  • It is recommended to clear any user information (if stored) at the time of sign-out.
  • The following example uses the js-cookie library for cookie parsing. You can use any cookie-parsing library of your choice.\u00a0
<button onClick={async () => {\nwindow.location.href = `/auth/logout?session_hint=${Cookies.get('session_hint')}`;\n}}>Logout</button>`\n

When a user clicks the sign-out button, Choreo will clear the session cookies and redirect the users to the OIDC logout endpoint of the configured identity provider (if available).\u00a0\u00a0

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-14-invoke-apis","title":"Step 1.4: Invoke APIs","text":"

To invoke Choreo APIs within the same organization as your web application, you can use the relative path /choreo-apis/<api-suffix>, regardless of whether managed authentication is enabled for the web application or not.

Note

To invoke a Choreo API from a web application, you need to create a Connection from the web application to the Choreo API.

For example, if the API URL is https://2d9ec1f6-2f04-4127-974f-0a3b20e97af5-dev.e1-us-east-azure.choreoapis.dev/rbln/item-service/api-e04/1.0.0, the <api-suffix> would be /rbln/item-service/api-e04/1.0.0. You can invoke the API using the /choreo-apis/rbln/item-service/api-e04/1.0.0 relative path from your single-page application.

Info

To copy the exact service URL of a Connection, you can follow the steps given below: 1. In the Choreo Console, go to the appropriate web application component. 2. In the left navigation menu, click Connections under Dependencies. 3. Click on the required Connection and copy the service URL.

If you enable Choreo's managed authentication, you don't have to manually add any logic to attach an access token to the API call because Choreo APIs accept the cookies set by Choreo's managed authentication. You can directly invoke the API as follows:

    const response = await fetch('/choreo-apis/<api-suffix>')\n

If Choreo's managed authentication is disabled, you must ensure that your web application attaches a valid access token to the API call.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-15-handle-session-expiry","title":"Step 1.5: Handle session expiry","text":"

When a user session exceeds the configured session expiry time, it automatically expires. A 401 Unauthorized response status code for a Choreo API request from a logged-in user indicates that the session may have expired, requiring the user to re-login.

To programmatically handle session expiry and automatically re-login upon receiving a 401 Unauthorized response from a Choreo API, you can encapsulate the request with re-login logic. The following sample code snippet shows how to wrap GET requests:

    export const performGet = async (url) => {\ntry {\n// API call\nreturn await fetch('/choreo-apis/<api-suffix>');\n} catch (error) {\nif (error instanceof HttpError && error.status === 401) {\n// Re-login\nwindow.location.href = \"/auth/login\";\n} else {\nthrow error;\n}\n}\n};\n
"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-16-set-up-a-custom-error-page","title":"Step 1.6: Set up a custom error page","text":"

You can set up Choreo's managed authentication to redirect to a customized error page within your web application by defining the error path in the configuration. In the event of an error during a redirection-based process, such as sign in or sign out, Choreo will automatically redirect the user to the designated custom error page.

Note

If you have not configured an error path, Choreo's managed authentication will use its default error page whenever an error occurs.

Choreo's managed authentication will include the following query parameters in the URL when redirecting to the custom error page:

Parameter Description code A short textual error code indicating the error message The description of the error

Now have successfully implemented Choreo's managed authentication for your web application. The next step is to enable managed authentication for the component, and subsequently deploy it.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-2-enable-managed-authentication-and-configure-the-paths","title":"Step 2: Enable managed authentication and configure the paths","text":"

To ensure that your web application functions seamlessly with managed authentication, it is essential to enable managed authentication for your web application component within Choreo.

You can enable managed authentication for your web application component at the time you deploy the component.

Tip

Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks.

  1. Sign in to the Choreo Console. This opens the project home page.
  2. In the Component Listing pane, click on the web application for which you want to enable managed authentication.
  3. In the left navigation menu, click Deploy.
  4. In the Set Up card, click Configure & Deploy.
  5. Add the necessary configurations for your component if applicable and click Next.
  6. Make sure Managed Authentication with Choreo toggle is enabled.
  7. Specify appropriate values for the following fields:

    Field Description Default value Post Login Path The relative path that the application will be redirected to on successful sign-in. In your code, you must implement the necessary logic to obtain signed-in user's information from the userinfo cookie set by managed authentication. See Obtain user information via the userinfo cookie section in Obtain user information claims. / Post Logout Path The relative path to which Choreo redirects you on successful sign-out. / Error Path The relative path to which Choreo redirects you when an error occurs during a redirection-based flow (i.e., sign in or sign out). See Set up a custom error page. Built-in error page Session Expiry Time The time in minutes after which the user session expires. For a seamless experience, the session expiry value should match the refresh token expiry time of the OIDC application in your identity provider. 10080 Minutes (7 Days) Additional Scopes All additional scopes required by the web application. The openid, profile, and email scopes are added by default together with the scopes required to invoke subscribed APIs. none

    Note

    If you need to change these configurations after you deploy the component, you can click Authentication Settings on the Set Up card, make the necessary changes, and deploy the component once again.

"},{"location":"authentication-and-authorization/secure-web-applications-with-managed-authentication/#step-3-configure-the-identity-provider-for-the-web-application","title":"Step 3: Configure the identity provider for the web application","text":"

You can configure your web application to work with the Choreo built-in identity provider, Asgardeo, or any external identity provider which supports OIDC/OAuth2.0 .

Note

The identity provider configured in this step should contain the users for the web application.

Click the respective tab for details depending on which identity provider you need to configure:

Configure Choreo built-in identity providerConfigure AsgardeoConfigure an external identity provider

Follow the steps given below to configure the built-in identity provider by generating authentication keys:

Note

Choreo built-in identity provider is configured by default. Therefore, this step is optional.

  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. In the left navigation menu, click Settings.
  3. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  4. In the Identity Provider list, select Choreo Built-In Identity Provider.
  5. Click Generate Secret.

    Note

    If the Regenerate Secret button is shown instead of the Generate Secret button, it indicates that OAuth keys are already generated for the component for the selected environment.

Tip

Refer to Configure a User Store with the Built-In Identity Provider for details on adding test users in Choreo built-in identity provider.

Tip

If you need to invoke APIs secured with role-based access control, you can test this within Choreo by creating roles for the application and mapping those roles to relevant permissions (scope) and user groups. For more information, see create roles and assign permissions and assign roles to user groups sections in Test Secure API Access with Choreo Built-In Security Token Service.

Step 3.1: Create and configure an OIDC/OAuth2.0 application in Asgardeo

  1. Sign in to Asgardeo.
  2. In the top navigation menu, click the Organization list and select your organization.
  3. In the Asgardeo Console left navigation menu, click Applications.
  4. Click + New Application.
  5. Click Standard-Based Application.
  6. Specify a name for the application and select OAuth2.0 OpenID Connect as the protocol.
  7. Click Register.
  8. Click the Protocol tab and follow these steps:

    1. Select Code and Refresh Token as the Allowed grant types.
    2. Specify the following as Authorized redirect URLs:
      • [your-web-application-url]/auth/login/callback
      • [your-web-application-url]/auth/logout/callback
    3. Specify your web application URL under Allowed origins.
    4. In the Access Token section, select JWT as the Token type.
    5. Click Update.

      Tip

      If you need to invoke APIs secured with role-based access control, you must create roles in the application and map those roles to relevant permissions (scope). Then those roles should be assigned to user groups. For more information, see the Asgardeo API authorization guide.

    6. Copy the Client ID and Client Secret of the application. You will need to use these values in the next step to link the OIDC/OAuth2.0 application to your Choreo component.

Step 3.2: Link the OIDC/OAuth2.0 application to the Choreo web application component

  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. In the left navigation menu, click Settings.
  3. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  4. In the Identity Provider list, select Asgardeo - [your-org-name].
  5. Paste the Client ID and Client Secret of the OIDC/OAuth2.0 application you created in Asgardeo.
  6. Click Add Keys.

Step 3.1: Create and configure an OIDC/OAuth2.0 application in the external identity provider

  1. Create an OIDC/OAuth2.0 application in your external identity provider.
  2. Configure the OIDC/OAuth2.0 application as follows:

    1. Set Code and Refresh Token as allowed grant types.
    2. Add the following as authorized redirect URL.
    3. Specify the following as authorized redirect URLs:
    4. Specify the access token type as JWT.

      Tip

      If you want to invoke APIs secured with role-based access control, you must ensure that users are assigned a role mapping that grants the necessary permission for API invocation. The approach of mapping application roles to users can vary depending on the identity provider.

Step 3.2: Link the OIDC/OAuth2.0 application to the Choreo component

  1. In the Choreo Console, go to the component for which you want to manage OAuth keys.
  2. In the left navigation menu, click Settings.
  3. Click the Authentication Keys tab and then click on the environment for which you want to generate keys.
  4. In the Identity Provider list, select your identity provider.
  5. Paste the Client ID and Client Secret of the OIDC/OAuth2.0 application you created in your external identity provider.
  6. Click Add Keys.
"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/","title":"Test Secure API Access with Choreo Built-In Security Token Service","text":"

API security can protect APIs from potential threats and vulnerabilities, with authentication and authorization playing key roles. Authentication ensures that only authorized users or applications can access the API. This involves using API keys, tokens, or more advanced authentication methods like OAuth 2.0. Authorization governs the actions permitted for authenticated users or applications within the API. Authorization mechanisms restrict access to specific resources and actions based on user roles or permissions.

Choreo simplifies security testing for developers, allowing them to easily test APIs with permissions in non-critical environments. With its integrated security token service, Choreo provides authorization features that generate scopes based on the correlation between scopes, roles, and user groups. Developers can create roles, assign permissions, and set up user-group mappings using Choreo's built-in identity provider (IdP).

This guide walks you through the following steps to test the invocation of secured APIs with permissions using Choreo's built-in authorization capability:

  • Assign scopes to an API in Choreo.
  • Create roles and assign permissions in Choreo.
  • Assign roles to user groups.
  • Test the API invocation.
    • When Choreo manages the authentication (i.e., managed authentication enabled).
    • When the application independently handles the authentication (i.e., managed authentication disabled).
"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#prerequisites","title":"Prerequisites","text":"

Before you try out this guide, ensure you have set up the following:

  • Configure the Choreo built-in identity provider with users. For step-by-step instructions, see Configure a User Store with the Built-In Identity Provider.
  • Deploy and publish an API via Choreo. If you don't have an existing service in Choreo, you can either develop a service or an API Proxy.
  • A web application for API subscription. If you don't have an application in Choreo, you must create a web application
  • Administrator rights in your Choreo organization. You need this access to configure role-group and role-permission mappings.
"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#step-1-assign-permissions-to-an-api-in-choreo","title":"Step 1: Assign permissions to an API in Choreo","text":"

You can provide fine-grained access control to your API resources with permissions. Follow the steps below to assign permissions to the resources in the API:

  1. Go to https://console.choreo.dev/ and sign in.
  2. In the Choreo Console top navigation menu, click the Project list and select the project that contains your component.
  3. In the Component Listing pane, click on the component for which you want to attach permissions.
  4. In the left navigation menu, click Deploy.
  5. On the Deploy page, go to the Set Up card and click Endpoint Configurations. This opens the Endpoint Configurations pane.
  6. Go to the Permissions List section and click + Add Permission(Scope).
  7. In the Permissions List section, enter a permission value and click + Add New.
  8. Click the copy icon in front of the added permission to copy the fully qualified name of it. Save this value for future reference.
  9. To attach permissions to a resource, click the Select Permissions list under the respective resource and select the permissions you want to attach.
  10. Click Apply.
  11. To apply the latest permissions to the deployed component, you must redeploy it. Follow the steps below to redeploy:

    1. Go to the Set Up card and click Configure & Deploy.
    2. In the Configurations pane that opens, click Next. This opens the Endpoint Details pane.
    3. Click Deploy.
  12. To publish your API to the Choreo Developer Portal, follow the steps given below:

    1. In the left navigation menu, click Manage and then click Lifecycle.
    2. Click Publish.
"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#step-2-create-roles-and-assign-permissions","title":"Step 2: Create roles and assign permissions","text":"

The permissions assigned to your API need to be associated with roles. Follow the steps below to create roles and assign permissions to the roles.

  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the project that contains your component.
  2. In the left navigation menu, click Settings.
  3. Click the Application Security tab.
  4. Click + Role.
  5. Specify an appropriate Role Name and Role description.
  6. Select the permissions you want to assign to the role, and then click Create.

    Tip

    The permissions(scopes) defined for APIs exposed via components in the project and the permissions(scopes) required by connections created for components in the project are listed here.

"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#step-3-assign-roles-to-user-groups","title":"Step 3: Assign roles to user groups","text":"

You must assign roles to the user groups defined in your Choreo built-in IdP to ensure that authenticated users can obtain access tokens with the required permissions.

  1. In the Choreo Console, go to the top navigation menu, click the Organization list, and select the organization where you created your component.
  2. Click the Application Security tab and then click Role Management.

    Tip

    The roles defined within different projects in the organization are listed here.

  3. Click Map Groups corresponding to a role that you want to assign to a group.

  4. Specify a group name and enter to add it. You can add multiple groups if necessary.
  5. Click Save.
"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#step-4-test-the-api-invocation","title":"Step 4: Test the API invocation","text":"

To test an API invocation, you must first create a connection to your API. To do this, you must have a web application created. You can use the web application you created while setting up the prerequisites.

To create a connection to the web application, follow the steps given below:

  1. In the Choreo Console, go to the top navigation menu, click the Project list, and select the project where you created the web application.
  2. On the project home page, click the web application listed under Component Listing.
  3. In the left navigation menu, click Dependencies and then click Connections.
  4. Create a connection to the API you deployed in Step 1.

Now you can proceed to deploy the web application.

When deploying, if your web application is a single-page application (SPA), you have the option to allow Choreo to handle authentication on behalf of the application. This approach eliminates the need to incorporate OAuth protocol-specific logic into your application.

"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#test-the-invocation-when-choreo-managed-authentication-is-enabled","title":"Test the invocation when Choreo-managed authentication is enabled","text":"

If managed authentication is enabled for your web application, Choreo automatically handles obtaining the necessary permission for API invocation. This occurs during the request for access tokens, allowing you to seamlessly invoke the subscribed APIs through your web application without additional intervention.

Note

If you change the permissions of an existing connection or create a new connection with permissions, you must redeploy your web application to ensure proper API invocation with managed authentication.

"},{"location":"authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/#test-the-invocation-when-the-application-manages-the-authentication","title":"Test the invocation when the application manages the authentication","text":"

If your application manages authentication independently, follow the steps below to generate the necessary OAuth credentials to obtain access tokens:

  1. In the left navigation menu, click Settings. This opens the settings of the web application component.
  2. Click the Authentication Keys tab.
  3. Click on an environment tab depending on the environment for which you want to generate credentials.
  4. Select Choreo Built-In Identity Provider as the identity provider.
  5. Click to expand Advanced Configurations and make sure the code and refresh grant types are selected. This is required to obtain access tokens with an authorization code grant.
  6. Configure the callback URL of the web application to receive the authorization code.
  7. Click Update Configurations.
  8. Click Regenerate Secret and make a note of the client ID and secret that is generated.
  9. Retrieve an access token using the authorization code grant, specifying the necessary OAuth scopes (You can see the endpoint details on the right side).
    • When prompted for authentication, enter the credentials of a user within the built-in identity provider (IdP) who possesses the required assigned groups.
    • Navigate through the OAuth flow to obtain the JWT access token.
  10. Invoke the subscribed API using the access token.
"},{"location":"choreo-cli/choreo-cli-overview/","title":"Choreo Command Line Interface (CLI) Overview","text":"

The Choreo Command Line Interface (CLI) is a command-line tool that helps you easily work with Choreo using commands. By utilizing commands, it significantly improves the development experience for Choreo users. This versatile tool simplifies different stages of the development process, making interactions more efficient and user-friendly.

Choreo serves as a comprehensive internal platform-as-a-service. The Choreo CLI serves as a pivotal tool aimed at enhancing its capabilities. With the Choreo CLI, you can leverage the following benefits:

  • Streamline Deployment Processes: Choreo CLI simplifies the entire process from creating a component in Choreo, building it, to deploying, testing, and monitoring independent of the language and framework used to implement the component.

  • Versatile workflow across frameworks: Regardless of your chosen framework, Choreo CLI offers a uniform end-to-end process. Choreo seamlessly integrates with different web application types (SPA, SSR, SSG, or simple static files), services (REST, GraphQL, gRPC), scheduled jobs, manual triggers, API proxies, and more. This versatility enables you to orchestrate a wide range of cloud-native components seamlessly.

"},{"location":"choreo-cli/choreo-cli-overview/#key-features-of-the-choreo-cli","title":"Key features of the Choreo CLI","text":"
  • Create and Manage Resources: Simplify project and component management. You can easily initiate and organize projects in Choreo through simple commands.

  • Create Builds and Deployments: Simplifies the process of creating builds and deploying components. You can build and promote components to environments easily with simple commands, ensuring a seamless transition from development to deployment.

    Note

    The Choreo CLI currently supports the following component types:

    • Service
    • Web Application
    • Webhook
    • Scheduled Task
    • Manual Task
  • Monitor with Logs : The integrated log functionality in the Choreo CLI allows you to effectively monitor your components. You can access valuable insights into your components behavior and performance directly from the command line.

For troubleshooting tips and answers to frequently asked questions, see the Choreo CLI FAQ.

"},{"location":"choreo-cli/get-started-with-the-choreo-cli/","title":"Get Started with the Choreo CLI","text":"

This guide walks you through the following sample use case:

  • Create a web application
  • Build the web application
  • Deploy the web application in the development environment
  • Promote the web application to the production environment

This guide utilized a simple to-do app built with Next.js and two basic environments: Development and Production.

"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#prerequisites","title":"Prerequisites","text":"

Follow the steps below to install the CLI:

  1. Install the Choreo CLI by running the command specific to your operating system:

    • For Linux and Mac OS

      curl -o- https://cli.choreo.dev/install.sh | bash\n

    • For Windows (via PowerShell)

      iwr https://cli.choreo.dev/install.ps1 -useb | iex\n

  2. Verify the installation by running the following command:

    choreo --version\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-1-login-to-choreo","title":"Step 1: Login to Choreo","text":"

Run the following command to login to Choreo:

choreo login\n

Follow the instructions on the console to open the link in the browser and login to Choreo.

"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-2-create-a-project","title":"Step 2: Create a project","text":"

A project in Choreo is a logical group of related components that typically represent a single cloud-native application. A project consists of one or more components.

Create a multi-repository project named \u2018web-app-project\u2019 by running the following command:

choreo create project web-app-project --type=multi-repository\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-3-create-a-web-application-component","title":"Step 3: Create a Web Application component","text":"

In Choreo, a component within your project represents a singular unit of work in a cloud-native application. It can be a microservice, API, web application, or job/task. Each component is associated with a directory path in a Git repository containing the source code for the program.

Note

The Choreo CLI currently supports the following component types:

  • Service
  • Web Application
  • Webhook
  • Scheduled Task
  • Manual Task

  1. Fork the repository https://github.com/wso2/choreo-sample-todo-list-app. This contains a sample web application that you can use for this guide.

  2. To initiate the creation of a Web Application component within your project, use the following command: This triggers a wizard prompting you to provide details for your Git repository and other configurations for your component.

    choreo create component my-web-app --project=web-app-project --type=webApp\n
  3. Select the option Enter remote repository URL manually.

  4. Enter the following values for the prompts.

    Prompt value Configure source repository Enter remote repository URL manually Remote repository URL Your forked repository Branch main Directory . Build-pack nodejs Language Version 20.x.x Port 8080

    Note

    The prompts may vary based on the type of component and the chosen build pack.

"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-4-view-component-details","title":"Step 4: View component details","text":"

To view comprehensive information about the component, including basic details and service endpoint URLs once the services are deployed, you can use the following command:

choreo describe component \"my-web-app\" --project=\"web-app-project\"\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-5-build-the-component","title":"Step 5: Build the component","text":"

You must build the components before deploying them to a specific environment. Execute the following command to trigger the build:

choreo create build \"my-web-app\" --project=\"web-app-project\"\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-51-view-build-status","title":"Step 5.1: View build status","text":"

To check the status of a specific build, run the following command, replacing with the actual build ID obtained from the previous command:

Note

Typically, a build takes approximately 2 to 5 minutes to complete.

choreo describe build <build-id> --project=\"web-app-project\" --component=\"my-web-app\"\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-52-view-build-logs","title":"Step 5.2: View build logs","text":"

Once the build is complete, you can view the build logs for verification or debugging purposes. In the unlikely case, the build encounters any issues, the logs will help you troubleshoot.

choreo logs --type=build --project=\"web-app-project\" --component=\"my-web-app\" --deployment-track=\"main\" --build-id=<build_id>\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-6-deploy-to-the-development-environment","title":"Step 6: Deploy to the Development environment","text":"

Once the build status indicates successful you can deploy the component in the Development environment by running the following command:

choreo create deployment \"my-web-app\" --env=Development --project=\"web-app-project\" --build-id=<build-id>\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-61-verify-the-deployment-in-the-development-environment","title":"Step 6.1: Verify the deployment in the Development environment","text":"

After deploying the component, you can retrieve the URL of the deployed web application and open the publicly available web page to verify its behavior. Use the following command to retrieve the URL:

choreo describe component \"my-web-app\" --project=\"web-app-project\"\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-62-view-runtime-logs","title":"Step 6.2: View runtime logs","text":"

To observe runtime application logs of the web application in the Development environment, execute the following command:

choreo logs --type component-application --component my-web-app --project web-app-project --env Development --follow\n
"},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-7-deploy-to-the-production-environment","title":"Step 7: Deploy to the Production environment","text":"

Once you verify your application in the Development environment, you can proceed to deploy it to the Production environment with the following command:

  • Be sure to substitute with the id obtained after triggering the build.
    choreo create deployment \"my-web-app\" --env=Production --project=\"web-app-project\" --build-id=<build-id>\n
    "},{"location":"choreo-cli/get-started-with-the-choreo-cli/#step-71-verify-the-deployment-in-the-production-environment","title":"Step 7.1: Verify the deployment in the Production environment","text":"

    To ensure a successful deployment to the Production environment, retrieve the URL of the deployed web application using the following command:

    choreo describe component \"my-web-app\" --project=\"web-app-project\"\n

    Congratulations! You successfully deployed your web application in Choreo using the Choreo CLI.

    "},{"location":"choreo-cli/get-started-with-the-choreo-cli/#view-all-cli-functions","title":"View all CLI functions","text":"

    Discover other functionalities of Choreo by running the following command.

    choreo --help\n
    "},{"location":"choreo-concepts/choreo-marketplace/","title":"Choreo Marketplace","text":"

    The Choreo Marketplace promotes and facilitates reusing and sharing services. It allows you to share all the services deployed in Choreo. You can easily browse and search available services within the Marketplace and refer to the service definitions, documentation, instructions on how you can use it, etc.

    "},{"location":"choreo-concepts/choreo-marketplace/#discover-services","title":"Discover services","text":"

    The Marketplace includes all services deployed in your organization. This may be a large number of services. Therefore, effective discoverability is desirable.

    You can use the search or apply various filter criteria to explore the services available.

    "},{"location":"choreo-concepts/choreo-marketplace/#search","title":"Search","text":"

    The top search bar provides universal searching to find the services. It allows you to search for a text in the following search attributes:

    • Name: The service name.
    • Label: The service labels.
    • Content: The service content: overview, summary, and documentation.
    • All: All of the above criteria.
    "},{"location":"choreo-concepts/choreo-marketplace/#filter","title":"Filter","text":"

    The Choreo Marketplace provides a filtering capability through the left-hand side filter panel. It allows you to filter with the following filter attributes:

    • Type: This filter enables you to categorize services based on their type, with two available options: \"Internal\" and \"Third-party\". \"Internal\" refers to services deployed within Choreo, while \"Third-party\" refers to services running externally to Choreo, independently added to the Marketplace.

    • Network Visibility: This filter enables you to categorize services based on their network visibility level, with three choices: \"Public,\" \"Organization,\" and \"Project\". \"Public\" filters services exposed publicly, \"Organization\" represents services exposed across the entire organization, and \"Project\" represents services exposed at the project level.

    "},{"location":"choreo-concepts/choreo-marketplace/#explore-a-service","title":"Explore a service","text":"

    You can click on the service card to open the detailed view of the service. The detailed service page features the service name, summary, version, labels, and service icon as the header.

    Choreo organizes the service content into four tabs. The four tabs contain information as follows:

    • Overview: Choreo displays the service overview provided by the service developer. If the service developer has not provided any content at service creation, this section will be disabled. The service developer can provide the overview content via the Manage \u2192 Marketplace section of the component.

    • API definition: Includes the API definition for the service, extracted from the component.yaml file in the user repository. If an API definition is not provided, this tab will be empty.

      Note

      If you are are currently using the component-config.yaml or endpoints.yaml configuration files, see the respective migration guide for instructions on migrating to the recommended component.yaml configuration file.

    • How to use: Includes instructions on how to use the selected service. This includes instructions on creating a connection.

    • Related documents: Includes any additional content the user has provided as documents through the Manage -> Marketplace section of the component.

    "},{"location":"choreo-concepts/choreo-marketplace/#add-a-service-to-the-choreo-marketplace","title":"Add a service to the Choreo Marketplace","text":"

    You can add services to the Marketplace as Choreo services as follows:

    "},{"location":"choreo-concepts/choreo-marketplace/#add-a-choreo-service","title":"Add a Choreo service","text":"

    In Choreo, a service exposed through the platform is termed a Choreo service, with each service being identifiable by an endpoint within a Choreo service component. The Marketplace showcases a service for each endpoint within a service component.

    Upon deployment to the initial environment, services get automatically added to the Marketplace. Choreo effortlessly collects essential details such as component name, endpoint name, description, and service definitions during this deployment, utilizing them to generate the corresponding service entries in the Marketplace.

    The service name follows the convention of component name - endpoint name, while all other details remain unchanged.

    "},{"location":"choreo-concepts/choreo-marketplace/#service-versioning-in-the-choreo-marketplace","title":"Service versioning in the Choreo Marketplace","text":"

    In the Choreo Marketplace, service versions are displayed in their major version format. Each service in the Choreo Marketplace represents the latest version of the service within its major version, following semantic versioning principles.

    For example, if a Choreo service has versions v1.0, v1.1, v1.2, and v2.0, the Choreo Marketplace displays services with versions v1 and v2 representing the latest versions v1.2 and v2.0 respectively.

    When you deploy a new minor version of a service already deployed in Choreo, the corresponding service in the marketplace automatically updates to reflect the latest version within the same major version.

    "},{"location":"choreo-concepts/choreo-marketplace/#semantic-version-based-intelligent-routing-in-the-choreo-marketplace","title":"Semantic-version-based intelligent routing in the Choreo Marketplace","text":"

    When you use a service from the Choreo marketplace as a dependency, the dependent service's traffic automatically routes to the latest version of the corresponding service within the same major version. This ensures that your dependencies remain up-to-date without requiring manual updates within a major version.

    For example, if you create a connection to connect your Choreo component\u00a0named Foo\u00a0to a Choreo service\u00a0named Bar, which is currently available in the Choreo Marketplace as version\u00a0v1, and if\u00a0the latest version of the service Bar within the\u00a0v1\u00a0range is\u00a0v1.2, the component Foo will automatically connect to\u00a0Bar\u00a0v1.2. Subsequently, when Bar\u00a0releases version\u00a0v1.3, traffic from\u00a0Foo\u00a0will automatically route to\u00a0Bar v1.3.

    "},{"location":"choreo-concepts/choreo-marketplace/#edit-services-in-the-choreo-marketplace","title":"Edit services in the Choreo Marketplace","text":"

    You can edit services in the Choreo Marketplace. During redeployment to any environment, Choreo automatically updates service definitions, visibility, and descriptions.

    "},{"location":"choreo-concepts/ci-cd/","title":"CI/CD","text":"

    Choreo provides a streamlined continuous integration and continuous deployment(CI/CD) experience to deploy applications and services efficiently across multiple environments.

    Choreo creates environments for each project, where all components within the project share the environments. An environment is an isolated deployment area with restricted network and resource access. Services deployed in one environment cannot communicate with services deployed in another.

    The Choreo cloud data plane provides two default environments (i.e., development and production). However, if you are in a private data plane organization, you can customize and create multiple environments based on your requirements.

    Choreo adopts a build once, deploy many strategy to manage components across multiple environments. An application is built only once (i.e., per commit if automatic build on commit is enabled or based on the selected commit during a manual build). Then it is promoted to subsequent environments. This allows testing changes in lower, non-production environments like development before promoting the build to production.

    Choreo injects configurations and secrets that you maintain at the environment level into components at runtime. This ensures a strict separation of environment-specific configurations from source code. Although configurations can vary across environments, the code and the built container remain unchanged. Configurations and secrets include:

    • Resource credentials to a database, cache, or other backing services.
    • Credentials to external cloud services such as Amazon S3 or external APIs.

    All configurations and secrets are encrypted at rest and in transit and stored in a secure vault. In a private data plane organization, you can store configurations and secrets in your infrastructure.

    "},{"location":"choreo-concepts/ci-cd/#build","title":"Build","text":"

    Choreo auto-generates build pipelines that may slightly differ depending on the component type you create. Generally, all build pipelines work as follows:

    • Builds a container image either from the provided source code or from a given Dockerfile for a specific commit.
    • Runs security and vulnerability scans if applicable, depending on the component type.
    • Pushes the container image to a container registry. In the cloud data plane, Choreo pushes the image to a Choreo-managed registry. If it is a private data plane organization, Choreo pushes the image to a registry that you own.
    • Updates service endpoints and API specifications from the provided repository if applicable.
    "},{"location":"choreo-concepts/ci-cd/#repeatable-builds","title":"Repeatable builds","text":"

    Choreo can replicate builds from an identical code version (Git commit). This means that multiple builds initiated from the same Git commit will generate Docker images with the same behavior.

    Note

    In the event of multiple builds from the same code version, Choreo preserves only the most recent version of the Docker image created from the particular code version.

    "},{"location":"choreo-concepts/ci-cd/#trigger-a-build","title":"Trigger a build","text":"

    On the Build page, click Build Latest. If necessary you have the option to select a particular commit and build an image.

    If you want to automatically trigger a build with each commit, you can enable\u00a0Auto\u00a0Build\u00a0on Commit.

    "},{"location":"choreo-concepts/ci-cd/#build-logs","title":"Build logs","text":"

    You can view build logs for specific builds on the Build page.

    To view details of a specific build, click View Details corresponding to the build.

    "},{"location":"choreo-concepts/ci-cd/#deployment","title":"Deployment","text":"

    Once you build an image in Choreo, you can deploy it via the Deploy page. To deploy an image, you can follow one of the approaches given below:

    • Manually deploy: In the Deploy page, go to the Set Up card and click Deploy.

    • Automatically deploy on build: In the Deploy page, go to Set Up card and enable Auto\u00a0Deploy on\u00a0Build. This automatically initiates deployment upon the completion of an automatic build.

    Info

    To enable Auto\u00a0Deploy on\u00a0Build, you must enable Auto\u00a0Build\u00a0on Commit. This is because automatic\u00a0deployment is not necessary or useful in scenarios where automatic build is not enabled.

    Note

    • You must trigger the first build in a Ballerina component manually to ensure that Choreo applies the required configurations to the development environment. You can enable automatic builds subsequently.
    • Choreo automatically checks the configurable defined in your source code against the configurable values applied in an environment. Choreo requests the configurable values on deployment and promotion. If you have changed the configurables in your Ballerina component, auto-build pipelines can fail as a precaution to avoid a component crash at runtime due to missing configurables.
    • The configurable verifying capability is only available for Ballerina components. For Dockerfile-based components, ensure to manage and update the configurations and secrets in environments ahead of time. You must also ensure backward compatibility between at least one release if you change the configurations.
    "},{"location":"choreo-concepts/ci-cd/#set-up-area-and-initial-deployment","title":"Set up area and initial deployment","text":"

    In the deploy phase, Choreo uses a setup area to merge the Docker image with its environment-independent configurations. Choreo then deploys this composite to the environment. This is known as the initial deployment.

    "},{"location":"choreo-concepts/ci-cd/#immutable-deployments","title":"Immutable deployments","text":"

    Once Choreo deploys a component with configurations, the configurations become immutable. Any subsequent change results in a new deployment.

    "},{"location":"choreo-concepts/ci-cd/#promote-a-component-to-a-higher-environment","title":"Promote a component to a higher environment","text":"

    Choreo builds a container once per GitHub commit and then promotes it to subsequent higher environments.

    You can go to the Deploy page of a component and promote it manually across environments.

    "},{"location":"choreo-concepts/ci-cd/#configurations","title":"Configurations","text":"

    Choreo allows you to define both environment-independent configurations and environment-specific configurations.

    "},{"location":"choreo-concepts/ci-cd/#environment-independent-configurations","title":"Environment-independent configurations","text":"

    These configurations apply to all environments.

    To change environment-independent configurations, go to the Deploy page of the component, make the necessary configuration changes via the Set Up card, and then trigger a new deployment to the initial environment. From there, you can proceed to promote the component to higher environments.

    "},{"location":"choreo-concepts/ci-cd/#environment-specific-configurations","title":"Environment-specific configurations","text":"

    These configurations apply to a particular environment.

    To change environment-specific configurations, go to the Deploy page of the component, make the necessary configuration changes via the specific environment card, and trigger a new deployment.

    To learn more about managing these configurations, see Configuration Management.

    "},{"location":"choreo-concepts/ci-cd/#task-execution","title":"Task execution","text":"

    The information on the Execute page is only applicable to scheduled and manual task components.

    To track and monitor executions associated with a deployed scheduled task or manual task, go to the left navigation menu and click\u00a0Execute.

    You can view current and historic execution details along with a quick snapshot of recent activity via the total count of executions within the last 30 days. For each execution, you can view vital details such as the unique execution ID, the time it was triggered, and relevant revision information. Furthermore, you can dive deeper into the details by clicking on a specific execution to access its associated logs. This information enhances transparency, troubleshooting capabilities, and overall execution management, allowing you to easily monitor and analyze workflows.

    "},{"location":"choreo-concepts/ci-cd/#zero-downtime-deployments","title":"Zero-downtime deployments","text":"

    Choreo performs rolling updates to ensure zero downtime between deployments and promotions.

    A new build undergoes a health check before traffic is switched to it from the current build.

    If you configure the necessary health checks for a component, it can prevent deploying and promoting unhealthy versions of a component.

    "},{"location":"choreo-concepts/component/","title":"Component","text":"

    A component within a project represents a single unit of work in a cloud native application. A component is usually a single microservice, API, or job/task. Each component in Choreo is attached to a given directory path in a Git repository which either contains program source code or a Dockerfile with build instructions. A component is Choreo\u2019s unit of deployment. Each component maps to a single pod in the Kubernetes cluster (data plane) at deployment time. Therefore, you can deploy, manage, and scale each component in Choreo independently.

    Choreo supports different component types for various use cases. These include component types such as services, API proxies, integrations, web applications, and so on. Each component type hosts unique features based on its characteristics. For example, a scheduled integration component can accept a cron expression as a configuration to schedule an integration job/task.

    "},{"location":"choreo-concepts/connections/","title":"Connections","text":"

    Services can exist in two main forms: standalone and integrated. Connecting services is an integral part in creating integrated solutions. Choreo allows you to connect services using Connections.

    Using Connections, you can integrate the service you intend to deploy on Choreo with other services on Choreo or external resources. Upon creating a connection to a service on Choreo, Choreo provides you a Connection ID along with a set of connection parameters. Thereafter, you have the capability to configure your service to establish a connection using this Connection ID and map connection parameters to environment variable names in your Choreo component. You can read these environment variable names in your service implementation to retrieve the values, to create a programmatic connection to the service you want to consume.

    At runtime, Choreo dynamically injects values into the environment variables based on the configured mapping. This approach ensures that the connection parameter values and the service connection creation remain loosely coupled, providing developers with flexibility and ease of maintenance.

    You can add Connections in different visibility levels: Project and Component. The visibility levels are described below:

    "},{"location":"choreo-concepts/connections/#project-connections","title":"Project Connections","text":"

    Project Connections are Connections you create to connect to services within a particular project. The Connections can be used by any component within the project.

    For example, if you want to share a third-party service like Twilio across the project for all the components within that project to reuse, you can create a project connection. Components can refer to Project Connections using the connection ID. Project connections created to consume Choreo services under the OAuth security scheme will share the same OAuth application across the project. Any component reusing such a connection will use the same client ID and client secret.

    "},{"location":"choreo-concepts/connections/#component-connections","title":"Component Connections","text":"

    Component Connections are Connections you define at the component level and used by only that component.

    For example, create a component connection if you want to connect a legacy service to a given component. Components can refer to the Component Connection using the connection ID. If your component consumes more than one Choreo service, the Component connections created to consume those Choreo services under the OAuth security scheme can share the same OAuth application by sharing the same client ID and secret between all such connections.

    Learn how you can share and reuse services using connections in Choreo.

    "},{"location":"choreo-concepts/data-planes/","title":"Data Planes","text":"

    Choreo's architecture comprises two key components: the control plane and the data plane. The control plane handles essential tasks such as administering organizations, users, and projects. In addition, it also governs the entire journey of application development, from the initial stages of creation, progressing to deployment, including measures to enforce governance and the provision for observability. The Choreo control plane is a SaaS that manages all cloud data planes and private data planes. It caters to diverse user personas, including CIOs, architects, and developers, as well as DevOps, site reliability engineers, and platform engineers.

    The data plane is the environment where user applications are deployed based on configurations set in the control plane. These applications can range from services and web applications to APIs, integrations, and scheduled tasks. The applications can be written in various programming languages, allowing for a polyglot approach. Importantly, all traffic related to the runtime of user applications is restricted to the Choreo data plane, ensuring strict containment of user data within its boundaries.

    Choreo's architecture features two distinct data plane types: cloud data planes and private data planes. A cloud data plane utilizes a multi-tenanted infrastructure model for deploying user applications, creating a shared yet secure environment for application runtime. In contrast, a private data plane(PDP) provides dedicated infrastructure for a single organization to run its user applications. This ensures an added layer of privacy and control for organizations with specific requirements.

    "},{"location":"choreo-concepts/data-planes/#private-data-planes","title":"Private data planes","text":""},{"location":"choreo-concepts/data-planes/#infrastructure","title":"Infrastructure","text":"

    Choreo private data planes can be deployed with almost all major cloud providers, such as Azure, AWS, and GCP, and are also compatible with on-premises infrastructure.

    The essential requirements for a private data plane include upstream-compatible Kubernetes clusters, a container registry, a key vault (secret store), and a logging service or log storage.

    "},{"location":"choreo-concepts/data-planes/#system-components","title":"System components","text":"

    Setting up the Choreo PDP system involves using a Helm installation on the Kubernetes infrastructure. The following software components are installed during the helm execution:

    • Cilium CNI and service mesh.
    • Choreo API Gateways and related components.
    • Choreo PDP agent.
    • Observability and logging APIs, along with observability agents.
    • Flux controller.

    All of these software components receive automatic updates, including security patches and bug fixes through the flux controller connected to the Choreo Update Management System.

    "},{"location":"choreo-concepts/data-planes/#connectivity-with-the-control-plane","title":"Connectivity with the control plane","text":"

    The private data plane requires communication with the Choreo control plane to manage various activities. All these communications are outbound from the private data plane, ensuring that there is no need to open any specific IP:Port from its perspective for these interactions. However, if an organization's network restricts all outbound traffic, it is necessary to permit outbound traffic to the public IP range of the Choreo control plane.

    The following table outlines the inbound and outbound connections from a private data plane:

    Data plane component Endpoint Direction Protocol Choreo PDP agent Choreo control plane (CP) (mizzen server) Outbound WSS Kubernetes API server Outbound (cluster internal) HTTPS, WS APIM/local adaptor Global adaptor Outbound HTTPS Azure Service Bus (CP) Outbound AMQP APIM/Enforcer Event hub (CP) Outbound AMQP Choreo secret resolver Cloud secret store Outbound (VPC internal) HTTPS Container registry Container registry (public) Inbound HTTPS Container registry Outbound (VPC internal) HTTPS Certificate manager Azure DNS service Outbound HTTPS LetsEncrypt Outbound HTTPS Flux source controller GitHub Outbound HTTPS Flux Helm controller Choreo container registry Outbound HTTPS

    All communication between the control plane and the private data plane is secured using TLS.

    "},{"location":"choreo-concepts/data-planes/#observability-architecture","title":"Observability architecture","text":"

    The following diagram depicts the architecture overview of Choreo's in-data-plane log and observability in Azure PDP:

    The private data plane observability architecture is centered around a strong commitment to data privacy and compliance. This is achieved through a strategic decision to retain logs and observability data within the data planes itself. Key aspects of this architecture include:

    • Data storage at source: Logs and observability data are stored within the data plane itself, enhancing security, simplifying access, and ensuring compliance.
    • Direct browser-to-data-plane interaction: The Choreo Console in the user's browser directly interacts with APIs in the data plane, reducing potential data routing complexities and ensuring a more secure, direct flow of information.
    • Reduced data exposure points: Fetching data directly from the data plane's APIs minimizes the number of data transfer points, effectively decreasing the chances of data exposure or interception.
    • Compliance with regulatory standards: The architecture supports data locality, aligning with global regulatory standards like GDPR and CCPA by keeping data in its original environment.
    • Improved performance and real-time insights: Direct interaction between the browser and data plane results in faster data retrieval, providing users with immediate insights.
    • User transparency and control: Users have a clear view of their data's location and access methods, alongside granular control over data access.
    "},{"location":"choreo-concepts/data-planes/#security","title":"Security","text":"

    The Choreo private data plane ensures extensive, production-grade security, ranging from infrastructure and architecture to zero-trust network security. All incoming traffic is protected by a firewall and must undergo authentication and authorization via the API Gateway. It also provides end-to-end network traffic encryption using Cilium transparent encryption, ensuring efficient data path encryption.

    For details on the private data plane security levels supported in Choreo pricing plans, see Private Data Plane Security Levels.

    "},{"location":"choreo-concepts/data-planes/#management-models","title":"Management models","text":"

    Choreo supports the following management models for private data planes (PDPs), fostering collaboration between WSO2 and customers across diverse scenarios:

    • WSO2 fully managed (infrastructure and PDP in WSO2 subscription) model
    • WSO2 fully managed (infrastructure and PDP in customer subscription) model
    • Customer self-managed (WSO2 provides installation script and updates) model

    To explore each management model in detail so that you can make informed decisions depending on the supported cloud-based operations and security, see Private Data Plane Management Models.

    "},{"location":"choreo-concepts/deployment-tracks/","title":"Deployment Tracks","text":"

    Deployment Tracks in Choreo are structured pathways for simplified software component deployment. They act like advanced CI/CD pipelines, ensuring your components reach their destinations seamlessly, whether from source code or prebuilt images. They establish an organized and structured approach that minimizes the chances of errors and challenges that are typically associated with deployment workflows.

    "},{"location":"choreo-concepts/deployment-tracks/#the-significance-of-deployment-tracks","title":"The significance of Deployment Tracks","text":"

    Deployment Tracks offer practical solutions to enhance the API consumer experience by addressing two critical challenges:

    • Streamlined deployment: Deployment Tracks serve as well-designed routes for your software components, enhancing the organization and reliability of the deployment process, similar to a well-structured express route.

    • Efficient API versioning: Especially beneficial for managed APIs, Deployment Tracks provide a straightforward method for creating API versions that seamlessly interact with previous iterations. This simplified version management benefits both API creators and consumers alike.

    "},{"location":"choreo-concepts/deployment-tracks/#streamlined-deployments","title":"Streamlined deployments","text":"

    For streamlined deployments, Choreo dissects two integral approaches that leverage Deployment Tracks: the comprehensive CI/CD integration and the focused CD-Only strategy.

    "},{"location":"choreo-concepts/deployment-tracks/#cicd-with-deployment-tracks","title":"CI/CD with Deployment Tracks","text":"

    A deployment track is linked to a particular branch within a GitHub repository. This connection is useful for handling deployments to various environments. On Choreo's Deploy page, you can easily visualize the deployments to specific environments associated with your selected deployment track. Moreover, the deployment track has a functionality that initiates automatic deployments for the linked branch. When activated, merging a pull request (PR) triggers a deployment to the development environment.

    "},{"location":"choreo-concepts/deployment-tracks/#cd-only-strategy-with-deployment-tracks","title":"CD-Only strategy with Deployment Tracks","text":"

    If you're inclined to use your own Continuous Integration (CI) systems and want to harness the deployment track as a Continuous Deployment (CD) pipeline, you can seamlessly link deployment tracks to a container registry repository. This configuration empowers users to effortlessly deploy images sourced directly from the linked container registry repository.

    "},{"location":"choreo-concepts/deployment-tracks/#efficient-api-versioning","title":"Efficient API versioning","text":"

    This section applies to only service components. When working with service components in Choreo, it is important to have an effective API versioning mechanism. Choreo follows a versioning mechanism based on Semantic Versioning (SemVer) but only includes the major version and minor version with the prefix v.

    For example, v1.2.

    You can follow the approach given below when you version APIs in Choreo:

    • Increment the major version when you make incompatible API changes.
    • Increment the minor version when you add functionality in a backward-compatible manner.

    What is Semantic Versioning?

    Semantic Versioning (SemVer) is a specification that defines how to assign and increment version numbers for software products, including APIs. For more information, see Semantic Versioning specification.

    One of the primary concerns when dealing with SaaS APIs is to minimize disruption for API consumers while continuously developing and deploying updates.

    In compliance with SemVer, changes that don't introduce breaking or additive modifications to the API are categorized as patch updates. Hover, from the perspective of API consumers, these changes should ideally not disrupt their API clients. Typically, API consumers are most concerned with major API version alterations, but there might be instances where minor version changes are communicated to them.

    Therefore, in the context of deployment tracks, API developers only need to specify the major and minor versions being delivered from a particular deployment track. This information is treated as the API version attribute of a deployment track. If the publisher requires versioning for internal tracking purposes, this can be accomplished in Git through the use of Git tags, on GitHub with GitHub releases, and so forth.

    "},{"location":"choreo-concepts/endpoint/","title":"Endpoint","text":"

    An Endpoint is a network-exposed function that resides within a component. In Choreo, service and integration components expose one or more endpoints. Each endpoint in a component can have a service contract (OpenAPI, GraphQL SDL) associated with it. This contract is used to expose the endpoint to consumers. In the absence of a contract, Choreo uses /* exposed on all HTTP verbs as the default contract to expose the service or the integration.

    Each endpoint exposed in a component is considered a single API. Therefore, Choreo allows you to do API management per endpoint for a given component. For example, you can perform lifecycle management and configure security settings per endpoint in a given component.

    See Configure Endpoints to learn how to configure endpoints when developing components in Choreo.

    "},{"location":"choreo-concepts/environments/","title":"Environments","text":"

    Choreo offers developers one or more environments to run their applications within a given data plane. By default, the Choreo cloud data plane provides two environments (i.e., development and production). Each project in Choreo is associated with one or more environments available in the organization. For example, project A may choose to utilize dev, staging, and production environments, while project B may only use development and production environments.

    You can promote components within a project across available environments. When you promote a component, its configuration values can be overridden with environment-specific values.

    The following diagram illustrates how a component is promoted across environments.

    "},{"location":"choreo-concepts/organization/","title":"Organization","text":"

    An organization in Choreo is a logical grouping of users and user resources. A first-time user must create an organization and be a member of it when signing in to Choreo. Users and resources in an organization cannot access resources in another organization unless an admin of the other organization invites them and adds them as a member of that organization. A user cannot create more than one organization.

    "},{"location":"choreo-concepts/organization/#switch-organizations","title":"Switch organizations","text":"

    If you are a member of more than one organization, you can switch from one organization to another when necessary. To do this, select the required organization from the Organization list in the Choreo Console header.

    "},{"location":"choreo-concepts/organization/#inviting-users","title":"Inviting users","text":"

    An organization administrator can invite users to the organization by assigning them specific groups. Invited users receive an invitation via email. An invited user must accept the invitation to join the organization and access the resources of that organization.

    "},{"location":"choreo-concepts/organization/#manage-user-permission","title":"Manage user permission","text":"

    Choreo manages user permissions with groups and roles.

    "},{"location":"choreo-concepts/organization/#groups","title":"Groups","text":"

    A group in Choreo is a collection of users, each with one or more roles assigned to them. Users within a group inherit the permissions associated with the roles assigned to that group. For instance, if a user is added to the API Publisher group, they will automatically receive the API Publisher role.

    Choreo comes with predefined groups already configured with specific roles, as follows:

    • API Publisher: A collection of users who have the API Publisher role.
    • API Subscriber: A collection of users who have the API Subscriber role.
    • Admin : A collection of users who have the Admin role.
    • Billing Admin : A collection of users who have the Billing Admin role.
    • Choreo DevOps : A collection of users who have the Choreo DevOps role.
    • Developer : Users who develop, deploy, and manage cloud native applications at scale.
    • External API Subscriber: A collection of users who have the External API Subscriber role.

    When creating a new group to invite members, be sure to assign a role to the group to ensure users have the required permissions.

    "},{"location":"choreo-concepts/organization/#roles","title":"Roles","text":"

    Choreo roles are defined as follows:

    • API Publisher: An API publisher can discover, create, publish, delete, test, and manage an API.
    • API Subscriber: An API subscriber is a developer in a particular organization. An API subscriber can subscribe to an application, manage subscriptions, manage applications, generate API keys, and manage API keys.
    • Admin: An administrator is responsible for all administration tasks, including user management, customizing the Developer Portal, managing projects, enabling analytics, managing domains, etc.
    • Billing Admin: Is responsible for billing administration that includes viewing tiers, creating and viewing organizations, managing invoices, viewing and creating subscriptions, and viewing and creating payment methods.
    • Choreo DevOps: A Choreo DevOps user is a user with access to the Choreo DevOps portal, enabling them to actively manage, ensure dependable deployment, and monitor components.
    • Developer : A user who can develop, deploy, and manage cloud native applications at scale.
    • External API subscriber: External API subscribers are API consumers who have access only to the API Developer Portal. They can join an organization with the sole purpose of consuming APIs.
    • Environment Manager (Deprecated): Manages deployment environments.
    "},{"location":"choreo-concepts/organization/#organization-id","title":"Organization ID","text":"

    The Organization ID serves as a unique identifier for each organization. To get the organization ID, follow the steps below:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. Click on the Organization list on the header and select your organization.
    3. In the left navigation, click Settings.
    4. In the header, click the Organization list. This will open the organization level settings page.
    5. Under Organization click Copy ID.
    "},{"location":"choreo-concepts/organization/#organization-handle","title":"Organization Handle","text":"

    The organization handle is a unique string that directly corresponds to your organization's name. To get the organization handle, follow the steps below:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. Click on the Organization list on the header and select your organization.
    3. In the left navigation, click Settings.
    4. Under Organization click Copy Handle.
    "},{"location":"choreo-concepts/project/","title":"Project","text":"

    A project in Choreo is a logical group of related components that typically represent a single cloud native application. A project consists of one or more components. All components within a project can ideally be (but is not restricted to) in a single GitHub repository under different paths. This is also known as the monorepo architecture.

    At deployment time, all components within a given project are deployed into a single namespace of the Kubernetes cluster. Components within a project can be exposed to the public internet, internally to the rest of the organization, or privately within the project only. A project in Choreo is represented as a cell with regard to the Cell-based architecture. The following diagram illustrates a project and how the components within a project are laid out at runtime:

    "},{"location":"choreo-concepts/resource-hierarchy/","title":"Resource Hierarchy","text":"

    The following diagram depicts the high-level resources and their relationships in Choreo.

    "},{"location":"choreo-concepts/resource-hierarchy/#organizations-and-data-planes","title":"Organizations and data planes","text":"

    Data planes are connected to the organization and are available for all the projects in the organization. When you create an environment in a project, the data plane connected to the organization is linked with an automatically generated Kubernetes namespace.

    "},{"location":"choreo-concepts/resource-hierarchy/#environments-and-data-planes","title":"Environments and data planes","text":"

    Choreo allows multiple Kubernetes clusters to be associated with an environment.

    This allows you to build highly resilient and resource-efficient solutions that utilize multiple clusters. Choreo synchronizes your applications and workloads between associated clusters in an environment. This allows you to perform multi-cluster deployment with a single click.

    The following diagram depicts how multiple clusters associate with different environments:

    Note

    It is not necessary to use a different cluster per environment. You can create multiple environments on the same cluster. The above diagram is only an example of a specific solution. Your application architecture may require an entirely different configuration than what is depicted in the diagram.

    "},{"location":"choreo-concepts/resource-hierarchy/#components-and-environments","title":"Components and environments","text":"

    Components belong to a project in Choreo and environments are provisioned per project as well. When a component is deployed, it is deployed as a container to the specified environment. Once deployed, you can promote the container image across the environments available in the project.

    "},{"location":"consuming-services/consuming-a-sevice/","title":"Consume a Service","text":"

    Choreo is a platform that allows you to create, deploy, and consume services seamlessly. The Choreo Developer Portal simplifies discovering and using APIs for API consumers.

    Typically, an application developer who may be internal or external to your organization would want to consume the APIs published in the Developer Portal to develop their applications. In this guide, you will learn how to discover, generate credentials, and test the consumption of a service published in the Choreo Developer Portal. You will also learn how to invoke the service via a web application.

    This guide walks you through the following steps:

    • Create an application in the Developer Portal and generate credentials for the application.
    • Subscribe the API to the application.
    • Consume a published REST API via your web application.
    "},{"location":"consuming-services/consuming-a-sevice/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, if you do not have a published service that you would want to consume via the Developer Portal, follow Develop a Service documentation to publish and deploy a sample REST API.

    "},{"location":"consuming-services/consuming-a-sevice/#discover-apis","title":"Discover APIs","text":"

    In the Choreo Developer Portal, developers can use the search option to find APIs by name. The APIs and services that are created and published through the Choreo Console become visible in the Developer Portal depending on the API's visibility as follows:

    • Public: The API is visible to all in the developer portal.

    • Private: The API is visible to the users who only sign in to the Developer Portal.

    • Restricted: The API is visible to only the user that has the roles that you specify. This option helps developers to enforce fine-grained access control to the API.

    To learn more about API visibility, see Control API Visibility.

    The Choreo Developer Portal lists APIs based on their major version.

    The overview page of an API displays the subscribed versions of the API along with the respective subscription details such as the subscribed application and the application creation date.

    Tip

    If you want to use an API, the recommended approach is to use the latest version of it. You can copy the major version pattern provided as the value of Endpoints(s) on the API overview page and use it in your client application. This ensures that your application always invokes the latest API version.

    "},{"location":"consuming-services/consuming-a-sevice/#create-an-application","title":"Create an application","text":"

    An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

    This section walks you through the steps to create an application in Choreo.

    Let's get started!

    "},{"location":"consuming-services/consuming-a-sevice/#step-1-create-an-application","title":"Step 1: Create an application","text":"

    To create an application in the Choreo Developer Portal, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. Click Applications. and then click +Create.
    3. Enter a name and description for the application.
    4. Click Create.

    This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

    "},{"location":"consuming-services/consuming-a-sevice/#step-2-generate-keys","title":"Step 2: Generate keys","text":"

    Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

    Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

    The following section walks you through the steps to generate an API access token in Choreo.

    Generate environment-specific keys and tokens

    You can generate keys and tokens to invoke production and non-production endpoints separately.

    Note

    The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

    1. In the Choreo Developer Portal header, click Applications.
    2. On the My Applications page, click on the application for which you want to generate keys and tokens.
    3. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
    4. Click to expand Advanced Configurations and review the options.

      • Grant Types: Select the grant types to use when generating the access token.
      • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
      • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
      • Application access token expiry time: Specify the access token expiry time in seconds.
      • Refresh token expiry time: Specify the refresh token expiry time in seconds.
      • ID token expiry time: Specify the ID token expiry time in seconds.
    5. Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

    To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

    Warning

    Make sure you do not use the test token in your production environment.

    "},{"location":"consuming-services/consuming-a-sevice/#subscribe-to-an-api","title":"Subscribe to an API","text":"

    You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API\u2019s major version.

    The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

    To subscribe to an API via an application, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. In the Developer Portal header, click Applications.
    3. On the My Applications page, click on the application with which you want to subscribe to an API.
    4. In the left navigation menu, click Subscriptions.
    5. In the Subscription Management pane that opens, click + Add APIs.
    6. Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

      Tip

      When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

      Once you subscribe to an API, you can invoke the API using the application keys.

    "},{"location":"consuming-services/consuming-a-sevice/#consume-the-api-via-your-web-application","title":"Consume the API via your web application","text":"

    You can invoke the API/service using the credentials you created above. Since Choreo services are secured, you need to invoke the services securely with the help of your IdP. To invoke the API/service you created securely, you need to follow the steps below:

    1. Create a web application in Choreo.
    2. Create an OAuth application in the IdP.
    3. Configure the web application to authenticate the API/service invocations from the IdP, and securely invoke the service/API in Choreo.
    4. Deploy the web application.

    In this guide, you will be using the following products and examples:

    • WSO2 Asgardeo as the IdP
    • choreo-samples/reading-list-app/reading-list-front-end as the web application. This is a React SPA that invokes the service using Axios. This web application is configured to read the choreo-samples/reading-list-app/reading-list-service as the service. You can modify this web application to read your service, or deploy the choreo-samples/reading-list-app/reading-list-service in Choreo and use it.
    "},{"location":"consuming-services/consuming-a-sevice/#step-1-create-a-web-application-component","title":"Step 1: Create a web application component","text":"

    Info

    You can use your own web application implementation in place of the sample web application. For this exercise, let's use the choreo-samples/reading-list-app/reading-list-front-end as the web application.

    To host the front-end application in Choreo, you must create a web application component. To create a web application component, follow the steps given below.

    1. In the Choreo console, select the project of the reading list application that you created in the previous steps, from the project list located on the header.
    2. Click Create under the Component Listing section to create a new component.
    3. On the Web Application card, click Create.
    4. Enter a unique name and a description for the web application. You can enter the name and description given below:

      Field Value Name Reading List Web App Description Frontend application for the reading list service
    5. Click Next.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub.
    7. In the Connect Repository pane, enter the following information:

      Field Description GitHub Account Your account GitHub Repository choreo-samples Branch main Buildpack Click React since the frontend is a React application built with Vite Build Context Path reading-list-app/reading-list-front-end Build Command npm install && npm run build Build Output dist Node Version 18
    8. Click Create. This initializes the service with the implementation from your GitHub repository and takes you to the Overview page of the component.

    Let's consume the service through the web app. Choreo services are by default secured. To consume a service in Choreo you need an access token. Let's configure the web application to connect to an IdP (For this guide, let's use Asgardeo) to generate an access token for a user.

    "},{"location":"consuming-services/consuming-a-sevice/#step-2-create-an-oauth-application-in-the-idp","title":"Step 2: Create an OAuth application in the IdP","text":"

    To invoke the service/API in Choreo you require a token. To obtain a token you need to create an OAuth application in the IdP. If you use any other IdP other than Asgardeo, create an OAuth application and set the following:

    • Allowed grant types: Code
    • Public client: Mark as a public client in an application.
    • Authorized redirect URLs: Enter the web app URL you copied earlier.
    • Allowed origins field: Add the same URLs that you added as authorized redirect URLs.
    • Access Token: Set JWT as the Token type.

    Choreo uses Asgardeo as the default identity provider for Choreo applications. When you create an application in the Choreo Developer Portal, it automatically creates a corresponding application in Asgardeo. You can go to the Asgardeo application to specify the configurations required for end users to sign in to the front-end application. Follow the steps below to configure the Asgardeo OAuth application:

    1. Access Asgardeo at https://console.asgardeo.io/ and sign in with the same credentials with which you signed in to Choreo.
    2. Make sure you are in the same organization that you were when you created the application in the Choreo Developer Portal. You can click the Organization list in the Asgardeo Console top menu and ensure you are in the correct organization.
    3. In the Asgardeo Console's left navigation, click Applications. You will see the readingListApp that Choreo automatically created for you.
    4. Click on the edit icon to edit the application.
    5. Click the Protocol tab and apply the following changes:

      1. Under Allowed grant types, select Code.
      2. Select the Public client checkbox.
      3. In the Authorized redirect URLs field, enter the web app URL you copied earlier and click the + icon to add the entry.
      4. In the Allowed origins field, add the same URLs that you added as authorized redirect URLs.
      5. Under Access Token, select JWT as the Token type.
      6. Click Update.
    "},{"location":"consuming-services/consuming-a-sevice/#step-3-configure-the-web-application-to-connect-to-the-idp-and-invoke-the-service","title":"Step 3: Configure the web application to connect to the IdP and invoke the service","text":"

    In this step, you are adding the configurations needed for the web app to successfully invoke the Reading List Service REST API. These configurations need to be updated for each environment you deploy the web app. Here you will be updating the configurations for the development environment.

    Note

    The web application is reading the environment-specific configurations from the window object at runtime. This is done via the config.js file in the root of the web application. In this section, you will mount the config.js file for the development environment. You will need to do the same for other environments as well when you deploy your web application to multiple environments.

    To configure the front-end application, follow the steps given below:

    1. While on the web application component page, click DevOps in the left navigation menu and then click Configs and Secrets.
    2. Click + Create.
    3. Select the mount configuration options as follows and click Next:

      Field Description Config Type Config Map Mount Type File Mount
    4. Specify values as follows for the mount configuration:

      Field Description Config Name Web App Config Mount Path /usr/share/nginx/html/config.js. Every config that needs to be exposed through the web server should be placed inside /usr/share/nginx/html/
    5. Copy the config details as a JSON file as shown below into the text area. Fill the placeholders with the values you copied from the previous steps as mentioned in the table below:

      window.config = {\nredirectUrl: \"<web-app-url>\",\nasgardeoClientId: \"<asgardeo-client-id>\",\nasgardeoBaseUrl: \"https://api.asgardeo.io/t/<your-org-name>\",\nchoreoApiUrl: \"<reading-list-service-url>\"\n};\n
      Field Description redirectUrl The web app URL you copied earlier. asgardeoClientId The Client ID of your OAuth application. In Asgardeo, you can find it on the Protocol tab of the readingListApp application asgardeoBaseUrl Specify the IdP API URL (For example, Asgardeo API URL) with your organization name. i.e., https://api.asgardeo.io/t/<ORG_NAME>. choreoApiUrl The reading list service URL. Copy the Public URL of the Reading List Service component from the endpoint table in the overview page for the relevant environment
    6. Click Create.

    Now you can proceed to deploy the web application.

    "},{"location":"consuming-services/consuming-a-sevice/#step-4-deploy-the-web-application","title":"Step 4: Deploy the web application","text":"

    To deploy the web application component, follow the steps below:

    1. In the left menu, click Deploy.
    2. In the Build Area card, click Deploy Manually. The deployment may take a few minutes to complete.
    3. Once the web application is deployed, copy the Web App URL from the development environment card.
    4. Navigate to the web app URL. You can verify that the web app is successfully hosted.

    That's it! You can use a user created in your IdP and invoke the service through your web application.

    "},{"location":"consuming-services/create-a-subscription/","title":"Create a subscription","text":"

    You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API\u2019s major version.

    The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

    To subscribe to an API via an application, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. In the Developer Portal header, click Applications.
    3. On the My Applications page, click on the application with which you want to subscribe to an API.
    4. In the left navigation menu, click Subscriptions.
    5. In the Subscription Management pane that opens, click + Add APIs.
    6. Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

      Tip

      When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

      Once you subscribe to an API, you can invoke the API using the application keys.

    "},{"location":"consuming-services/create-an-application/","title":"Create an application","text":"

    An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

    This section walks you through the steps to create an application in Choreo.

    Let's get started!

    "},{"location":"consuming-services/create-an-application/#step-1-create-an-application","title":"Step 1: Create an application","text":"

    To create an application in the Choreo Developer Portal, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. Click Applications. and then click +Create.
    3. Enter a name and description for the application.
    4. Click Create.

    This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

    "},{"location":"consuming-services/create-an-application/#step-2-generate-keys","title":"Step 2: Generate keys","text":"

    Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

    Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

    The following section walks you through the steps to generate an API access token in Choreo.

    Generate environment-specific keys and tokens

    You can generate keys and tokens to invoke production and non-production endpoints separately.

    Note

    The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

    1. In the Choreo Developer Portal header, click Applications.
    2. On the My Applications page, click on the application for which you want to generate keys and tokens.
    3. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
    4. Click to expand Advanced Configurations and review the options.

      • Grant Types: Select the grant types to use when generating the access token.
      • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
      • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
      • Application access token expiry time: Specify the access token expiry time in seconds.
      • Refresh token expiry time: Specify the refresh token expiry time in seconds.
      • ID token expiry time: Specify the ID token expiry time in seconds.
    5. Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

    To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

    Warning

    Make sure you do not use the test token in your production environment.

    "},{"location":"consuming-services/generate-an-access-token/","title":"Generate an Access Token","text":"

    Using access tokens for request authorization strengthens security measures, particularly in preventing certain types of denial-of-service (DoS) attacks aimed at published APIs. API consumers generate access tokens to access the API, incorporating them into their HTTP header requests as simple string values.

    When you register an application on the Developer Portal, you can generate a consumer key and a consumer secret for it. The consumer key and the consumer secret represent the credentials of the application. Similar to a user's username, the consumer key becomes the unique identifier of the application so that you can use it to authenticate the request to the API. Choreo issues an access token for the application against the mentioned consumer key.

    This section walks you through the steps to generate an access token for your application in Choreo.

    Let's get started!

    "},{"location":"consuming-services/generate-an-access-token/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, be sure you have the following:

    1. An application in the Choreo Developer Portal. If you do not have an application created, create a new application
    2. Generate keys for the application.
    3. Subscribe APIs to the application.
    "},{"location":"consuming-services/generate-an-access-token/#generate-an-access-token-via-curl","title":"Generate an access token via cURL","text":"

    You can follow the steps below to generate an access token for your application via cURL:

    1. In the Choreo Developer Portal header, click Applications.
    2. On the My Applications page, click on the application for which you want to generate the token.
    3. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
    4. Copy the Consumer Key, Consumer Secret, and Token Endpoint values.
    5. Use the following template and compile the cURL command with the values you copied in the above step.

      Format

      curl -k -X POST <token_endpoint> -d \"grant_type=client_credentials\" -H \"Authorization: Basic <base64encode(consumer-key:consumer-secret)>\"\n
      6. Execute the cURL command to generate an access token.

    "},{"location":"consuming-services/generate-an-access-token/#generate-an-access-token-via-the-choreo-console-for-testing-purposes","title":"Generate an access token via the Choreo Console (for testing purposes)","text":"

    You can follow the steps below to generate an access token for testing purposes:

    1. In the Choreo Developer Portal header, click Applications.
    2. On the My Applications page, click on the application for which you want to generate keys and tokens.
    3. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
    4. Click Generate Token.
    "},{"location":"consuming-services/manage-application/","title":"Manage Applications","text":"

    An application in Choreo is a logical representation of a physical application such as a mobile app, web app, device, etc. To consume an API in Choreo, you need to create an application that maps to your physical application and then subscribes to the required API over a usage policy plan that gives you a usage quota. A single application can have multiple subscriptions to APIs. Using the consumer key and consumer secret, you can generate an access token that you can use to invoke all the APIs subscribed to the same application.

    This section walks you through the steps to create an application in Choreo.

    Let's get started!

    "},{"location":"consuming-services/manage-application/#step-1-create-an-application","title":"Step 1: Create an application","text":"

    To create an application in the Choreo Developer Portal, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. Click Applications. and then click +Create.
    3. Enter a name and description for the application.
    4. Click Create.

    This creates the application and opens the application overview page. You can view details such as the token type, workflow status, and the application owner of the API.

    "},{"location":"consuming-services/manage-application/#step-2-generate-keys","title":"Step 2: Generate keys","text":"

    Choreo provides an OAuth 2.0 bearer token-based authentication for API access. An API access token/key is a string that is passed as an HTTP header of an API request to authenticate access to the API.

    Once you create an application in Choreo, you can generate credentials for it. When you generate credentials for the first time, Choreo provides a consumer key and consumer secret for the application. The consumer key becomes the unique identifier of the application and is used to authenticate the application.

    The following section walks you through the steps to generate an API access token in Choreo.

    Generate environment-specific keys and tokens

    You can generate keys and tokens to invoke production and non-production endpoints separately.

    Note

    The capability to access production endpoints depends on your role. If you have permission to access production endpoints, you can generate keys and tokens to invoke production endpoints.

    1. In the Choreo Developer Portal header, click Applications.
    2. On the My Applications page, click on the application for which you want to generate keys and tokens.
    3. In the left navigation menu, click the required environment under Credentials. This opens the Application Keys pane of the specific environment.
    4. Click to expand Advanced Configurations and review the options.

      • Grant Types: Select the grant types to use when generating the access token.
      • Public Client: Select Allow authentication without the client secret if your application can be considered as a public client such as an application running on a browser or mobile device.
      • PKCE for enhanced security: Select Mandatory if you want the application to send a code challenge in the authorization request and the corresponding code verifier in the token request. Asgardeo supports SHA-256 and plain.
      • Application access token expiry time: Specify the access token expiry time in seconds.
      • Refresh token expiry time: Specify the refresh token expiry time in seconds.
      • ID token expiry time: Specify the ID token expiry time in seconds.
    5. Click Generate Credentials. This opens the Application Keys pane with values populated for the credentials.

    You can use this consumer key and consumer secret values to generate an API access token by invoking the token endpoint. You can also revoke the access token by invoking the revoke endpoint.

    To generate a test token for testing purposes, you can click Generate Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client and obtain a test token.

    Warning

    Make sure you do not use the test token in your production environment.

    "},{"location":"consuming-services/manage-application/#grant-types","title":"Grant types","text":"

    Choreo authentication is based on OAuth 2.0. In OAuth 2.0, grant types are methods that allow client applications to obtain an access token depending on the type of the resource owner, the type of the application, and the trust relationship between the authorization server and the resource owner.

    "},{"location":"consuming-services/manage-application/#authorization-code-grant","title":"Authorization code grant","text":"

    The Authorization code flow provides a secure way for a client application to obtain an access token without exposing the user's credentials to the client application. The user only authenticates with the authorization server, which then issues an authorization code that can be exchanged for an access token.

    This helps to protect user credentials and prevents credentials from being compromised by malicious client applications.

    "},{"location":"consuming-services/manage-application/#refresh-token-grant","title":"Refresh token grant","text":"

    A refresh token is a token that you can use to get a new access token when your current access token is expired or when you need a new access token. You can use the refresh token grant type for this purpose. Issuing a refresh token is optional for the authorization server. If the authorization server issues a refresh token, it includes it in the response with the access token. You can use this refresh token and send it to the authorization server to obtain a new access token. Choreo's default authorization server, Asgardeo, issues refresh tokens for all grant types other than the client credentials grant type, as recommended by the OAuth 2.0 specification.

    Note

    • Keep your refresh token private, similar to the access token.
    • The process to get a new access token using the Refresh Token grant type requires no user interaction.
    "},{"location":"consuming-services/manage-application/#client-credentials-grant","title":"Client credentials grant","text":"

    The client credentials flow provides a secure way for client applications to obtain an access token without user authentication. This is useful in scenarios where the client application needs to access its own resources, such as data storage or APIs, but does not require access to user data. However, it is important to ensure that the client credentials are kept secure because any party who has these credentials can obtain access tokens and access the client's resources.

    "},{"location":"consuming-services/manage-application/#implicit-grant","title":"Implicit grant","text":"

    The implicit grant flow is an OAuth 2.0 grant type that enables a client application to obtain an access token directly from the authorization server without an intermediate authorization code exchange. This flow is commonly used in browser-based applications where the client application runs in a web browser.

    However, it is important to note that the access token is exposed in the browser's URL fragment, which can make it vulnerable to certain types of attacks, such as cross-site scripting (XSS). As a result, this flow is typically not recommended for applications that require high security.

    "},{"location":"consuming-services/manage-application/#password-grant","title":"Password grant","text":"

    The password grant flow is an OAuth 2.0 grant type that enables a client application to obtain an access token by presenting the user's username and password directly to the authorization server. This flow is generally considered less secure than other grant types, as it requires the client application to handle and transmit the user's credentials.

    The password grant is primarily used in scenarios where the client application is highly trusted, and the user experience is prioritized over security concerns. It is generally not recommended for use in public-facing applications or scenarios where sensitive data is accessed.

    "},{"location":"consuming-services/manage-application/#revoke-access-tokens","title":"Revoke access tokens","text":"

    Revoking JWT access tokens can be challenging due to their self-validating nature. Once a token is issued, it contains all the necessary information within itself to validate its authenticity, without requiring additional server-side lookups or interactions.

    It is recommended to use an expiry time that is not more than 900 seconds.

    In traditional session-based authentication, the server can easily revoke a session by invalidating its associated session ID. However, in the case of JWTs, there is no central authority that maintains a list of valid or invalid tokens. As a result, revoking a JWT token requires the use of denylist or allowlist techniques, which can add additional complexity to the authentication flow and may not always be foolproof.

    To mitigate these challenges, it is recommended to use short-lived JWT access tokens and regularly refresh them. This reduces the risk of unauthorized access if a token is stolen or leaked, as the token will expire after a short period of time. Additionally, implementing other security measures such as strong encryption and secure token storage can further enhance the security of JWT-based authentication.

    The Choreo Developer Portal keeps the lifespan of a token to 15 minutes (900 seconds) by default. Application Developers can increase the time if necessary, but as mentioned above, it is recommended to keep it to the minimal possible value.

    "},{"location":"consuming-services/manage-subscription/","title":"Manage Subscriptions","text":"

    You must subscribe to a published API to use it in your application. New API subscriptions cover all minor versions within the subscribed API\u2019s major version.

    The subscription process is designed to ensure the secure authentication of API requests via application keys. Alternatively, you can generate credentials for an API without an explicit subscription to an application. However, this approach limits the capability to control advanced configurations such as access token expiry time, revoke token expiry time, ID token expiry time, and enabling access to the API without a secret. Generating keys in the API is recommended for testing or short-term usage but not for long-term production usage.

    To subscribe to an API via an application, follow the steps given below:

    1. Sign in to the Choreo Developer Portal.
    2. In the Developer Portal header, click Applications.
    3. On the My Applications page, click on the application with which you want to subscribe to an API.
    4. In the left navigation menu, click Subscriptions.
    5. In the Subscription Management pane that opens, click + Add APIs.
    6. Click Add to subscribe to an API. Depending on your requirement, you can subscribe to one or more APIs.

      Tip

      When a new minor version of an API is published, the major version-based invocation URL will automatically route to the latest minor version within the subscribed API's major version. This ensures that existing client applications can continue to function without disruption while benefiting from the improvements or additions in the newer minor version.

      Once you subscribe to an API, you can invoke the API using the application keys.

    "},{"location":"consuming-services/share-applications/","title":"Share Applications","text":"

    Choreo's application-sharing feature allows you to share your applications with members within your organization. This facilitates collaborative efforts when there is a need for multiple members to work on the same application.

    Follow the steps given below to share an application with members of your organization:

    1. Sign in to the Choreo Developer Portal and click the Applications tab.
    2. On the Applications page, click on the application you want to share.
    3. On the Application Overview page that opens, click the Share button displayed on the right side.
    4. In the Share Application dialog, enter one or more email addresses depending on the members with whom you want to share the applications.

      Note

      You must type an email address and press enter for it to get added.

    5. Click Confirm. This will share the application in read-only mode with the specified members.

    To see the members with whom the application is shared, go to the Application Overview page and take a look at the email addresses in the Shared with field.

    "},{"location":"develop-components/bring-your-own-image/","title":"Bring Your Own Image (BYOI)","text":"

    Choreo allows you to deploy and manage prebuilt container images from external container registries as Choreo components. This enables you to deploy and effectively manage your container images within the Choreo environment.

    Info

    This feature is currently only available on private data planes (PDPs) for the following component types:

    • Service
    • Web Application
    • Scheduled Task
    • Manual Task
    "},{"location":"develop-components/bring-your-own-image/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, ensure you have the following:

    • A container registry: Ensure you have a container registry containing the images you want to deploy. Choreo is compatible with various container registries, including but not limited to GCR (Google Container Registry), ACR (Azure Container Registry), GitHub Container Registry, and Docker Hub.

    • An image in the registry: You need an image ready for deployment.

    • (Optional) An external build/CI pipeline: This is to initiate automatic deployments during the build process outside of Choreo.

    When using a container registry to deploy a component, Choreo cannot create an image from the source code (Git) or initiate a new deployment when a new image is ready. However, you can use your existing build process to trigger a deployment on Choreo by sending an HTTP POST request to a webhook with the new image details.

    This feature is currently only available on private data planes (PDPs). You can find this option under Deploy an image from a container registry in the Select Source step during component creation for service components, web applications, scheduled tasks, and manual tasks.

    "},{"location":"develop-components/bring-your-own-image/#step-1-register-a-container-registry","title":"Step 1: Register a container registry","text":"

    To get started, establish a connection between your container registry and Choreo.

    Info

    When you use your Choreo credentials, Choreo does not pull your images into its control plane. Instead, it functions as an orchestrator, facilitating your data plane's ability to retrieve images from an external container registry. Choreo passes on these credentials to the data plane for authentication and access.

    To register your container registry, follow these steps:

    1. Sign in to the Choreo Console.
    2. In the Choreo Console header, go to the Organization list and select your organization.
    3. In the left navigation menu, click Settings. This opens the organization settings page.
    4. Click the Credentials tab and then click the Container Registries tab.
    5. Click +Add Registry to configure the Git repository connection.
    6. Specify a Registry Display Name.
    7. Select the Authentication Type. Fill in the required information depending on your authentication type. For details on each authentication type, see Authentication types.
    8. Click Save.
    "},{"location":"develop-components/bring-your-own-image/#authentication-types","title":"Authentication types","text":"

    Choreo provides the following authentication options:

    Public (anonymous) access

    You can use this option to establish a connection with a container registry that permits unrestricted public or anonymous access (for example, Public Docker Hub). In this case, only the registry host information is necessary.

    For example, the following are the Docker Hub registry hosts for reference:

    Vendor Registry host Docker Hub (public repositories) registry.hub.docker.com Docker Hub (private repositories) registry.docker.com

    * If necessary, you can use other mirrors instead of the above.

    Basic authentication

    To use basic authentication to authenticate to the container registry, you must provide the username and password.

    Docker config

    You can provide a Docker config in JSON format to authenticate to the container registry. This option only allows you to register one container registry. That is, it only allows a single registry under auths.

    You must provide the credentials directly within the configuration. Choreo cannot utilize references to executable authentication plugins.

    Sample Docker config format:

        {\n\"auths\": {\n\"index.docker.io/v1/\": {\n\"auth\": \"c3R...zE2\"\n}\n}\n}\n
    Vendor-specific authentication

    This option is specifically for private data planes, where your cloud provider manages authentication at the Kubernetes level. Choreo requires knowledge of the registry host because the data plane already possesses implicit (preconfigured) access to the registry.

    Follow the guidelines below based on your container registry:

    ACRGARAWS ECRDocker Hub (Private)GHCR

    Azure Container Registry

    Recommended authentication options:

    • Service principal-based basic authentication

    • Vendor-specific authentication on Azure private data planes

      Contact Choreo support to enable infrastructure-level private access to your registry from your Azure private data plane on AKS. If you are on a self-managed PDP on Azure, follow this guide.

    Google Artifact Registry

    Recommended authentication options:

    • Service account-based basic authentication

      Use the service account key in JSON format (_json_key) as the username and specify the minified JSON contents of the service account key as the password.

      You can use jq as follows to minify the service account JSON key file:

      jq -c . <service-account.json>

    • Vendor-specific authentication on GCP private data planes

      Contact Choreo support to enable infrastructure-level private access to your registry from your GCP private data plane on GKE. If you are on a self-managed PDP on GCP, see https://cloud.google.com/artifact-registry/docs/access-control#grant-project.

    Elastic Container Registry

    ECR does not allow the creation of static access passwords for basic authentication. The passwords (that is, access tokens) provided by AWS are only valid for 10 hours and must be manually regenerated. However, when an ECR is attached to an EKS cluster at an infrastructure level, this limitation does not apply because the authentication is handled by AWS internally. For details, see https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html.

    Choreo recommends using ECR when you are exclusively on an AWS private data plane using the vendor-specific authentication option. Contact Choreo support to enable a private connection between your ECR and the underlying EKS clusters on your data plane. If you are on a self-managed PDP, you can follow this guide.

    Recommended authentication options:

    • Basic authentication

      Use your Docker Hub username/password or an access token. You can generate an access token from your Docker Hub account settings and use it in place of the password. For details, see https://docs.docker.com/docker-hub/access-tokens/.

    • Docker config

      Sign in to the Docker CLI and copy the contents of the docker config JSON. Note that external credential stores and multiple repositories within the same config object are not supported. For more information, see https://docs.docker.com/engine/reference/commandline/login/.

    GitHub Container Registry

    Recommended authentication option:

    • Basic authentication using a PAT token

      Create a personal access token (PAT) and use it in place of the password. You cannot use your own GitHub password. You must provide a PAT token.

    "},{"location":"develop-components/bring-your-own-image/#step-2-create-a-component-in-choreo","title":"Step 2: Create a component in Choreo","text":"
    1. In the left navigation, click Overview and select your project. Alternatively, select your project from the Project list in the Choreo Console header.
    2. Under Component Listing click + Create.
    3. Select your component type (BYOI is only available for Service, Web Application, Scheduled Task, or Manual Task components).
    4. Enter a display name, a unique name, and a description for the component.

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    5. Click either the Docker Hub tab or the Container Registry tab depending on your vendor.

    6. Under Deploy an image from Container Registry/Docker Hub, select the container registry you have registered in Step 1.
    7. Enter the full image URL. The image URL format in general is as follows: [container-registry-host]/[repository-name]/[image-name]:[tag]

      Tip

      When a public image from Docker Hub lacks a specified repository name, it typically defaults to /library/. For example, you can access the public Nginx image https://hub.docker.com/_/nginx as registry.hub.docker.com/library/nginx:1.25.

    "},{"location":"develop-components/bring-your-own-image/#step-3-deploy-the-component-in-choreo","title":"Step 3: Deploy the component in Choreo","text":"

    To deploy the component and bring your image to Choreo, follow the steps given below:

    1. In the left navigation menu, click Deploy.
    2. In the Build Area card, click Update Image & Deploy.
    3. In the Endpoint pane that opens, you can see the endpoint ready to be deployed. Click the edit icon next to the endpoint name. Optionally, you can define the endpoints for your service when you manually deploy the service. For more information, see Expose service endpoints.
    4. Change the Network Visibility to Public. This setting securely exposes the endpoint for consumption.
    5. Click Update.

      Info

      In this example, you deploy a Ballerina service as a REST endpoint. Therefore, Choreo generated the REST endpoint automatically. If you deploy a non-Ballerina service, you must manually add the REST endpoint and set the network visibility to Public.

    6. Select your update image option. Refer to the update options listed below.

      You have the capability of updating the image when you are deploying the component in Choreo in one of the following three ways:

      Option Description Update Image Tag This option allows you to update the tag of the image. Update Image URL With this option, you can change the image name, tag, and the image repository of the image URL. Previous Images This option allows you to select a previous image and redeploy the image.
    7. Click Deploy. This deploys the service to the development environment.

    "},{"location":"develop-components/bring-your-own-image/#step-4-expose-service-endpoints","title":"Step 4: Expose service endpoints","text":"

    Info

    This section only applies to service components.

    After creating a service component in Choreo, you have the option to define the endpoints for your service when manually deploying a new image.

    1. In the left navigation menu, click Deploy.
    2. In the Build Area card, click Update Image & Deploy.
    3. In the Endpoint pane that opens, optionally, you can define the endpoints for your service when you manually deploy the service.
    4. Click Create/Update Endpoints.
    5. Under the Edit endpoints.yaml section, you can edit the endpoints YAML file in the provided editor. Alternatively, you can upload the associated API specification/schema files (OpenAPI/GraphQL schemas). Instead of specifying the file path, you can also reference this file in the endpoints.yaml file by its file name, similar to the Git-based Choreo components. The endpoints template follows the standard definitions for defining endpoints in Choreo. For more details, see Configure Endpoints.
    "},{"location":"develop-components/bring-your-own-image/#auto-deploy-images-in-choreo-with-an-external-cibuild-pipeline","title":"Auto-deploy images in Choreo with an external CI/build pipeline","text":"

    Choreo does not have automatic detection and deployment for newly added images or tags in the linked container registry. To overcome this limitation, Choreo allows you to integrate your own CI pipelines and initiate deployments manually. This approach enables you to use your existing CI setup or build a pipeline for image creation and pushing. You can then trigger automatic deployments using a webhook.

    Follow the steps below to configure your CI/build pipeline:

    1. Build and push the container image associated with a Choreo component to your container registry.
    2. In the left navigation menu, click DevOps and then click External CI.
    3. Generate a token for your CI pipeline from the Manage Tokens section.

      Note

      • The tokens are bound to a specific component.
      • It is recommended to reference the token from a secure location available to your CI pipeline. For example, use a GitHub secret if you are using GitHub Actions.
    4. To trigger an automatic deployment to your development environment, you can initiate an HTTP POST request to the Choreo webhook endpoint with the updated image details. Alternatively, you can use the provided Webhook snippets. This action will seamlessly deploy the image to the development environment.

    "},{"location":"develop-components/configure-endpoints-body/","title":"Configure endpoints body","text":"

    Services and integrations are exposed to other services, integrations, or applications through endpoints. A service or an integration can expose multiple endpoints, each representing a unique entry point into the service. For example, a service may expose a REST API endpoint and a GraphQL endpoint, each providing different ways to interact with the service. Endpoints provide specific details for how the service or the integration can be consumed. For instance, the port number, protocol, and the schema such as open API specification (OAS) or GraphQL schema. By defining these details, endpoints make it possible for other services, integrations, and applications to discover and interact with the service in a standardized way.

    Choreo defines endpoints by combining port binding, protocol, endpoint name, network visibility, endpoint schema, and additional protocol-related fields. The following table describes each attribute of an endpoint.

    Field Description Name A unique identifier for the endpoint within the service component. Port The network port on which the endpoint is accessible. Type The endpoint protocol. Supported protocols: REST, GraphQL, gRPC, WS, UDP, and TCP. Network Visibility Determines the level of visibility of an endpoint. Possible values are:
    • Project: Allows components within the same project to access the endpoint.
    • Organization: Allows any component within the same organization to access the endpoint but restricts access to components outside the organization.
    • Public: Allows any client to access the endpoint, regardless of location or organization.
    Schema Specifies the structure and format of the data exchanged through the endpoint. Context (HTTP and GraphQL only) A context path that you add to the endpoint's URL for routing purposes."},{"location":"develop-components/configure-endpoints-body/#configure-endpoints","title":"Configure endpoints","text":"

    The method of defining endpoints depends on the buildpack. For buildpacks other than Ballerina and WSO2 MI, it is required to have an component.yaml file in project root directory to create the Service component.

    "},{"location":"develop-components/configure-endpoints-body/#configure-endpoints-with-buildpacks-except-ballerina","title":"Configure endpoints with buildpacks (except Ballerina)","text":"

    When you build a service component using any other buildpacks(Java, Python, NodeJS, Ruby, PHP, Go, Dockerfile, etc) other than Ballerina and WSO2 MI, you can configure the endpoint details with the component.yaml source configuration file. You must place this file inside the .choreo directory at the build context path and commit it to the source repository.

    To learn about the component.yaml file, see Overview of the component.yaml file.

    "},{"location":"develop-components/configure-endpoints-body/#configure-endpoints-with-the-ballerina-buildpack","title":"Configure endpoints with the Ballerina buildpack","text":"

    When you create a service component with the Ballerina buildpack, Choreo automatically detects the endpoint details for REST APIs. You can override the auto-generated endpoint configuration by providing the component.yaml file in the source directory.

    Note

    Automatic endpoint generation is not supported for dynamic endpoint parameters such as variable ports. Therefore, you must use an component.yaml file to define dynamic endpoint parameters.

    To learn about the component.yaml file, see Overview of the component.yaml file.

    "},{"location":"develop-components/configure-endpoints-body/#expose-endpoints-as-managed-apis","title":"Expose endpoints as managed APIs","text":"

    Exposing endpoints as managed APIs is crucial to ensure secure and controlled access to the services being exposed. When a user wants to expose their written service to the outside world or to the organization at large, there is an inherent security risk involved. To mitigate this risk, the Choreo platform is built with an internal (access within the organization only) or external (publicly accessible) gateway that is protected with Choreo API management making the services secure by design.

    Note

    This feature is not available for gRPC, UDP, and TCP endpoints.

    If you want to expose an endpoint as a managed API in Choreo, you need to set the network visibility to either Organization or Public. This allows the endpoint to be exposed through the Choreo API Gateway, which provides a number of benefits, including:

    • Expose APIs to external and internal consumers
    • Full lifecycle API Management
    • API throttling
    • Secure APIs with industry-standard authorization flows
    • API analytics and monitoring

    Once you deploy the service component, Choreo will expose the endpoint as a managed API through the Choreo API Gateway. You can then use the full lifecycle API management features provided by Choreo to test, deploy, maintain, monitor, and manage your API using the API management features.

    "},{"location":"develop-components/configure-endpoints-body/#understand-the-default-component-url","title":"Understand the default component URL","text":"

    The default URL of a component corresponds to the default endpoint of the component and is structured as follows:

    <domain>/<project-name>/<component-name>

    This URL does not include the default endpoint name. For all other endpoints, the URL structure includes the endpoint name, as follows:

    <domain>/<project-name>/<component-name>/<endpoint-name>

    If a component has multiple endpoints, Choreo allows you to change the endpoint corresponding to the default component URL. For a component with a single endpoint, the default URL automatically corresponds to that endpoint.

    "},{"location":"develop-components/configure-endpoints-body/#change-the-default-endpoint-of-a-component","title":"Change the default endpoint of a component","text":"

    To change the default endpoint of a component, follow the steps given below:

    Note

    • You cannot change the default endpoint if it has associated published APIs. You must go to the Lifecycle page and unpublish the relevant APIs before updating the default endpoint. For instructions on unpublishing an API, see Lifecycle Management.
    • Choreo does not allow you to change the default endpoint of a component if you create multiple deployment tracks within its current major version, or promote the component beyond its initial environment.
    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component for which you want to change the default endpoint.
    3. In the left navigation menu, click Deploy.
    4. On the Deploy page, go to the Set Up card and click Configure & Deploy.
    5. In the Environment Configurations pane that opens, click Next.
    6. In the File Mount pane that opens, click Next.
    7. In the Endpoint Details pane that opens, click the Default Endpoint list, select the endpoint you want to set as the default endpoint, and then click Update.
    8. Click Deploy. This deploys the component with the selected endpoint as the default, and the default URL will now correspond to this endpoint.
    "},{"location":"develop-components/configure-endpoints/","title":"Configure Endpoints","text":"

    Services and integrations are exposed to other services, integrations, or applications through endpoints. A service or an integration can expose multiple endpoints, each representing a unique entry point into the service. For example, a service may expose a REST API endpoint and a GraphQL endpoint, each providing different ways to interact with the service. Endpoints provide specific details for how the service or the integration can be consumed. For instance, the port number, protocol, and the schema such as open API specification (OAS) or GraphQL schema. By defining these details, endpoints make it possible for other services, integrations, and applications to discover and interact with the service in a standardized way.

    Choreo defines endpoints by combining port binding, protocol, endpoint name, network visibility, endpoint schema, and additional protocol-related fields. The following table describes each attribute of an endpoint.

    Field Description Name A unique identifier for the endpoint within the service component. Port The network port on which the endpoint is accessible. Type The endpoint protocol. Supported protocols: REST, GraphQL, gRPC, WS, UDP, and TCP. Network Visibility Determines the level of visibility of an endpoint. Possible values are:
    • Project: Allows components within the same project to access the endpoint.
    • Organization: Allows any component within the same organization to access the endpoint but restricts access to components outside the organization.
    • Public: Allows any client to access the endpoint, regardless of location or organization.
    Schema Specifies the structure and format of the data exchanged through the endpoint. Context (HTTP and GraphQL only) A context path that you add to the endpoint's URL for routing purposes."},{"location":"develop-components/configure-endpoints/#configure-endpoints_1","title":"Configure endpoints","text":"

    The method of defining endpoints depends on the buildpack. For buildpacks other than Ballerina and WSO2 MI, it is required to have an component.yaml file in project root directory to create the Service component.

    "},{"location":"develop-components/configure-endpoints/#configure-endpoints-with-buildpacks-except-ballerina","title":"Configure endpoints with buildpacks (except Ballerina)","text":"

    When you build a service component using any other buildpacks(Java, Python, NodeJS, Ruby, PHP, Go, Dockerfile, etc) other than Ballerina and WSO2 MI, you can configure the endpoint details with the component.yaml source configuration file. You must place this file inside the .choreo directory at the build context path and commit it to the source repository.

    To learn about the component.yaml file, see Overview of the component.yaml file.

    "},{"location":"develop-components/configure-endpoints/#configure-endpoints-with-the-ballerina-buildpack","title":"Configure endpoints with the Ballerina buildpack","text":"

    When you create a service component with the Ballerina buildpack, Choreo automatically detects the endpoint details for REST APIs. You can override the auto-generated endpoint configuration by providing the component.yaml file in the source directory.

    Note

    Automatic endpoint generation is not supported for dynamic endpoint parameters such as variable ports. Therefore, you must use an component.yaml file to define dynamic endpoint parameters.

    To learn about the component.yaml file, see Overview of the component.yaml file.

    "},{"location":"develop-components/configure-endpoints/#expose-endpoints-as-managed-apis","title":"Expose endpoints as managed APIs","text":"

    Exposing endpoints as managed APIs is crucial to ensure secure and controlled access to the services being exposed. When a user wants to expose their written service to the outside world or to the organization at large, there is an inherent security risk involved. To mitigate this risk, the Choreo platform is built with an internal (access within the organization only) or external (publicly accessible) gateway that is protected with Choreo API management making the services secure by design.

    Note

    This feature is not available for gRPC, UDP, and TCP endpoints.

    If you want to expose an endpoint as a managed API in Choreo, you need to set the network visibility to either Organization or Public. This allows the endpoint to be exposed through the Choreo API Gateway, which provides a number of benefits, including:

    • Expose APIs to external and internal consumers
    • Full lifecycle API Management
    • API throttling
    • Secure APIs with industry-standard authorization flows
    • API analytics and monitoring

    Once you deploy the service component, Choreo will expose the endpoint as a managed API through the Choreo API Gateway. You can then use the full lifecycle API management features provided by Choreo to test, deploy, maintain, monitor, and manage your API using the API management features.

    "},{"location":"develop-components/configure-endpoints/#understand-the-default-component-url","title":"Understand the default component URL","text":"

    The default URL of a component corresponds to the default endpoint of the component and is structured as follows:

    <domain>/<project-name>/<component-name>

    This URL does not include the default endpoint name. For all other endpoints, the URL structure includes the endpoint name, as follows:

    <domain>/<project-name>/<component-name>/<endpoint-name>

    If a component has multiple endpoints, Choreo allows you to change the endpoint corresponding to the default component URL. For a component with a single endpoint, the default URL automatically corresponds to that endpoint.

    "},{"location":"develop-components/configure-endpoints/#change-the-default-endpoint-of-a-component","title":"Change the default endpoint of a component","text":"

    To change the default endpoint of a component, follow the steps given below:

    Note

    • You cannot change the default endpoint if it has associated published APIs. You must go to the Lifecycle page and unpublish the relevant APIs before updating the default endpoint. For instructions on unpublishing an API, see Lifecycle Management.
    • Choreo does not allow you to change the default endpoint of a component if you create multiple deployment tracks within its current major version, or promote the component beyond its initial environment.
    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component for which you want to change the default endpoint.
    3. In the left navigation menu, click Deploy.
    4. On the Deploy page, go to the Set Up card and click Configure & Deploy.
    5. In the Environment Configurations pane that opens, click Next.
    6. In the File Mount pane that opens, click Next.
    7. In the Endpoint Details pane that opens, click the Default Endpoint list, select the endpoint you want to set as the default endpoint, and then click Update.
    8. Click Deploy. This deploys the component with the selected endpoint as the default, and the default URL will now correspond to this endpoint.
    "},{"location":"develop-components/deploy-a-containerized-application/","title":"Deploy a Containerized Application","text":"

    Using Choreo, you can easily deploy applications written in different language frameworks (such as Java, Go, NodeJS, Python, etc.) on shared or private data planes using containers.

    Choreo supports deploying containerized applications for the following component types:

    • Service
    • Web Application
    • Scheduled Task
    • Manual Task
    • Event Handler
    • Test Runner
    "},{"location":"develop-components/deploy-a-containerized-application/#connect-your-repository-to-choreo","title":"Connect your repository to Choreo","text":"

    To connect your GitHub repository to Choreo, you should authorize the Choreo Apps GitHub application to access your account or organization. When you attempt to connect your GitHub repository via the Component creation page, the Choreo Apps authorization prompt will appear.

    • Connect GitHub Repository

    • Authorize GitHub Application

    • Grant Repository Access

      The Choreo Apps requires the following permission:

      • Read access to issues and metadata
      • Read and write access to code, pull requests, and repository hooks

    Note

    You can revoke access if you do not want Choreo to have access to your GitHub account. Choreo needs write access only to send pull requests to a user repository. Choreo does not directly push any changes to a repository.

    Alternatively, you can connect a public repository without requiring authorization from the Choreo Apps GitHub application. You can paste a public repository URL in the Provide Repository URL field at the time of component creation.

    Tip

    Authorizing the repository with the Choreo Apps GitHub application becomes essential if you want to enable Auto Deploy for the component. If you own the repository, you can subsequently authorize it with the Choreo Apps GitHub application to enable Auto Deploy.

    After granting access to the required repositories, you can choose a repository and an associated branch to connect to the Choreo component. For the containerized application deployments, you should select the Dockerfile as the Buildpack and provide Dockerfile Path and Docker Context Path for the Docker build.

    The following table describes the individual fields in the Create Component pane.

    Field Description GitHub Account Your GitHub account or organization. If you want to add another GitHub account, you can expand the list and click + Add. GitHub Repository Depending on the repository access you provided, the list will show available repositories to be connected. Branch The branch of the repository. Buildpack Determines the implementation of the component: Any language or other language as a Docker container. Dockerfile Path The path to your Dockerfile. This path is defined relative to the repository root.For example, if the Dockerfile is at the repository root, the value for this field is /Dockerfile. Docker Context Path The Docker build context path. To include the repository root, leave the default / value. Port* The port at which your service is running. OpenAPI Filepath* The path to an OpenAPI specification (in YAML/JSON) relative to the repository root. If you don't provide a path, the system automatically generates a default allow-all specification.

    Note

    • Fields marked with * are not visible for all component types.

    • To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. You can refer to the sample Dockerfile for guidance.

    • To ensure that the defined USER instruction is valid, it must conform to the following conditions:

      • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
      • Usernames are not considered valid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
    "},{"location":"develop-components/deploy-a-containerized-application/#deploy-the-containerized-component","title":"Deploy the containerized component","text":"

    Choreo will automatically apply deployment configurations and settings based on the component type you select during creation. For example, if you select the Service component type, Choreo will deploy it as a Kubernetes deployment with appropriate scaling configurations.

    You can run unit tests in the build pipeline by adding the relevant command to the Dockerfile. For example:

    • Go-based sample
    • Python-based sample
    "},{"location":"develop-components/deploy-a-containerized-application/#application-configurations","title":"Application configurations","text":"

    You must provide any required configurations for running the application in the Configs & Secrets section of the component's DevOps page. Alternatively, you can also review the configurations when you manually deploy via the Deploy page.

    After clicking the Create button, you can select the confidentiality of the configuration and specify how to mount it to the container.

    Configuration types
    • ConfigMap: Stores non-confidential data as key-value pairs.
    • Secret: Stores and manages sensitive information, such as passwords, OAuth tokens, and ssh keys as key-value pairs.
    Mount types
    • Environment Variables: Mounts the selected ConfigMap or Secret as an environment variable in the container.
    • File Mount: Mounts the selected ConfigMap or Secret as a file in the container. Here, the key is the file name, and the value is the file content.

    The following image shows adding a ConfigMap with File Mount mount type to be read by the application.

    Note

    The JSON file includes ${DB_PASS} as an environment variable defined in a Secret. The application reads the JSON file and substitutes the placeholders with the corresponding environment variables.

    "},{"location":"develop-components/deploy-a-containerized-application/#deployment-configurations","title":"Deployment configurations","text":"

    Choreo lets you configure deployment settings such as scaling, resource limits, and health checks based on your selected component type.

    For more information about these configurations, see Choreo's DevOps capabilities.

    You can configure the Endpoints to expose your service using the Service Component in Choreo. See Service Component Overview for more information.

    "},{"location":"develop-components/deploy-a-containerized-application/#build-deploy-and-promote","title":"Build, deploy, and promote","text":"

    After adding the application configuration, you can build and deploy it by clicking the Deploy Manually button. Choreo will start the build process with the selected commit in the Build Area.

    Note

    The Auto Deploy on Commit feature, which automatically builds and deploys the application upon pushing a code change to the repository, is enabled by default. To turn off this feature, navigate to the Build Area of the Deploy page.

    Choreo scans your Dockerfile for security vulnerabilities during the build phase, and if there are no issues found, it proceeds with the build process. After building the image, it scans it again for vulnerabilities before deployment to the environment. You can view the build logs from the right-side panel, as shown in the image below.

    Once the build process is complete, Choreo will deploy the application automatically to the Development environment. To promote the build to higher environments, you can click the Promote button. The number of environment cards visible on the page may vary depending on your environment configurations.

    "},{"location":"develop-components/deploy-a-containerized-application/#troubleshoot-security-vulnerability-scan-failures-trivy","title":"Troubleshoot security vulnerability scan failures (Trivy)","text":"

    By default, Choreo utilizes the Aqua Trivy (OSS) image vulnerability scanner to detect security vulnerabilities in all Dockerfile-based build pipelines. The scanner will fail the pipeline if any CRITICAL CVEs (Common Vulnerabilities and Exposures) are detected. CVEs of other severity levels are recorded but does not fail the pipeline.

    If you cannot fix a critical CVE immediately, you can opt to ignore it. To ignore a critical CVE, add a trivyignore (<docker-build-context-path>/.trivyignore) file to your build context path. In the file, add the CVEs you need the pipeline to ignore, one entry per line as follows:

    CVE-2023-xxxx\nCVE-2023-yyyy\n

    You can add comments in the file by using # in front of the comment as follows:

    # comments can be added like this\nCVE-2023-xxxx\n
    "},{"location":"develop-components/deploy-an-application-with-buildpacks/","title":"Deploy an Application with Buildpacks","text":"

    Using Choreo, you can easily deploy applications written in different language frameworks (such as Java, Go, NodeJS, Python, Ruby, PHP, etc.) on shared or private data planes.

    Choreo supports deploying applications with buildpacks for the following component types:

    • Service
    • Web Application
    • Scheduled Task
    • Manual Task
    • Webhook
    • Event Handler
    • Test Runner
    "},{"location":"develop-components/deploy-an-application-with-buildpacks/#buildpacks","title":"Buildpacks","text":"

    Buildpacks are a fundamental building block in modern application development. They convert your source code into a secure, efficient, production-ready container image without a Dockerfile. With Choreo, developers can take advantage of this powerful tool to effortlessly deploy their applications without the hassle of manual configuration.

    Choreo uses Google Buildpacks as default buildpacks for Java, Go, NodeJS, Python, PHP, and Ruby. Choreo uses its own buildpacks for Ballerina and WSO2 MI.

    "},{"location":"develop-components/deploy-an-application-with-buildpacks/#develop-a-component","title":"Develop a component","text":"

    To develop a service component that exposes a Service in Go, you can follow the Develop a Service guide.

    Follow the guidelines below based on your language:

    PythonBallerinaGo.NETJavaNodeJSPHPRubyWSO2 MISpring Boot

    Supported Versions - 3.10.x, 3.11.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Reading Books List Service Manual Task Hello World Task

    Supported Versions - 2201.3.5, 2201.4.1, 2201.5.0, 2201.5.1, 201.6.0, 2201.7.0

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Echo Service Manual Task Covid19 Statistics To Email Webhook Salesforce New Case To Google Sheet Scheduled Task Shopify New Customers to HubSpot Create/Update Contact

    For more examples, see Choreo samples.

    Supported Versions - 1.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Greeting Service Manual Task Hello World Task Web Application Hello World Web Application

    For more examples, see Choreo samples.

    Supported Versions - 6.x, 7.x, 8.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Greeting Service

    For more examples, see Choreo samples.

    Supported Versions - 8, 11, 17, 18 (OpenJDK Runtime Environment Temurin)

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Product Management Service Manual Task Hello World Task

    Info

    When working on Java projects:

    • The Main class should be defined in the manifest file.
    • If Maven files such as mvn.cmd exist in the project without the .mvn directory, the build will fail. To ensure a successful build, you must either commit the .mvn directory along with any Maven files or not include any Maven files in the project if you choose not to commit the .mvn directory.
    Procfile

    A Procfile is a configuration file used to declare the commands that are run by your application's containers. If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. In Java projects, it is optional to include a Procfile.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web: java -jar target/sample.jar

    For more examples, see Choreo samples.

    Supported Versions - 12.x.x, 14.x.x, 16.x.x, 18.x.x, 20.x.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Reading Books List Service Manual Task Hello World Task Procfile

    A Procfile is a configuration file used to declare the commands that are run by your application's containers. If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. In NodeJS projects, it is optional to include a Procfile.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web: node app.js

    For more examples, see Choreo samples.

    Supported Versions - 8.1.x, 8.2.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Hello World Service Manual Task Hello World Task Web Application Hello World Web Application Procfile

    A Procfile is a configuration file used to declare the commands that are run by your application's containers. If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. In PHP projects, it is optional to include a Procfile.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web:php -S 0.0.0.0:8000 index.php

    For more examples, see Choreo samples.

    Supported Versions - 3.1.x, 3.2.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Hello World Service Manual Task Hello World Task Web Application Hello World Web Application Procfile

    A Procfile is a configuration file used to declare the commands that are run by your application's containers. If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. In Ruby projects, it is optional to include a Procfile.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web: ruby app.rb web:bundle exec ruby app.rb -p 8080

    For more examples, see Choreo samples.

    Supported Versions - 4.1.0.x, 4.2.0.x

    Refer below examples for different component types. Follow the readme.md inside the example.

    Component Type Example Service Hello World Service

    For more examples, see Choreo samples.

    Supported Java Versions - 8, 11, 17, 18 (OpenJDK Runtime Environment Temurin)

    Info

    You can use this buildpack only with web applications. For other component types, use the Java buildpack. Additionally, if the generated artifact is a WAR file, it is necessary to include a Procfile.

    Procfile

    A Procfile is a configuration file used to declare the commands that are run by your application's containers. If you want to customize the default entry point of the container, you can include a Procfile with the web process type in the project root directory. In Java projects, it is optional to include a Procfile.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web: java -jar target/sample.war

    "},{"location":"develop-components/deploy-an-application-with-buildpacks/#procfile","title":"Procfile","text":"

    A Procfile is a configuration file used to declare the commands that are run by your application's containers.

    Info

    In Python projects, it is mandatory to have a Procfile with the web process type in the project root directory.

    Here's an example Procfile for an application:

    web: <command to start your application>\n

    e.g.,

    web: python main.py web: gunicorn --bind :8080 --workers 1 --threads 8 --timeout 0 main:app web: flask run --host=0.0.0.0

    For more examples, see Choreo samples.

    "},{"location":"develop-components/deploy-an-application-with-buildpacks/#configure-build-time-environment-variables","title":"Configure build-time environment variables","text":"

    You can configure the environment variables necessary to build the component using the Build Configurations Editor on the component Build page.

    Info

    The capability to configure build-time environment variables is not available for components created using Ballerina or WSO2 MI buildpacks.

    During the build process, the build-time environment variables and their values are passed to the buildpack. Therefore, you can configure both buildpack-specific environment variables and those required for the component build.

    For example, if you want to override the Maven command of the Java buildpack, you can use GOOGLE_MAVEN_BUILD_ARGS as the environment key and clean install as the value.

    For more examples, see Google Cloud's buildpacks documentation.

    "},{"location":"develop-components/develop-a-webhook/","title":"Develop a Webhook","text":"

    Choreo allows developers to design high-quality webhooks. To explore this capability, let's consider a scenario where a team of software engineers in an organization should be notified via email whenever someone creates a GitHub issue with the bug label in a specific repository.

    In this tutorial, you will address the requirement by doing the following:

    • Create a webhook by connecting to a forked GitHub repository where you have the webhook implementation that addresses the described requirement.
    • Deploy the webhook to the development environment.
    • Modify the webhook implementation to connect the webhook to GitHub, enabling it to act in response to selected GitHub-related events.
    • Test the webhook.
    • Promote the webhook to the production environment.
    "},{"location":"develop-components/develop-a-webhook/#prerequisites","title":"Prerequisites","text":"

    Before you try out the steps in this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
    • Fork the Choreo samples repository, which contains the sample integration for this guide.

    "},{"location":"develop-components/develop-a-webhook/#step-1-create-a-webhook-component","title":"Step 1: Create a Webhook component","text":"

    To create a project, add a Webhook component to it, design the webhook, test it, and then commit it to make it available in the Choreo Console, follow these sub-steps:

    First, let's create a Webhook component as follows:

    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Go to the Webhook card and click Create.
    4. This opens the Create a Webhook pane, where you can specify a name and description for the component. Enter a unique name and description.
    5. Go to the GitHub tab.
    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Select the Access Mode depending on your requirement.

    8. Enter the following information:

      Field Description GitHub Account Your account GitHub Repository choreo-samples Branch main Buildpack Ballerina Project Path github-event-to-email-webhook
    9. Click Create.

    Choreo creates the Webhook component with the sample implementation and opens the component Overview page.

    "},{"location":"develop-components/develop-a-webhook/#step-2-deploy","title":"Step 2: Deploy","text":"

    Let's deploy the webhook to the development environment to make it invokable:

    1. In the Choreo Console left navigation menu, click Deploy.
    2. In the Build Area card, click Configure & Deploy.
    3. In the Configurations pane, enter the following information:

      1. In the webhookSecret field, enter any value.

        Note

        You must save this value for later use.

      2. In the toEmail field, enter the email address to send notification emails.

      3. Click Deploy.

      You can monitor the deployment progress in the Console pane that opens on the right of the page.

    Once Choreo completes the deployment, the Development card indicates the Deployment Status as Active.

    Notes

    In the deployment card, you can click the icon corresponding to configurables to open the Configurations pane and edit configurations:

    "},{"location":"develop-components/develop-a-webhook/#step-3-connect-the-webhook-to-the-github-repository","title":"Step 3: Connect the webhook to the GitHub repository","text":"

    To allow the webhook to read the labels of issues in a specific GitHub repository, you must connect the webhook to the GitHub repository. To do this, follow these steps:

    1. In the Choreo Console left navigation menu, click Overview.

    2. On the Overview page, copy the invoke URL. You can click the copy icon within the URL field.

    3. Go to your GitHub account and open the repository for which you want to generate notification emails.

    4. In the top menu, click the Settings tab.

    5. In the left navigation menu, click Webhooks.

    6. Click Add webhook and enter the following information:

      Field Value Payload URL The invoke URL you copied in Step 3, sub-step 1. Content Type Select application/json Secret The last webhook secret you configured in Step 2.

      Tip

      • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      • Project Path specifies the location of the project to build the component.

    7. Under Which events would you like to trigger this webhook?, select Let me select individual events.

    8. Select the Issues checkbox in the list of events displayed.

      By doing so, you select GitHub issues as events that need to trigger this webhook.

    9. In the same list of events, clear the Pushes checkbox to ensure that GitHub does not trigger your webhook when the team pushes changes to the selected GitHub repository.

    10. Click Add webhook to save the configuration.

    Now you have integrated Choreo with GitHub via the webhook you created and deployed. You can proceed to test the webhook.

    "},{"location":"develop-components/develop-a-webhook/#step-4-test","title":"Step 4: Test","text":"

    To test your webhook, create a GitHub issue with the Bug label in the repository that you connected to the webhook.

    You will receive a mail similar to the following to the email address you provided in Step 2.

    "},{"location":"develop-components/develop-a-webhook/#step-5-promote","title":"Step 5: Promote","text":"

    To promote the webhook to the Production environment, follow these steps:

    1. On the Deploy page, go to the Development card and click Promote.

    2. In the Configuration Types pane, leave the default selection (i.e., Use default configuration values) unchanged.

      If you have configured any default values for the configurable variables, selecting Use default configuration values allows you to proceed with those values.

      If you have not configured any default values for configurable variables, follow the steps given below to specify values.

    3. Click Next.

    4. In the webhookSecret field, enter any value.

      Note

      You must save this value for later use.

    5. In the toEmail field, enter the email address to send notification emails.

    6. Click Promote.

    Once the component is promoted to production, the Production card displays the deployment status as Active.

    Now you have successfully created, deployed, and tested a Webhook component and promoted it to production.

    "},{"location":"develop-components/develop-an-api-proxy/","title":"Develop an API Proxy","text":"

    An API proxy acts as an intermediary between an existing API and Choreo, intercepting all requests made to the API. It also functions as a managed API, which allows you to apply essential API management features such as security policies and rate limiting.

    In this guide, you will:

    • Create an API proxy component to expose an existing API.
    • Deploy the API proxy.
    • Test the API proxy to verify its functionality.
    • Manage the API.
    • Consume the API.
    "},{"location":"develop-components/develop-an-api-proxy/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    "},{"location":"develop-components/develop-an-api-proxy/#step-1-create-an-api-proxy","title":"Step 1: Create an API proxy","text":"

    To create an API proxy, you can either upload an OpenAPI specification or provide an OpenAPI specification URL. In this guide, you will specify a URL to an OpenAPI definition of a sample API.

    Follow the steps given below:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the API Proxy card. This opens the Create an API Proxy pane, where you can upload an OpenAPI definition or provide the URL of an OpenAPI. In this guide, you will define resources manually. Therefore, click Skip Source to proceed.
    4. Specify the values given in the following table as API proxy details:

      Info

      In the Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Display Name HR API Name hr-api Context abc-hr Version 1.0 Target https://samples.choreoapps.dev/company/hr Access Mode External
    5. Click Create.

    This creates the API proxy component and takes you to the Overview page. Now you can proceed to define resources for the API proxy.

    "},{"location":"develop-components/develop-an-api-proxy/#step-2-define-resources-for-the-api-proxy","title":"Step 2: Define resources for the API proxy","text":"

    To add a new resource that can retrieve a department by the department ID, follow the steps given below:

    1. In the left navigation menu, click Develop and then click Resources.
    2. Select GET as the HTTP Verb and enter /department/{departmentId} as the URI Pattern.
    3. Click + to add the resource.
    4. Click to expand the added resource and specify appropriate values for the Operation ID and Description fields. You can specify the values given in the following table:

      Field Value Operation ID findDepartment Description Find a department by department ID
    5. To remove the five default resources that start with /*, click the delete icon corresponding to each resource. This marks the resources for deletion.

    6. Click Save.
    "},{"location":"develop-components/develop-an-api-proxy/#step-3-deploy-the-api-proxy","title":"Step 3: Deploy the API proxy","text":"

    To deploy the API proxy to the development environment, follow the steps given below:

    1. In the left navigation menu, click Deploy.

    2. In the Build Area card, click Configure & Deploy. This opens the Configure & Deploy pane, where you can select the API access mode depending on how you want the API to be accessible. Here, you can select External.

    3. Click Deploy. The Development card indicates the Deployment Status as Active when the API proxy is successfully deployed.

    Now you are ready to test the API proxy.

    "},{"location":"develop-components/develop-an-api-proxy/#step-3-test-the-api-proxy","title":"Step 3: Test the API proxy","text":"

    Choreo allows you to test your API proxy using either the integrated OpenAPI Console or cURL.

    In this guide, you will use the OpenAPI Console to test the API proxy.

    Follow the steps given below:

    Tip

    Choreo enables OAuth 2.0 to secure APIs by default. Therefore, you need an access token to invoke an API.

    • Choreo automatically generates a key to test the API via the OpenAPI Console. To view the key, click the show key icon in the Security Header field.
    • Choreo allows you to disable security for an entire API or a specific API resource for testing purposes. If you want to disable security, follow these steps:
      1. In the left navigation menu, click Deploy.
      2. Go to the Build Area card and click Security Settings.
      3. In the Security Settings pane, perform one of the following actions depending on your requirement:
        • To disable security for the entire API, clear the OAuth2 checkbox.
        • To disable security for a specific API resource, go to the Permissions section, click to expand the relevant resource and then turn off the Security toggle.
      4. Click Apply.

    1. In the left navigation menu, click Test and then click OpenAPI Console.

    2. Select Development from the environment drop-down list.

    3. Expand the GET /department/{departmentId} resource and click Try it Out to test it.

    4. Enter 1 as the departmentId and click Execute. You will see a response similar to the following:

    This indicates that your API proxy is working as expected.

    "},{"location":"develop-components/develop-an-api-proxy/#step-4-manage-the-api-proxy","title":"Step 4: Manage the API proxy","text":"

    Now that you have a tested API proxy, you can publish it and make it available for application developers to consume. Depending on your requirement, you can apply security, throttling, and other settings to the API before you publish it.

    In this guide, you will apply rate limiting to the API and publish it.

    "},{"location":"develop-components/develop-an-api-proxy/#step-41-apply-a-rate-limiting-level-to-the-api-proxy","title":"Step 4.1: Apply a rate limiting level to the API proxy","text":"

    To apply a rate limiting level to the API, follow the steps given below:

    1. In the left navigation menu, click Deploy.
    2. Go to the required environment card and click the setting icon corresponding to API Configuration.
    3. In the API Configuration pane that opens, click Rate Limiting to expand the section.
    4. Select API Level as the Rate Limiting Level.
    5. Specify appropriate values for the Request Limit and Time Unit fields. In this guide, you can proceed with the default values. This applies a rate-limiting policy to the entire API. If necessary, you can also apply rate limits at the operation level. For more information, see API Rate Limiting.
    6. Click Apply. This applies the rate limiting level to the API proxy and redeploys it.
    "},{"location":"develop-components/develop-an-api-proxy/#step-42-publish-the-api-proxy","title":"Step 4.2: Publish the API proxy","text":"

    To publish the API proxy to the Choreo Developer Portal, follow the steps given below:

    1. In the left navigation menu, click Lifecycle under Manage. This takes you to the Lifecycle page where you can see the different lifecycle stages the API can be in. You can see that the current lifecycle stage is Created.
    2. Click Publish.
    3. In the Publish API dialog that opens, click Confirm to proceed publishing the API with the specified display name. If you want to change the display name, make the necessary changes and then click Confirm. This changes the API lifecycle state to Published.
    "},{"location":"develop-components/develop-an-api-proxy/#step-5-invoke-the-api","title":"Step 5: Invoke the API","text":"

    To generate credentials for the published API and to invoke it via the Choreo Developer Portal, follow the steps below:

    1. To open the published API in the Choreo Developer Portal via the Lifecycle page, click Go to Devportal. This takes you to the HR API in the Choreo Developer Portal.

    2. To generate credentials to test the API, follow the steps given below:

      1. In the Developer Portal left navigation menu, click Production under Credentials.
      2. Click Generate Credentials. Choreo generates new tokens and populates the Consumer Key and Consumer Secret fields.

        Tip

        If you want to test the API via an API test tool or through code, click Generate Access Token and copy the test token that is displayed. Alternatively, click cURL and copy the generated cURL command to use via a cURL client. You do not need to generate an access token if you are testing the API via the Try Out capability in the Choreo Developer Portal.

    3. To invoke a resource via the Try Out capability in the Choreo Developer Portal, follow the steps given below:

      1. In the Developer Portal left navigation menu, click Try Out.
      2. In the Endpoint list, select Development as the environment to try out the API.
      3. To generate an access token to try out the API, click Get Test Key. This populates the Access Token field with a test key.
      4. Expand the GET /department/{departmentId} resource and click Try it out.
      5. Enter 1 as the departmentId and click Execute. You will see a response similar to the following:

    Now, you have gained hands-on experience creating, deploying, testing, and publishing an API proxy using Choreo API Manager.

    To learn more about the API management capabilities supported by Choreo API Manager, see API Management.

    "},{"location":"develop-components/develop-components-using-vs-code/","title":"Develop Components Using VS Code","text":"

    The Choreo VS Code extension provides comprehensive component management capabilities to streamline local development within Choreo.

    "},{"location":"develop-components/develop-components-using-vs-code/#prerequisites","title":"Prerequisites","text":"

    To ensure a smooth development experience with the Choreo extension, make sure you have the following:

    1. Visual Studio Code installed with the Choreo extension version 2.0.0 or later.

    2. A locally cloned GitHub repository to create new components or link to existing Choreo components.

    3. Git version 2.0.0 or later.

    "},{"location":"develop-components/develop-components-using-vs-code/#get-started","title":"Get started","text":"

    To use the capabilities of the Choreo extension in the VS Code editor, you need an active Choreo account. If you already have an account, follow these steps to set up the extension:

    1. Install the Choreo VS Code extension and wait for activation. On successful activation, the Choreo extension opens in the VS Code editor.
    2. Sign in to Choreo using one of the following methods:

      • In the Choreo activity pane, click Sign In.
      • Use the Sign In command provided by the Choreo extension.

      This redirects you to an external URI to complete the authentication process. On successful sign-in, the Choreo activity pane displays your account details along with any components detected within the VS Code workspace.

    "},{"location":"develop-components/develop-components-using-vs-code/#create-a-new-component","title":"Create a new component","text":"
    1. Open the source code directory where you want to build, deploy, and manage components using Choreo.
    2. Create a new component using one of the following methods:

      • In the Choreo activity pane, click Create Component.
      • Use the Create New Component command provided by the Choreo extension.
    3. If the Choreo extension cannot determine the project context of the opened workspace, it prompts you to select the organization and the project to which the new component belongs.

    4. Specify component details such as the name, type, buildpack, etc.

      On successful creation, the component details view opens, and the Choreo activity pane displays the new component.

      Tip

      Once the component is created, a .choreo/context.yaml file is generated in the root of the Git repository. For more details, see Understand the project context.

    The component details view allows you to manage your component by performing various actions such as the following:

    • Triggering builds for selected commits.
    • Viewing lists of builds and statuses.
    • Diagnosing build failures with build logs.
    • Deploying builds in available environments.
    • Accessing runtime logs and deployed component URLs.
    • Invoking deployed service endpoints.
    "},{"location":"develop-components/develop-components-using-vs-code/#understand-the-project-context","title":"Understand the project context","text":"

    Context files contain metadata related to the project, allowing the extension to establish an association between local directories and Choreo projects. These files, such as the context.yamlfile, resides in the /.choreo directory within the root of the Git repository.

    The Choreo extension scans the root of the opened Git repository to find the context.yaml file and lists the components of the associated project. This allows you to easily open and manage the components they are developing within the VS Code workspace.

    A context.yaml file can contain multiple projects, whereas, a workspace opened via VS Code can have multiple context.yaml files with different project associations. In such cases, VS Code allows you to switch between these projects, add new project associations, or remove existing ones, allowing you as a developer to focus on components of a particular project at a time.

    You can decide whether to commit the context.yaml file to the Git repository. Committing this file enables other team members working on the same repository to have a seamless developer experience with Choreo.

    If the context.yaml file for a particular project is not committed to the Git repository or is unavailable for other reasons, you can easily regenerate it using one of the following methods:

    • In the Choreo activity pane, click Link Directory.
    • Use the Link Directory command provided by the Choreo extension.
    "},{"location":"develop-components/develop-components-using-vs-code/#discover-additional-features","title":"Discover additional features","text":"

    To access a range of functionalities provided by the Choreo extension, open the VS Code command palette and type Choreo.

    "},{"location":"develop-components/develop-components-using-vs-code/#troubleshoot-issues","title":"Troubleshoot issues","text":"

    To troubleshoot Choreo extension issues, follow these steps:

    1. To open the OUTPUT pane, go to the VS Code editor main menu, click View, and then click Output.

    2. Select Choreo from the drop-down menu on the right-hand side to view the Choreo output for troubleshooting.

    "},{"location":"develop-components/develop-components-using-vs-code/#get-help","title":"Get help","text":"

    For assistance with the Choreo VS Code extension, create GitHub issues.

    "},{"location":"develop-components/develop-components-with-git/","title":"Develop Components With Git","text":"

    Choreo enables you to develop components by connecting your GitHub, Bitbucket, or GitLab repository. You have the flexibility to either connect an existing repository or start with an empty repository and commit the source code later. By integrating your repositories with Choreo, you can automate tasks and optimize workflows across multiple systems, all within the Choreo platform. Choreo currently supports GitHub, Bitbucket, and GitLab as Git providers.

    Tip

    Choreo supports both Bitbucket Server and Bitbucket Cloud. The currently supported Bitbucket Server version is 8.9.2.

    In Choreo, you can connect a Git repository that contains Ballerina source code or a Docker project. To connect a Git repository to Choreo as a Docker project, your Git repository must include the following:

    • A Dockerfile: Specifies the instructions to build the Docker image.
    • A build context: A set of files in the specified path used to build the image.

    Once you connect your Git repository to Choreo, you can build, deploy, and manage your application easily.

    "},{"location":"develop-components/develop-components-with-git/#connect-a-git-repository-to-choreo","title":"Connect a Git repository to Choreo","text":"
    1. Sign in to the Choreo Console.
    2. In the Choreo Console header, go to the Organization list and select your organization.
    3. In the left navigation menu, click Settings. This opens the organization-level settings page.
    4. Click the Credentials tab.
    5. Click +Add Credentials to configure the Git repository connection.
    6. Enter a Credential Name, select the Git provider, and enter the Personal Access Token you obtained from the Git provider.
    7. Click Save.
    "},{"location":"develop-components/develop-components-with-git/#authorize-github-with-choreo","title":"Authorize GitHub with Choreo","text":"

    Authorizing Choreo as a GitHub application grants Choreo the following permissions to perform the respective actions on your behalf within the repository:

    Permission Read Write Description Issues Y N Read component ID label to filter the pull requests Metadata Y N List repositories Contents Y Y List branches and create a branch to commit sample code Pull Request Y Y Create a pull request if you start with a Choreo sample Webhooks Y Y Trigger automatic deployment and configuration generation"},{"location":"develop-components/develop-components-with-git/#add-git-submodules-to-a-project","title":"Add Git submodules to a project","text":"

    Choreo provides Git submodule support when you connect your GitHub repository to Choreo. This allows you to manage and include external repositories effectively within Choreo build pipelines. Key benefits of this capability include:

    • Code sharing without duplication: Use submodules to maintain shared libraries across multiple projects, ensuring a single source of truth.
    • Efficient third-party library management: Manage third-party libraries as submodules to update them independently and track changes easily, avoiding direct code integration.

    For example, when you work with the Micro Integrator (MI) runtime in Choreo, you can use Git submodules to reuse MI templates and sequences across components without duplication.

    Tip

    If you encounter an error stating that you cannot clone a submodule due to insufficient permissions, follow the instructions below to grant the necessary permissions:

    • For a personal account:

      1. Sign in to your personal GitHub account.
      2. In the upper-right corner, click your profile picture, and then click\u00a0Settings.
      3. In the left navigation menu, go to the Integrations section and click Applications.
      4. Under the Installed GitHub Apps tab, click Configure corresponding to choreo.dev.
      5. Under Repository Access, grant access to the necessary repositories.
    • For an organization account:

      1. Sign in to your organization's GitHub account.
      2. In the upper-right corner, click your profile picture, and then click\u00a0Settings.
      3. In the left navigation menu, go to the Third-Party Access section and click GitHub Apps.
      4. Click Configure corresponding to choreo.dev.
      5. Under Repository Access, grant access to the necessary repositories.

        Note

        Choreo currently does not support accessing private repositories in other organizations.

    "},{"location":"develop-components/develop-components-with-git/#authorize-bitbucket-with-choreo","title":"Authorize Bitbucket with Choreo","text":"

    Authorizing using a personal access token (PAT) from Bitbucket grants Choreo the following permissions to perform the respective actions on your behalf within the repository.

    Permission Read Write Description Account Y N Get user information and workspace details Repositories Y Y List branches and create a branch to commit sample code Pull Requests Y Y Create a pull request if you start with a Choreo sample Webhooks Y Y Trigger automatic deployment and configuration generation"},{"location":"develop-components/develop-components-with-git/#authorize-self-managed-gitlab-with-choreo","title":"Authorize self-managed GitLab with Choreo","text":"

    Authorizing using a personal access token (PAT) obtained from your GitLab self-managed server grants Choreo the following permissions to perform the respective actions on your behalf within the repository.

    Permission Description API Grants full read/write access to the API, covering all groups and projects, as well as read/write access to the repository."},{"location":"develop-components/manage-component-source-configurations/","title":"Manage Component Source Configurations","text":"

    In Choreo, you can configure service endpoints and connections via the component.yaml source configuration file. This file ensures that the configurations required to initialize endpoints and connections are defined, as they cannot be inferred from the source code. This guide provides an overview of how to configure and manage these settings effectively.

    The source configuration file must be committed to your repository within the .choreo directory at the root of the project directory. This ensures the ability to version the configuration files alongside repository commits, enabling better tracking and management of configurations.

    Note

    • The component-config.yaml and endpoints.yaml files will eventually be deprecated and replaced by the component.yaml file.
      • For details on how you can migrate to the component.yaml file from the component-config.yaml file, see Migrate from the component-config.yaml.
      • For details on how you can migrate to the component.yaml file from the endpoints.yaml file, see Migrate from the endpoints.yaml.
    • Choreo prioritizes configuration files in the following order: component.yaml takes the highest precedence, followed by component-config.yaml, and then endpoints.yaml.
    "},{"location":"develop-components/manage-component-source-configurations/#overview-of-the-componentyaml-file","title":"Overview of the component.yaml file","text":"

    File location:

    <build-context-path>/.choreo/component.yaml\n

    Note

    • For components built using Buildpacks, replace build-context-path with the <project-directory>. For example, <project-directory>/.choreo/component.yaml.
    • For components built using Docker, replace build-context-path with the <docker-context-path>. For example, <docker-context-path>/.choreo/component.yaml.

    Sample component.yaml file content:

    Click the respective tab to view the structure for your current configuration file version:

    Version 1.1Version 1.0
    # +required The configuration file schema version\nschemaVersion: 1.1\n# +optional Incoming connection details for the component\nendpoints:\n# +required Unique name for the endpoint.\n# This name will be used when generating the managed API\n- name: greeter-sample\n# +optional Display name for the endpoint.\ndisplayName: Go Greeter Sample\n# +required Service section has the user service endpoint details\nservice:\n# +optional Context (base path) of the API that gets exposed via the endpoint.\nbasePath: /greeting-service\n# +required Numeric port value that gets exposed via the endpoint\nport: 9090\n# +required Type of traffic that the endpoint is accepting.\n# Allowed values: REST, GraphQL, WS, GRPC, TCP, UDP.\ntype: REST\n# +optional Network level visibilities of the endpoint.\n# Accepted values: Project|Organization|Public(Default).\nnetworkVisibilities: - Public\n- Organization\n# +optional Path to the schema definition file. Defaults to wild card route if not provided\n# This is only applicable to REST or WS endpoint types.\n# The path should be relative to the docker context.\nschemaFilePath: openapi.yaml\n# +optional Outgoing connection details for the component.\ndependencies:\n# +optional Defines the connection references from the Internal Marketplace.\nconnectionReferences:\n# +required Name of the connection.\n- name: hr-connection\n# +required Name of the connection instance.\nresourceRef: service:/HRProject/UserComponent/v1/ad088/PUBLIC\n

    The descriptor-based approach of the component.yaml file simplifies and streamlines endpoint and connection configuration management. The use of versioned schemas ensures backward compatibility, providing a seamless transition with future updates.

    You can define the following root-level configurations via the component.yaml file:

    Configuration Required Description schemaVersion Required The version of the component.yaml file. Defaults to the latest version. endpoints Optional The list of endpoint configurations. dependencies Optional The list of dependency configurations.
    # +required The configuration file schema version\nschemaVersion: 1.0\n# +optional Incoming connection details for the component\nendpoints:\n# +required Unique name for the endpoint.\n# This name will be used when generating the managed API\n- name: greeter-sample\n# +optional Display name for the endpoint.\ndisplayName: Go Greeter Sample\n# +required Service section has the user service endpoint details\nservice:\n# +optional Context (base path) of the API that gets exposed via the endpoint.\nbasePath: /greeting-service\n# +required Numeric port value that gets exposed via the endpoint\nport: 9090\n# +required Type of traffic that the endpoint is accepting.\n# Allowed values: REST, GraphQL, WS, GRPC, TCP, UDP.\ntype: REST\n# +optional Network level visibilities of the endpoint.\n# Accepted values: Project|Organization|Public(Default).\nnetworkVisibilities: - Public\n- Organization\n# +optional Path to the schema definition file. Defaults to wild card route if not provided\n# This is only applicable to REST or WS endpoint types.\n# The path should be relative to the docker context.\nschemaFilePath: openapi.yaml\n# +optional Outgoing connection details for the component.\ndependencies:\n# +optional Defines the service references from the Internal Marketplace.\nserviceReferences:\n# +required Name of the service reference.\n- name: choreo:///apifirst/mttm/mmvhxd/ad088/v1.0/PUBLIC\n# +required Name of the connection instance.\nconnectionConfig: 19d2648b-d29c-4452-afdd-1b9311e81412\n# +required Environment variables injected into the component for connection configuration.\nenv:\n# +required Key name of the connection configuration.\n- from: ServiceURL\n# +required Environment variable injected into the container.\nto: SERVICE_URL\n

    The descriptor-based approach of the component.yaml file simplifies and streamlines endpoint and connection configuration management. The use of versioned schemas ensures backward compatibility, providing a seamless transition with future updates.

    You can define the following root-level configurations via the component.yaml file:

    Configuration Required Description schemaVersion Required The version of the component.yaml file. Defaults to the latest version. endpoints Optional The list of endpoint configurations. dependencies Optional The list of dependency configurations.

    Endpoint configurations In the endpoints section of the component.yaml file, you can define multiple service endpoint configurations. Each endpoint must have a unique name and the required fields specified in the schema overview.

    Why have a unique name?

    When you define multiple endpoints, the endpoint.name is appended to the Choreo-generated URL. A unique name ensures the endpoint is easily recognizable and readable within the URL.

    Configuration Required Description name Required A unique identifier for the endpoint within the service component. Avoid using excessively long names. displayName Optional A display name for the endpoint. service Required Service details for the endpoint. .basePath Required The base path of the API exposed via this endpoint. .port Required The numeric port value exposed via this endpoint. type Required The type of traffic the endpoint accepts. For example, REST, GraphQL, gRPC, UDP, or TCP. networkVisibilities Required The network-level visibility of the endpoint. For example, project, organization, or public. schemaFilePath Required The file path to the swagger definition file. Defaults to the wildcard route if not specified. This field should be a relative path to the project path when using Java, Python, NodeJS, Go, PHP, Ruby, or WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, the path should be relative to the component root or Docker context.

    Dependency configurations

    In the dependencies section of the component.yaml file, you can define multiple service connection configurations under dependencies.serviceReferences. You can use the service references generated in the in-line developer guide when creating a service connection. For instructions on copying connection configurations, see the in-line developer guide displayed during connection creation.

    You must include the following configurations in the dependencies.serviceReferences schema:

    Configuration Required Description name Required A unique name for the service reference. connectionConfig Required A unique name for the connection instance. env Required The list of environment variable mappings to inject into the container. .from Required The key name of the connection configuration. .to Required The environment variable to inject into the container.

    Note

    Choreo automatically generates connection configurations when you create a connection. The properties such as name, connectionConfig, and env.from are automatically generated. However, you must manually set the env.to value.

    "},{"location":"develop-components/manage-component-source-configurations/#endpoint-configurations","title":"Endpoint configurations","text":"

    In the endpoints section of the component.yaml file, you can define multiple service endpoint configurations. Each endpoint must have a unique name and the required fields specified in the schema overview.

    Why have a unique name?

    When you define multiple endpoints, the endpoint.name is appended to the Choreo-generated URL. A unique name ensures the endpoint is easily recognizable and readable within the URL.

    Configuration Required Description name Required A unique identifier for the endpoint within the service component. Avoid using excessively long names. displayName Optional A display name for the endpoint. service Required Service details for the endpoint. .basePath Required The base path of the API exposed via this endpoint. .port Required The numeric port value exposed via this endpoint. type Required The type of traffic the endpoint accepts. For example, REST, GraphQL, gRPC, UDP, or TCP. networkVisibilities Required The network-level visibility of the endpoint. For example, project, organization, or public. schemaFilePath Required The file path to the swagger definition file. Defaults to the wildcard route if not specified. This field should be a relative path to the project path when using Java, Python, NodeJS, Go, PHP, Ruby, or WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, the path should be relative to the component root or Docker context."},{"location":"develop-components/manage-component-source-configurations/#dependency-configurations","title":"Dependency configurations","text":"

    In the dependencies section of the component.yaml file, you can define multiple connection configurations under dependencies.connectionReferences. You can use the connection reference generated in the in-line developer guide when creating a connection. For instructions on copying connection configurations, see the in-line developer guide displayed during connection creation.

    You must include the following configurations in the dependencies.connectionReferences schema:

    Configuration Required Description name Required The name given to the connection. resourceRef Required A unique, human-readable identifier for the service you are connecting.

    Note

    Choreo automatically generates connection configurations when you create a connection. The properties such as name and resourceRef are automatically generated. The configurations required to establish the connection will be injected into Choreo-defined environment variables.

    "},{"location":"develop-components/manage-component-source-configurations/#overview-of-the-component-configyaml-file","title":"Overview of the component-config.yaml file","text":"

    File location:

    <build-context-path>/.choreo/component-config.yaml\n

    Sample component-config.yaml file content:

    apiVersion: core.choreo.dev/v1beta1\nkind: ComponentConfig\nspec:\n# +optional Incoming connection details for the component (AKA endpoints).\ninbound:\n# +required Unique name for the endpoint.\n# This name will be used when generating the managed API\n- name: Greeting Service\n# +required Numeric port value that gets exposed via the endpoint\nport: 9090\n# +required Type of traffic that the endpoint is accepting.\n# Allowed values: REST, GraphQL, GRPC, TCP, UDP, WS.\ntype: REST\n# +optional Network level visibility of the endpoint. Defaults to Public\n# Accepted values: Project|Organization|Public.\nnetworkVisibility: Public\n# +optional Context (base path) of the API that gets exposed via the endpoint.\n# This is mandatory if the endpoint type is set to REST, GraphQL or WS.\ncontext: /greeting\n# +optional The path to the schema definition file. Defaults to wildcard route if not specified.\n# This is only applicable to REST and WS endpoint types.\n# The path should be relative to the Docker context.\nschemaFilePath: greeting_openapi.yaml\n# +optional Outgoing connection details for the component.\noutbound:\n# +optional Defines the service references from the Internal Marketplace.\nserviceReferences:\n# +required Name of the service reference.\n- name: choreo:///apifirst/mttm/mmvhxd/ad088/v1.0/PUBLIC\n# +required Name of the connection instance.\nconnectionConfig: 19d2648b-d29c-4452-afdd-1b9311e81412\n# +required Environment variables injected to the component for connection configuration.\nenv:\n# +required Key name of the connection configuration.\n- from: ServiceURL\n# +required Environment variable injected to the container.\nto: SERVICE_URL\n

    The component-config.yaml file complements and enhances the existing endpoint configuration process. It allows you to define how the endpoints (inbound connections) in your service are exposed and how your service connects to external services or components (outbound connections).

    You can define the following root-level configurations via the component-config.yaml file:

    Configuration Required Description apiVersion Required The version of the component-config.yaml file defaults to core.choreo.dev/v1beta1. kind Required The resource type of the file defaults to ComponentConfig. spec.inbound Optional The list of inbound connection configurations. spec.outbound Optional The list of outbound connection configurations. Inbound connection configurations (spec.inbound)

    In the spec.inbound configuration section, you can specify endpoints to set up inbound connections. To specify endpoints, you can follow the existing endpoints schema structure. For details on the endpoints schema structure, see the endpoints schema documentation.

    Outbound connection configurations (spec.outbound)

    In the spec.outbound section, you can define serviceReferences. To define serviceReferences, you can use the service references generated in the Internal Marketplace when creating a service connection. To copy the outbound connection configurations, see the inline developer guide displayed when you create a connection.

    You must include the following configurations in the serviceReferences schema:

    Configuration Required Description name Required A unique name for the service reference. connectionConfig Required A unique name for the connection instance. env Optional The list of environment variable mappings to inject into the container. env.from Required The key name of the connection configuration. env.to Required The environment variable to inject into the container."},{"location":"develop-components/manage-component-source-configurations/#overview-of-the-endpointsyaml-file","title":"Overview of the endpoints.yaml file","text":"

    File location:

    <build-context-path>/.choreo/endpoints.yaml\n

    Sample endpoints.yaml file content:

    # +required Version of the endpoint configuration YAML\nversion: 0.1\n# +required List of endpoints to create\nendpoints:\n# +required Unique name for the endpoint.\n# This name will be used when generating the managed API\n- name: Greeting Service\n# +required Numeric port value that gets exposed via this endpoint\nport: 9090\n# +required Type of the traffic this endpoint is accepting.\n# Allowed values: REST, GraphQL, GRPC, UDP, TCP, WS.\ntype: REST\n# +optional Network level visibility of this endpoint. Defaults to Public\n# Accepted values: Project|Organization|Public.\nnetworkVisibility: Project\n# +optional Context (base path) of the API that is exposed via this endpoint.\n# This is mandatory if the endpoint type is set to REST, GraphQL or WS.\ncontext: /greeting\n# +optional Path to the schema definition file. Defaults to wild card route if not provided\n# This is only applicable to REST and WS endpoint types.\n# The path should be relative to the docker context.\nschemaFilePath: greeting_openapi.yaml\n

    The endpoints.yaml configuration file allows you to define configurations for multiple endpoints necessary for Choreo service components. This schema is essential to identify the context, port binding, network exposure level, and other attributes required to generate a Choreo endpoint.

    You can define the following root-level configurations via the endpoints.yaml file:

    Configuration Required Description version Required The version of the endpoints.yaml file. name Required A unique name for the endpoint, which Choreo will use to generate the managed API. port Required The numeric port value that gets exposed via this endpoint. type Required The type of traffic this endpoint accepts, such as REST, GraphQL, gRPC, WS, UDP, or TCP. Currently, the MI preset supports only the REST type. networkVisibility Required The network level visibility of this endpoint, which defaults to Public if not specified. Accepted values are Project, Organization, or Public. context Required The context (base path) of the API that Choreo exposes via this endpoint. schemaFilePath Required The swagger definition file path. Defaults to the wildcard route if not provided. This field should be a relative path to the project path when using the Java, Python, NodeJS, Go, PHP, Ruby, and WSO2 MI buildpacks. For REST endpoint types, when using the Ballerina or Dockerfile buildpack, this field should be a relative path to the component root or Docker context."},{"location":"develop-components/manage-component-source-configurations/#migration-guide","title":"Migration guide","text":"

    With the upcoming deprecation of the component-config.yaml file and the endpoints.yaml file, Choreo provides a seamless migration path to the component.yaml file. See the following guidelines for details depending on the configuration you want to migrate from:

    "},{"location":"develop-components/manage-component-source-configurations/#migrate-from-the-component-configyaml-file","title":"Migrate from the component-config.yaml file","text":"

    To migrate from the component-config.yaml file to the component.yaml file, do the following:

    • Add the schemaVersion in the component.yaml and omit apiVersion and kind.
    • Move endpoint configurations from the spec.inbound section to the endpoints section in the component.yaml file.

      • Copy the value of spec.inbound.context to endpoints.service.basePath.
      • Copy the value of spec.inbound.port to endpoints.service.port.
      • Copy the value of spec.inbound.networkVisibility to endpoints.networkVisibilities.
    • Move dependency configurations from the spec.outbound section to the dependencies section in the component.yaml file.

    "},{"location":"develop-components/manage-component-source-configurations/#migrate-from-the-endpointsyaml-file","title":"Migrate from the endpoints.yaml file","text":"

    To migrate from the endpoints.yaml file to the component.yaml file, do the following:

    • Add the schemaVersion in the component.yaml and omit version.
    • Move endpoint configurations from the endpoints.yaml file to the endpoints section in the component.yaml file.
      • Copy the value of context to endpoints.service.basePath.
      • Copy the value of port to endpoints.service.port.
      • Copy the value of networkVisibility to endpoints.networkVisibilities.
    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/","title":"Manage Deployment Tracks for Choreo Components","text":"

    Choreo allows you to create and manage dedicated deployment tracks for components, facilitating independent version control and deployment. This capability also allows you to unlink deployment tracks from associated branches or relink them to different branches so that you can align with your preferred Git workflows, such as the feature branch workflow or GitFlow workflow.

    Info

    Deployment track creation and management does not apply to API Proxy and BYOI components.

    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#create-a-deployment-track","title":"Create a deployment track","text":"

    Prerequisites:

    • Create a component in Choreo.

    Follow the steps below to create a deployment track for a component:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component you want to create a deployment track for.
    3. On the header of the component overview page, click the Deployment Track drop-down list.
    4. Click + Create New to open the Create Deployment Track dialog.
    5. In the Create Deployment Track dialog, do the following:
      1. Select a branch to associate with the deployment track.
      2. Optionally, specify a description for the deployment track.
      3. To create a deployment track for a service component, specify a unique API version indicating the major and minor version numbers.
    6. Click Create.
    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#unlink-a-deployment-track","title":"Unlink a deployment track","text":"

    If you want to detach a branch reference from a deployment track, you must unlink the branch.

    Info

    When you unlink the branch of a deployment track, the active deployments are unaffected. However, while you can redeploy the existing deployment, you cannot perform a new deployment.

    Follow the steps below to unlink a deployment track of a component:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component for which you want to unlink a deployment track.
    3. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
    4. Click the edit icon corresponding to the deployment track you want to unlink.
    5. In the Edit Branch dialog that opens, click the Branch Name list and select None.
    6. Click Save.
    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#link-a-deployment-track","title":"Link a deployment track","text":"

    To associate a branch reference to an unlinked deployment track, you must link a branch.

    Info

    To build and deploy the contents of the linked branch, you must perform a manual build and deploy.

    Prerequisites:

    • A minimum of two branches in your GitHub repository.

    Follow the steps below to link a branch to an unlinked deployment track:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component you want to associate a branch reference for.
    3. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
    4. Click + Link Branch corresponding to the unlinked deployment track for which you want to associate a branch.
    5. In the Link Branch dialog that opens, click the Branch Name list and select the branch you want to relink.
    6. Click Save.
    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#relink-a-deployment-track","title":"Relink a deployment track","text":"

    To switch the branch reference of a linked deployment track, you must relink to an appropriate branch.

    Info

    If you unlink the existing branch of a deployment track and link a different branch, you must perform a manual build and deploy to build and deploy the contents of the recently linked branch.

    Prerequisites:

    • A minimum of two branches in your GitHub repository.

    Follow the steps below to switch the branch reference of a linked deployment track:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component you want to relink a deployment track for.
    3. On the header of the component overview page, click the Deployment Track drop-down list and then click View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
    4. Click the Edit Branch icon corresponding to the deployment track you want to relink.
    5. In the Edit Branch dialog that opens, click the Branch Name list and select the branch you want to relink.
    6. Click Save.

    Now that you understand how to create and manage deployment tracks for components, let\u2019s explore a sample scenario to see how a developer can use deployment tracks to manage version releases in Choreo.

    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#sample-scenario-manage-version-releases-with-deployment-tracks","title":"Sample Scenario: Manage version releases with deployment tracks","text":"

    Let\u2019s consider the following version release scenario:

    • To initiate work on a new feature, a developer creates a new branch, named feature-x from either the main or dev branch.
    • Once development is complete, the developer proceeds to merge the feature-x branch into the dev branch for testing.
    • Upon successful testing in the dev branch, the developer proceeds to merge all the changes into the main branch for production deployment.

    Following are the actions you need to take from a deployment track perspective to manage the version release:

    1. To prepare for the new version release, unlink the main branch from the associated deployment track (let\u2019s consider this as the deployment track 1).
    2. Proceed to merge the dev branch containing the tested changes into the main branch.
    3. Unlink the dev branch from the associated deployment track (let\u2019s consider this as deployment track 2).
    4. Link deployment track 2 containing the latest version of the service to the main branch for deployment.
    5. To facilitate ongoing development and testing, create another deployment track (let\u2019s consider this as deployment track 3) and link it to the dev branch.

    Tip

    • As a developer, you can strategically unlink and relink deployment tracks to effectively manage different versions of your services within Choreo.
    • You can create new deployment tracks for ongoing development branches like dev to ensure a continuous development and release cycle.
    "},{"location":"develop-components/manage-deployment-tracks-for-choreo-components/#delete-a-deployment-track","title":"Delete a deployment track","text":"

    If you no longer need a deployment track, you can delete it.

    Note

    If the component exposes an endpoint or proxy and you want to delete the last version in the major version range, the recommended approach is to retire that version first. This allows consumers to transition to the next major version and prevents a sudden break in their experience. For example, if you have deployment tracks for v1.0 and v2.0, notify consumers to switch to v2.0 before deleting v1.0. Then, retire the APIs in v1.0 and proceed to delete the associated deployment track.

    Prerequisites:

    • At least 2 deployment tracks in a component.

    Follow the steps below to delete a deployment track:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component for which you want to delete a deployment track.
    3. On the header of the component overview page, click the Deployment Track drop-down list.
    4. Click + View All. This takes you to the component settings page where you can see all the deployment tracks linked to the component.
    5. Click the Delete icon corresponding to the deployment track you want to delete.
    6. Click Delete to confirm the deletion.
    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/","title":"Manage the Micro Integrator Runtime Version in Your Integration Project","text":"

    Choreo allows you to use a preferred WSO2 Micro Integrator (MI) runtime version in your integration project. Currently, Choreo supports MI product versions 4.1.0 and 4.2.0. You have the flexibility to deploy WSO2 updates within these specified versions.

    When you create an integration project, you can specify a required runtime version to gain control over the environment in which your integration runs. This version management capability empowers you to tailor your projects depending on your runtime requirements, enhancing the customization and adaptability of your integration workflows.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#understand-the-version-string","title":"Understand the version string","text":"

    WSO2 Micro Integrator (MI) utilizes a versioning system consisting of three-digit numbers, such as 4.1.0 and 4.2.0, following semantic versioning principles. The product remains committed to receiving updates from WSO2, including security fixes, bug resolutions, and enhancements. Within the Choreo platform, the MI runtime version is constructed by combining the product release version with its corresponding update level.

    In Choreo, the MI runtime version is structured as a four-digit number, for example, 4.1.0.14 or 4.2.0.17. The first three digits represent the product release version, while the last digit signifies the update level of the product. The fourth digit is optional and can be omitted.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#version-management-in-wso2-integration-studio","title":"Version management in WSO2 Integration Studio","text":"

    If you are using WSO2 Integration Studio to build and deploy integration artifacts in WSO2 Micro Integrator, you can create multiple runtime environments and execute projects on any selected environment. WSO2 Integration Studio also allows you to configure multiple Micro Integrator runtime environments, offering flexibility and customization in the execution of integration processes.

    You can specify the Runtime version when you create an integration project in WSO2 Integration Studio. In the project creation wizard, specify the runtime version in the Runtime version field, as shown below.

    An integration project is structured as a Maven project with multiple sub-modules. The root pom.xml file holds crucial information about the target runtime. The runtime version you configure when you create a new project is saved within the root pom.xml file. The version information is stored in the element under the in the pom.xml file. If there is a need to update the runtime version, you have the flexibility to modify the value to a valid runtime version and ensure that the project runs in the required runtime environment.

    You can establish multiple runtime environments by utilizing updated MI instances. With a valid WSO2 subscription, you can also access and download updates to set up an updated MI server locally. This update process allows you to select a preferred update level as the runtime version. Consequently, you can run your integration on a runtime with the latest updates, ensuring optimal performance and access to new features.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#configure-a-micro-integrator-runtime-environment-in-integration-studio","title":"Configure a Micro Integrator runtime environment in Integration Studio","text":"

    If you are using WSO2 Integration Studio, follow these steps to set up a remote server instance with a Micro Integrator runtime environment to execute your integration project:

    Note

    If you have not downloaded and installed WSO2 Integration Studio, you can follow the installation instructions in the WSO2 API Manager documentation.

    1. Launch WSO2 Integration Studio and click\u00a0Add Server\u00a0in the\u00a0Getting Started\u00a0view.
    2. In the Define a New Server dialog, click to expand the WSO2 directory and select WSO2 Remote Server.
    3. Enter the WSO2 Micro Integrator Management API URL in the Server URL field and click Test Connection.

      Note

      The Management API of WSO2 Micro Integrator is an internal REST API introduced to substitute MI\u00a0admin services. The default HTTPS port of the Management API of WSO2 Micro Integrator is 9164. If you have not manually changed the default port, you must set the Management API URL as https://localhost:9164/management. If you have changed the default HTTPS port, you must set the port number appropriately when specifying the Server URL. For more information on the default ports of WSO2 Micro Integrator, see WSO2 Micro Integrator default ports in the WSO2 API Manager documentation.

    4. Click Finish.

    5. In the Add and Remove dialog, select the integration components to move from the left side to the right side.
    6. Click Add >.
    7. Click Finish.

    Your integration project is now running in a remote server instance with the Micro Integrator runtime environment you require. If you need to make changes to the integration project, expand the remote server instance, right-click on the deployed exporter project, and select Redeploy to apply the changes.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#convention-for-version-interpretation-in-choreo-deployments","title":"Convention for version interpretation in Choreo deployments","text":"

    You can use the following convention to indicate the required MI runtime version in your integration project:

    Version format Example Description Product version 4.1.0, 4.2.0 Deploy on the latest update level of the mentioned product version. Product version with update level 4.1.0.15, 4.2.0.17 Deploy on the exact update level of the mentioned product version. GA version 4.1.0.0, 4.2.0.0 Deploy on the exact GA version without any update. Default version Empty value Deploy on the latest update level of the default product version.

    Choreo utilizes Alpine images for configuring and deploying the Micro Integrator runtime. This includes automated configuration of the JRE/JDK, customized to the compatibility of the chosen runtime version, simplifying the setup procedure.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#migrate-between-runtime-versions","title":"Migrate between runtime versions","text":"

    Changing the runtime version in an integration project may become necessary during product version upgrades or when you want to apply updates.

    To change the runtime version of a MI Integration, follow the below steps.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#update-the-runtime-version-in-the-integration-project","title":"Update the runtime version in the integration project","text":"

    To change the runtime version in the integration project, follow the steps below: 1. Open the project in Integration Studio. 2. Right-click on the project and select Change Runtime MI Version. 3. Specify the new runtime version as shown below: 4. Alternatively, you can manually update the version by opening the root pom.xml file. Open pom.xml and change the required runtime version in <project.runtime.version> element under <properties> section.

    To test the changes locally, you must download and set up the runtime environment locally. Then, you must configure the Integration Studio runtime environment by directing it to the locally installed MI runtime. Once the setup is complete, you can deploy your integrations on the MI runtime environment and proceed to the testing phase.

    After completing the tests to ensure everything works as expected, you can follow below steps to deploy the project in Choreo:

    1. Commit and push the changes to your repository.
    2. Go to https://console.choreo.dev/ and sign in.
    3. Select your project from the Project list in the header.
    4. Select your MI integration component from the Component list in the header.
    5. In the left navigation menu, click Build.
    6. Select the latest commit and click Build.
    7. In the left navigation menu, click Deploy.
    8. Click on the Configure and Deploy and deploy the component.
    9. Verify the Runtime version by checking the logs by selecting the Runtime Logs under the Observability section.

    You will see the runtime version in the logs as shown below:

    Next, you must conduct additional testing in the development environment on Choreo before you promote the integration to production environments.

    "},{"location":"develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/#troubleshoot-errors","title":"Troubleshoot errors","text":"

    The following error codes can help you troubleshoot errors that occur during the integration component build:

    Error code Description 110 - 119 Internal server error. 121 Malformed runtime version. 122 The specified runtime version is not available. Either the product or update level is not available. 123 Trivy security vulnerabilities found in the libs directory. 124 Trivy security vulnerabilities found in the dropins directory. 125 Trivy security vulnerabilities found in the libs or dropins directory. 126 Error building integration project."},{"location":"develop-components/submit-and-manage-workflow-approval-requests/","title":"Submit and Manage Workflow Approval Requests","text":"

    In Choreo, if an administrator configures a workflow to require approval, you must submit a request to obtain approval to perform the task.

    Upon submitting a workflow approval request, Choreo notifies all authorized assignees via email about the review request. When an authorized assignee approves or rejects the request, you will receive an email with details of the decision.

    The approach to request approval can vary depending on the workflow.

    "},{"location":"develop-components/submit-and-manage-workflow-approval-requests/#request-approval-for-environment-promotion","title":"Request approval for environment promotion","text":"

    Prerequisites:

    • Ensure you have a component created, built, and deployed to the development environment.
    • Ensure that an approval workflow is configured for environment promotion.
    • Ensure you are promoting the component to a critical environment, such as production.

    To request approval to promote a component from the development environment to production, follow these steps:

    1. Sign in to the Choreo Console.
    2. In the Component Listing pane, click on the component you want to deploy. This takes you to the Overview page of the component.
    3. In the left navigation menu, click Deploy.
    4. Go to the Development card and click Request to Promote.
    5. In the Request Approval pane that opens, enter your request details and click Submit. This creates a request and notifies all authorized assignees via email about the request.

      Note

      When an environment promotion request for a specific component is pending review, Choreo restricts other developers from making the same request until the pending request is either approved or rejected.

    When an authorized assignee approves the request, you will receive a confirmation email and can proceed to promote the component to production.

    "},{"location":"develop-components/submit-and-manage-workflow-approval-requests/#cancel-a-workflow-approval-request","title":"Cancel a workflow approval request","text":"

    If you want to cancel a workflow approval request that is already submitted, you can do so before the request is approved or rejected.

    When you submit a workflow approval request, the Request to Promote button changes to Cancel Request. To cancel an approval request, click Cancel Request. Upon confirming the cancellation, all configured approvers are notified immediately, and the request will no longer be pending.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/","title":"Work with the Micro Integrator Runtime in Choreo","text":"

    WSO2 Micro Integrator (WSO2 MI) is a lightweight, high-performance integration runtime. It allows you to run integrations developed using WSO2 Integration Studio within Choreo.

    The topics on this page walk you through the key aspects you need to understand to use the WSO2 MI runtime effectively in Choreo.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#integration-types","title":"Integration types","text":"

    Choreo supports the following WSO2 MI integrations that cater to different use cases and requirements. Each integration type serves a specific purpose. Therefore, it is essential to understand their differences to easily choose the most appropriate integration for your use case.

    • Service: Exposes an integration as an API via HTTP, making it possible to create a RESTful interface for your integration services. This type is ideal for scenarios where you need to provide an API for external systems or clients to interact with your integration.
    • Event Handler: Triggers an integration based on external events such as messages arriving on a queue or updates in a database. This type is well-suited for implementing event-driven architectures or responding to changes in your system's environment.
    • Scheduled Task: Runs an integration automatically at predefined time intervals, ensuring that specific integration tasks occur at regular intervals. This type is ideal for batch processing, data synchronization, or periodic maintenance tasks.
    • Manual Task: Initiates an integration via user action, giving you full control over when the integration executes. This type is useful for on-demand tasks, testing, or debugging purposes.
    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#develop-integrations-with-wso2-integration-studio","title":"Develop integrations with WSO2 Integration Studio","text":"

    WSO2 Integration Studio is a powerful, Eclipse-based graphical development environment that enables you to build and deploy integration artifacts in WSO2 Micro Integrator. This comprehensive IDE offers a robust set of tools for designing and testing integration flows and crafting integration artifacts. By utilizing the visual, drag-and-drop capabilities of WSO2 Integration Studio, developers can significantly reduce the time and effort needed to construct and deploy integration flows.

    In addition to streamlining the development process, Integration Studio offers features such as debugging, testing, and version control to ensure the quality and reliability of integration flows. By creating an Integration project and Composite Exporter project in WSO2 Integration Studio, developers can export their integration projects as a single deployment artifact, known as a composite application. This composite application encompasses all the components and configurations necessary for deploying the integration project to WSO2 Micro Integrator.

    The Composite Exporter project simplifies the deployment process by allowing developers to package their integration projects as a single, self-contained artifact that can be easily deployed and managed. This approach enhances the consistency and reliability of integration projects while streamlining the overall deployment process.

    To start developing integrations with WSO2 Integration Studio, see WSO2 API Manager Documentation - Developing Integration Solutions.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#integration-project-directory-structure","title":"Integration project directory structure","text":"

    An Integration Project in WSO2 Integration Studio is a multi-module Maven project that can contain multiple modules with WSO2 Synapse configurations and a composite application module to export all the configurations as a single deployable artifact.

    An integration project directory structure includes the following key components:

    • WSO2 Synapse configurations: These modules contain the essential configurations for the integration project.
    • Composite Application module: This module is responsible for exporting all the Synapse configurations as a single deployable artifact.

    Optionally, you can include the following components in your integration project:

    • OpenAPI definition file: You can add the OpenAPI definition file to any location within the project. When creating a component, you'll need to define the path to this file. Choreo will automatically generate an OpenAPI definition for you based on your integration project, if you don't provide one.
    • Java libraries: If your integration project requires additional Java libraries, you can add them to the libs directory located in the project root.
    • deployment.toml file: This optional configuration file allows you to customize the preconfigured settings of WSO2 MI instances running on Choreo. By including this file, you can tailor the behavior of your WSO2 MI instances to better suit your project's specific requirements.

    Understanding the Integration Project directory structure is crucial for organizing your project and ensuring that all necessary components are included in the final deployable artifact.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#openapi-support","title":"OpenAPI support","text":"

    OpenAPI Support plays a crucial role in enhancing the functionality of integrations exposed as APIs. By providing an OpenAPI definition for your exposed integration, you can streamline testing and management processes, ensuring a more efficient and user-friendly experience. Choreo will automatically generate an OpenAPI definition for you based on your integration project, if you don't provide one, saving you time and effort.

    To incorporate OpenAPI support, store the OpenAPI definition file within the repository hosting your Integration Studio project. When creating the project, simply point to the file's location in the repository. If needed, you can change the location of the OpenAPI definition file later via the deploy page.

    By leveraging OpenAPI Support, you can optimize the way you test and manage your integrations, resulting in a more efficient development process and a smoother user experience.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#work-with-third-party-libraries","title":"Work with third-party libraries","text":"

    The use of third-party libraries in your Micro Integrator project can offer several advantages, such as enhanced functionality, improved integration capabilities, optimized performance, and reduced development time.

    Here are some of the benefits of adding third-party JARs to the Micro Integrator:

    • Increased functionality: Third-party libraries can extend the core Micro Integrator distribution, allowing for greater flexibility and customization of integration solutions.
    • Enhanced integration capabilities: Third-party libraries enable the Micro Integrator to interact with existing systems such as databases or other APIs, improving overall integration capabilities.
    • Optimized performance: By offering optimized implementations of common functions, third-party libraries can improve the performance of the Micro Integrator.
    • Efficient development: Developers can avoid re-implementing commonly used functions, reducing development time and increasing efficiency.

    To incorporate third-party libraries into your Micro Integrator project, create a new directory called libs at the root of your project. If your project root and GitHub repository root are not the same, place the libs directory in the project root. After adding the required JAR files to the libs directory, the Micro Integrator runtime will automatically include them when deploying the component. This process ensures that any dependencies needed by your integration flow are available at runtime.

    In addition to jar libraries, you may also need to incorporate OSGi bundle JARs into your project. To do this, create another directory called dropins at the root of your project. Similarly, if the project root and GitHub repository root differ, place the dropins directory in the project root. Within the dropins directory, add the OSGi bundle JAR files. The OSGI runtime will pick up these bundles during deployment, enabling you to utilize their functionality within your Micro Integrator project.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#importing-custom-certificates-to-mi","title":"Importing custom certificates to MI","text":"

    The feature enables Choreo MI users to import certificates into the MI client-truststore.jks file. This functionality proves valuable when users need to establish connections with servers or services utilizing SSL/TLS encryption and possessing self-signed certificates or certificates issued by private certificate authorities (CAs) that are not automatically trusted. Importing the certificate to the MI client-truststore.jks file enables MI clients to establish secure connections with the server or service seamlessly, eliminating SSL/TLS errors or warnings.

    Before importing the certificate, it is necessary to obtain the certificate file, which can be in PEM or DER format. You can get the certificate from the server or service provider or export it from a web browser. Certificates should be added to the /wso2mi/certs/ folder. Users need to verify that the mount path for the certificate file aligns with this specific path.

    1. In the Choreo console, select the component you wish to add a certificate to.
    2. From the left navigation click Deploy.
    3. Click on the Configs and Secrets tab.
    4. Click Create.
    5. Select ConfigMap as the Config Type and File Mount as the Mount Type.
    6. Click Next.
    7. Specify the following values as mount configurations:

      Field Value Config Name An appropriate name for the certificate. Mount path /wso2mi/certs/<filename>. For example, /wso2mi/certs/certificate.crt
    8. Click Upload File and attach the certificate.

    9. Click Create.
    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#working-with-sensitive-data-using-mi-secure-vault","title":"Working with sensitive data using MI Secure Vault","text":"

    MI Secure Vault is a feature that allows users to securely store sensitive data, such as passwords and tokens, and provide access to that data to MI Integrations. This feature provides an added layer of security to your integrations by reducing the risk of accidental exposure of sensitive data.

    To use MI Secure Vault to work with sensitive data, follow these steps:

    1. Select the component from the Choreo Console.
    2. From the left navigation, click Deploy.
    3. Click on the Configure and Deploy.
    4. Click on the Add Environment Configurations
    5. Specify the following values as configurations:

      Field Value Name An appropriate name for the secret/alias. Value Value for the secret
    6. Select Mark as a Secret.

    7. Click Add.
    8. Click Deploy.
    9. Once the secret has been created, you can access it in your integration code using the following syntax:

    <property name=\"secret_value_1\" expression=\"wso2:vault-lookup('user_pass')\" scope=\"default\" type=\"STRING\"/>\n
    This code retrieves the secret named \"user_pass\" from the MI Secure Vault and stores it in the property named \" secret_value_1\". You can then use this property in your integration code to access the secret value.

    You can refer to the Accessing secrets section of MI Secure Vault documentation for more information on these features. By using MI Secure Vault to store and access sensitive data in your integrations, you can ensure that your integrations remain secure and protect sensitive data from unauthorized access.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#scan-third-party-libraries-to-identify-security-vulnerabilities","title":"Scan third-party libraries to identify security vulnerabilities","text":"

    Scanning third-party libraries for security vulnerabilities is essential for identifying potential weaknesses in an application that could be exploited by attackers. Taking a proactive approach to security helps organizations detect and mitigate risks before they can be exploited, preventing data breaches, system compromises, and other security incidents.

    Choreo incorporates a security vulnerability scanning process during deployment. It uses Trivy to scan and detect critical vulnerabilities in third-party libraries added to the integration component. If the scan uncovers any critical vulnerabilities, the deployment process is halted. The deployment pane displays the Trivy scan status and any security failures in the Library (Trivy) vulnerable scan step, which can be accessed by clicking on it. Once the vulnerability has been addressed, you can redeploy the component.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#customize-wso2-micro-integrator-preconfigured-settings","title":"Customize WSO2 Micro Integrator preconfigured settings","text":"

    Customizing WSO2 Micro Integrator Preconfigured Settings is essential for ensuring that the integration solution works optimally within the specific context of your organization. While WSO2 MI comes with preconfigured settings designed for general use, these settings may not be suitable for every organization's unique requirements. Customizing these settings can help optimize performance and ensure compatibility with your organization's systems and applications.

    To customize the preconfigured settings of WSO2 MI instances running on Choreo, define a deployment.toml file in the GitHub repository subpath of your Micro Integrator project:

    Note

    If you change critical configuration parameters such as port offset and hostname, it can break internal communication. Therefore, the recommended approach is to update only the necessary configuration parameters.

    Given below is a sample deployment.toml file that can be used to configure the JMS transport. For more information on WSO2 MI configuration parameters, see the MI Config Catalog.

    [[transport.jms.sender]]\nname = \"myQueueSender\"\nparameter.initial_naming_factory = \"org.apache.activemq.jndi.ActiveMQInitialContextFactory\"\nparameter.provider_url = \"$env{JMS_PROVIDER_URL}\"\nparameter.connection_factory_name = \"QueueConnectionFactory\"\nparameter.connection_factory_type = \"queue\"\nparameter.cache_level = \"producer\"\n\n[[transport.jms.listener]]\nname = \"myQueueListener\"\nparameter.initial_naming_factory = \"org.apache.activemq.jndi.ActiveMQInitialContextFactory\"\nparameter.provider_url = \"$env{JMS_PROVIDER_URL}\"\nparameter.connection_factory_name = \"QueueConnectionFactory\"\nparameter.connection_factory_type = \"queue\"\nparameter.cache_level = \"consumer\"\n
    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#environment-variables","title":"Environment variables","text":"

    Using environment variables is a recommended practice when developing integration artifacts with WSO2 Integration Studio, as it improves configuration management, security, portability, and manageability. By leveraging environment variables, organizations can streamline the management and maintenance of their integrations, ensuring that updates can be implemented quickly and efficiently.

    The component's Deploy page provides a user-friendly interface to manage environment variables across different environments. For information on managing environment variables for complex use cases, see Configurations and secrets.

    Environment variables offer several benefits:

    • Configuration management: They simplify the process of managing and updating configuration settings, making it easier to maintain consistency across different environments.
    • Security: Environment variables help protect sensitive information by storing it securely and separating it from the main codebase.
    • Portability: By using environment variables, you can ensure that your integration artifacts can be easily migrated and deployed across various environments with minimal changes.
    • Manageability: Environment variables offer a centralized way to manage configuration settings, making it easier to update and maintain your integrations over time.

    For a comprehensive list of parameters that can be configured as environment variables, see WSO2 API Manager Documentation - Injecting Parameters - Supported parameters.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#configure-logging","title":"Configure logging","text":"

    Configuring logging is crucial when developing and maintaining a software system, as it can significantly improve efficiency during the development, testing, and maintenance phases of the software development process. Logging captures events and messages that occur during an application's execution, providing valuable insights for troubleshooting and debugging issues.

    With Micro Integrator instances, you can configure and customize logging according to your requirements. Logging configurations can be added to each MI instance's environment, allowing you to fine-tune logging depending on the specific environment or deployment scenario.

    To configure logging in MI instances, follow the steps given below:

    Tip

    You can use environment variables with specific naming conventions.

    1. Start the variable name with logging_level_ followed by the package or class name.
    2. Replace the dot character in the package name with an underscore.
    3. Set the variable value to the required logging level for the corresponding package or class.

      For example, to enable wire logs, change the logging level of the org.apache.synapse.transport.http.wire package to debug.

    To configure logging, set the environment variable as follows:

    1. In the left navigation menu, click Deploy and then click Configs & Secrets.
    2. Click + Create.
    3. Select ConfigMap as the Config Type and Environment Variables as the Mount Type.
    4. Click Next.
    5. Specify the following values as mount configurations:

      Field Value Config Name An appropriate name for the configuration. Name logging_level_org_apache_synapse_transport_http_wire Value debug
    6. Click Create.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#connectors","title":"Connectors","text":"

    WSO2 Micro Integrator (MI) Connectors are prebuilt connectors designed to simplify integration between WSO2 MI and various other systems. They enable seamless connections to databases, message brokers, REST APIs, and more, allowing you to perform actions such as sending messages, executing queries, or retrieving data. These connectors are easy to use, making it straightforward to incorporate them into your WSO2 MI integration flows. Micro Integrator connectors are versatile and can be utilized in various integration scenarios, including data integration, service-oriented architecture (SOA) integration, and event-driven architecture (EDA) integration.

    WSO2 Integration Studio is a comprehensive development environment that facilitates the creation of integration flows using WSO2 Micro Integrator Connectors. With Integration Studio, you can design and implement integration flows that connect diverse systems and execute various actions, such as sending messages, executing queries, or retrieving data. You can build integration flows using either prebuilt connectors provided by WSO2 MI or custom connectors developed using the Connector Development Toolkit. Integration Studio offers a graphical user interface that simplifies the process of building and testing integration flows while also providing a set of tools for managing and deploying these flows in a WSO2 MI runtime environment.

    For more information, see the following topics in the WSO2 API Manager documentation.

    • Connectors Overview
    • Adding Connectors
    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#deploying-integrations-in-choreo","title":"Deploying integrations in Choreo","text":"

    WSO2 MI buildpack is where you can deploy integrations developed with WSO2 Micro Integrator as an API. In this preset, you have three different ways to define endpoints. Choreo gives priory to the definition of endpoints in the below-mentioned order.

    1. Using component.yaml file This is the most flexible method to define endpoints. You can configure the endpoint details with the component.yaml configuration file. Place this file in the .choreo directory in the project path of the component. If the Micro Integrator project has inbound endpoints, you can expose them via different endpoints using the component.yamlfile.

      To learn about the component.yaml file, see Overview of the component.yaml file.

    2. Auto generating endpoints If component.yaml is not provided and if the source Micro Integrator project has APIs, Choreo scans the project and generates the API endpoints. If the project has few APIs, an endpoint will be generated for each API. The visibility of this auto-generated endpoint is set to Public by default. You can change the visibility in the deployment flow.

    3. Provide default endpoints If component.yaml is not provided and if the source Micro Integrator project doesn't have APIs, Choreo generates a default endpoint which will expose the default micro integrator port (8290) with Public visibility and wildcard context.

    Note

    If you are currently using component-config.yaml or endpoints.yaml configuration files, see the respective migration guide for instructions on migrating to the recommended component.yaml configuration file.

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#explore-choreo-examples-on-github","title":"Explore Choreo examples on GitHub","text":"

    For a hands-on experience with MI-based integrations in Choreo, we recommend exploring our samples in Choreo Console. You can filter out the samples based on the buildpack WSO2 MI. This will point you to the samples in the Choreo samples GitHub repository

    "},{"location":"develop-components/work-with-the-micro-integrator-runtime-in-choreo/#choreo-samples-github-repository","title":"Choreo samples - GitHub Repository","text":"
    • Fork the Repository: Start by forking the repository to your account.

    • Explore & run: Navigate through the different integration scenarios. Each example has a README.md with setup and execution instructions.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/","title":"Develop a Manual Task","text":"

    This guide walks you through the steps to develop, deploy, test, and observe a manual task using Choreo.

    In this guide, you will:

    • Develop a manual task to fetch the weather forecast for a specified location for the next 24 hours from the OpenWeatherMap API.
    • Process the weather data to a specific format.
    • Send the formatted data to a specified email address.
    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#prerequisites","title":"Prerequisites","text":"

    Before you try out the steps in this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
    • Fork the Choreo samples repository, which contains the sample integration for this guide.

      Repository file structure

      To work with the sample repository, it is important to familiarize yourself with the repository file structure. The sample code for this guide is in the <sample-repository-dir>/weather-to-email-integration directory. To understand how the functionality is implemented, you must read the code comments. The following table describes what you will find in each file in the repository:

      File path File content Ballerina.toml Contains metadata about the project Dependencies.toml Lists the dependencies required for the project main.bal Contains the entry point of the project, including the main function types.bal Contains custom data types used in the project utils.bal Contains utility functions and helper functions used in the project
    • Go to OpenWeatherMap and sign up to obtain an API key. For details on how to obtain an API key, see the OpenWeatherMap documentation.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-1-create-a-manual-task-component","title":"Step 1: Create a manual task component","text":"
    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Manual Task card.
    4. Enter a unique name and a description for the component. You can use the name and description given below:

      Field Value Component Name WeatherToEmail Description My first manual task
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Enter the following information:

      Field Description Organization Your GitHub account Repository choreo-samples Branch main Buildpack Ballerina Project Directory weather-to-email-integration

      Tip

      • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      • Project Directory specifies the location of the project to build the component.

    8. Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-2-build-the-manual-task","title":"Step 2: Build the manual task","text":"

    To build the manual task, follow the steps given below:

    1. In the left navigation menu, click Build.
    2. In the Builds pane, click Build. This opens the Commits pane where you can see all the commits related to the component.
    3. Select the latest commit and click Build. This triggers the build process and displays the build progress in the Build Logs pane.

      Info

      The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with the build status.

    Here, you will see the build status as Success.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-3-deploy-the-manual-task","title":"Step 3: Deploy the manual task","text":"

    To deploy the manual task, follow the steps given below:

    1. In the left navigation menu, click Deploy.
    2. In the Set Up card, click Configure & Deploy.
    3. In the Configurations pane, specify values as follows for the configurable variables:

      Tip

      The configurable variables populated here are defined in the sample Ballerina project used in this guide. To learn how to declare configurable variables in Ballerina, see the Ballerina documentation on declaring configurable variables. If configurable variables are detected in a connected Ballerina project, Choreo prompts for the respective values during component deployment.

      Field Value apiKey The API key you obtained in the prerequisites section latitude Latitude of the location to get the weather forecast longitude Longitude of the location to get the weather forecast email The email address to receive the formatted weather forecast information

      Note

      If you use Ballerina as the buildpack and you want to set a configurable variable as a secret, click the lock icon corresponding to the configurable variable. This marks it as a secret and conceals the input value.

      For example, if you consider the configurable variables in this guide and set the apiKey as a secret, its input value will be concealed as follows:

      If you want to update the input value at a later time, you can click Update Secret Content and specify a new value.

    4. Click Deploy.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-4-execute-the-manual-task","title":"Step 4: Execute the manual task","text":"

    To execute the manual task, follow the steps given below:

    1. In the left navigation menu, click Execute.
    2. Click Run Now. This triggers the task.

      Inject dynamic values into your application as command-line arguments

      If you want to inject dynamic values into your application as command-line arguments when you run a manual task, follow the steps given below:

      1. Click the drop-down icon next to Run Now and then click Run with Arguments.
      2. In the Runtime Arguments pane that opens, enter the arguments you want to pass to your application.
      3. Click Execute. This triggers the task with the specified arguments.

      The capability to run a manual task with arguments is supported for the following buildpacks:

      DockerfileGoJavaNodeJSWSO2 MIBallerina

      To explore a Dockerfile-based manual task with arguments, try out the Hello World Task sample. For instructions, see the readme.md file in the sample repository.

      Info

      When you work on Docker projects, the Run with Arguments capability is not supported if the Dockerfile contains CMD. In such scenarios, you must use ENTRYPOINT to define your default commands.

      To explore a Go-based manual task with arguments, try out the Hello World Go Task sample. For instructions, see the readme.md file in the sample repository.

      To explore a Java-based manual task with arguments, try out the Hello World Java Task sample. For instructions, see the readme.md file in the sample repository.

      Info

      When you work on Java projects:

      • The Run with Arguments capability is not supported if Procfile is available in the project.
      • The Main class should be defined in the manifest file.
      • If Maven files such as mvn.cmd exist in the project without the .mvn directory, the build will fail. To ensure a successful build, you must either commit the .mvn directory along with any Maven files or not include any Maven files in the project if you choose not to commit the .mvn directory.

      To explore a NodeJS-based manual task with arguments, try out the Hello World NodeJS Task sample. For instructions, see the readme.md file in the sample repository.

      Info

      When you work on NodeJS projects:

      • The Run with Arguments capability is not supported if Procfile is available in the project.
      • The project root must contain the package.json file with the main attribute defined.

      To explore a WSO2 MI-based manual task with arguments, try out the Weather to Logs Task sample. For instructions, see the readme.md file in the sample repository.

      Info

      When you work on WSO2 MI projects and you want to deploy a WSO2 MI integration as a manual task in Choroeo, you must use the WSO2 MI automation mode. For details, see Running the Micro Integrator in Automation Mode.

      To explore a Ballerina manual task with arguments, try out the Weather to Email Task sample. For instructions, see the README.md file in the sample repository.

      Info

      If you want to pass arguments to Ballerina main functions, you can use the Run with Arguments capability. For details on the arguments you can pass, see the Ballerina documentation. You can also override configurable values in the same manner. For more information, see Provide values to configurable variables.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-5-test-the-manual-task","title":"Step 5: Test the manual task","text":"

    Once the task is triggered, an email with the subject [WSO2 Choreo Demo] Next 24H Weather Forecast is sent from choreo.demo@gmail.com to the email address specified as the email configurable variable value in Step 3.

    If the manual task ran successfully, you should receive an email similar to the following to the email address you specified:

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-6-observe-the-manual-task","title":"Step 6: Observe the manual task","text":"

    The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

    To visualize and monitor the performance of the manual task you deployed, click Observability in the left navigation menu. You can observe the following:

    • The throughput and latencies of requests served over a given period.
    • The logs that are generated over a given period.
    • The flame graph (Diagnostics View) that is generated over a given period.
    • The low-code diagram.

    To learn more about the observability details you can view via Choreo observability, see Observability Overview.

    "},{"location":"develop-components/develop-integrations/develop-a-manual-task/#step-7-monitor-executions","title":"Step 7: Monitor executions","text":"

    To track and monitor executions associated with the deployed scheduled task, go to the left navigation menu and click Execute.

    Tip

    The Execute view is applicable to both scheduled and manual tasks.

    You can view the following information:

    • The total number of executions within the past 30 days.

    • The currently active executions and those that are already complete.

      Here, you can view information such as the execution ID, the revision of the execution, and the time it was triggered.

    • Detailed execution logs for a specific execution.

      You can click on an execution to view detailed logs related to it.

      Info

      It may take a few minutes for the logs to appear. You may need to manually refresh to view the latest logs.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/","title":"Develop a Scheduled Task","text":"

    Choreo is a versatile integration platform that allows you to create various types of integrations depending on your requirement.

    If you have a requirement to automatically run a specific integration at regular intervals, you can use Choreo to develop a scheduled task. This type of integration can automate the synchronization of data between different systems at specified intervals, reducing errors and improving productivity by eliminating the need for manual intervention.

    This guide walks you through the steps to develop, deploy, test, and observe a scheduled task using Choreo.

    In this guide, you will:

    • Develop a scheduled task to fetch the weather forecast for a specified location for the next 24 hours from the OpenWeatherMap API.
    • Process the weather data to a specific format.
    • Send the formatted data to a specified email address at a specific time every day.
    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#prerequisites","title":"Prerequisites","text":"

    Before you try out the steps in this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
    • Fork the Choreo samples repository, which contains the sample integration for this guide.

      Repository file structure

      To work with the sample repository, it is important to familiarize yourself with the repository file structure. The sample code for this guide is in the <sample-repository-dir>/weather-to-email-scheduled-task directory. To understand how the functionality is implemented, you must read the code comments. The following table describes what you will find in each file in the repository:

      File path File content Ballerina.toml Contains metadata about the project Dependencies.toml Lists the dependencies required for the project main.bal Contains the entry point of the project, including the main function types.bal Contains custom data types used in the project utils.bal Contains utility functions and helper functions used in the project
    • Go to OpenWeatherMap and sign up to obtain an API key. For details on how to obtain an API key, see the OpenWeatherMap documentation.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-1-create-a-scheduled-task-component","title":"Step 1: Create a scheduled task component","text":"
    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Scheduled Task card.
    4. Enter a unique name and a description for the component. You can use the name and description given below:

      Field Value Component Name WeatherToEmail Description My first scheduled task
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Enter the following information:

      Field Description Organization Your GitHub account Repository choreo-samples Branch main Buildpack Ballerina Project Directory weather-to-email-scheduled-task

      Tip

      • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      • Project Directory specifies the location of the project to build the component.
    8. Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    Now you can proceed to build and deploy the scheduled task.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-2-build-the-scheduled-task","title":"Step 2: Build the scheduled task","text":"

    To build the scheduled task, follow the steps given below:

    1. In the left navigation menu, click Build.
    2. In the Builds pane, click Build. This opens the Commits pane where you can see all the commits related to the component.
    3. Select the latest commit and click Build. This triggers the build process and displays the build progress in the Build Logs pane.

      Info

      The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with the build status.

    Here, you will see the build status as Success.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-3-deploy-the-scheduled-task","title":"Step 3: Deploy the scheduled task","text":"

    To deploy the scheduled task, follow the steps given below:

    1. In the left navigation menu, click Deploy.
    2. In the Set Up card, click Configure & Deploy.
    3. In the Configurations pane, specify values as follows for the configurable variables:

      Tip

      The configurable variables populated here are defined in the sample Ballerina project used in this guide. To learn how to declare configurable variables in Ballerina, see the Ballerina documentation on declaring configurable variables. If configurable variables are detected in a connected Ballerina project, Choreo prompts for the respective values during component deployment.

      Field Value apiKey The API key you obtained in the prerequisites section latitude Latitude of the location to get the weather forecast longitude Longitude of the location to get the weather forecast email The email address to receive the formatted weather forecast information

      Note

      If you use Ballerina as the buildpack and you want to set a configurable variable as a secret, click the lock icon corresponding to the configurable variable. This marks it as a secret and conceals the input value.

      For example, if you consider the configurable variables in this guide and set the apiKey as a secret, its input value will be concealed as follows:

      If you want to update the input value at a later time, you can click Update Secret Content and specify a new value.

    4. Click Next.

    5. In this step, you must define a schedule to run the task. In this guide, you set the schedule to receive the weather information daily at 8.00 AM UTC. Enter values as follows to configure the schedule:

      Field Value Select Time Zone Select a time zone to schedule the task Select Range Day Every 1 At 08:00

      Tip

      When you develop a scheduled task, you can define a schedule depending on your requirement. If you want to test and verify the immediately, you can schedule the deployment to run in just a few minutes after you create it. However, to avoid unnecessary expenses, make sure you reschedule or stop the deployment once you test and verify.

    6. Click Deploy. This deploys the scheduled task to the development environment and indicates the Scheduled Status as Active in the Development card.

    You can test the scheduled task when it runs at the configured time.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-4-test-the-scheduled-task","title":"Step 4: Test the scheduled task","text":"

    When the scheduled task runs at the configured time, an email with the subject [WSO2 Choreo Demo] Next 24H Weather Forecast is sent from choreo.demo@gmail.com to the email address specified as the email configurable variable value in Step 3.

    If the scheduled task ran successfully, you should receive an email similar to the following to the email address you specified:

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-5-observe-the-scheduled-task","title":"Step 5: Observe the scheduled task","text":"

    The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

    To visualize and monitor the performance of the scheduled task you deployed, click Observability in the left navigation menu. You can observe the following:

    • The throughput and latencies of requests served over a given period.
    • The logs that are generated over a given period.
    • The flame graph (Diagnostics View) that is generated over a given period.
    • The low-code diagram.

    To learn more about the observability details you can view via Choreo observability, see Observability Overview.

    "},{"location":"develop-components/develop-integrations/develop-a-scheduled-task/#step-6-monitor-executions","title":"Step 6: Monitor executions","text":"

    To track and monitor executions associated with the deployed scheduled task, go to the left navigation menu and click Execute.

    Tip

    The Execute view is applicable to both scheduled and manual tasks.

    You can view the following information:

    • The total number of executions within the past 30 days.

    • The currently active executions and those that are already complete.

      Here, you can view information such as the execution ID, the revision of the execution, and the time it was triggered.

    • Detailed execution logs for a specific execution.

      You can click on an execution to view detailed logs related to it.

      Info

      It may take a few minutes for the logs to appear. You may need to manually refresh to view the latest logs.

    "},{"location":"develop-components/develop-integrations/develop-an-event-handler/","title":"Develop an Event Handler","text":"

    An Event Handler executes predefined actions in response to specific events. Choreo simplifies the process of creating and deploying such integrations.

    This guide walks you through the steps to create and deploy an Event Handler using WSO2 MI and Choreo.

    In this guide, you will build a simple event handler that monitors RabbitMQ for new messages and displays them once they become available.

    "},{"location":"develop-components/develop-integrations/develop-an-event-handler/#prerequisites","title":"Prerequisites","text":"

    Before you try out the steps in this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
    • Use an existing RabbitMQ instance or start a new RabbitMQ instance on a server that can be accessed via the internet. Obtain the username, hostname, password, and vhost from the RabbitMQ instance to use later as environment variables.

    • Fork the Choreo samples repository, which contains the sample integration for this guide.

    "},{"location":"develop-components/develop-integrations/develop-an-event-handler/#step-1-create-an-event-handler-component","title":"Step 1: Create an event handler component","text":"
    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Event Handler card.
    4. Enter a unique name and a description for the component. You can use the name and description given below:

      Field Value Component Name SalesOrderListener Description RabbitMQ integration
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Enter the following information:

      Field Description Organization Your GitHub account Repository choreo-samples Branch main Buildpack WSO2 MI because you are creating the REST API from a WSO2 Integration Studio project Project Directory mi-rabbitmq-listener

      Tip

      • Buildpack specifies the type of build to run depending on the implementation of the component. It converts the integration code into a Docker image that can run on Choreo cloud. If an integration is developed using WSO2 Integration Studio, select Micro Integrator as the buildpack. If an integration is developed using the Ballerina language, select Ballerina as the buildpack.

      • Project Directory specifies the location of the project to build the component.
    8. Click Create.

    "},{"location":"develop-components/develop-integrations/develop-an-event-handler/#step-2-deploy-the-integration","title":"Step 2: Deploy the integration","text":"

    To deploy the integration, follow the steps given below:

    1. In the left navigation menu, click Deploy.
    2. In the Build Area card, click Configure & Deploy.
    3. In the Configurations pane, click + Add corresponding to Environment Variables and add the following environment variables:

      Tip

      Use the values from your RabbitMQ instance as per the Prerequisites section, for the environment variables.

      Name Value HOSTNAME Hostname of your RabbitMQ server VHOST Virtual hostname of your RabbitMQ server USERNAME Username for connecting to RabbitMQ PASSWORD Password associated with the RabbitMQ username
    4. Click Deploy. This deploys the event handler to the development environment and indicates the Deployment Status as Active in the Development card.

    "},{"location":"develop-components/develop-integrations/develop-an-event-handler/#step-3-test-the-integration","title":"Step 3: Test the integration","text":"

    To test the integration, follow the steps given below:

    1. Send a sales order message to the SalesOrderQueue on the RabbitMQ server.
      • You can send a sample sales order message similar to the following:
        {\n\"order_id\": \"12345\",\n\"customer_name\": \"John Doe\",\n\"product\": \"Widget\",\n\"quantity\": 10,\n\"total_amount\": 100.00\n}\n
    2. Observe the logs:
      • In the left navigation menu, click Logs and then click Runtime Logs. You will see the order message in the logs.

    Now you have gained hands-on experience in creating, configuring, and deploying an event handler.

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/","title":"Develop an Integration with Integration Studio","text":"

    The seamless integration of APIs, microservices, applications, and data across different languages and formats requires the ability to expose integrations as APIs. Choreo simplifies building, deploying, and managing integration components, making it easy for you to quickly expose integrations as APIs.

    Note

    • To develop integrations that you need to use in Manual Task and Schedule Task components in Choreo, you need to use the automation mode in the WSO2 Micro Integrator. See Running MI in Automation Mode.
    • To develop integrations for any other component types (Service, webhook, event-handler, etc) you need to use the server mode.

    This guide walks you through the steps to expose an integration you created in WSO2 Integration Studio as an API in Choreo.

    In this guide, you will:

    • Create a component to expose the sample integration in the Choreo samples repository as an API.
    • Deploy, test, and observe the integration component.
    • Publish the integration component as an API to the Choreo Developer Portal.
    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#prerequisites","title":"Prerequisites","text":"

    Before you try out the steps in this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
    • Fork the Choreo samples repository, which contains the sample integration for this guide.

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#step-1-create-the-integration-component","title":"Step 1: Create the integration component","text":"
    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a unique name and a description for the component. You can enter the name and description given below:

      Field Value Component Name Hello World Description Hello World REST API
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Enter the following information:

      Field Description Organization Your GitHub account Repository choreo-samples Branch main Buildpack WSO2 MI because you are creating the REST API from a WSO2 Integration Studio project Project Directory hello-world-mi
    8. Click Create. Choreo initializes the component with the sample integration.

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#step-2-deploy-the-integration-component","title":"Step 2: Deploy the integration component","text":"

    To deploy the integration component to the development environment, follow the steps given below:

    1. In the Choreo Console left navigation menu, click Deploy.
    2. In the Build Area card, click Configure & Deploy.
    3. In the Configurations pane, click Next. This displays details of the endpoint ready to be deployed.
    4. Click Deploy. This deploys the integration component to the development environment. The Development card indicates the Deployment Status as Active when the integration is successfully deployed.

      Tip

      Choreo uses endpoints to expose Service component to the network. You can read more about configuring endpoints in Configure Endoints.

      Tip

      Automatic deployment is enabled for the component by default. Therefore, you are required to perform only the first deployment manually.

    Now you can test the integration.

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#step-3-test-the-integration","title":"Step 3: Test the integration","text":"

    To test the integration using the OpenAPI Console. Follow the steps given below:

    1. In the Choreo Console left navigation menu, click Test and then click Console.
    2. In the OpenAPI Console that opens, select Development from the environment drop-down list.
    3. Click to expand the GET /integration operation.
    4. Click Try it out and then click Execute. This sends a request to your deployed integration.
    5. Go to the Response body section and observe the response returned by the integration. If the integration works as expected, you should see a response similar to the following:

      {\"Hello\" : \"Integration\"}

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#step-4-observe-the-integration","title":"Step 4: Observe the integration","text":"

    The observability view in Choreo displays graphs that depict details such as throughput, latency, diagnostic data, and logs to identify and troubleshoot anomalies in components you deploy.

    To visualize and monitor the performance of the integration component you deployed, click Observability in the left navigation menu. You can observe the following:

    • The throughput and latencies of requests served over a given period.
    • The logs that are generated over a given period.
    • The flame graph (Diagnostics View) that is generated over a given period.

    To learn more about the observability details you can view via Choreo observability, see Observability Overview.

    "},{"location":"develop-components/develop-integrations/develop-an-integration-with-integration-studio/#step-5-publish-the-integration-component","title":"Step 5: Publish the integration component","text":"

    To publish the integration component, follow the steps given below:

    1. In the Choreo Console left navigation menu, click Manage and then click Lifecycle. This opens the Lifecycle Management pane, where you can see the different lifecycle stages that an API can be in. You can see that the current lifecycle stage is Created.
    2. In the Lifecycle Management pane, click Publish. This changes the API lifecycle stage to Published and exposes the integration as an API in the Choreo Developer Portal.

    To open the published API in the Developer Portal via the Lifecycle Management pane, click Go to Devportal. In the Choreo Developer Portal, you can view the published API, manage subscriptions for it, and generate access tokens for testing purposes.

    Now, you have gained hands-on experience in exposing an integration designed using WSO2 Integration Studio as a REST API in Choreo.

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/","title":"Develop a Ballerina Service","text":"

    Choreo allows you to develop and deploy applications using your preferred programming language. This guide demonstrates how to deploy a service component that exposes a REST API using the Ballerina language. No prior knowledge of the Ballerina language is required to follow this guide.

    A REST API is a web service adhering to Representational State Transfer (REST) principles, using HTTP methods to access and manage resources. This guide walks you through building a Ballerina service component, deploying it on Choreo, and using it with an HTTP client application.

    In this guide, you will:

    • Build a simple greeting service using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.

      • Request:

        $ curl GET http://localhost:9090/greeter/greet?name=Ballerina

      • Response:

        $ hello Ballerina!

    • Deploy the service in Choreo. The service will run on port 9090.

    • Test the service.
    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample greetings service implementation in Ballerina.

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

    Note

    The specified file paths are relative to <sample-repository-dir>/greeting-service.

    Filepath Description service.bal The greetings service code written in the Ballerina language. tests/service_test.bal Test files related to the service.bal file. Ballerina.toml The Ballerina configuration file.

    Let's get started!

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#step-1-create-a-service-component","title":"Step 1: Create a service component","text":"

    To create a Ballerina service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Ballerina Greetings Component Name ballerina-greetings Description Send greetings
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account Repository choreo-samples Branch main
    8. Select Ballerina as the buildpack.

    9. In the Ballerina Project Directory, specify /greeting-service.
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service that exposes a REST API written in the Ballerina language. Next, let's build and deploy the service.

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository and configured the endpoint details, it's time to build and deploy the service.

    Note

    If you are rebuilding the Ballerina service component after changing the Ballerina version, ensure that before building the code, the version of the Ballerina distribution mentioned in the Ballerina.toml file matches the distribution version specified in the Dependencies.toml file.

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Configurations pane that opens, click Next to skip the configuration.
    4. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

      To build and deploy the service, follow the steps below:

    Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

    For detailed instructions, see the following sections:

    • Step 3: Test
    • Step 4: Manage
    "},{"location":"develop-components/develop-services/develop-a-ballerina-service/#manage-the-deployment","title":"Manage the deployment","text":"

    If you want to view Kubernetes-level insights to perform a more detailed diagnosis of this Ballerina REST API, see Choreo's DevOps capabilities.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/","title":"Develop a Service with Docker","text":"

    Choreo is a platform that allows you to create and deploy applications in any language.

    In this guide, you will:

    • create a containerized service component using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.
    • Deploy it in Choreo using a Dockerfile. The service will run on port 9090.
    • Test the service.

    If you want to create a service component that exposes a Ballerina service, see Develop a Ballerina Service .

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample greetings service implementation with the Dockerfile.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

    Note

    The specified file paths are relative to <sample-repository-dir>/greeting-service-go

    Filepath Description main.go The Go-based greeter service code. Dockerfile The Dockerfile to build the container image of the application. .choreo/component.yaml Choreo-specific configuration that provides information about how Choreo exposes the service. openapi.yaml The OpenAPI contract of the greeter service. This is required to publish the service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml file.

    Let's get started!

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#configure-the-service-port-with-endpoints","title":"Configure the service port with endpoints","text":"

    In Choreo, you can expose your services via endpoints.

    You are going to run the greeter service on port 9090. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

    To configure the endpoint details of a containerized component, Choreo looks for an component.yaml file inside the .choreo directory. Be sure to place the .choreo directory at the root of the Docker build context path.

    In the greeter sample, the component.yaml file is in the greeting-service-go/.choreo/ directory.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#step-1-create-a-service-component-from-a-dockerfile","title":"Step 1: Create a service component from a Dockerfile","text":"

    To create a containerized service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Greetings Component Name greetings Description Send greetings
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context /greeting-service-go Dockerfile /greeting-service-go/Dockerfile

      Info

      1. To successfully build your container with Choreo, it is essential to explicitly define a user ID (UID) under the USER instruction in your Dockerfile. For reference, see sample Dockerfile. To ensure that the defined USER instruction is valid, it must conform to the following conditions:

        • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
        • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      2. The Dockerfile used in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that we have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then we can deploy that image test the greeter service.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

      You can access the following scans under Build.

      • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
      • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
      • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

        Info

        If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

    "},{"location":"develop-components/develop-services/develop-a-service-with-docker/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click Next to skip the configuration.
    4. In the File Mount pane, click Next to skip the configuration.
    5. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

    To perform a more detailed diagnosis of this Dockerfile-based REST API by viewing Kubernetes-level insights, see Choreo's DevOps capabilities.

    "},{"location":"develop-components/develop-services/develop-a-service/","title":"Develop a Service","text":"

    Choreo allows you to create and deploy applications in your preferred programming language.

    In this guide, you will:

    • Build a simple greeting service using a sample service implementation. The sample implementation will have a single resource named greet that accepts a single query parameter as input.
    • Deploy the service in Choreo using a Go buildpack. The service will run on port 9090.
    • Test the service.
    "},{"location":"develop-components/develop-services/develop-a-service/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample greetings service implementation in Go.

    "},{"location":"develop-components/develop-services/develop-a-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service:

    Note

    The specified file paths are relative to <sample-repository-dir>/greeting-service-go

    Filepath Description main.go The Go-based greeter service code. .choreo/component.yaml Choreo-specific configuration that provides information about how Choreo exposes the service. openapi.yaml The OpenAPI contract of the greeter service. This is required to publish the service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml file.

    Let's get started!

    "},{"location":"develop-components/develop-services/develop-a-service/#configure-the-service-port-with-endpoints","title":"Configure the service port with endpoints","text":"

    In Choreo, you can expose your services via endpoints.

    You are going to run the greeter service on port 9090. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

    To configure the endpoint details of a containerized component, Choreo looks for an component.yaml file inside the .choreo directory. Be sure to place the .choreo directory at the root of the Docker build context path.

    In the greeter sample, the component.yaml file is in the greeting-service-go/.choreo/ directory.

    "},{"location":"develop-components/develop-services/develop-a-service/#step-1-create-a-service-component","title":"Step 1: Create a service component","text":"

    To create a containerized service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Greetings Component Name greetings Description Send greetings
    5. Go to the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Go as the buildpack.

    9. Enter the following information:

      Field Value Go Project Directory /greeting-service-go Language Version 1.x
    10. Click Create. This creates the component and lists it under Component Listing on the project home page.

    You have successfully created the service. The next step is to build and deploy it.

    "},{"location":"develop-components/develop-services/develop-a-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository and configured the endpoint details, it's time to build and deploy the greeter service.

    "},{"location":"develop-components/develop-services/develop-a-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. On the project home page, click on the Greetings component you created. This takes you to the component overview page.
    2. In the left navigation menu, click Build.
    3. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/develop-a-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click Next to skip the configuration.
    4. In the File Mount pane, click Next to skip the configuration.
    5. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/","title":"Expose a Ballerina GraphQL Endpoint via a Service","text":"

    Choreo offers the flexibility to develop and deploy applications in a language of your preference. This guide shows you how to deploy a service component that exposes a GraphQL API using the Ballerina language in Choreo. No prior knowledge of the Ballerina language is required to follow this guide.

    GraphQL API is a query language and runtime that provides a single endpoint for retrieving flexible and efficient data in a strongly-typed and self-documenting way. By following this guide, you will build a service component in Ballerina and deploy it on Choreo for any GraphQL client application to utilize it.

    This guide shows how to build a simple reading list service and deploy it in Choreo using Ballerina. The GraphQL endpoint you create in this guide has two operations: Query and Mutation. The Query type operations read the data in the data source, and the Mutation operations update the data in the data source. The reading list service has two queries and three mutations as follows:

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#queries","title":"Queries","text":"

    Retrieve the reading list

    This resource accepts an optional filter, status, which filters the reading list by reading status. Accepted values for status are reading, read, and to_read.

    Sample request:

    $ curl -X POST -H \"Content-Type: application/json\" -d '{\"query\": \"query {allBooks (status: \\\"reading\\\") { id title author status }}\"}' http://localhost:8090\n

    Sample response

    $ {\n  \"data\": {\n    \"allBooks\": [\n      {\n        \"id\": 1,\n        \"title\": \"Sample Book\",\n        \"author\": \"Test Author\",\n        \"status\": \"to_read\"\n      }\n    ]\n  }\n}\n

    Retrieve a book item from the reading list

    This resource accepts a filter, id, which will select the book item from the reading list by book id. The id is an Integer value.

    Sample request

    $ curl -X POST -H \"Content-Type: application/json\" -d '{\"query\": \"query {book (id: 1) { id title author status }}\"}' http://localhost:8090\n

    Sample response

    $ {\n  \"data\": {\n    \"book\": {\n      \"id\": 1,\n      \"title\": \"Sample Book\",\n      \"author\": \"Test Author\",\n      \"status\": \"to_read\"\n    }\n  }\n}\n

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#mutations","title":"Mutations","text":"

    Add a book item to the reading list

    This remote function accepts a book record as the input and consists of the title and the author. When you add a new book to the reading list, the method updates the reading status of the newly added book to to_read. This method returns the added book item upon successful execution.

    Sample request

    $ curl -X POST -H \"Content-type: application/json\" -d '{ \"query\": \"mutation { addBook(book: {title: \\\"Sample Book\\\", author: \\\"Test Author\\\"}) { id title author status } }\" }' 'http://localhost:8090'\n

    Sample response

    $ {\n  \"data\": {\n    \"addBook\": {\n      \"id\": 1,\n      \"title\": \"Sample Book\",\n      \"author\": \"Test Author\",\n      \"status\": \"to_read\"\n    }\n  }\n}\n

    Update the reading status of a book

    This remote function requires id and status as inputs to update the reading status of the selected book. The id refers to the id of the book. It is an integer. The status refers to the reading status that needs to be updated. This method returns the updated book item upon successful execution.

    Sample request

    $ curl -X POST -H \"Content-type: application/json\" -d '{ \"query\": \"mutation { setStatus(id: 1, status: \\\"reading\\\") { id title author status } }\" }' 'http://localhost:8090'\n

    Sample response

    $ {\n  \"data\": {\n    \"setStatus\": {\n      \"id\": 1,\n      \"title\": \"Sample Book\",\n      \"author\": \"Test Author\",\n      \"status\": \"reading\"\n    }\n  }\n}\n

    Delete a book item from the reading list

    This remote function requires the id as the input to delete the book item from the reading list. This method returns the removed book item upon successful execution.

    Sample request

    $ curl -X POST -H \"Content-type: application/json\" -d '{ \"query\": \"mutation { deleteBook(id: 1) { id title author status } }\" }' 'http://localhost:8090'\n

    Sample response

    $ {\n  \"data\": {\n    \"deleteBook\": {\n      \"id\": 1,\n      \"title\": \"Sample Book\",\n      \"author\": \"Test Author\",\n      \"status\": \"reading\"\n    }\n  }\n}\n

    Our next step is to set up the resources that you will require to follow the guide, including the sample reading list application and the Choreo GitHub app.

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#prerequisites","title":"Prerequisites","text":"
    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample GraphQL service implementation for this guide.

    Let's get started!

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the reading list service.

    Note

    The following file paths are relative to the path <sample-repository-dir>/reading-list-graphql.

    Filepath Description service.bal The reading list service code written in the Ballerina language. Ballerina.toml The Ballerina configuration file. .choreo/component.yaml The configuration file with endpoint details."},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#step-1-create-a-service-component","title":"Step 1: Create a service component","text":"

    To create a Ballerina service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Ballerina Reading List Component Name ballerina-reading-list Description Manage a reading list
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Ballerina as the buildpack.

    9. Enter the following information:

      Field Value Ballerina Project Directory reading-list-graphql
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service component that exposes a GraphQL API written in the Ballerina language. Next, let's build and deploy the service.

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that we have connected the source repository, it's time to build and deploy the reading list service.

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Configurations pane that opens, click Next to skip the configuration.
    4. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

      To build and deploy the service, follow the steps below:

    Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

    For detailed instructions, see the following sections:

    • Step 3: Test
    • Step 4: Manage
    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/","title":"Expose a gRPC Endpoint via a Service","text":"

    Choreo allows you to create and deploy applications in your preferred programming language. One powerful option is gRPC, a high-performance and language-agnostic remote procedure call (RPC) framework. It utilizes Protocol Buffers to define services and generate client/server code.

    In this guide, you will learn to use Choreo to create a service component that exposes a gRPC server implemented in Go, enabling efficient and scalable communication with any gRPC client application. No prior knowledge of the Go language is necessary to follow this guide.

    By following this guide, you will:

    • Create a simple gRPC server using a Service component.
    • Link the containerized gRPC service to the Choreo component using the Dockerfile. The greeter service has a single RPC method named sayHello. Following is the proto file the server and the client application are using:

      syntax = \"proto3\";\noption go_package = \"github.com/wso2/choreo-samples/go-grpc/pkg\";\nservice greeter {\nrpc SayHello (HelloRequest) returns (HelloReply) {}\n}\nmessage HelloRequest {\nstring name = 1;\n}\nmessage HelloReply {\nstring message = 1;\n}\n
    • Deploy the gRPC server component in Choreo.

    • Create a gRPC client using a Manual Trigger component.
    • Deploy the gRPC client.
    • Invoke the gRPC server using a gRPC client and check the response through the Choreo log view.
    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    Let's get started!

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the greeter service.

    Note

    The following file paths are relative to the path <sample-repository-dir>/go-grpc.

    File Path Description main.go The greeter service code written in the Go language. greeter_client/main.go The greeter client application written in the Go language. Dockerfile.server The Dockerfile to build the container image of the server application. Dockerfile.client The Dockerfile to build the container image of the client application. .choreo/component.yaml The Choreo-specific configuration that provides information about how Choreo exposes the service. pkg/greeter.proto The interface definition of the gRPC service. This is used to generate the server and client stubs for the Go application."},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#configure-the-service-port-with-endpoints","title":"Configure the service port with endpoints","text":"

    In Choreo, you can expose your services via endpoints.

    Let's run the gRPC server service component on port 8080. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

    Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of the containerized component. Ensure the .choreo directory is at the root of the Docker build context path.

    In the gRPC server sample, the component.yaml file is at go-grpc/.choreo/component.yaml, where the build context path is go-grpc.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-1-create-a-service-component-with-a-grpc-endpoint","title":"Step 1: Create a service component with a gRPC endpoint","text":"

    To create a containerized service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go gRPC Server Component Name go-grpc-server Description Send greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context go-grpc Dockerfile go-grpc/Dockerfile.server

      Info

      1. To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. To ensure that the defined USER instruction is valid, it must conform to the following conditions:

        • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
        • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      2. The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the greeter service.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

      You can access the following scans under Build.

      • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
      • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
      • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

        Info

        If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click Next to skip the configuration.
    4. In the File Mount pane, click Next to skip the configuration.
    5. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    6. Once you have successfully deployed your service, navigate to the component overview page and copy the gRPC service URL. You need to provide that URL when setting up the client application later in this guide.

    You have successfully deployed the gRPC server. Currently, the gRPC service is only accessible by the components deployed within the same project.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-3-invoke-the-grpc-service","title":"Step 3: Invoke the gRPC service","text":"

    Let's invoke the gRPC service that you created above, using a gRPC client.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-31-create-a-manual-task-for-the-grpc-client","title":"Step 3.1: Create a manual task for the gRPC client","text":"

    To create a manual task component, follow these steps:

    1. On the Choreo Console header, click the Project list and select the project where you created the gRPC service component. This opens the project home page.
    2. Go to the Component Listing section and click + Create.
    3. Click the Manual Task card.
    4. Enter a display name, a unique name, and a description for the component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go gRPC Client Component Name go-grpc-client Description Receive greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context go/grpc Dockerfile go/grpc/Dockerfile.client
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-32-build-the-grpc-client-component","title":"Step 3.2: Build the gRPC client component","text":"

    To build the component, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-33-setup-environment-variables-and-deploy-the-grpc-client","title":"Step 3.3: Setup environment variables and deploy the gRPC client","text":"

    The client application, in this case, the gRPC client, requires the server URL of the gRPC server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

    1. On the Choreo Console left navigation menu, click Deploy.
    2. In the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click + Add.
    4. Specify the following name and value to configure the environment variable for the client application:

      Field Value Name GREETER_SERVICE Value Paste the URL value copied after deploying the gRPC service via step 2.2 above. Make sure to drop the http:// or grpc:// part and the trailing / from the URL when copying. For example, if the URL is http://go-grpc-server-3192360657:8080/, add only go-grpc-server-3192360657:8080.
    5. Click Add and then click Next.

    6. Click Deploy.
    "},{"location":"develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/#step-34-execute-the-grpc-client-component","title":"Step 3.4: Execute the gRPC client component","text":"

    To execute the gRPC client, follow these steps:

    1. In the left navigation menu, click Execute.
    2. Click Run Now. This triggers the gRPC client and generates logs. You can trigger multiple runs to generate multiple logs.

    For details on what you can monitor via the execute page, see Monitor executions.

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/","title":"Expose a Prism-Based Mock Server Using an OpenAPI Specification","text":"

    Choreo supports deploying Prism-based mock servers using OpenAPI specifications. With the Choreo Prism mock service component, you can serve multiple mock servers, each based on a different OpenAPI specification, as separate endpoints.

    By default, these mock servers serve static content generated from the examples in the configured OpenAPI Specification (OAS).

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the Prism mock service artifacts for this guide.

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#step-1-create-a-prism-mock-service-component","title":"Step 1: Create a Prism mock service component","text":"

    To create a Prism mock service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component.

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Prism Mock as the buildpack.

    9. Select prism-mock-service as the Project Directory.
    10. Click Create. This creates the component and takes you to the Overview page of the component.
    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#step-2-build-and-deploy-the-component","title":"Step 2: Build and deploy the component","text":"

    Now that you have successfully created the Prism mock service, it's time to build and deploy it.

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest. This builds the service from the latest commit.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    Once you have successfully deployed the service, you can test, manage, and observe it like any other component type in Choreo.

    "},{"location":"develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/#serve-dynamic-content","title":"Serve dynamic content","text":"

    The Prism mock service can serve dynamic content according to the schema definitions in the OpenAPI specification. To use the Prism mock service with dynamic content, clients must add the prefer:dynamic=true header in the request.

    To generate meaningful dynamic responses, you can use the x-faker attribute in schema definitions of the OpenAPI specification. For more information on dynamically generated responses with the x-faker attribute, see the Prism documentation.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/","title":"Expose a TCP Server via a Service","text":"

    Choreo offers the flexibility to design and deploy applications in the programming language of your choice. One viable choice for specific network communication needs is TCP (Transmission Control Protocol). TCP provides a reliable, stream-oriented communication mechanism that ensures data integrity and orderliness during transmission. It's the go-to option for scenarios where guaranteed data delivery and error recovery are paramount.

    In this guide, you will learn to use Choreo to create a service component that exposes a TCP server implemented in Go, enabling efficient and scalable communication with any TCP client application. No prior knowledge of the Go language is necessary to follow this guide.

    By following this guide, you will:

    • Setup a TCP server
      • Create a simple TCP server using a service component.
      • Link the containerized TCP service to the Choreo component using a Dockerfile.
      • Deploy the TCP server component in Choreo.
    • Setup a TCP client
      • Create a TCP client using a manual task component.
      • Link the containerized TCP client to the Choreo component using a Dockerfile.
      • Deploy the TCP client component in Choreo.
    • Invoke the TCP server using a TCP client and observe the response through the Choreo log view.
    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    Let's get started!

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the sample service.

    Note

    The following file paths are relative to the path <sample-repository-dir>/docker-tcp-service.

    File Path Description server/main.go The greeter service code written in the Go language. client/main.go The greeter client application written in the Go language. Dockerfile.server The Dockerfile to build the container image of the server application. Dockerfile.client The Dockerfile to build the container image of the client application. .choreo/component.yaml The Choreo-specific configuration provides information about how Choreo exposes the service."},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#configure-the-service-port-with-endpoints","title":"Configure the service port with endpoints","text":"

    In Choreo, you can expose your services via endpoints.

    Let's run the TCP server service component on port 5050. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

    Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of a containerized component. Place the .choreo directory at the root of the Docker build context path.

    In our TCP server sample, the component.yaml file is at docker-tcp-service/.choreo/component.yaml, where the build context path is docker-tcp-service.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-1-create-a-service-component-with-a-tcp-endpoint","title":"Step 1: Create a service component with a TCP endpoint","text":"

    To create a containerized service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go TCP Server Component Name go-tcp-server Description Send greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context docker-tcp-service Dockerfile docker-tcp-service/Dockerfile.server

      Info

      1. To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. To ensure that the defined USER instruction is valid, it must conform to the following conditions:

        • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
        • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      2. The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the service.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

      You can access the following scans under Build.

      • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
      • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
      • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

        Info

        If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click Next to skip the configuration.
    4. In the File Mount pane, click Next to skip the configuration.
    5. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    6. Once you have successfully deployed your service, navigate to the component overview page and copy the TCP service address. You need to provide that address when setting up the client application later in this guide.

    You have successfully deployed the TCP server. Currently, the TCP service is only accessible by the components deployed within the same project.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-3-invoke-the-tcp-service","title":"Step 3: Invoke the TCP service","text":"

    Now let's use a TCP client to invoke the TCP service that you created above. To do this, you can create a manual trigger component as the TCP client. This is the recommended approach because, in this example, it's more efficient to have a client that connects to the server, sends a request, and then stops. Here, a continuously executing task isn't required. Furthermore, if you use a manual trigger component, you won't need to expose an endpoint in the client for invocation, unlike with an API.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-31-create-a-manual-trigger-for-the-tcp-client","title":"Step 3.1: Create a manual trigger for the TCP client","text":"

    To create a manual task component, follow these steps:

    1. On the Choreo Console header, click the Project list and select the project where you created the TCP service component. This opens the project home page.
    2. Go to the Component Listing section and click + Create.
    3. Click the Manual Task card.
    4. Enter a display name, a unique name, and a description for the component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go TCP Client Component Name go-tcp-client Description Receive greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context docker-tcp-service Dockerfile docker-tcp-service/Dockerfile.client
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-32-build-the-tcp-client-component","title":"Step 3.2: Build the TCP client component","text":"

    To build the component, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-33-setup-environment-variables-and-deploy-the-tcp-client","title":"Step 3.3: Setup environment variables and deploy the TCP client","text":"

    The client application, in this case, the TCP client, requires the server URL of the TCP server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

    1. On the Choreo Console left navigation menu, click Deploy.
    2. In the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click + Add.
    4. Specify the following name and value to configure the environment variable for the client application:

      Field Value Name SERVER_ADDRESS Value Paste the URL value copied after deploying the TCP service via step 2.2 above. Make sure to drop the tcp:// part and the trailing / from the URL when copying. For example, add only go-tcp-server-1097922445:8080.
    5. Click Add and then click Next.

    6. Click Deploy.
    "},{"location":"develop-components/develop-services/expose-a-tcp-server-via-a-service/#step-34-execute-the-tcp-client-component","title":"Step 3.4: Execute the TCP client component","text":"

    To execute the TCP client, follow these steps:

    1. In the left navigation menu, click Execute.
    2. Click Run Now. This triggers the TCP client and generates logs. You can trigger multiple runs to generate multiple logs.

    For details on what you can monitor via the execute page, see Monitor executions.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/","title":"Expose a UDP Server via a Service","text":"

    Choreo offers the flexibility to design and deploy applications in the programming language of your choice. One compelling choice for certain network communication needs is UDP (User Datagram Protocol). UDP is a high-speed, connectionless protocol ideal for scenarios where lightweight, real-time data transmission is essential.

    In this guide, you will learn to use Choreo to create a Service component that exposes a UDP server implemented in Go, enabling efficient and scalable communication with any UDP client application. No prior knowledge of the Go language is necessary to follow this guide.

    By following this guide, you will:

    • Setup a UDP server
      • Create a simple UDP server using a Service component.
      • Link the containerized UDP service to the Choreo component using the Dockerfile.
      • Deploy the UDP server component in Choreo.
    • Setup a UDP client
      • Create a UDP client using a manual task component.
      • Link the containerized UDP client to the Choreo component using the Dockerfile.
      • Deploy the UDP client component in Choreo.
    • Invoke the UDP server using a UDP client and check the response through the Choreo log view.
    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#prerequisites","title":"Prerequisites","text":"

    Before you try out this guide, complete the following:

    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample service implementation for this guide.

    Let's get started!

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the sample service.

    Note

    The following file paths are relative to the path <sample-repository-dir>/docker-udp-service.

    File Path Description server/main.go The greeter service code written in the Go language. client/main.go The greeter client application written in the Go language. Dockerfile.server The Dockerfile to build the container image of the server application. Dockerfile.client The Dockerfile to build the container image of the client application. .choreo/component.yaml The Choreo-specific configuration provides information about how Choreo exposes the service."},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#configure-the-service-port-with-endpoints","title":"Configure the service port with endpoints","text":"

    In Choreo, you can expose your services via endpoints.

    Let's run the UDP server service component on port 5050. To securely expose the service through Choreo, you must provide the port and other required information to Choreo. For detailed information on each attribute of an endpoint, see Configure Endpoints.

    Choreo looks for an component.yaml file inside the .choreo directory to configure the endpoint details of a containerized component. Place the .choreo directory at the root of the Docker build context path.

    In our gRPC server sample, the component.yaml file is at docker-udp-service/.choreo/component.yaml, where the build context path is docker-udp-service.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-1-create-a-service-component-with-a-udp-endpoint","title":"Step 1: Create a service component with a UDP endpoint","text":"

    To create a containerized service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go UDP Server Component Name go-udp-server Description Send greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context docker-udp-service Dockerfile docker-udp-service/Dockerfile.server

      Info

      1. To successfully build your container with Choreo, it is essential to explicitly define a User ID (UID) under the USER instruction in your Dockerfile. For reference, see the sample Dockerfile. To ensure that the defined USER instruction is valid, it must conform to the following conditions:

        • A valid User ID is a numeric value between 10000-20000, such as 10001 or 10500.
        • Usernames are considered invalid and should not be used. For example, my-custom-user-12221 or my-custom-user are invalid User IDs.
      2. The Dockerfile utilized in this guide is a multi-stage Dockerfile, which is designed to keep the final image size small and provides the ability to build the application with a specific version of tools and libraries.

    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service from a Dockerfile. Next, you can build and deploy the service.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository, and configured the endpoint details, it's time to build the service and create an image. Then you can deploy the image and test the service.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

      You can access the following scans under Build.

      • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
      • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
      • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

        Info

        If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click Next to skip the configuration.
    4. In the File Mount pane, click Next to skip the configuration.
    5. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    6. Once you have successfully deployed your service, navigate to the component overview page and copy the UDP service address. You must provide that address when setting up the client application later in this guide.

    You have successfully deployed the UDP server. Currently, the UDP service is only accessible by the components deployed within the same project.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-3-invoke-the-udp-service","title":"Step 3: Invoke the UDP service","text":"

    Now let's use a UDP client to invoke the UDP service that you created above. To do this, you can create a manual trigger component as the UDP client. This is the recommended approach because, in this example, it's more efficient to have a client that connects to the server, sends a request, and then stops. Here, a continuously executing task isn't required. Furthermore, if you use a manual trigger component, you won't need to expose an endpoint in the client for invocation, unlike with an API.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-31-create-a-manual-trigger-for-the-udp-client","title":"Step 3.1: Create a manual trigger for the UDP client","text":"

    To create a manual task component, follow these steps:

    1. On the Choreo Console header, click the Project list and select the project where you created the UDP service component. This opens the project home page.
    2. Go to the Component Listing section and click + Create.
    3. Click the Manual Task card.
    4. Enter a display name, a unique name, and a description for the component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name Go UDP Client Component Name go-udp-client Description Receive greetings
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select Docker as the buildpack.

    9. Enter the following information:

      Field Value Docker Context docker-udp-service Dockerfile docker-udp-service/Dockerfile.client
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-32-build-the-udp-client-component","title":"Step 3.2: Build the UDP client component","text":"

    To build the component, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-33-setup-environment-variables-and-deploy-the-udp-client","title":"Step 3.3: Setup environment variables and deploy the UDP client","text":"

    The client application, in this case, the UDP client, requires the server URL of the UDP server service. This is read from the client application as an environment variable. Follow the steps below to configure the environment variable for the client application:

    1. On the Choreo Console left navigation menu, click Deploy.
    2. In the Set Up card, click Configure & Deploy.
    3. In the Environment Configurations pane that opens, click + Add.
    4. Specify the following name and value to configure the environment variable for the client application:

      Field Value Name SERVER_ADDRESS Value Paste the URL value copied after deploying the UDP service via step 2.2 above. Make sure to drop the udp:// part and the trailing / from the URL when copying. For example, add only go-udp-server-1097922445:8080.
    5. Click Add and then click Next.

    6. Click Deploy.
    "},{"location":"develop-components/develop-services/expose-a-udp-server-via-a-service/#step-34-execute-the-udp-client-component","title":"Step 3.4: Execute the UDP client component","text":"

    To execute the UDP client, follow these steps:

    1. In the left navigation menu, click Execute.
    2. Click Run Now. This triggers the UDP client and generates logs. You can trigger multiple runs to generate multiple logs.

    For details on what you can monitor via the execute page, see Monitor executions.

    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/","title":"Expose a WebSocket Endpoint via a NodeJS Service","text":"

    Choreo allows you to create and deploy applications in your preferred programming language, offering a seamless platform for building dynamic and scalable solutions. This guide walks you through the steps to deploy a WebSocket service using the NodeJS buildpack.

    WebSockets provide real-time, two-way communication between a client and server over a persistent TCP connection. This makes WebSocket APIs ideal for applications that require real-time updates.

    In this guide, you will:

    • Build a simple WebSocket service using a sample implementation in NodeJS.
    • Deploy the service in Choreo, allowing any WebSocket client application to establish a connection and exchange real-time messages with your service.
    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#prerequisites","title":"Prerequisites","text":"
    • If you are signing in to the Choreo Console for the first time, create an organization as follows:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Enter a unique organization name. For example, Stark Industries.
      3. Read and accept the privacy policy and terms of use.
      4. Click Create.

      This creates the organization and opens the Project Home page of the default project created for you.

    • Fork the Choreo samples repository, which contains the sample WebSocket service implementation for this guide.

    Let's get started!

    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

    It is important to understand the purpose of the key files in the sample service. The following table provides a brief overview of each file in the NodeJS chat Application.

    Note

    The following file paths are relative to the path <sample-repository-dir>/websocket-chat-app/websocket-chat-service-nodejs.

    Filepath Description server.js The NodeJS chat service. .choreo/component-config.yaml The configuration file with endpoint details."},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#step-1-create-a-service-component","title":"Step 1: Create a service component","text":"

    To create a NodeJS service component, follow these steps:

    1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Service card.
    4. Enter a display name, a unique name, and a description for the service component. You can enter the values given below:

      Info

      In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

      Field Value Component Display Name NodeJS Chat Service Component Name nodejs-chat-service Description Manage a chat service
    5. Click the GitHub tab.

    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Under Connect Your Repository, enter the following information:

      Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
    8. Select NodeJS as the buildpack.

    9. Enter the following information:

      Field Value NodeJS Project Directory websocket-chat-app/websocket-chat-service-nodejs
    10. Click Create. This creates the component and takes you to the Overview page of the component.

    You have successfully created a service component that provides a WebSocket API built with NodeJS. The next step is to proceed with building and deploying the service.

    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#step-2-build-and-deploy","title":"Step 2: Build and deploy","text":"

    Now that you have connected the source repository, it's time to build and deploy the chat service.

    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#step-21-build","title":"Step 2.1: Build","text":"

    To build the service, follow these steps:

    1. In the left navigation menu, click Build.
    2. On the Build page, click Build Latest.

      Note

      Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

    "},{"location":"develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/#step-22-deploy","title":"Step 2.2: Deploy","text":"

    To deploy the service, follow these steps:

    1. In the left navigation menu, click Deploy.
    2. On the Set Up card, click Configure & Deploy.
    3. In the Configurations pane that opens, click Next to skip the configuration.
    4. Review the Endpoint Details and click Deploy.

      Note

      Deploying the service component may take a while. Once deployed, the Development environment card indicates the Deployment Status as Active.

    Once you have successfully deployed your service, you can test, manage, and observe it like any other component type in Choreo.

    During testing, once the WebSocket connection is established, you can send {\"type\": \"Connect\", \"username\": \"user1\"} to the WebSocket endpoint to connect to the chat service. You can then send chat messages by using {\"type\": \"Data\", \"message\": \"Hello, World!\"}.

    Note

    Some clients, such as certain browsers, may not support adding headers to the WebSocket handshake. In these cases, you can include the access token or Test key required for WebSocket API invocation within the sec-websocket-protocol header, along with any specified subprotocols.

    For example: sec-websocket-protocol: choreo-oauth2-token, {access token}, subprotocols

    If you are using a Test Key, replace choreo-oauth2-token with choreo-test-key.

    "},{"location":"develop-components/develop-services/service-component-overview/","title":"Service Component Overview","text":"

    Explore how to create, deploy, manage, and observe service components in Choreo.

    "},{"location":"develop-components/develop-services/service-component-overview/#what-is-a-service-component","title":"What is a service component?","text":"

    A service component in Choreo lets you deploy and expose REST, GraphQL, gRPC, UDP, WS or TCP services. It is a fundamental building block for creating cloud-native applications in Choreo. They provide a simple and effective way to expose functionality as a service to other components within Choreo or to the outside world.

    Service components encapsulate business logic and provide standardized interfaces, called endpoints, for communicating with other components or systems. You can deploy and scale services independently, which makes them highly flexible and adaptable to changing workloads.

    With the help of the service component, developers can quickly create APIs and microservices, making it easier to implement and manage complex software systems. Service components can also be integrated with other Choreo components, that acts as message processors, connectors, and data sources, etc to create powerful end-to-end solutions.

    You can expose a service to other components through endpoints. For details on configuring endpoints, see Configure Endpoints.

    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/","title":"Build and Deploy a Single-Page Web Application","text":"

    A web application is an application program hosted on a server and serves ingress traffic through a browser. In Choreo, you can deploy a web application by creating a Web Application component and connecting it to a Git repository that contains the implementation of the web application. Web applications can fall into one of the following categories:

    • Single page applications (SPAs): Examples include React, Angular, Vue, Svelte, etc.
    • Web servers: These serve static content or provide server-side rendering/static site generation (SSR/SSG).
    • Static content: Examples include websites and other static resources that do not require a backend, usually comprising static HTML/JS/CSS files.
    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#prerequisites","title":"Prerequisites","text":"
    • To deploy a Web Application component, you must have a GitHub account with a repository containing the web application's implementation. For this guide, fork the https://github.com/wso2/choreo-samples repository, which contains the sample web application implementation.
    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#create-a-web-application","title":"Create a web application","text":"

    You can create a web application in Choreo as follows:

    • Build and deploy a SPA from the source code.

      • Create a Web Application component by connecting a repository that includes the web application source code.
      • Select the relevant buildpack. Default buildpacks include React, Angular, and Vue.js. If you are using a different SPA framework, you can try one of these buildpacks because the configurations can be overridden to support most Javascript-based SPAs.
      • Enter the build command based on your package manager. NPM, yarn, and pnpm are supported and the relevant package manager is run based on the dependency lock file in your repository (defaults to NPM if no lock file is present).
      • Specify the build output directory.
      • Specify the NodeJS version. Choreo does not pick the Nodejs version from the package.json engine property. The required Node version must be explicitly set in the build configuration.

      Once you create the Web Application component, Choreo automatically generates a build pipeline for your single-page application and deploys it.

    • Bring your Dockerfile.

      • Create a Web Application component by connecting a repository that contains the Dockerfile for your containerized web application.
      • Commit a Dockerfile to your connected git repository to have full control over your build process.

      This approach is recommended if you are deploying a web server and not just a single-page application (or a single-page application with a complex build process).

    • Host static websites.

      • To host static web content, you can create a Web Application component and connect it to the GitHub repository that contains the required static assets.
      • Select the Static Websites buildpack. This buildpack does not trigger a build process. It only fetches the files from the path specified in the repository and serves as it is.

    Now let's take a look at how you can build and deploy a SPA from source code:

    Follow the steps below to create a sample Web Application component and deploy it in Choreo:

    1. Sign in to the Choreo Console at https://console.choreo.dev/login/. This opens the Project Home page.
    2. If you already have one or more components in your project, click + Create. Otherwise, proceed to the next step.
    3. Click the Web Application card.
    4. This opens the Create a Web Application pane, where you can specify a name and description for the component. Enter a unique name and description.
    5. Go to the GitHub tab.
    6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

      Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

      Note

      The Choreo GitHub App requires the following permissions:

      • Read and write access to code and pull requests.
      • Read access to issues and metadata.

      You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

    7. Enter the following information:

      Field Description GitHub Account Your account GitHub Repository choreo-samples Branch main
    8. Select React as the Buildpack.

    9. Enter the following information:

      Field Description Project Directory /react-single-page-app Build Command npm run build Build Path build Node Version 18

      Tip

      Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks. To learn how to set up authentication for your web application with Choreo's managed authentication, see Secure Web Applications with Managed Authentication.

    10. Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

    You have successfully created a Web Application component from the source code. Now let's build and deploy the web application.

    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#build-your-web-application","title":"Build your web application","text":"

    To build the web application, follow the steps given below:

    1. In the left navigation menu, click Build.
    2. In the Builds pane, click Build. This opens the Commits pane, where you can see all the commits related to the component.
    3. Select the latest commit and click Build. This triggers the build process and displays the progress in the Build Logs pane.

      You can access the following scans in the Build Logs pane:

      • The Dockerfile scan: Choreo performs a scan to check if a non-root user ID is assigned to the Docker container to ensure security. If no non-root user is specified, the build will fail.
      • Container (Trivy) vulnerability scan: This detects vulnerabilities in the final docker image.
      • Container (Trivy) vulnerability scan: The details of the vulnerabilities open in a separate pane. If this scan detects critical vulnerabilities, the build will fail.

      Info

      If you have Choreo environments on a private data plane, you can ignore these vulnerabilities and proceed with the deployment.

      Note

      The build process can take a while to complete. When the build process is complete, the build will be listed in the Builds pane along with its status.

    Here, you will see the build status as Success.

    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#deploy-and-access-your-web-application","title":"Deploy and access your web application","text":"
    1. In the left navigation menu, click Deploy.
    2. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can add a file mount if necessary. In this guide, you will not add a file mount.
    3. Click Next. This takes you to the Authentication Settings pane.
    4. Keep the default settings and click\u00a0Deploy.

      Note

      • The deployment process can take a few minutes to complete. On successful deployment, you will see the\u00a0Deployment Status\u00a0as\u00a0Active\u00a0in the\u00a0Development\u00a0card.
    5. To verify that you have successfully hosted the web application, click the\u00a0Web App URL\u00a0in the\u00a0Development\u00a0card. This takes you to the web application.

    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#create-a-short-url-for-your-web-application-in-production","title":"Create a short URL for your web application in production","text":"

    Info

    This feature is only available on the Choreo cloud data plane.

    When you promote your component to the Production environment, you have the option to create a personalized short URL for your web application. The URL follows the https://{your-short-prefix}.choreoapps.dev structure, where you can select a name of your preference for {your-short-prefix}.

    To create a short URL for your web application, follow the steps given below:

    1. Click Promote in the Development card and promote your web application to production.
    2. In the Production card, click Create a short URL.
    3. Specify a Short URL prefix of your choice and click Save.

      Note

      Short URL names/prefixes are subject to availability, provided on a first-come-first-serve basis.

    "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#manage-runtime-configurations-for-web-applications","title":"Manage runtime configurations for web applications","text":"

    For web applications with a backend server, Choreo allows you to mount runtime configurations and secrets as environment variables and/or file mounts for a specific environment. Alternatively, you can also inject them into the client application during server-side rendering or when serving static content.

    However, in the case of SPAs that run completely on the browser, Choreo does not support baking-in environment variables or other configurations. This is because Choreo follows a multi-environment deployment model, where configuration should be kept separate from the build and injected at runtime. For example, in most React SPA frameworks, the process.env stub is available during build time. However, it does not actually read in variables from the runtime. Instead, it is baked into the final JavaScript output during the build process.

    To manage runtime configurations, Choreo recommends the following approach (although this is a React example, the approach is generally applicable to other SPA frameworks as well).

    Note

    • With SPAs, anything you mount as a runtime config will be available to your users in the browser.
    • Do not include sensitive secrets that are not browser-safe.

    Follow the steps given below to manage runtime configurations for the React application you created above:

    1. Go to your forked Choreo samples repository.
    2. Open the public directory.
    3. Create and commit a new file named config.js in the public directory of your React application. This file should contain the runtime configuration variables you want to expose to your application, such as API endpoints or feature flags. Let's expose the API URL and a feature flag as follows:

      window.config = {\napiUrl: 'https://api.example.com',\n    featureFlags: {\n        enableNewFeature: true,\n        enableExperimentalFeature: false,\n    },\n};\n
      4. In your index.html file inside the public directory, add a script tag as follows to include the config.js file inside the tag. The config.js file will be accessible via JavaScript at runtime.

      <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\" />\n    <title>My React App</title>\n</head>\n<body>\n    <div id=\"root\"></div>\n    <script src=\"%PUBLIC_URL%/config.js\"></script>\n</body>\n</html>\n
      This makes the window.config object available to your app at runtime.

    4. In your React component, you can access the configuration variables by referencing the window.config object as follows:

      import React from 'react';\n\nfunction MyComponent() {\nconst apiUrl = window.config.apiUrl;\nconst enableNewFeature = window.config.featureFlags.enableNewFeature;\nconst enableExperimentalFeature = window.config.featureFlags.enableExperimentalFeature;\n\n// ...\n}\n
      Now you can deploy your component.

    5. When you deploy your component to Choreo, create a config file mount in the specified path for each environment (where your index.html expects the config.js file as in this example). https://wso2.com/choreo/docs/devops-and-ci-cd/manage-configurations-and-secrets/#apply-a-file-mount-to-your-container.

    6. "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#limitations","title":"Limitations","text":"

      The following limitations are specific to the Choreo cloud data plane:

      • Request size limit, including headers, cookies, and payloads: 256KB
      • Response body size limit: 20MB
      • Only one open port is permitted per web application. While you can have multiple ports open for project-level communication within a data plane, incoming traffic from the internet can only be directed to one port. This differs from the Service type components, which support multiple endpoints.
      "},{"location":"develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/#troubleshoot-a-web-application","title":"Troubleshoot a web application","text":"
      • I\u2019m seeing a blank page or a 502 error after I deploy my web application

        If you encounter a blank page or a 502 error after deploying your web application, it typically indicates that the wrong directory is being served. To resolve this issue, follow these steps:

        • Double-check the build output directory, especially if you are using a Dockerfile-less buildpack. Ensure that the specified output directory matches the actual output directory generated during the build process. For example, if you have erroneously entered public/ as the output directory when it should have been build/.

        By verifying and correcting the output directory alignment, you should be able to address the issue of encountering a blank page or experiencing a 502 error on deploying your web application.

      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/","title":"Develop Web Applications Locally with Choreo\u2019s Managed Authentication","text":"

      Choreo\u2019s managed authentication capability exposes a set of backend for frontend (BFF) endpoints, facilitating authentication and authorization for web applications. These endpoints are readily available for single-page web applications deployed on Choreo.

      As a web application developer, there may be instances where it becomes necessary to run the application on your personal workstation. In such situations, the expectation is for authentication and authorization during local development to work in the same manner as it would when the application is deployed to Choreo, eliminating the need to modify the source code.

      Choreo's local development capability ensures a seamless local application development experience where the authentication and authorization process aligns with Choreo\u2019s deployment environment. This facilitates a smoother transition from development to deployment, improving workflow efficiency.

      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#how-local-development-works-in-choreo","title":"How local development works in Choreo","text":"

      Local development uses a proxy that sits in front of the locally running web application. This proxy intercepts all incoming requests. The requests to /choreo-apis/* and /auth/* are then forwarded to Choreo, while all other requests are forwarded to the locally running web application. The proxy runs on HTTPS using a self-signed certificate, crucial for secure, HTTP-only cookie-based managed authentication. Upon running the proxy, you can access the web application using the proxy's URL and start developing the application locally. You will observe that the behavior of the web application, in terms of the managed authentication functionality, is similar to how it would be after deploying to Choreo.

      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#configure-local-development","title":"Configure local development","text":""},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#prerequisites","title":"Prerequisites","text":"
      • Create a single-page application (SPA) with managed authentication enabled. For details on how to set up managed authentication for your web application, see Secure Web Applications with Managed Authentication.
      • Promote and deploy the application to the environment where you want to enable local development.

        Note

        • The web application that you run locally will use the same managed authentication configuration as the environment where you are configuring local development.
        • Local development is only allowed in non-critical environments.
      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#apply-configurations","title":"Apply configurations","text":"
      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
      3. In the left navigation menu, click Deploy.
      4. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
      5. In the Local Development pane that opens, click the Local Development toggle to enable it.
      6. If you want to update the port on which the local development proxy server runs, click to expand Advanced Configurations and specify a value for Proxy Port.
      7. Click Apply.

      Now you have done the necessary configurations to set up local development. The next section walks you through the steps to access your web application so that you can develop it locally.

      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#access-your-web-application-to-develop-it-locally","title":"Access your web application to develop it locally","text":""},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#prerequisites_1","title":"Prerequisites","text":"
      • Ensure that local development is enabled in the environment where you want to proceed with local development.
      • Ensure that your web application is running locally on http://localhost on a specific port.
      "},{"location":"develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/#access-your-web-application-locally","title":"Access your web application locally","text":"

      You can either use the Choreo built-in identity provider or external identity provider to access your web application locally.

      Use the Choreo built-in identity providerUse an external identity provider
      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
      3. In the left navigation menu, click Deploy.
      4. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
      5. In the Local Development pane that opens, copy the command given under Step 1.
      6. Paste the command in a terminal, ensure you replace [APP_PORT] with the port on which your application is running locally, and run the command.
      7. To access the application and proceed to develop it, go to the URL given under Step 2 in the Local Development pane.

        Note

        The local development proxy runs on HTTPS using a self-signed certificate. Your browser may warn that the certificate is not valid. Accept the risk and proceed.

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component you created and deployed by following the prerequisites.
      3. In the left navigation menu, click Deploy.
      4. Go to the respective environment card depending on the environment where you want to enable local development and click Local Development.
      5. In the Local Development pane that opens, copy the redirect URLs given under Step 1.
      6. Go to the settings in the OAuth application in your identity provider and specify the copied URLs as allowed redirect URLs.
      7. Go to the Local Development pane in the Choreo Console and copy the command given under Step 2.
      8. Paste the command in a terminal, ensure you replace [APP_PORT] with the port on which your application is running locally, and run the command.
      9. To access the application and proceed to develop it, go to the URL given under Step 3 in the Local Development pane.

        Note

        The local development proxy runs on HTTPS using a self-signed certificate. Your browser may warn that the certificate is not valid. Accept the risk and proceed.

      "},{"location":"develop-components/sharing-and-reusing/create-a-connection/","title":"Create a Connection","text":"

      Connections in Choreo provide a simple and uniform approach to seamlessly integrate components with services or resources.

      Choreo allows you to create connections to services deployed in Choreo or registered as external services. It also allows you to create connections to any Choreo-managed database.

      To create a connection to a service or a database, follow the step-by-step instructions in the respective tab:

      Create a connection to a serviceCreate a connection to a database

      Create a connection to a Choreo service

      Follow these steps to create a connection to a service deployed in Choreo:

      1. In the Choreo Console, go to the top navigation menu and set the visibility level as project or component as follows:

        • Project Connection: Select an organization and a project in that organization.
        • Component Connection: Select an organization, a project in that organization, and a component in the selected project.
      2. In the left navigation menu, click Dependencies and then Connections. This page lists all the existing connections.

      3. Click +Create. This opens the Marketplace view where you can browse and search for services or databases.
      4. Click the Services tab. You can search and apply filters to efficiently find a service.
      5. Click on the service you want to connect to.
      6. Enter a name and a description for the connection and then click Next. This displays the Service URL for both development and production environments.
      7. Click Create.

      This creates the connection and displays its details for each environment, along with an inline guide on how to use the connection in your component.

      Create a connection to an external service

      Follow these steps to create a connection to an external service:

      1. Follow steps 1\u20135 from the previous section.
      2. Expand the Environment to Endpoint section and verify the service endpoints assigned to the Choreo environments.
      3. Click Create.

      For step-by-step instructions on using a connection in your service, see Use a Connection in Your Service.

      For step-by-step instructions on using a connection in your web application, see Use a Connection in Your Web Application.

      Prerequisites:

      • Create a Choreo-managed database. For details, see Choreo-Managed Databases and Caches.
      • Add the database to the Marketplace. For details, see Add Choreo-Managed Databases and Caches to the Marketplace.

      Follow these steps to create a connection to a Choreo-managed database:

      1. In the Choreo Console, go to the top navigation menu and set the visibility level as project or component as follows:

        • Project Connection: Select an organization and a project in that organization.
        • Component Connection: Select an organization, a project in that organization, and a component in the selected project.
      2. In the left navigation menu, click Dependencies and then Connections. This page lists all the existing connections.

      3. Click +Create. This opens the Marketplace view where you can browse and search for services or databases.
      4. Click the Databases tab. You can search and apply filters to efficiently find a database.
      5. Click on the database you want to connect to.
      6. To create the connection, follow these steps:

        1. Enter a name and description.
        2. Under Environment Configuration, select credentials for each environment.

          Note

          By default, the selected database is applied to all environments. To use different databases for specific environments, select the appropriate database and provide the corresponding credentials for each environment.

        3. Click Create.

      This creates the connection and displays the database connection details for each environment, along with an inline guide on how to use the connection in your component.

      For step-by-step instructions on using a database in your component, see Use a Database Connection in Your Component.

      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/","title":"Use a Connection in Your Service","text":"

      Choreo allows you to share and reuse your services, accelerating development and enhancing efficiency in building integrated applications through connections.

      For step-by-step on instruction on creating a connection, see Create a Connection.

      To learn more about Choreo Connections, see the documentation on Connections.

      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/#consume-a-service-through-a-connection","title":"Consume a service through a connection","text":"

      You can consume a Choreo-deployed service within another service. Consuming connections from within Choreo services is seamless and straightforward. Follow the steps below to consume a Choreo service:

      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/#step-1-add-connection-configurations","title":"Step 1: Add connection configurations Step 2: Read configurations within the application Step 2: Read configurations within the application","text":"

      To integrate another service into your application, click the appropriate tab below based on your current configuration file and follow the step-by-step instructions:

      Component.yaml file (v1.1)Component.yaml file (v1.0)Component-config.yaml file
      1. Copy and paste the snippet from the in-line developer guide into the component.yaml file.

        The following is a sample snippet:

        dependencies:\nconnectionReferences:\n- name: <CONNECTION_NAME>\nresourceRef: <RESOURCE_IDENTIFIER>\n
        Field Description name The name given to the connection. resourceRef A unique, readable identifier of the service being connected to.
      2. If you've previously added a connectionReferences section under dependencies, append this as another item under connectionReferences. Upon deploying the component, Choreo automatically creates a subscription if applicable and the necessary configurations to establish the connection will be injected into the Choreo-defined environment variables.

        The following table details the Choreo-defined environment variables:

        Configuration Key Choreo-Defined Environment Variable Name ServiceURL CHOREO_<CONNECTION_NAME>_SERVICEURL ConsumerKey CHOREO_<CONNECTION_NAME>_CONSUMERKEY ConsumerSecret CHOREO_<CONNECTION_NAME>_CONSUMERSECRET TokenURL CHOREO_<CONNECTION_NAME>_TOKENURL

        If you'd like to use custom environment variable names instead of the Choreo-defined ones, add the dependency as a service reference under dependencies in the same file. For more details, refer to the instructions under the component.yaml file (v1.0) tab.

        The following table provides details on the configuration keys associated with the connection:

        Name Type Description Optional Sensitive ServiceURL string Service URL of the Choreo service false false ConsumerKey string Consumer key of the Choreo service false false ConsumerSecret string Consumer secret of the Choreo service false true TokenURL string Token URL of the STS false false

      Note

      This component.yaml v1.0 is a legacy configuration format. For new projects, we recommend using the latest version (v1.1) of component.yaml for improved usability and features.

      1. Copy and paste the snippet from the in-line developer guide into the component.yaml file.

        The following is a sample snippet:

        dependencies:\nserviceReferences:\n- name: <SERVICE_NAME>\nconnectionConfig: <CONNECTION_ID>\nenv:\n- from: ServiceURL\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: ConsumerKey\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: ConsumerSecret\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: TokenURL\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n
        Field Description name The name of the service you are connecting to. connectionConfig The unique connection identifier for the connection. env The environment variable mapping. from The key of the configuration entry. to The environment variable name to which Choreo will inject the value of the key.
      2. Replace <YOUR_ENV_VARIABLE_NAME_HERE> with an appropriate environment variable name of your choice. If you have previously added a service reference section under dependencies, append this as another item under serviceReferences.

        Upon deploying the component, Choreo automatically creates a subscription if applicable and populates the specified environment variables with actual values.

        The following table provides details on the configuration keys associated with the connection:

        Name Type Description Optional Sensitive ServiceURL string Service URL of the Choreo service false false ConsumerKey string Consumer key of the Choreo service false false ConsumerSecret string Consumer secret of the Choreo service false true TokenURL string Token URL of the STS false false

      Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

      The following is a sample code snippet in NodeJS:

      const serviceURL = process.env.SVC_URL;\n

      Note

      This component-config.yaml is a legacy configuration format. For new projects, we recommend using the latest version (v1.1) of component.yaml for improved usability and features.

      1. Copy and paste the snippet from the in-line developer guide into the component-config file under the spec section.

        The following is a sample snippet:

        outbound:\nserviceReferences:\n- name: <SERVICE_NAME>\nconnectionConfig: <CONNECTION_ID>\nenv:\n- from: ServiceURL\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: ConsumerKey\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: ConsumerSecret\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: TokenURL\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n
        Field Description name The name of the service you are connecting to. connectionConfig The unique connection identifier for the connection. env The environment variable mapping. from The key of the configuration entry. to The environment variable name to which Choreo will inject the value of the key.
      2. Replace <YOUR_ENV_VARIABLE_NAME_HERE> with an appropriate environment variable name of your choice. If you have previously added an outbound service reference, append this as another item under serviceReferences.

        Upon deploying the component, Choreo automatically creates a subscription if applicable and populates the specified environment variables with actual values.

        The following table provides details on the configuration keys associated with the connection:

        Name Type Description Optional Sensitive ServiceURL string Service URL of the Choreo service false false ConsumerKey string Consumer key of the Choreo service false false ConsumerSecret string Consumer secret of the Choreo service false true TokenURL string Token URL of the STS false false

      Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

      The following is a sample code snippet in NodeJS:

      const serviceURL = process.env.SVC_URL;\n
      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/#step-2-read-configurations-within-the-application","title":"Step 2: Read configurations within the application","text":"

      Once you add the connection configuration snippet, you can proceed to read those configurations within your application. The steps to follow depend on the programming language you are using.

      The following is a sample code snippet in NodeJS:

      const serviceURL = process.env.CHOREO_<CONNECTION_NAME>_SERVICEURL;\n
      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/#step-3-acquire-an-oauth-20-access-token","title":"Step 3: Acquire an OAuth 2.0 access token","text":"

      To consume a Choreo service with the visibility level set to organization or public and secured by the OAuth 2.0 security scheme, you must obtain an OAuth 2.0 token from the token endpoint. Subsequently, you can use the token to invoke the service.

      • For languages with OAuth 2.0-aware HTTP clients, you must pass the OAuth 2.0-related configurations such as client id, client secret and so on, obtained when creating the connection to your HTTP client configuration. The HTTP client autonomously manages token retrieval and refreshing.

      • For languages without OAuth 2.0-aware HTTP clients, you must manually initiate a call to the token endpoint. This includes fetching the token and managing token expiration and refresh directly within your application code. The following is a sample curl command to obtain a token:

        CONSUMER_KEY=\"your_consumer_key\"\nCONSUMER_SECRET=\"your_consumer_secret\"\nTOKEN_URL=\"your_token_url\"\n# Encode client credentials as Base64\nCLIENT_CREDENTIALS=$(echo -n \"$CLIENT_ID:$CLIENT_SECRET\" | base64)\ncurl -X POST $TOKEN_URL \\\n-H \"Content-Type: application/x-www-form-urlencoded\" \\\n-H \"Authorization: Basic $CLIENT_CREDENTIALS\" \\\n--data-urlencode \"grant_type=client_credentials\"\n
      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-service/#step-4-invoke-the-service","title":"Step 4: Invoke the Service","text":"

      You can invoke the service as follows:

      • For languages with OAuth 2.0-aware HTTP clients, you can invoke the service in a straightforward manner. The HTTP client seamlessly manages OAuth 2.0 authentication without requiring additional intervention.

        As the service URL you can use the URL that you resolved in step 2. For sample requests and responses, see the API definition provided via the Choreo marketplace for the service.

      • For languages without OAuth 2.0-aware HTTP clients, you can use the token obtained in step 3 to make calls to the dependent service. Subsequently, add the obtained token to the HTTP authorization header with the bearer prefix. As the service URL you can use the URL that you resolved in step 2. For sample requests and responses, see the API definition of the service provided via the Choreo marketplace.

        The following is a sample code snippet in NodeJS:

        const response = await axios.get(serviceURL/{RESOURCE_PATH}, {\nheaders: {\n'Authorization': `Bearer ${accessToken}`\n}\n});\n

        Note

        If you want to consume a Choreo service at the project visibility level, you don't need to obtain a token. You can directly invoke the service using the resolved URL.

      "},{"location":"develop-components/sharing-and-reusing/use-a-connection-in-your-web-application/","title":"Use a Connection in Your Web Application","text":"

      Choreo simplifies the process of integrating services into your web application. The approach to connect to a service can vary based on your web application.

      To connect to a selected service, follow the step-by-step instructions given below depending on the authentication mechanism used in your web application.

      Managed authenticationCustom authentication or no authentication

      Choreo-managed authentication allows you to seamlessly handle authentication for your web application. You can configure your web application to work with the built-in identity provider of Choreo or any external identity provider that supports OIDC/OAuth2.0

      Note

      Choreo's managed authentication is currently available only for web applications created with React, Angular, or Vue.js buildpacks.

      Follow the steps below to use an existing connection within your web application:

      Step 1: Add the connection configuration

      To integrate a service into your application, you must first add the connection configuration as follows:

      1. For single page applications (SPAs), you must add the connection configuration as a file mount. You can mount a file via the Configurations pane on the Deploy page. You must mount a file (for example, config.js) and add the configuration provided in the in-line developer documentation into it.

        The following is a sample configuration:

             window.configs = {\napiUrl: '<SERVICE_URL>',        };\n
      2. To ensure accessibility of the config.js file via JavaScript at runtime, add a script tag as follows in the index.html file to reference the config.js file:

        <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<title>My React App</title>\n</head>\n<body>\n<div id=\"root\"></div>\n<script src=\"%PUBLIC_URL%/config.js\"></script>\n</body>\n</html>\n

        Note

        If you use an external IdP, you must add the IdP's configuration to the same file.

        For more information on working with IdPs, see Configure Asgardeo as an External Identity Provider.

      Step 2: Read the configuration

      Once you add the connection configuration, you can proceed to read the configuration from your application. The steps to read depend on the programming language you use.

      The following is a sample code snippet in NodeJS:

           const serviceURL = window?.configs?.apiUrl ? window.configs.apiUrl : \"/\";\n

      Step 3: Invoke the service

      If you use Choreo-managed authentication, Choreo handles the security handshaking for the application during deployment. The connected service will be accessible under the same domain as your application. Therefore, you can call the configured path directly using your preferred HTTP client.

      The following is a sample code snippet in NodeJS:

           const response = await axios.get(serviceURL/{RESOURCE_PATH});\n

      Note

      If you are using an external IdP provider instead of Choreo-managed authentication, you must obtain an access token from your IdP and add it to the HTTP authorization header with the bearer prefix.

      If you are not using Choreo-managed authentication or your web application lacks authentication, follow the steps below to connect to a service from your web application:

      Step 1: Add the connection configuration

      For single-page applications (SPAs), you must add the connection configuration as a file mount. You can mount a file via the Configurations pane on the Deploy page. You must mount a file (for example, config.js) and add the following configuration into it.

      The following is a sample configuration:

           window.configs = {\napiUrl: '<SERVICE_URL>',\nconsumerKey: '<CONSUMER_KEY>',\nconsumerSecret: '<CONSUMER_SECRET>',\ntokenUrl: '<TOKEN_URL>',\n};\n

      For other types of web applications, you must add the respective configuration into your application.

      Step 2: Read the configuration

      Once you have added the connection configuration, you can proceed to read the configuration from your application. The steps to read depend on the programming language you use.

      The following is a sample code snippet in NodeJS:

           const serviceURL = window?.configs?.apiUrl ? window.configs.apiUrl : \"/\";\n

      Step 3: Acquire an OAuth 2.0 access token

      • For languages with OAuth 2.0-aware HTTP clients, you must pass the OAuth 2.0-related configurations such as client id, client secret and so on, obtained when creating the connection to your HTTP client configuration. The HTTP client autonomously manages token retrieval and refreshing.

      • For languages without OAuth 2.0-aware HTTP clients, you must manually initiate a call to the token endpoint. This includes fetching the token and managing token expiration and refresh directly within your application code. The following is a sample curl command to obtain a token:

        CONSUMER_KEY=\"your_consumer_key\"\nCONSUMER_SECRET=\"your_consumer_secret\"\nTOKEN_URL=\"your_token_url\"\n# Encode client credentials as Base64\nCLIENT_CREDENTIALS=$(echo -n \"$CLIENT_ID:$CLIENT_SECRET\" | base64)\ncurl -X POST $TOKEN_URL \\\n-H \"Content-Type: application/x-www-form-urlencoded\" \\\n-H \"Authorization: Basic $CLIENT_CREDENTIALS\" \\\n--data-urlencode \"grant_type=client_credentials\"\n

      Step 4: Invoke the service

      You can invoke the service as follows:

      • For languages with OAuth 2.0-aware HTTP clients, you can invoke the service in a straightforward manner. The HTTP client seamlessly manages OAuth 2.0 authentication without requiring additional intervention.

        As the service URL you can use the URL that you resolved in step 2 above. For sample requests and responses, see the API definition provided via the Choreo marketplace for the service.

      • For languages without OAuth 2.0-aware HTTP clients, you can use the token obtained in step 3 above to make calls to the dependent service. Subsequently, add the obtained token to the HTTP authorization header with the bearer prefix.

        As the service URL you can use the URL that you resolved in step 2 above. For sample requests and responses, see the API definition of the service provided via the Choreo marketplace.

        The following is a sample code snippet in NodeJS:

            const response = await axios.get(serviceURL/{RESOURCE_PATH}, {\nheaders: {\n'Authorization': `Bearer ${accessToken}`\n}\n})\n
      "},{"location":"develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/","title":"Use a Database Connection in Your Component","text":"

      Choreo allows you to share and reuse Choreo-managed databases, accelerating development and enhancing efficiency in building integrated applications through connections.

      For step-by-step instructions on creating a database connection, see Create a Connection.

      To learn more about Choreo Connections, see the documentation on Connections.

      "},{"location":"develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/#consume-a-database-through-a-connection","title":"Consume a database through a connection","text":"

      To consume a Choreo-managed database via a connection, follow these steps:

      "},{"location":"develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/#step-1-add-connection-configurations","title":"Step 1: Add connection configurations","text":"
      1. Copy and paste the snippet from the inline developer guide into the component-config file under the spec section.

        The following is a sample snippet:

        outbound:\nserviceReferences:\n- name: database:hrdbProd\nconnectionConfig: 01ef700c-e378-138e-a11f-6e8e5a924f54\nenv:\n- from: HostName\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: Port\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: Username\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: Password\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n- from: DatabaseName\nto: <YOUR_ENV_VARIABLE_NAME_HERE>\n
        Field Description Name The name of the database you are connecting to. ConnectionConfig The unique connection identifier for the connection. env The environment variable mapping. from The key of the configuration entry. to The environment variable name to which Choreo will inject the value of the key.
      2. Replace <YOUR_ENV_VARIABLE_NAME_HERE> with appropriate environment variable names. If you have already added an outbound service reference, append this as another entry under serviceReferences.

        The following table provides details on the configuration keys associated with the connection:

        Name Type Description Optional Sensitive HostName string The hostname of the database server where the database resides. false false Port string The port number on which the database server listens for connections. false false Username string The username for database access. false false Password string The password for database access. false true DatabaseName string The name of the database to connect. false false
      "},{"location":"develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/#step-2-read-configurations-within-the-application","title":"Step 2: Read configurations within the application","text":"

      Once you add the connection configuration snippet, you can read the configurations within your application. The steps to follow depend on the programming language you are using.

      The following is a sample code snippet in JavaScript:

      const hostName = process.env.HOST_NAME;\n
      "},{"location":"develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/#step-3-initiate-a-database-connection","title":"Step 3: Initiate a database connection","text":"

      To initiate a connection to the database, follow these steps:

      In this example, you will connect to a MySQL database.

      Step 3.1: Install the required packages

      For the MySQL database, install the mysql2 package using npm:

      // Install the mysql2 package\nnpm install mysql2\n
      Step 3.2: Import required packages
      const client = require('mysql2')\n
      Step 3.3: Establish a connection

      To establish the connection, use the environment variables for hostName, username, password, databaseName, and port as follows:

      var connection = client.createConnection({\nhost: hostName,\nuser: username,\npassword: password,\ndatabase: databaseName,\nport: port\n});\nconnection.connect((err) => {\nif (err) {\nreturn;\n}\n// Connection is successful\n});\n
      By following these steps, your component can interact with the Choreo-managed database seamlessly.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/","title":"Configure Container Resources, Commands, and Arguments","text":"

      In Choreo, you can view detailed information about the container that comprises a component, such as its image tag, the corresponding commit ID, any imposed resource usage limits, and so on.

      Each component in Choreo is limited to a single main container.

      Resource Limits

      Resource limits ensure that a single component does not take up more resources than it requires, which can affect other workloads on the data plane. If a process exceeds the allocated memory limit, the corresponding container will be forcefully shut down and restarted. If the process exceeds the allocated CPU limit, it gets throttled and can result in significant latencies in compute and I/O operations.

      Choreo allows you to edit the default container configuration depending on your requirement.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/#update-container-configurations","title":"Update container configurations","text":"

      Follow these steps to update container configurations:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to edit container configurations.
      3. In the left navigation menu, click DevOps and then click Containers.
      4. On the Containers page, click Edit to update the corresponding container configuration.
      5. Apply the necessary changes and click Save.

      The following topics walk you through the container configuration changes you can apply.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/#update-resource-requests-and-limits","title":"Update resource requests and limits","text":"

      Note

      The capability to update resource requests and limits is only available in paid pricing plans.

      To update resource requests and limits, move the corresponding slider to a required position. A resource request cannot be less than its corresponding limit.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/#set-the-image-pull-policy","title":"Set the image pull policy","text":"

      You can select one of the following options as the image pull policy.

      • Always: The image is always pulled from the container registry, even if a matching tag is already present in the data plane.
      • If Not Present - The image is pulled from the container registry only if a matching image is not present in the data plane.

        Tip

        The recommended option is If Not Present.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/#specify-container-ports","title":"Specify container ports","text":"

      You can specify appropriate values for the Container Port and Service Port. The Service Port is the port exposed outside of the container to your project-scoped endpoint. If you do not know the value to specify as the Service Port, specify the Container Port value in both fields.

      Tip

      You do not need to configure port values manually for Ballerina components. The capability to edit port values is primarily for containerized/Dockerfile-based components.

      You can also select an appropriate Protocol.

      "},{"location":"devops-and-ci-cd/configure-container-resources-commands-and-arguments/#define-a-command-and-arguments-for-the-container","title":"Define a command and arguments for the container","text":"

      You can define a command and arguments for a container when you want to provide or override the ENTRYPOINT of a container. For example, in a scenario where you want to run legacy or third-party applications, you would want to provide or override the ENTRYPOINT of a container.

      When you define a command and arguments,

      • It specifies the ENTRYPOINT array and it is not executed within a shell.
      • Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged.
      • $$ are reduced to $, which allows escaping the $(VAR_NAME) syntax. This means that \"$$(VAR_NAME)\" produces the string literal \"$(VAR_NAME)\".
      • Escaped references are never expanded, regardless of whether the variable exists or not.

      The ENTRYPOINT of the container image is used if you do not define a command and arguments for the container.

      "},{"location":"devops-and-ci-cd/configure-storage/","title":"Configure Storage","text":"

      All components you create in Choreo have a default read-only file system, which you cannot access or write to from your applications.

      Volume mounts allow you to create either temporary or persisted writable file system storage locations for your applications.

      "},{"location":"devops-and-ci-cd/configure-storage/#volume-mount-types","title":"Volume mount types","text":"Type Description Empty Directory (In-Memory) A fast, temporary in-memory (tmpfs) storage location. This volume gets erased when you restart or remove the attached container. Available on all data planes. Empty Directory (Disk) A temporary storage location on disk. This volume gets destroyed when you restart or remove the attached container. Only available on private data planes. Persistent Volume A permanent storage location. This volume persists even if you restart or remove the attached container. Only available on private data planes.

      Tip

      All components have a writable location in the /tmp directory at the time of component creation. You can also configure other writable locations if required.

      "},{"location":"devops-and-ci-cd/configure-storage/#create-a-temporary-storage-space-for-your-container","title":"Create a temporary storage space for your container","text":"

      Empty directory (in-memory or on-disk) mounts allow you to create temporary file systems that your application can read from and write to. This option provides a convenient way to create a scratch space to write files temporarily before storing them in a more permanent storage location such as a cloud-backed storage bucket. For example, unzipping a file, temporarily writing results from a memory-intensive operation to disk, a temporary local cache, etc. However, it is important to note that these volumes destroy when you restart or update a container because the volumes are attached to the lifetime of a container.

      Follow these steps to create a temporary storage space for your container:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to create a temporary storage.
      3. In the left navigation menu, click DevOps and then click Storage.
      4. Click + Create.
      5. In the Create a Volume Mount pane, specify a name for the volume and select Empty Directory (In-Memory).

      1. Click Next.

        In-memory (tmpfs) storage uses up container memory

        Storage capacity for this type of volume will count against the container's memory limit. Uncontrolled writes to this location may starve your application process of memory and can result in the container getting killed and restarted if the memory limits exceed.

      2. To add a mount location, specify a Mount Path and click Add mount.

        Tip

        • You can add multiple mount locations to a volume.
        • Mount paths should be absolute file paths and will be available to your application to read/write from.

      3. Click Create. This applies the volume mount immediately to your container and triggers a rolling restart.

      "},{"location":"devops-and-ci-cd/configure-storage/#create-a-persistent-storage-space-for-your-container","title":"Create a persistent storage space for your container","text":"

      Follow these steps to create a persistent storage space for your container:

      Note

      Persistent volume options are only available in private data plane organizations.

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to create a persistent storage.
      3. In the left navigation menu, click DevOps and then click Storage.
      4. Click + Create.
      5. In the Create a Volume Mount pane, specify a name for the volume and select Persistent Volume.
      6. Select a Storage Class.
      7. Move the Storage Capacity slider to set the required capacity.
      8. Select an appropriate Access Mode.

        Check and specify an access mode supported by the storage class

        • You must check the cloud provider documentation to select an appropriate access mode that the storage class supports. Choreo does not verify whether the storage class supports the access mode you select.
        • If the storage class does not support the access mode you select, it can result in a runtime mount error.

      9. Click Next.

      10. To add a mount location, specify a Mount Path and click Add mount.

        Tip

        • You can add multiple mount locations to a volume.
        • Mount paths should be absolute file paths and will be available to your application to read/write from.
      11. Click Create. This applies the volume immediately to your container.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/","title":"Configure VPNs on the Choreo Cloud Data Plane","text":"

      Secure access to private networks from the Choreo cloud data plane is an essential use case for cloud data plane users.

      Choreo allows this secure connection using Tailscale. For this, Choreo provides a prebuilt Tailscale image component that can act as a forward proxy, which you can deploy in your Choreo project as a service. This service allows you to forward traffic to your external networks via Tailscale\u2019s peer-to-peer WireGuard network.

      The following diagram illustrates the high-level deployment architecture of the Tailscale pre-installed forward proxy:

      Let's take a look at the specifics of each part to understand the deployment architecture.

      • Choreo project

        In Choreo, a project groups various components. For more information on what a project in Choreo is, see the documentation on Project.

      • Tailscale proxy

        This acts as the Tailscale pre-installed forward proxy, facilitating secure peer-to-peer WireGuard connections from the Choreo cloud data plane to private networks. It includes a Tailscale Daemon, SOCKS5 proxy, and a configurable TCP forwarder.

        • Tailscale daemon

          This is the core component of Tailscale. It is a software service that provides secure network connectivity and private networking solutions. For more details see the Tailscale documentation.

        • SOCKS5 proxy

          This uses Tailscale\u2019s userspace networking mode, rather than the kernel mode. Therefore, the inbuilt SOCKS5 proxy handles the forwarded traffic and directs it through the Tailscale network.

        • TCP forwarder

          Forwards inbound TCP (transmission control protocol) traffic from the Tailscale proxy container\u2019s network interface to the SOCKS5 proxy, ensuring it reaches its destination via the secured WireGuard tunnel.

      • User applications and the Choreo API gateway

        User applications within the same namespace (project) can use the Kubernetes service created to front the Tailscale proxy, for connecting to the corresponding private endpoints. You can either expose this service within the organization via the internal API gateway or expose it to the public via the external API gateway. For more details, see the documentation on Choreo endpoints.

      Now that you understand the deployment architecture, let\u2019s explore how you can use Tailscale to secure connections to your private networks.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#configure-and-use-tailscale-to-access-private-network-endpoints","title":"Configure and use Tailscale to access private network endpoints","text":"

      This section walks you through the steps to create, configure, deploy, and use the Tailscale proxy component.

      Let's get started.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#prerequisites","title":"Prerequisites","text":"
      • Understand the basics of how Tailscale works.
      • Have a Tailscale account (Tailnet). There are multiple plans available for you to set up your Tailscale network. For details, see Tailscale plans.
      • Install Tailscale and connect your private data center or server to it, so that your private services are accessible via your Tailscale network. To quickly get started with Tailscale, see the Tailscale quickstart.
      • If you are signing in to the Choreo Console for the first time, create an organization as follows:

        1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
        2. Enter a unique organization name. For example, Stark Industries.
        3. Read and accept the privacy policy and terms of use.
        4. Click Create.

        This creates the organization and opens the organization home page.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#step-1-create-the-tailscale-proxy","title":"Step 1: Create the Tailscale proxy","text":"Step 1.1: Create a project

      Follow the steps given below to create a project:

      1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
      2. On the organization home page, click + Create Project.
      3. Enter a display name, unique name, and description for the project. You can enter the values given below:

        Info

        In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

        Field Value Project Display Name Tailscale Proxy Project Name tailscale-proxy-project Project Description My Tailscale project
      4. Click Create. This creates the project and takes you to the project home page.

      Step 1.2: Create the Tailscale proxy component
      1. On the project home page, click Service under Create a Component.
      2. Enter a display name, component name, and a description for the service. For this guide, let's enter the following values:

        Field Value Component Display Name Tailscale proxy Component Name tailscale-proxy Description Tailscale proxy component
      3. Click the Container Registry tab.

      4. In the Container Registry list, select Choreo Samples Registry.
      5. Click the Tailscale Proxy card.
      6. Click Create.

      Now you have successfully created the Tailscale proxy. You can proceed to configure and deploy it.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#step-2-configure-and-deploy-the-tailscale-proxy","title":"Step 2: Configure and deploy the Tailscale proxy","text":"

      Here, you will add the required volume mounts, set the Tailscale authentication key, configure the TCP forwarder, configure endpoints, and deploy the Tailscale proxy. Follow the steps given below:

      Step 2.1: Add required volume mounts

      Tailscale requires the following volume mounts for its operations:

      • /var/run/tailscale
      • /.local

      To create the volume mounts, follow the step-by-step instructions in Configure Storage.

      Step 2.2: Configure and deploy the component

      To configure and deploy the component, follow the steps given below:

      1. In the left navigation menu, click Deploy.
      2. On the Build Area card, click Configure & Deploy.
      3. In the Environment Configurations pane that opens, click + Add and add the TS_AUTH_KEY environment variable as a secret. To add the environment variable, you must obtain an authentication key from your Tailscale network.
        • For details on how to obtain an authentication key from your Tailscale network, see Auth keys in the Tailscale documentation.
      4. Click Next.
      5. In the File Mount pane that opens, click + Add.
      6. To mount a configuration file to the Tailscale proxy component and specify the port mapping for the TCP forward proxy running there, do the following:

        1. Specify /config.yaml as the Mount Path.
        2. Specify the following in the sample configuration file:

          portMappings:\n    8080: \"100.108.78.93:8090\"\n    8081: \"100.108.78.93:1433\"\n

          Note

          In this sample configuration, the TCP traffic arriving at port 8080 on your Tailscale proxy will be forwarded to port 8090 on the node with IP address 100.108.78.93 in your Tailscale network. Similarly, port 8081 will map to the corresponding address. You can find the IP addresses of your nodes on the Tailscale machines page in your Tailscale network's admin console or via the Tailscale clients running on your machine.

      7. Click Next.

      8. In the Endpoints pane that opens, click + Add and edit the endpoints.yaml configuration to expose your Tailscale proxy as a service. The following is a sample endpoints.yaml configuration you can use:

        Note

        The sample endpoints.yaml file given below defines two project-level endpoints. These endpoints can be used by other components within the same project to access the services. If you want to directly expose your private endpoint via the Choreo gateway either with the Public or Organization visibility, you can set the networkVisibility property of the endpoint to Public or Organization.

        version: 0.1\nendpoints:\n- name: Private HTTP service\nport: 8080\ntype: REST\nnetworkVisibility: Project\ncontext: /\n- name: Private DB service\nport: 8081\ntype: TCP\nnetworkVisibility: Project\ncontext: /\n
      9. Click Save.

      10. Click Next and then click Deploy.

        Note

        Deploying the component may take a while. You can track the progress by observing the logs. Once the deployment is complete, the build status changes to Active on the Development environment card.

      When the component is deployed, you can observe a new node connected to your Tailscale network. To view this, go to the Tailscale machines page of your Tailscale coordination server.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#step-3-access-private-network-endpoints-with-the-tailscale-proxy","title":"Step 3: Access private network endpoints with the Tailscale proxy","text":"

      Now you have successfully deployed the Tailscale proxy in your project and it is connected to your Tailnet. You can proceed to use the Tailscale proxy to provision access for other components to securely access private network endpoints.

      You can configure endpoints of the Tailscale proxy to use it for various aspects within Choreo.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#post-deployment-actions","title":"Post-deployment actions","text":""},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#handle-node-key-expiry","title":"Handle node key expiry","text":"

      Tailscale nodes have a default node key expiry time of 180 days. Nodes require re-authentication after key expiry to avoid connection losses and application downtime. There is an option to disable node key expiry if necessary. For more details, see Node key expiry documentation.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#handle-auth-key-expiry","title":"Handle auth key expiry","text":"

      Auth keys are used to register new nodes into your Tailscale network. The default expiry time for auth keys is 90 days, but nodes remain connected even after auth key expiry. This becomes an issue only if the Tailscale Proxy component is redeployed or restarted.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#update-port-mapping-configurations","title":"Update port mapping configurations","text":"

      If you want to add a new private endpoint to your network and access it via the same Tailscale proxy within Choreo, you must add a new port mapping entry in the port mapping configuration of your Tailscale proxy deployment.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#best-practices","title":"Best practices","text":""},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#configure-health-checks","title":"Configure health checks","text":"

      Since the Tailscale proxy acts as a forward proxy, it is important to configure health checks. You can use one of the open ports of the TCP forwarder as a health endpoint. For details on how to set up health probes in Choreo, see Set up health checks.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#use-tailscale-acls","title":"Use Tailscale ACLs","text":"

      You can use Tailscale ACLs to precisely manage permission for users and devices on your Tailnet.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#disable-scale-to-zero-for-the-tailscale-proxy","title":"Disable scale-to-zero for the Tailscale proxy","text":"

      It is recommended to disable Scale-to-Zero for the Tailscale proxy because it acts as a forward proxy and should always be up and running to make consistent connections with the Tailscale VPN mesh. If you enable Scale-to-Zero, you may experience service downtime.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#run-multiple-replicas-with-hpa-horizontal-pod-autoscaler","title":"Run multiple replicas with HPA (horizontal pod autoscaler)","text":"

      To achieve high availability and resiliency for the Tailscale proxy, you must run multiple replicas with HPA. To configure multiple replicas for the Tailscale proxy component, go to the Scaling page under DevOps. For more details, see Autoscale component replicas

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#security-best-practices","title":"Security best practices","text":"

      Before deploying the Tailscale proxy in production environments, it is recommended to follow the Tailscale production best practices and security best practices.

      Note

      Choreo blocks incoming connections from other nodes in your Tailnet to the Tailscale proxy to prevent access to your project\u2019s namespace in the Choreo cloud data plane.

      "},{"location":"devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/#troubleshoot-issues","title":"Troubleshoot issues","text":"

      For assistance in resolving common Tailscale proxy issues, see Troubleshoot Tailscale proxy issues.

      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/","title":"Manage Configurations and Secrets","text":"

      Choreo allows you to easily manage and version your component's configurations and secrets as file mounts or environment variables.

      Note

      All configurations and secrets applied to a Choreo component are stored in an encrypted secret vault in the cloud data plane, which is managed by WSO2. If you are on a private data plane, the configurations and secrets are stored in an Azure key vault or AWS secret manager attached to your data plane in your cloud environment.

      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#the-difference-between-configurations-and-secrets","title":"The difference between configurations and secrets","text":"

      Choreo considers all configurations and secrets to be sensitive content when storing them, but gives you the option to choose between secret or configuration when you create a file mount or an environment variable.

      • Secrets are write-only. Once you create a secret, you cannot see or retrieve its content via the Choreo Console. However, you can overwrite the existing content at any time.
      • Configurations can be read and updated via the Choreo Console after you create them.

        Note

        If you want to include sensitive data such as database passwords, cloud credentials, service accounts, and so on, the recommended approach is to use a secret instead of a configuration.

      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#apply-a-file-mount-to-your-container","title":"Apply a file mount to your container","text":"

      Follow these steps to apply a file mount to a component you have created:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to define configurations and secrets.
      3. In the left navigation menu, click DevOps and then click Configs & Secrets.
      4. Click + Create.
      5. In the Create a Config or Secret pane, click File Mount.
      6. If you want to create the file mount as a secret, select Mark as a Secret. Otherwise, proceed to the next step.

        Note

        If you create the file mount as a secret, you will not be able to read the file content after you create the file mount.

      7. In the Display Name field, specify a name for the file mount.

        Tip

        The display name does not affect the file mount or its content. It is only a reference to identify the configuration or secret you create.

      8. In the File Mount Path field, specify where to mount the file inside the container. Use an absolute file path with the file name and extension if applicable.

        Tip

        The file name in the mount path does not need to match the configuration name or the name of the file you upload.

      9. Upload a configuration file or copy and paste the configuration content into the editor.

      10. Click Create.

        Note

        Configurations and secrets are applied immediately to your environment on creation. To ensure that the container reflects the new content, your existing running replicas undergo a rolling restart.

      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#apply-environment-variables-to-your-container","title":"Apply environment variables to your container","text":"

      Follow these steps to apply environment variables to a component you have created:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to define configurations and secrets.
      3. In the left navigation menu, click DevOps and then click Configs & Secrets.
      4. Click + Create.
      5. In the Create a Config or Secret pane, click Environment Variables.
      6. If you want to create the environment variable values as secrets, select Mark as a Secret. Otherwise, proceed to the next step.

        Note

        If you create environment variables as secrets, you will not be able to read the values you set for the environment variables after you create them.

      7. In the Display Name field, specify a name to identify the configuration or secret.

        Tip

        The display name you specify does not affect the environment variables you set. It is only a reference to identify the configuration or secret you create.

      8. Under Add Environment Variables, specify the necessary environment variables as key-value pairs. You can click Add Item to add any number of environment variables.

      9. Click Create.

      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#update-an-existing-configuration-or-secret","title":"Update an existing configuration or secret","text":"

      Follow these steps to update a configuration or secret you have defined:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to update configurations and secrets.
      3. In the left navigation menu, click DevOps and then click Configs & Secrets.
      4. Click the edit icon corresponding to the configuration or secret you want to update.
      5. Apply the necessary changes and click Save.
      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#delete-an-existing-configuration-or-secret","title":"Delete an existing configuration or secret","text":"

      Follow these steps to delete a configuration or secret you have defined:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to delete configurations and secrets.
      3. In the left navigation menu, click DevOps and then click Configs & Secrets.
      4. Click the delete icon corresponding to the configuration or secret you want to delete.
      5. Enter the name of the configuration or secret to confirm deletion.
      6. Click Delete.
      "},{"location":"devops-and-ci-cd/manage-configurations-and-secrets/#manage-ballerina-configurables","title":"Manage Ballerina configurables","text":"

      Choreo manages the Ballerina configurables for the Ballerina components you create.

      When you deploy or promote a Ballerina application, you can modify the Ballerina configurables via the Deploy page.

      Tip

      You can use configurables instead of environment variables to add file mounts to a Ballerina component. Environment variables are primarily for components written in other languages.

      "},{"location":"devops-and-ci-cd/manage-environments/","title":"Manage Environments","text":"

      By default, all projects created in the cloud data planes (irrespective of the data plane region) are provisioned with two environments (i.e., development and production).

      The environments are listed in the order of deployment and promotion. The initial deployment takes place in the first environment and you can proceed to promote a component to subsequent environments.

      "},{"location":"devops-and-ci-cd/manage-environments/#create-a-new-environment","title":"Create a new environment","text":""},{"location":"devops-and-ci-cd/manage-environments/#prerequisites","title":"Prerequisites","text":"
      • To create additional environments, you must have a Choreo subscription or a private data plane.
      • To create a new environment in a private data plane organization, you must have the ENVIRONMENT-MANAGEMENT permission. By default, ENVIRONMENT-MANAGEMENT permission is granted to Admin and Choreo DevOps roles.

      To create a new environment, follow the steps given below:

      1. Sign in to the Choreo Console and switch to the organization where you want to create a new project.
      2. In the left navigation menu, click DevOps and then click Environments (note that this is the Environments page under your organization, not your projects).
      3. On the Environments page, click Create and specify the following details to create a new environment:

        • Name: A display name for the new environment.
        • Data Plane - The data plane to create the new environment.

          Tip

          The Data Plane list displays all the private data planes registered under your organization.

        • DNS Prefix: A DNS prefix to identify the exposed APIs in the environment. Here, the base domain depends on the custom domain attached to the API gateways provisioned on the selected data plane.

        • Mark environment as a Production environment: Select if you want this environment to be a production environment.

          Tip

          In Choreo, you can have multiple non-production and production environments. To work in a production environment, you must have privileged permissions to access and deploy to production environments.

      "},{"location":"devops-and-ci-cd/manage-environments/#change-the-order-of-promotion","title":"Change the order of promotion","text":"

      The order in which environments are listed on the Environments page is the same order in which promotion takes place.

      To change the order of promotion across environments in an organization, follow the steps given below:

      1. Sign in to the Choreo Console and switch to the organization for which you want to change the order of promotion.
      2. In the left navigation menu, click DevOps and then click Environments.
      3. On the Environments page, click and drag environment list items to rearrange the order of listed environments.

        Note

        Although changes to the order of promotion for environments are applied immediately, the change does not affect the components already running in environments. Only subsequent builds and promotions will follow the new order.

      To see the changes, go to the Deploy page of a component (in any project).

      "},{"location":"devops-and-ci-cd/manage-environments/#delete-an-environment","title":"Delete an environment","text":"

      To delete an environment, follow the steps given below:

      Warning

      Environment deletion is a permanent, non-reversible operation.

      1. Sign in to the Choreo Console and switch to your organization.
      2. In the left navigation menu, click DevOps and then click Environments.
      3. In the Environments list, click the delete icon corresponding to the environment you want to delete. This displays a confirmation dialog with details on the impact of deletion.
      4. Review the details, then type the environment name to confirm the deletion.
      5. Click Delete.
      "},{"location":"devops-and-ci-cd/set-up-health-checks/","title":"Set Up Health Checks","text":"

      Health checks ensure that a running container is always healthy and ready to serve traffic.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#liveness-probes","title":"Liveness probes","text":"

      Liveness probes run periodically on your container and restart if the probe fails. This allows the container to self-heal in scenarios where the application may have crashed or become unresponsive.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#readiness-probes","title":"Readiness probes","text":"

      Similar to liveness probes, readiness probes run periodically throughout the lifecycle of a container. However, unlike liveness probes, these probes do not restart the container if the probe fails. Instead, they stop the container from receiving network traffic.

      Readiness probes on single replicas

      You must be mindful when you configure readiness probes on a single-running replica. If the readiness probe fails, your application stops receiving traffic because there is only one active replica. The application may not recover unless the liveness probe fails and restarts the container.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#probe-types","title":"Probe types","text":"

      You can configure the following probe types for both readiness and liveness probes.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#http-get-request","title":"HTTP GET request","text":"

      This probe sends an HTTP GET request to a specified port and path on the container. A response status code in the range of 200-399 indicates that the request is a success.

      Depending on your requirement, you can configure additional HTTP headers.

      The recommended approach is to create a /healthz or /health endpoint in your service for this purpose.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#tcp-connection-probe","title":"TCP connection probe","text":"

      This probe attempts to open a socket to the container on the specified port. If it cannot establish a TCP connection, it becomes a failure.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#execute-a-command","title":"Execute a command","text":"

      This probe executes a given script inside the container. A non-zero return from the command is considered a failure.

      For example, [\"cat\", \"/tmp/healthy\"] is considered healthy if the file /tmp/healthy is present. If not, it becomes a failure (non-zero exit code). In such scenarios, the application is responsible for writing and maintaining this file in the specified location.

      "},{"location":"devops-and-ci-cd/set-up-health-checks/#configure-liveness-and-readiness-probes","title":"Configure liveness and readiness probes","text":"

      Follow these steps to configure liveness and readiness probes on a container:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to configure liveness and readiness probes.
      3. In the left navigation menu, click DevOps and then click Health Checks.
      4. On the Health Checks page, click + Create.
      5. Configure the liveness probe depending on your requirement.

      6. Click Save.

      7. Configure the readiness probe depending on your requirement.
      8. Click Save.

        Note

        You can update or remove a probe at any time.

      Follow these steps to ensure that the container works as expected:

      1. In the left navigation menu, click Runtime under DevOps.
      2. On the Runtime page, check the details to confirm that the container works as expected. If the container does not start, check the events and conditions to see if any of the probes are causing the container to fail.
      "},{"location":"devops-and-ci-cd/view-runtime-details/","title":"View Runtime Details","text":"

      In Choreo, you can view details about running replicas of a component in a specific environment (i.e., Development or Production).

      To view the runtime details of a component, follow the steps given below:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component for which you want to view runtime details.
      3. In the left navigation menu, click DevOps and then click Runtime. This opens the Runtime page populated with data retrieved from the underlying Choreo data plane.

      The runtime details you can see here are analogous to a zoomed-in view of a specific environment on the Deploy page.

      The following topics walk you through the specific details you can view and actions you can perform via the Runtime page.

      "},{"location":"devops-and-ci-cd/view-runtime-details/#redeploy-a-release","title":"Redeploy a release","text":"

      On the Runtime page, you can click Redeploy Release to immediately redeploy all resources, including configurations and secrets, to a specific environment. This triggers a rolling update to sync all the latest changes to the data plane.

      What is a release?

      A release in Choreo uniquely identifies an underlying deployment of a component to an environment for a given version. For example, if you deploy a component to two environments across two versions, the component will have four active releases.

      The capability to redeploy a release also allows you to quickly restart all the running replicas of a component in a specific environment.

      "},{"location":"devops-and-ci-cd/view-runtime-details/#view-running-instances","title":"View running instances","text":"

      The running instances you see on the Runtime page provide insights into the active replicas of your component in the selected environment.

      • You can view details of each active replica and its associated real-time CPU and memory usage, status, restarts, and the time of the last activity.
      • If you want to see the real-time logs and information on conditions and events of a replica, click the menu icon of the replica and then click Real-time Logs or Conditions & Events depending on what you need to view. These options provide insights that help to diagnose issues in deployments.

        Note

        • All metrics such as the total and replica-level CPU and memory usage displayed on the Runtime page are real-time data and are instantaneous representations of a component's current state.
        • You can take a look at the observability metrics of a component to see historical data and usage trends.
      "},{"location":"devops-and-ci-cd/view-runtime-details/#observe-real-time-container-logs","title":"Observe real-time container logs","text":"

      Unlike the logs available in the Observability Metrics of a component, these logs are fetched in real-time from the data plane and are not historical. Therefore, you can only see logs of active containers and the last shutdown container.

      • Display Previous Logs: Enable to retrieve logs from the last shutdown/crashed/restarted container of an instance.
      • Since Seconds: Specify the duration in seconds to fetch corresponding logs.
      • Filter Logs: Enable to filter and displays matching log lines. This is a fuzzy string search.
      "},{"location":"devops-and-ci-cd/view-runtime-details/#view-container-conditions-and-events","title":"View container conditions and events","text":"

      Conditions and events provide information necessary to troubleshoot failing deployments.

      If a component is not behaving as expected and you cannot detect any issues via the application logs, these events can provide necessary debugging information, such as the following:

      • Failing health checks (liveness and readiness probes).
      • Missing or invalid configuration/secret mounts.
      • Missing or invalid storage volume mounts.
      • Scheduling issues in the underlying data plane.
      "},{"location":"devops-and-ci-cd/autoscale/autoscale-component-replicas/","title":"Autoscale Component Replicas","text":"

      Choreo allows you to automatically scale your component replicas up or down in number based on resource consumption to ensure high availability.

      Note

      Autoscaling capabilities are only available in paid plans for private data plane organizations. In the free tier, components run in a single-replica, low-availability mode.

      The following parameters allow you to scale component replicas:

      • Min replicas: The minimum number of replicas to run at any given time. It is recommended to keep the value at a minimum of 2.
      • Max replicas: The maximum number of replicas to scale up to. In the cloud data plane, this is restricted to a maximum of 5. There is no restriction on the value in private data planes.
      • CPU Threshold: The average CPU utilization across all running replicas. If the CPU utilization across all active instances reaches the threshold, the number of active replicas automatically scales up until the average CPU utilization falls below the threshold.
      • Memory Threshold: The average memory usage across all running replicas. Like the CPU Threshold, if all active instances reach the memory threshold, the number of active replicas automatically scales up until the average memory usage falls below the threshold.

      Tip

      If you update a scaling parameter, it may not immediately reflect in the Choreo Console because the change can take some time to propagate.

      Run a fixed number of replicas

      If you want to run exactly 3 replicas for a component, you must set the minimum and maximum replicas to 3.

      Scale to zero

      • Although it is possible to set the minimum number of replicas to 0, your component does not scale to zero automatically during low usage. It can only go down to 1 replica.
      • Setting both the minimum and maximum replicas to 0 suspends the deployment.
      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/","title":"Autoscale Components with Scale-to-Zero","text":"

      Choreo provides the scale-to-zero capability for HTTP applications you deploy in the data plane. This lets you run your components in a serverless mode.

      Scale to zero is very useful in lower environments, where you can significantly reduce infrastructure costs by scaling down idle workloads. In production environments, you can also use scale-to-zero capability if your application's behavior aligns with this feature behavior. In the paid tier, if you want to run your application with more guaranteed high availability, it is recommended to choose HPA (Horizontal Pod Autoscaler) scaling method and configure a minimum replica count of 2 or higher.

      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/#how-scale-to-zero-works-in-choreo","title":"How Scale to Zero works in Choreo","text":"

      Info

      For service components and web-apps you create after February 23, 2024, Choreo enables the scale-to-zero feature by default.

      When Scale to Zero is enabled, your apps will automatically scale down to zero unless they receive HTTP traffic. When the application receives an HTTP request, your workload quickly scales up from zero to handle the request. When a new request is received by the deployment, the deployment will scale up to one replica and serve the request. When the deployment remains idle for a set period (approximately 5 minutes), it will automatically scale back to zero until a new request is received.

      When Scale to Zero is enabled, you can set the maximum number of replicas for deployments with this capability. Choreo dynamically scales deployments up to meet high HTTP traffic demand, up to the specified number of replicas. If the pending requests surpass the defined threshold under Number of pending requests to spawn a new pod, Choreo automatically adds a new replica to handle the increased load.

      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/#enable-scale-to-zero","title":"Enable scale to zero","text":"

      For service components and web-apps you create after February 23, 2024, Choreo enables the scale-to-zero feature by default. When deploying or promoting the component, the deployment will automatically scale-to-zero. Upon the next request to the deployed service, a replica will be created to serve the request.

      Note

      • For the services which contain at least one endpoint with the network visibility as Project, Choreo will not automatically scale-to-zero those components when you deploy or promote them.
      • HTTP services that run on a port other than the below list of ports will not automatically scale-to-zero your component when deploying or promoting: 5000, 6000, 7000, 8000, 9000, 7070 to 7079, 8080 to 8089, and 9090 to 9099 or 8290.

      To enable scale-to-zero for service components created before February 23, 2024, follow the steps given below:

      1. Sign in to the Choreo Console.
      2. In the Component Listing pane, click on the component you want to scale-to-zero.
      3. Make sure the component is deployed to an environment and is ready to receive traffic.
      4. In the left navigation menu, click DevOps and then click Scaling.

        • If you are a free user, you will see a view similar to the one below. You can click the scale-to-zero card to enable scale-to-zero for your component.

        • If you are a paid user or you are running your applications in your own private data plane, you will see a view similar to the one below. You can click the scale-to-zero card to enable scale-to-zero for your component.

        Note

        The scale-to-zero service should start within 60 seconds. If it doesn\u2019t, the gateway will timeout the request.

      You can independently scale Choreo components in both the Development and Production environments. The deployment card indicates the scaling status of each environment. To configure the scale-to-zero feature for a specific environment, click on the scale-to-zero link, which redirects to the Devops \u2192 Scaling page.

      When you turn on the scale-to-zero for your application, the minimum replicas for your app will be set to zero. However, you can still select an appropriate maximum number of replicas.

      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/#limitations","title":"Limitations","text":"
      • The scale-to-zero feature currently exclusively supports web applications and HTTP services. TCP and HTTPS services are not supported to be scaled to zero.
      • To scale to zero, your HTTP service must run on one of the specified ports: 5000, 6000, 7000, 8000, 9000, 7070 to 7079, 8080 to 8089, and 9090 to 9099 or 8290. If you have an endpoint in your component running in any other port, your component will not automatically scale-to-zero when deploying or promoting. Also, if you try to switch to the \u201cscale-to-zero\u201d option in the \u201cDevops\u201d \u2192 \u201cScaling\u201d view, it will fail.
      • Scheduled tasks and manually triggered components cannot connect to a service on a project scope if scale-to-zero is enabled. Attempting to do so results in the following error:

        Host not found, not forwarding request.

        To allow a task-type component to invoke a project-level service, set it to HPA mode if you are on a paid plan, or to no scaling if you are on the Developer plan.

      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/#architecture","title":"Architecture","text":"

      When your Choreo application scales down to zero, an intermediary proxy service intercepts incoming requests. If a request is directed at your application, this service initiates a scale-up. Requests are held in the proxy's queue until your application becomes active. After scaling up, the proxy forwards the queued requests to your application.

      If your application remains without HTTP traffic for an extended period (default idle time is 5 minutes), it will be scaled down to zero until more HTTP requests arrive. Conversely, if there's a surge in HTTP traffic to your scaled-up application, Choreo will further increase its scale to manage the demand. Choreo considers adding additional replicas if the number of queued requests surpasses the 'Target Pending Requests' threshold, which is set to 100 by default. You can adjust this threshold in the user interface.

      Note

      The initial request after a long period of inactivity experiences a delay because the application must first scale up from zero. If your API operates in a service-chain sequence (e.g., service-1 activates service-2, which in turn calls service-3), this waiting time may extend further. If your application or its chain takes a considerable time to scale up, be aware that the first request might face a timeout.

      "},{"location":"devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/#troubleshooting","title":"Troubleshooting","text":"

      When Choreo enables scale-to-zero by default, it will configure the readiness probe with some default values. However, in some cases, you may observe that your first request responds with a 503 status code. To overcome these behaviors, fine-tune the readiness probe in the DevOps \u2192 Health Checks view to match your application's needs.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/","title":"Integrate and Manage Generative AI Services","text":"

      Generative AI (GenAI) services leverage advanced machine learning models to create original content such as text, images, music, or code, by identifying and learning patterns from existing data. Powered by deep neural networks and other machine learning models, these services can generate human-like outputs in various formats. This versatility makes GenAI ideal for tasks such as content creation, image generation, conversation automation, etc.

      Choreo enables seamless integration with GenAI services, allowing you to incorporate these capabilities within your applications.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#register-a-genai-service","title":"Register a GenAI service","text":"

      To use a GenAI service in Choreo, you need to register it. Once registered, the service becomes available in the Internal Marketplace, allowing you to consume it via a Connection.

      You can register a GenAI service at two levels:

      • Organization level: This makes the service accessible from any project within the organization.
      • Project level: This restricts the service to a specific project.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#prerequisites","title":"Prerequisites","text":"

      Before registering a GenAI service, obtain the following details from the service provider: - API key. - Service URL. - Other necessary parameters. For example, client credentials.

      To register a GenAI service, follow these steps:

      Note

      Ensure that you register the service at the appropriate level depending on the usage. If the service must be shared among multiple projects, register it at the organization level. Otherwise, register it at the project level.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#step-1-select-a-service-provider","title":"Step 1: Select a service provider","text":"
      1. Sign in to the Choreo Console.
      2. Follow one of these steps depending on your requirements:
        • To register a GenAI service at the organization level, go to the Choreo Console header and select your organization from the Organization list.
        • To register a GenAI service at the project level, go to the Choreo Console header and select your project from the Project list.
      3. In the left navigation menu, click Dependencies and then click GenAI Services.
      4. Click + Register.
      5. Select a service provider.
      6. Click Next.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#step-2-provide-service-details","title":"Step 2: Provide service details","text":"
      1. Under Register Service, enter the following details for the service:

        • A Name and Version.
        • The Service URL.
      2. Click Next.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#step-3-add-configurations","title":"Step 3: Add configurations","text":"
      1. Under Add Configurations, enter details for the service. !!! note - The configuration details to enter vary depending on the selected service provider. - To successfully register a service, ensure you provide all the required configurations.

      2. Click Register.

      Once registered, the GenAI service is automatically listed in the Internal Marketplace.

      If you want to remove the service from the Internal Marketplace, see Remove a GenAI service from the Internal Marketplace.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#discover-genai-services","title":"Discover GenAI services","text":"

      The GenAI services you register are discoverable via the Internal Marketplace for you to consume via a Connection.

      For details on consuming a GenAI service via a connection, see Create a Connection.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#manage-genai-services","title":"Manage GenAI services","text":"

      When you create a GenAI service, it gets listed in the GenAI Services list.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#view-or-update-genai-service-details","title":"View or update GenAI service details","text":"

      To view or update a GenAI service, follow these steps.

      1. Sign in to the Choreo Console.
      2. In the left navigation menu, click Dependencies and then click GenAI Services. This lists all the GenAI services you have created.
      3. Click on a service to view or update its details.
        • General Details: Displays service metadata. For example, the service name, overview, labels, etc.
        • Service Definition: Displays the service definition. To update the definition, click Upload and select the new definition file.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#add-a-genai-service-to-the-internal-marketplace","title":"Add a GenAI service to the Internal Marketplace","text":"

      Info

      To add a GenAI service to the Internal Marketplace, you must provide all the required configurations.

      1. In the Choreo Console left navigation menu, click Dependencies and then click GenAI Services.
      2. Click on the service you want to add to the Internal Marketplace.
      3. Click Add to Marketplace.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/#remove-a-genai-service-from-the-internal-marketplace","title":"Remove a GenAI service from the Internal Marketplace","text":"
      1. In the Choreo Console left navigation menu, click Dependencies and then click GenAI Services.
      2. Click on the service you want to remove from the Internal Marketplace.
      3. Click Remove from Marketplace.

      This removes the service from the Internal Marketplace. Therefore, the service will not be available to consume via a Connection. However, the connections created before removal will continue to work as expected.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/","title":"Integrate and Manage Third-Party Services","text":"

      Third-party services are external applications, platforms, or APIs you can integrate with your system to enhance its functionality, extend capabilities, or provide specialized features. These services are developed and maintained by external entities, providing expertise in specific domains outside your application's core focus.

      The following topics walk you through the steps to seamlessly register, manage, and consume third-party services, adhering to API-first principles.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#register-a-third-party-service-in-choreo","title":"Register a third-party service in Choreo","text":"

      To use a third-party service in Choreo, you need to register it. Once registered, the service becomes available in the Internal Marketplace, allowing you to consume it via a Connection.

      You can register a third-party service at two levels:

      • Organization level: This makes the service accessible from any project within the organization.
      • Project level: This restricts the service to a specific project.

      Choreo allows you to register the following third-party service types:

      • REST APIs
      • GraphQL APIs
      • Asynchronous APIs
      • SOAP
      • gRPC
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#prerequisites","title":"Prerequisites","text":"

      Before registering a third-party service, obtain the following details from the service provider:

      • API specification. For example, OpenAPI or GraphQL schema.
      • Service URL.
      • Other necessary parameters. For example, client credentials, API keys, etc.

      To register a third-party service, follow these steps:

      Note

      Ensure you register the service at an appropriate level depending on the service usage. If the service must be shared among multiple projects, register it at the organization level. Otherwise, register it at the project level.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#step-1-provide-basic-details","title":"Step 1: Provide basic details","text":"
      1. Sign in to the Choreo Console.
      2. Follow one of these steps depending on your requirement:
        • To register a third-party service at the organization level, go to the Choreo Console header and select your organization from the Organization list.
        • To register a third-party service at the project level, go to the Choreo Console header and select your project from the Project list.
      3. In the left navigation menu, click Dependencies and then click Third-Party Services.
      4. Click + Register.
      5. Provide details for the service:
        • Enter a Name and Version.
        • Upload the service definition file. This automatically detects the service type.
        • Verify the Service Type.
      6. Click Define Endpoints.

      Now you are ready to define endpoints for the service.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#step-2-define-service-endpoints","title":"Step 2: Define service endpoints","text":"

      An endpoint is a set of parameters required to connect to a service. The required parameters are service URL, API key header, etc. These parameters provide the necessary information for a client application to interact with the service.

      To define service endpoints, follow these steps:

      1. Under Define New Endpoint,

        • Enter a Name for the endpoint.
        • Enter the Endpoint URL.
      2. Under Additional Parameters, add any other parameters required to connect to the service. For example, API key, authorization token, etc.

        Note

        • If you want to keep a parameter confidential,\u00a0select the Secret\u00a0checkbox.
        • If there are multiple endpoints, the parameter names will be the same for all the endpoints.
      3. Select the environments where the endpoint should be accessible.

        Note

        Service consumers can create connections to the endpoint only from the selected environments.

      4. Click OK.

      5. If you want to add more endpoints, click + New Endpoint and repeat steps 1 to 4.

      6. Click Register.

      When you define all required parameter values for at least one endpoint, the service will be automatically listed in the Internal Marketplace. Otherwise, you must add the service to the Internal Marketplace after providing the endpoint values.

      If you want to remove a third-party service from the Internal Marketplace, see Remove a third-party service from the Internal Marketplace.

      For details on managing third-party services, see Manage third-party service.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#discover-third-party-services","title":"Discover third-party services","text":"

      The third-party services you register are discoverable via the Internal Marketplace to consume via a Connection.

      For details on consuming a third-party service via a connection, see Create a Connection.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#manage-third-party-services","title":"Manage third-party services","text":"

      When you create a third-party service, it gets listed in the Third-Party Services list.

      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#view-or-update-third-party-service-details","title":"View or update third-party service details","text":"

      To view or update a third-party service, follow these steps.

      1. Sign in to the Choreo Console.
      2. In the left navigation menu, click Dependencies and then click Third-Party Services. This lists all the third-party services you have created.
      3. Click on a service to view or update its details.
        • General Details: Displays service metadata. For example, the service name, overview, labels, etc.
        • Service Definition: Displays the service definition. To update the definition, click Upload and select the new definition file.
        • Endpoints: Displays service endpoint details. You can add, modify, or delete service endpoints.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#add-a-third-party-service-to-the-internal-marketplace","title":"Add a third-party service to the Internal Marketplace","text":"

      Info

      To add a third-party service to the Internal Marketplace, you must provide all required parameters for at least one endpoint.

      1. In the Choreo Console left navigation menu, click Dependencies and then click Third-Party Services.
      2. Click on the service you want to add to the Internal Marketplace.
      3. Click Add to Marketplace.
      "},{"location":"integrate-and-manage-external-services/integrate-and-manage-third-party-services/#remove-a-third-party-service-from-the-internal-marketplace","title":"Remove a third-party service from the Internal Marketplace","text":"
      1. In the Choreo Console left navigation menu, click Dependencies and then click Third-Party Services.
      2. Click on the service you want to remove from the Internal Marketplace.
      3. Click Remove from Marketplace.

      This removes the service from the Internal Marketplace. Therefore, the service will not be available to consume via a Connection. However, the connections created before removal will continue to work as expected.

      "},{"location":"manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/","title":"Add Choreo-Managed Databases and Caches to the Marketplace","text":"

      When you create a Choreo-managed database or cache, you can add it to the Marketplace, making it available for consumption through a connection.

      Note

      To add a Choreo-managed database or cache to the Marketplace, you must register at least one credential for it.

      "},{"location":"manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/#step-1-register-credentials","title":"Step 1: Register credentials","text":"

      When you create a database or cache server, you get super admin credentials by default. You can use these credentials to create new user credentials. The steps to create new user credentials depend on the type of database or cache you are using.

      You can register either the default super admin credentials or any custom credentials you create using the super admin credentials.

      To register credentials for a database, follow these steps:

      1. Sign in to the Choreo Console.
      2. Go to the Choreo Console header and select your organization from the Organization list.
      3. In the left navigation menu, click Dependencies and then click Databases.
      4. Click on a required database to view its details.
      5. Click the Databases tab.
      6. Click to expand the database for which you want to register credentials, then click Add Credentials.
      7. In the Add Credentials dialog, do one of the following depending on your requirements:
        • If you want to use the custom credentials you created using the super admin credentials, select Add New Credentials and specify appropriate values for each field.
        • If you want to use the default super admin credentials, select Add Super Admin Credentials and specify appropriate values for each field.
      8. Click Save.

      Tip

      Choreo allows you to delete registered credentials to prevent their use when establishing new connections. However, deleting credentials will not affect any existing database connections that are already using them.

      "},{"location":"manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/#step-2-add-the-database-or-cache-to-the-marketplace","title":"Step 2: Add the database or cache to the Marketplace","text":"
      • On the Databases tab, click +Add to Marketplace corresponding to the database you want to add.

      Once the database is added to the Marketplace, it can be consumed via a connection. For details on creating a connection to a Choreo-managed database, see Create a connection to a database.

      Note

      To remove a database or cache that you added to the Marketplace, click the corresponding Remove from Marketplace. This action prevents new connections to the removed database, but existing connections remain unaffected.

      For details on using a database connection in your component, see Use a Database Connection in Your Component.

      "},{"location":"manage-databases-and-caches/billing-for-platform-services/","title":"Billing for Platform Services (Databases and Caches)","text":"

      Any platform services you create within your Choreo Organization will be included in your current Choreo subscription. The quantity included will vary depending on the service plan of the resources you create.

      A few important considerations:

      • Usage is billed hourly. If you create a database that you later remove within the same month, you will only be charged for the hours during which it was active.
      • Fixed pricing based on service plans. Choreo does not charge extra for network bandwidth usage.

      Try out the free trial

      Choreo provides a 7 day free trial for all database types on the 'Hobbyist' service plan (for free tier users).

      "},{"location":"manage-databases-and-caches/choreo-managed-caches/","title":"Choreo-Managed Cache","text":"

      Fully compatible with legacy Redis\u00ae OSS.

      Choreo-Managed Cache provides fully-managed in-memory NoSQL databases on AWS, Azure, GCP, and Digital Ocean and can be used as a cache, database, streaming engine, or message broker.

      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#create-a-choreo-managed-cache","title":"Create a Choreo-Managed Cache","text":"

      Follow the steps below to create a Choreo-Managed Cache:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then click Databases.
      4. Click + Create and select Choreo-Managed Cache as the data store type. Provide a display name for this server and follow the instructions.
      5. Select a preferred cloud provider (AWS, Azure, GCP, or Digital Ocean).
        • The cloud provider provisions the compute and storage infrastructure for your data store.
        • The functionality remains the same across cloud providers, though service plans and costs may differ.
      6. Select a region for your data store.
        • Available regions depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
      7. Select a service plan.
        • Service plans vary in terms of dedicated CPU, memory (RAM), and storage space allocated for your data store, as well as high-availability configurations for production use cases.
      8. Click Create.
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#connect-to-your-choreo-managed-cache","title":"Connect to your Choreo-Managed Cache","text":"

      To connect to your Choreo-Managed Cache, follow these guidelines:

      • Use any legacy Redis\u00ae OSS compatible driver (in any programming language) to connect to your Choreo-Managed Cache.
      • You can find the connection parameters in the Overview section in the Choreo Console under the relevant database. Note that Choreo-Managed Cache enforces TLS.
      • Choreo-Managed Cache instances accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#high-availability-and-automatic-backups","title":"High availability and automatic backups","text":"

      The high availability and the automatic backup retention periods for a Choreo-Managed Cache can vary as follows depending on the service plan you select.

      Service plan High availability Backup features Backup history Hobbyist Single-node with limited availability. Single backup only for disaster recovery None Startup Single-node with limited availability. Single backup only for disaster recovery 1 day Business Two-node (primary + standby) with higher availability (automatic failover if the primary node fails). Automatic backups 3 days Premium Three-node (primary + standby + standby) with highest availability (automatic failover if the primary node fails). Automatic backups 13 days

      In general, service plans are recommended for production scenarios due to the following reasons:

      • Provides another physical copy of the data in case of hardware, software, or network failures.
      • Reduces the data loss window in disaster scenarios.
      • Ensures quicker restoration with controlled failover in case of failures, as the standby is already installed and running.
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#automatic-backups","title":"Automatic backups","text":"
      • Choreo runs full backups daily to automatically backup Choreo-Managed Caches and has write-ahead logs (WAL) copied at 5-minute intervals or for every new file generated.
      • Choreo encrypts all backups at rest.
      • Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the data store.
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#failure-recovery","title":"Failure recovery","text":"
      • Minor failures: Choreo automatically handles minor failures such as service process crashes or temporary loss of network access in all plans without requiring significant changes to the service deployment. Choreo automatically restores the service to normal operation once it automatically restarts the crashed process or when it restores the network access.

      • Severe failures: Failures such as losing a node entirely in case of hardware or severe software problems, require more drastic recovery measures. The monitoring infrastructure automatically detects a failing node when the node starts reporting issues in the self-diagnostics or when it stops communicating. In such cases, the monitoring infrastructure automatically schedules a new replacement node to be created.

        • In the event of a data store failover, the service URI of your service remains the same; only the IP address will change to point to the new primary node.
        • Hobbyist and Startup plans provide a single node, and in case of failure, a new node starts up, restores its state from the latest available backup, and resumes serving traffic.
        • As there is just a single/primary node, the caching service becomes unavailable for the duration of the restoration operation. Therefore, all write operations made since the last backup will be lost.
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#limitations","title":"Limitations","text":""},{"location":"manage-databases-and-caches/choreo-managed-caches/#connection-limits","title":"Connection limits","text":"

      The number of simultaneous connections in a Choreo-Managed Cache depends on the total available memory on the server instances.

      You can use the following to estimate:

      max_number_of_connections = 4 x m\n

      Here, m represents the memory in megabytes, where at least 10,000 connections are available, even on the smallest servers. For example, on a server with 4GB memory (4,096 MB), the simultaneous connections are:

      4 x 4096 = 16384 // 16k connections\n

      This number is estimated by the exact available memory so it can vary between different plans and cloud providers. To see the exact maximum connections allowed, use the * redis-cli and info command as follows:

      echo \"info\" | redis-cli -u REDIS_URI | grep maxclients\n
      "},{"location":"manage-databases-and-caches/choreo-managed-caches/#restricted-commands","title":"Restricted commands","text":"

      To maintain the stability and security of a managed environment, Choreo restricts certain commands on Choreo-Managed Cache services.

      Support for Lua scripts on Choreo-Managed Cache

      • Choreo-Managed Cache has built-in support for running Lua scripts to perform various actions directly on the server. Scripting is typically controlled using the EVAL, EVALSHA, and SCRIPT LOAD commands.
      • For all newly-created cache instances, EVAL, EVALSHA, and SCRIPT LOAD commands are enabled by default.

      The following commands are disabled on Choreo:

      • bgrewriteaof: Initiates a background append-only file rewrite.
      • cluster: Manages Caching cluster commands.
      • command: Provides details about all Caching commands.
      • debug: Contains sub-commands for debugging Caching.
      • failover: Manages manual failover of a master to a replica.
      • migrate: Atomically transfers a key from one caching instance to another.
      • role: Returns the role of the instance in the context of replication.
      • slaveof: Makes the server a replica of another instance, or promotes it as master.
      • acl: Manages caching access control lists.
      • bgsave: Creates a snapshot of the data set into a dump file.
      • config: Alters the configuration of a running caching server.
      • lastsave: Returns the UNIX timestamp of the last successful save to disk.
      • monitor: Streams back every command processed by the Caching server.
      • replicaof: Makes the server a replica of another instance.
      • save: Synchronously saves the dataset to disk.
      • shutdown: Synchronously saves the dataset to disk and then shuts down the server.

      The following eval commands are also disabled:

      • eval: Executes a Lua script server-side.
      • eval_ro: Read-only variant of the eval command.
      • evalsha: Executes a script cached on the server side by its SHA1 digest.
      • evalsha_ro: Read-only variant of the evalsha command.
      • fcall: Calls a Caching function.
      • fcall_ro: Read-only variant of the fcall command.
      • function: Manages Caching functions.
      • script: Manages the script cache.
      "},{"location":"manage-databases-and-caches/choreo-managed-databases-and-caches/","title":"Choreo-Managed Databases, Vector Databases, and Caches","text":"

      Choreo allows you to create PostgreSQL and MySQL databases as well as Choreo-Managed Cache instances on all major cloud providers (AWS, Azure, GCP, and DigitalOcean) as fully Choreo-managed platform services. These databases and caches can be seamlessly provisioned to offer persistence and caching capabilities for all your Choreo components. Choreo provides various service plans for each type, ranging from smaller instances for development purposes to production-grade databases with automatic backups and high-availability multi-nodes.

      "},{"location":"manage-databases-and-caches/choreo-managed-databases-and-caches/#postgresql-on-choreo","title":"PostgreSQL on Choreo","text":"

      PostgreSQL (also known as Postgres), is an open-source object-relational database management system. You can create PostgreSQL databases on Choreo as fully Choreo-managed, flexible SQL databases that are ideal for both structured and unstructured data. If you want to perform an efficient vector similarity search, you can create a PostgreSQL vector database.

      • Create a PostgreSQL database on Choreo
      "},{"location":"manage-databases-and-caches/choreo-managed-databases-and-caches/#mysql-on-choreo","title":"MySQL on Choreo","text":"

      MySQL is a user-friendly, flexible, open-source relational database management system with a well-established history in the SQL database realm. Choreo allows you to swiftly create fully Choreo-managed MySQL databases, enabling rapid setup and utilization.

      • Create a MySQL database on Choreo
      "},{"location":"manage-databases-and-caches/choreo-managed-databases-and-caches/#choreo-managed-cache","title":"Choreo-Managed Cache","text":"

      A fully-managed cache compatible with legacy Redis\u00ae OSS. A versatile, in-memory NoSQL database that serves as a cache, database, streaming engine, and message broker. Choreo-managed Cache allows you to have fully-managed instances that can be swiftly provisioned and integrated into your applications within minutes.

      • Create a Choreo-managed Cache

      PostgreSQL, MySQL, and Redis\u00ae are trademarks and property of their respective owners. All product and service names used in this documentation are for identification purposes only.

      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/","title":"Choreo-managed MySQL Databases","text":"

      MySQL on Choreo offers fully managed, flexible relational databases on AWS, Azure, GCP, and Digital Ocean.

      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#create-a-choreo-managed-mysql-database","title":"Create a Choreo-managed MySQL database","text":"

      Follow the steps below to create a Choreo-managed MySQL database:

      1. From the environment list on the header, located next to the Deployment Tracks list, select your Organization.
      2. In the left navigation menu, click Dependencies and then Databases.
      3. Click Create and select MySQL as the database type. Provide a display name for this server and follow the instructions.
      4. Select your preferred cloud provider from AWS, Azure, GCP, and Digital Ocean.
      5. Choreo uses the cloud provider to provision the compute and storage infrastructure for your database.
      6. There is no functional difference between databases created on different cloud providers, apart from changes to service plans (and associated costs).
      7. Choose the region for your database.
      8. Available regions will depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
      9. Select the service plan.
      10. Service plans vary in the dedicated CPU, memory (RAM), storage space allocated for your database, the backup retention periods, and high-availability configurations for production use cases.
      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#connect-to-your-choreo-managed-mysql-database","title":"Connect to your Choreo-managed MySQL database","text":"

      To connect to your Choreo-managed MySQL database, consider the following guidelines:

      • You can use any MySQL driver, ORM, or supported generic SQL library (may depend on the programming language) to connect to the database.
      • You can find the connection parameters in the Overview section in the Choreo Console under the relevant database.
      • MySQL databases accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#high-availability-and-automatic-backups","title":"High Availability and Automatic Backups","text":"

      The high availability characteristics and the automatic backup retention periods for Choreo-managed MySQL databases vary based on your service plan as explained below:

      Service Plan High Availability Backup Retention Time Hobbyist Single-node with limited availability None Startup Single-node with limited availability 2 days Business Two-node (primary + standby) with higher availability 14 days Premium Three-node (primary + standby + standby) with highest availability 30 days

      In general, we recommend service plans for production scenarios for multiple reasons: - Provides another physical copy of the data in case of hardware, software, or network failures. - Typically reduces the data loss window in disaster scenarios. - Provides a quicker time to restore with a controlled failover in case of failures, as the standby is already installed and running.

      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#automatic-backups","title":"Automatic Backups","text":"
      • Choreo runs full backups daily to automatically back up Choreo-managed MySQL databases and record binary logs continuously. Choreo encrypts all backups at rest.

      • Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the database.

      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#connection-limits","title":"Connection Limits","text":"

      The maximum number of simultaneous connections to MySQL databases is fixed for each service plan and depends on how much RAM your service plan offers.

      Note

      An extra_connection with a value of 1 is added for system processes for all MySQL databases, regardless of the service plan.

      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#for-plans-under-4-gib-ram","title":"For plans under 4 GiB RAM","text":"

      For plans under 4 GiB of RAM, the number of allowed connections is 75 per GiB:

      max_connections = 75 x RAM + extra_connection\n
      "},{"location":"manage-databases-and-caches/choreo-managed-mysql-databases/#for-plans-with-over-4-gib-ram","title":"For plans with over 4 GiB RAM:","text":"

      For plans with 4 GiB or more RAM, the number of allowed connections is 100 per GiB:

      max_connections = 100 x RAM + extra_connection\n
      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/","title":"Choreo-Managed PostgreSQL Databases and Vector Databases","text":"

      PostgreSQL on Choreo offers fully Choreo-managed, efficient object-relational databases on AWS, Azure, GCP, and Digital Ocean. Additionally, Choreo allows you to create fully-managed PostgreSQL vector databases if you want to perform efficient vector similarity search.

      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#create-a-choreo-managed-postgresql-database","title":"Create a Choreo-managed PostgreSQL database","text":"

      Follow the steps below to create a Choreo-managed PostgreSQL database:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then Databases.
      4. Click Create and select PostgreSQL as the database type. Provide a display name for this server and follow the instructions.
      5. Select your preferred cloud provider from AWS, Azure, GCP, or Digital Ocean.
        • The cloud provider is used to provision the compute and storage infrastructure for your database.
        • There is no functional difference between databases created on different cloud providers, apart from changes to service plans (and associated costs).
      6. Choose the region for your database.
      7. Available regions will depend on the selected cloud provider. Choreo currently supports US and EU regions across all providers.
      8. Select the service plan.
      9. Service plans vary in the dedicated CPU, memory (RAM), storage space allocated for your database, the backup retention periods, and high-availability configurations for production use cases.
      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#create-a-choreo-managed-postgresql-vector-database","title":"Create a Choreo-managed PostgreSQL vector database","text":"

      Follow the steps below to create a Choreo-managed PostgreSQL vector database:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then Vector\u00a0Databases.
      4. Follow steps 4 onwards in the Create a Choreo-managed PostgreSQL database section.
      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#connecting-to-your-choreo-managed-postgresql-database","title":"Connecting to your Choreo-managed PostgreSQL database","text":"

      To connect to your Choreo-managed PostgreSQL database, consider the following guidelines:

      • You can use any PostgreSQL driver, ORM, or supported generic SQL library (may depend on the programming language) to connect to the database.
      • The connection parameters can be found in the Overview section in the Choreo Console under the relevant database.
      • PostgreSQL databases accept traffic from the internet by default. You can restrict access to specific IP addresses and CIDR blocks under Advanced Settings.
      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#high-availability-and-automatic-backups","title":"High Availability and Automatic Backups","text":"

      The high availability characteristics and the automatic backup retention periods for Choreo-managed PostgreSQL databases vary based on the selected service plan as shown below.

      Service Plan High Availability Backup Retention Time Hobbyist Single-node with limited availability None Startup Single-node with limited availability 2 days Business Two-node (primary + standby) with higher availability 14 days Premium Three-node (primary + standby + standby) with highest availability 30 days

      Service plans with standby nodes are generally recommended for production scenarios for multiple reasons: - Provides another physical copy of the data in case of hardware, software, or network failures. - Typically reduces the data loss window in disaster scenarios. - Provides a quicker time to restore with a controlled failover in case of failures, as the standby is already installed and running.

      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#automatic-backups","title":"Automatic Backups","text":"
      • Choreo runs full backups daily to automatically back up Choreo-managed PostgreSQL databases and copies the write-ahead logs (WAL) at 5-minute intervals or for every new file generated. Choreo encrypts all backups at rest.

      • Choreo automatically handles outages and software failures by replacing broken nodes with new ones that resume correctly from the point of failure. The impact of a failure will depend on the number of available standby nodes in the database.

      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#failure-recovery","title":"Failure Recovery","text":"
      • Minor failures: Choreo automatically handles minor failures such as service process crashes or temporary loss of network access in all plans without requiring significant changes to the service deployment. Choreo automatically restores the service to normal operation once Choreo automatically restarts the crashed process or when Choreo restores the network access.

      • Severe failures: To handle severe failures such as losing a node entirely in case of hardware or severe software problems, requires more drastic recovery measures. The monitoring infrastructure automatically detects a failing node, both when the node starts reporting issues in the self-diagnostics or when it stops communicating. In such cases, the monitoring infrastructure automatically schedules a new replacement node to be created.

        • In the event of database failover, the Service URI of your service remains the same; only the IP address will change to point to the new primary node.
        • Hobbyist and Startup plan provide a single node, and in case of failure, a new node starts up, restores its state from the latest available backup, and resumes serving traffic. In this plan, as there is just a single node providing the service, the service will become unavailable for the duration of the restoration. In addition, any write operations made since the backup of the latest WAL file will be lost. Typically, this time window is limited to either five minutes of time or one WAL file.
      "},{"location":"manage-databases-and-caches/choreo-managed-postgresql-databases/#connection-limits","title":"Connection limits","text":"

      The following connection limits apply to Choreo-managed PostgreSQL databases based on the selected service plan.

      Service Plan Max Connections Hobbyist 25 Startup/Business/Premium-4 100 Business-16 400 Premium-8 200"},{"location":"manage-message-brokers/choreo-managed-message-brokers/","title":"Choreo Managed Message Brokers","text":"

      Choreo allows you to create Apache Kafka services across major cloud providers (AWS, Azure, GCP, and DigitalOcean) as Choreo-managed platform services for your message brokering needs. These fully managed Kafka instances can seamlessly integrate with Choreo components, providing scalable messaging for real-time data pipelines and event-driven applications. Choreo offers multiple Kafka service plans, ranging from lightweight instances for development purposes to production-grade clusters with automatic backups, high-availability multi-nodes, and partitioning.

      Note

      • Kafka service creation is available only for paid Choreo users.
      • Kafka service billing will be included in your Choreo subscription, with pricing varying based on the service plan of the resources you create. For more details, see Choreo Platform Services Billing.
      "},{"location":"manage-message-brokers/choreo-managed-message-brokers/#apache-kafka-on-choreo","title":"Apache Kafka on Choreo","text":"

      Apache Kafka is an open-source platform for real-time event streaming and handling large-scale, event-driven data. You can create Kafka services on Choreo as fully-managed, scalable, message brokers, ideal for handling large volumes of event-driven data.

      • Create a Choreo-managed Kafka service
      "},{"location":"manage-message-brokers/configure-a-kafka-service/","title":"Configure a Kafka Service","text":"

      After creating a Kafka service, you can create topics, configure advanced settings, and manage access to ensure secure and efficient message processing.

      "},{"location":"manage-message-brokers/configure-a-kafka-service/#create-a-kafka-topic","title":"Create a Kafka topic","text":"

      Kafka topics are logical channels used to organize and transfer messages between producers and consumers. They form the core of Kafka's architecture, enabling data streams to be written and read. Kafka topics can also be partitioned to improve scalability and fault tolerance.

      To create a Kafka topic, follow these steps:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then click Message Brokers.
      4. In the Message Brokers list, click the Kafka service for which you want to create a topic.
      5. Click the Topics tab.
      6. Click + Create.
      7. In the Create Topic dialog that opens,
      8. Enter a name for the topic.
      9. To configure advanced settings, click to expand Advanced Configurations and apply the required settings. For details, see Advanced topic configurations.
      10. Click Create.
      "},{"location":"manage-message-brokers/configure-a-kafka-service/#advanced-topic-configurations","title":"Advanced topic configurations","text":"

      Choreo allows you to customize settings for Kafka topics, including the number of partitions, replication factor, cleanup policy, retention size (bytes), retention duration (hours), and the minimum number of in-sync replicas.

      Cleanup Policy: Determines how messages that reach their retention limit are handled. There are three options:

      • Delete (default): Messages are removed when the retention limit is exceeded.
      • Compact: Retains only the latest record for each unique key, ensuring only the most recent data is kept.
      • Compact and Delete: Combines both approaches, where old records are deleted based on retention limits, but the latest record for each key is retained.

      Replication: Sets the number of partition copies to ensure data durability. The default is 3.

      Partitions: Defines the number of segments the topic should be divided into for parallel processing. The default is 1 partition.

      Retention Bytes: Sets the maximum size of retained messages. Older messages are discarded on reaching this limit. The default is unlimited (-1).

      Retention Hours: Defines the retention period for messages before deletion. The default is 168 hours (7 days).

      Min In-Sync Replicas: Specifies the minimum number of replicas that must acknowledge a write for it to be considered successful. The default is 2.

      "},{"location":"manage-message-brokers/configure-a-kafka-service/#manage-service-users-and-access-control-lists","title":"Manage service users and access control lists","text":"

      Choreo-managed Kafka services use access control lists (ACLs) and user definitions to control access to topics. You can manage users and ACL entries from the corresponding tabs on the Kafka service details page.

      "},{"location":"manage-message-brokers/configure-a-kafka-service/#manage-users","title":"Manage users","text":"

      To manage users for a Choreo-managed Kafka service, follow these steps:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then click Message Brokers.
      4. In the Message Brokers list, click the Kafka service for which you want to manage users.
      5. Click the Users tab.
      6. Click + Add User, specify a username, and then click Add.

      By default, new users do not have any permissions. You can grant necessary permissions to users through access control lists (ACLs).

      "},{"location":"manage-message-brokers/configure-a-kafka-service/#configure-access-control-lists-acls","title":"Configure access control lists (ACLs)","text":"

      An ACL entry defines access permission for a user. Each entry includes:

      • Username: The username.
      • Topic: The associated Kafka topic to grant access to the user.
      • Permission: The permission to grant the user.

      To add an ACL entry, follow these steps:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then click Message Brokers.
      4. In the Message Brokers list, click the Kafka service for which you want to add an ACL entry.
      5. Click the Access Control List tab.
      6. Click + Add Entry, select a username, topic, and permission.
      7. Click Add.
      "},{"location":"manage-message-brokers/create-choreo-managed-kafka-services/","title":"Create Choreo-Managed Kafka Services","text":"

      Kafka on Choreo offers fully managed, distributed message broker services across AWS, Azure, GCP, and DigitalOcean. These services are designed to handle high-throughput, fault-tolerant data streaming use cases such as real-time analytics, event sourcing, and log aggregation.

      Note

      • Kafka service creation is available only for paid Choreo users.
      • Kafka service billing will be included in your Choreo subscription, with pricing varying based on the service plan of the resources you create. For more details, see Choreo Platform Services Billing.
      "},{"location":"manage-message-brokers/create-choreo-managed-kafka-services/#create-a-choreo-managed-kafka-service","title":"Create a Choreo-managed Kafka service","text":"

      Follow the steps below to create a Choreo-managed Kafka service:

      1. Sign in to the Choreo Console at https://console.choreo.dev/.
      2. In the header, click the Organization list. This opens the organization home page.
      3. In the left navigation menu, click Dependencies and then click Message Brokers.
      4. Click + Create.
      5. Specify a display name for the Kafka service and click Next.
      6. Select your preferred cloud provider from AWS, Azure, GCP, or Digital Ocean.
        • The cloud provider provisions the computing and storage infrastructure for your Kafka service.
        • There is no functional difference between Kafka services across providers except for variations in service plans and associated costs.
      7. Select a region for your Kafka service.
        • Available regions depend on the selected cloud provider. Choreo currently supports US, EU, and AU regions across all providers.
      8. Select a service plan.
        • Service plans differ based on the allocation of CPU, memory (RAM), and storage for your Kafka server, as well as backup retention periods and high-availability options suited for production environments.
      9. Click Create. This creates the Kafka service and takes you to the Overview tab on the service details page.
      "},{"location":"manage-message-brokers/create-choreo-managed-kafka-services/#connect-to-your-choreo-managed-kafka-service","title":"Connect to your Choreo-managed Kafka service","text":"

      To connect to your Choreo-managed Kafka service, use the connection parameters from the Overview tab on the service details page. Choreo secures Kafka connections via client certificate authentication.

      To use the Kafka service with producer and consumer applications, you must configure them with the provided credentials and connection parameters.

      By default, Kafka services accept traffic from the internet. However, if you want to restrict access to specific IP addresses or CIDR blocks, you can configure the necessary advanced settings.

      To use the Kafka service in producer and consumer applications, you must add the required parameters as configurations and secrets in Choreo. You can obtain the parameter values from the Overview tab on the service details page and include key configurations such as the access key, access certificate, CA certificate, and service URI. Ensure you create a topic before producing or consuming Kafka messages. If a topic already exists, you can proceed.

      "},{"location":"manage-message-brokers/create-choreo-managed-kafka-services/#set-up-configurations-and-secrets","title":"Set up configurations and secrets","text":"

      Follow these steps to set up required configurations and secrets:

      1. Create two Choreo components. One for the producer and another for the consumer application. For a producer and consumer implementation in Go, see sample implementation
      2. Define the required configurations and secrets at the component level for each. You can configure the service.key, service.cert, and ca.pem using file mounts. The following sample implementation uses a file mount for the CA certificate. You can follow the same approach for the other files.

      3. Set other configurations, such as TOPIC_NAME and SERVICE_URI as environment variables. You can define these as shown in the following sample implementation.

      "},{"location":"manage-message-brokers/create-choreo-managed-kafka-services/#sample-implementation","title":"Sample implementation","text":"ProducerConsumer
          package main\n\n    import (\n        \"context\"\n        \"crypto/tls\"\n        \"crypto/x509\"\n        \"fmt\"\n        \"log\"\n        \"os\"\n        \"time\"\n\n        \"github.com/segmentio/kafka-go\"\n    )\n\n    // loadPEMFromFile reads a PEM file from the specified file path.\n    func loadPEMFromFile(filePath string) ([]byte, error) {\n        data, err := os.ReadFile(filePath)\n        if err != nil {\n            return nil, fmt.Errorf(\"failed to read file %s: %w\", filePath, err)\n        }\n        return data, nil\n    }\n\n    // loadCertificates loads the necessary certificates for TLS configuration.\n    func loadCertificates() (tls.Certificate, *x509.CertPool, error) {\n        serviceCert, err := loadPEMFromFile(\"/service.cert\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load service cert: %v\", err)\n        }\n\n        serviceKey, err := loadPEMFromFile(\"/service.key\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load service key: %v\", err)\n        }\n\n        caCert, err := loadPEMFromFile(\"/ca.pem\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load ca cert: %v\", err)\n        }\n\n        keypair, err := tls.X509KeyPair(serviceCert, serviceKey)\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load key and cert: %v\", err)\n        }\n\n        caCertPool := x509.NewCertPool()\n        if !caCertPool.AppendCertsFromPEM(caCert) {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to append ca cert\")\n        }\n\n        return keypair, caCertPool, nil\n    }\n\n    // createKafkaDialer initializes a Kafka dialer with the provided certificates and CA pool.\n    func createKafkaDialer(keypair tls.Certificate, caCertPool *x509.CertPool) *kafka.Dialer {\n        return &kafka.Dialer{\n            Timeout:   10 * time.Second,\n            DualStack: true,\n            TLS: &tls.Config{\n                Certificates: []tls.Certificate{keypair},\n                RootCAs:      caCertPool,\n            },\n        }\n    }\n\n    // setupKafkaProducer initializes and returns a Kafka producer.\n    func setupKafkaProducer(dialer *kafka.Dialer, serviceURI, topicName string) *kafka.Writer {\n        return kafka.NewWriter(kafka.WriterConfig{\n            Brokers: []string{serviceURI},\n            Topic:   topicName,\n            Dialer:  dialer,\n        })\n    }\n\n    // sendMessages sends a specified number of messages to the Kafka topic.\n    func sendMessages(producer *kafka.Writer, count int) {\n        for i := 0; i < count; i++ {\n            message := fmt.Sprintf(\"Hello from Go using SSL %d!\", i+1)\n            err := producer.WriteMessages(context.Background(), kafka.Message{Value: []byte(message)})\n            if err != nil {\n                log.Printf(\"failed to send message: %v\", err)\n            } else {\n                log.Printf(\"message sent: %s\", message)\n            }\n            time.Sleep(time.Second)\n        }\n    }\n\n    func main() {\n        // Load environment variables\n        serviceURI := os.Getenv(\"SERVICE_URI\")\n        if serviceURI == \"\" {\n            log.Fatalln(\"service uri is not set\")\n        }\n\n        topicName := os.Getenv(\"TOPIC_NAME\")\n        if topicName == \"\" {\n            log.Fatalln(\"topic name is not set\")\n        }\n\n        // Load certificates and configure TLS\n        keypair, caCertPool, err := loadCertificates()\n        if err != nil {\n            log.Fatalf(\"failed to load certificates: %v\", err)\n        }\n\n        // Create Kafka dialer\n        dialer := createKafkaDialer(keypair, caCertPool)\n\n        // Set up Kafka producer\n        producer := setupKafkaProducer(dialer, serviceURI, topicName)\n        defer func() {\n            if err := producer.Close(); err != nil {\n                log.Printf(\"failed to close producer: %v\", err)\n            }\n        }()\n\n        // Send messages\n        sendMessages(producer, 100)\n    }\n
          package main\n\n    import (\n        \"context\"\n        \"crypto/tls\"\n        \"crypto/x509\"\n        \"fmt\"\n        \"log\"\n        \"os\"\n        \"time\"\n\n        \"github.com/segmentio/kafka-go\"\n    )\n\n    // loadPEMFromFile reads a PEM file from the specified file path.\n    func loadPEMFromFile(filePath string) ([]byte, error) {\n        data, err := os.ReadFile(filePath)\n        if err != nil {\n            return nil, fmt.Errorf(\"failed to read file %s: %w\", filePath, err)\n        }\n        return data, nil\n    }\n\n    // loadCertificates loads the necessary certificates for TLS configuration.\n    func loadCertificates() (tls.Certificate, *x509.CertPool, error) {\n        serviceCert, err := loadPEMFromFile(\"/service.cert\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load service cert: %v\", err)\n        }\n\n        serviceKey, err := loadPEMFromFile(\"/service.key\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load service key: %v\", err)\n        }\n\n        caCert, err := loadPEMFromFile(\"/ca.pem\")\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load ca cert: %v\", err)\n        }\n\n        keypair, err := tls.X509KeyPair(serviceCert, serviceKey)\n        if err != nil {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to load key and cert: %v\", err)\n        }\n\n        caCertPool := x509.NewCertPool()\n        if !caCertPool.AppendCertsFromPEM(caCert) {\n            return tls.Certificate{}, nil, fmt.Errorf(\"failed to append ca cert\")\n        }\n\n        return keypair, caCertPool, nil\n    }\n\n    // createKafkaDialer initializes a Kafka dialer with the provided certificates and CA pool.\n    func createKafkaDialer(keypair tls.Certificate, caCertPool *x509.CertPool) *kafka.Dialer {\n        return &kafka.Dialer{\n            Timeout:   10 * time.Second,\n            DualStack: true,\n            TLS: &tls.Config{\n                Certificates: []tls.Certificate{keypair},\n                RootCAs:      caCertPool,\n            },\n        }\n    }\n\n    // setupKafkaConsumer initializes and returns a Kafka consumer.\n    func setupKafkaConsumer(dialer *kafka.Dialer, serviceURI, topicName string) *kafka.Reader {\n        return kafka.NewReader(kafka.ReaderConfig{\n            Brokers: []string{serviceURI},\n            Topic:   topicName,\n            Dialer:  dialer,\n        })\n    }\n\n    // consumeMessages continuously reads messages from the Kafka topic.\n    func consumeMessages(consumer *kafka.Reader) {\n        for {\n            msg, err := consumer.ReadMessage(context.Background())\n            if err != nil {\n                log.Printf(\"could not read message: %v\", err)\n                continue\n            }\n            log.Printf(\"received: %s\", msg.Value)\n        }\n    }\n\n    func main() {\n        // Load environment variables\n        serviceURI := os.Getenv(\"SERVICE_URI\")\n        if serviceURI == \"\" {\n            log.Fatalln(\"service uri is not set\")\n        }\n\n        topicName := os.Getenv(\"TOPIC_NAME\")\n        if topicName == \"\" {\n            log.Fatalln(\"topic name is not set\")\n        }\n\n        // Load certificates and configure TLS\n        keypair, caCertPool, err := loadCertificates()\n        if err != nil {\n            log.Fatalf(\"failed to load certificates: %v\", err)\n        }\n\n        // Create Kafka dialer\n        dialer := createKafkaDialer(keypair, caCertPool)\n\n        // Set up Kafka consumer\n        consumer := setupKafkaConsumer(dialer, serviceURI, topicName)\n        defer func() {\n            if err := consumer.Close(); err != nil {\n                log.Printf(\"failed to close consumer: %v\", err)\n            }\n        }()\n\n        // Consume messages\n        consumeMessages(consumer)\n    }\n
      "},{"location":"manage-message-brokers/monitor-a-kafka-service/","title":"Monitor a Kafka Service","text":"

      You can monitor the health and performance of your Kafka services via the service metrics and service logs.

      "},{"location":"manage-message-brokers/monitor-a-kafka-service/#service-metrics","title":"Service metrics","text":"

      Service metrics provide real-time insights into the performance of your Kafka service.

      To view service metrics for a Kafka service, go to the Metrics tab on the service details page.

      The service metrics include the following:

      • CPU Usage %: Displays the percentage of CPU resources consumed by the service.
      • Disk Usage %: Represents the percentage of disk space utilized by the service.
      • Disk IO Reads: Displays the input/output operations per second (IOPS) for disk reads.
      • Disk IO Writes: Displays the input/output operations per second (IOPS) for disk writes.
      • Load Average: Displays the 5-minute average CPU load, indicating the system's computational load.
      • Memory Available %: Represents the percentage of memory resources utilized by the service.
      • Network Received: Indicates the volume of network traffic received by the service in bytes per second.
      • Network Sent: Indicates the amount of network traffic transmitted by the service in bytes per second.
      "},{"location":"manage-message-brokers/monitor-a-kafka-service/#service-logs","title":"Service logs","text":"

      Service logs provide a detailed record of Kafka service activity, such as producer and consumer operations, connection statuses, and error reports. These logs are essential for troubleshooting issues and analyzing message flow. Logs are retained for up to 4 days.

      To view Choreo-managed Kafka service logs, go to the Logs tab on the service details page.

      "},{"location":"monitoring-and-insights/generate-custom-reports/","title":"Generate Custom Reports","text":"

      Choreo insights allow you to generate custom reports to view the information that is important to you to make timely decisions for the betterment of your business. With custom reports, you can generate reports for a set of metrics of your choice and aggregate results by specific fields. Once generated, the metrics can be filtered out using any selected group-by filters. Custom reports support three visualizations: overtime charts, pie charts, and tables.

      "},{"location":"monitoring-and-insights/generate-custom-reports/#metrics","title":"Metrics","text":"

      Choreo Insights allow you to retrieve data for the following metrics:

      • Successful Hit Count
      • Response Cache Hits
      • Request Mediation Latency
      • Response Mediation Latency
      • Backend Latency
      • Total Latency
      • API Errors
      • Target Errors
      "},{"location":"monitoring-and-insights/generate-custom-reports/#group-by","title":"Group-by","text":"

      Group-by fields specify how to group the metric data. e.g., You can select Successful Hit Count in the Metrics field and API Name under Group-by to retrieve the successful hit count grouped by the API name.

      Choreo Insights allow you to group metric data by the following fields:

      • API Name
      • API Version
      • API Resource Template
      • API Method
      • API Creator
      • Application
      • Application Owner
      • Destination
      • User Agent
      • Platform

      To generate a custom report, follow the steps below:

      1. In the left navigation menu, click Custom Reports.

      2. Select metric(s) from the Metrics drop-down selector.

      3. Select a minimum of 1 and a maximum of 3 group-by field(s) from the Group By drop down selector.

      4. Set the order of the group-by filters by drag and drop to determine the grouping order of the selected metric(s).

      5. Once you determine the order of the group-by fields, you can set values for each group-by field from the respective dropdown.

      6. Click Generate.

      "},{"location":"monitoring-and-insights/generate-custom-reports/#download-reports","title":"Download Reports","text":"

      Choreo Insights allow you to download report data related to each chart as a PDF or a CSV file.

      To do this, click the Download icon on the top right of the relevant chart and select the required file format.

      "},{"location":"monitoring-and-insights/insights-overview/","title":"Insights Overview","text":"

      Choreo provides comprehensive insights into APIs created within both the on-premises API Manager and the Choreo platform. Choreo insights provide a range of metrics, including API traffic, error rates, and latency, allowing you to monitor and optimize API performance effectively.

      With Choreo insights, you can:

      • Analyze API traffic: Monitor the volume of requests and responses to understand usage patterns.
      • Track errors: Identify and analyze errors to improve API reliability.
      • Monitor latency: Measure and optimize the response times of your APIs.
      • Generate reports: Generate detailed reports to keep stakeholders informed and support data-driven decision-making.
      • Configure alerts: Set up alerts for specific events or thresholds to proactively manage API performance.
      • Obtain granular insights: Obtain detailed information on a per-application, per-API, and per-user basis for more targeted analysis.
      • Drill down into data: Dive deeper into data to perform root cause analysis.

      By leveraging these insights, businesses can make informed decisions to enhance their API strategies and drive their digital transformation initiatives forward.

      "},{"location":"monitoring-and-insights/insights-overview/#view-insights","title":"View insights","text":"

      To view usage insights, go to the Choreo Console and click Usage Insights in the left navigation menu.

      If you are viewing insights on the Choreo platform at the organization level, note the following:

      • Permission-based access: Signed-in users can only view insights for components or projects that they have permission to access.
      • Data exclusion: Insights exclude data from components you cannot access and the data related to deleted components.
      • Comprehensive view permission: To view insights for all components, including deleted ones, across the organization regardless of project visibility, you must have the View Organization Insights permission under OBSERVABILITY-MANAGEMENT with the mapping level defined at the Organization level.
      • Admin role: Users with the admin role have the View Organization Insights permission by default and can view organization-wide insights.
      • Configuring permissions: For detailed steps on configuring permissions, see Control Access in the Choreo Console.

      By ensuring proper permissions are set, organizations can manage access to insights effectively while maintaining data security and relevance.

      "},{"location":"monitoring-and-insights/insights-overview/#analyze-statistics","title":"Analyze statistics","text":"

      Once you access the Usage Insights page, you can access the following subpages.

      "},{"location":"monitoring-and-insights/insights-overview/#overview","title":"Overview","text":"

      The Overview page gives you a quick overview of the system status.

      The information displayed is as follows:

      • Total Traffic

        This widget displays the total traffic of the selected environment received during a given time interval. Both successful requests and failed requests are displayed. To investigate further, you can click the arrow icon on the bottom right corner of the widget to open the Traffic page.

      • Error Request Count

        This widget displays the total number of requests that have resulted in errors in your selected environment during the selected time range.

      • Average Error Rate

        This widget displays the average error rate (i.e., error count/total request count) of the selected environment for a given time interval. You can use this widget as an indicator to understand the health of the system. If the error rate is high, you can investigate further by clicking the arrow on the bottom right of the widget and opening the Errors page.

      • 95th Percentile Latency

        This widget displays the 95th percentile of all API latencies in your selected environment for the given time interval. You can use this widget to know whether the complete system operates under given SLAs. This metric provides the first indication of slow APIs. To investigate further, you can click the arrow on the bottom right of the widget to open the Latency page where you can further analyze the latency.

      • API Request Summary

        This chart displays the total successful requests, the total requests that have resulted in errors, and the latency in a timeline. The y-axis on the left displays the request count and the error count. The x-axis shows time, and the y-axis on the right shows the latency in milliseconds. The granularity of the data points is decided based on the time range you have selected. The tooltip provides the exact value of all three metrics accurately.

      "},{"location":"monitoring-and-insights/insights-overview/#traffic","title":"Traffic","text":"

      The Traffic page shows information related to the traffic that goes through your API management deployments. This includes API usage, application usage, resource usage, etc. You can use this page to investigate the usage of APIs and applications, traffic patterns, etc.

      You can filter the information displayed in the widgets as follows:

      Filtering Option Description By API In the API field, you can select one or more APIs for which you want to view analytics. All is selected by default. Once you select an API, you can further filter by a specific application that uses the selected API via the Application field described below. By Application In the Application field, you can select the applications for which you want to view analytics. All is selected by default. The available applications are all the applications that have subscribed to one or more of the APIs you selected in the API field.

      You can view the following information for the APIs you have selected using the above filtering criteria:

      • API Usage Over Time

        This timeline shows the count of API hits for the APIs for the filtered APIs. If multiple APIs are selected, the timeline shows each API in a separate line with a legend separating each line. You can also zoom in on a selected time range by selecting that area in the chart. To restore to the original view use the Zoom out button on the top right-hand corner of the plot.

      • API Usage By Application

        This widget shows the per-application breakdown of requests for the APIs you selected. You can use the pie chart view or the line chart view. You can switch between the two views using the small icon at the upper-right corner of the widget.

      • API Usage By Target

        This widget shows the per-backend breakdown of requests for the APIs you selected. This information is useful when multiple APIs share the same backend that has traffic restrictions. You can use these stats to scale your backends proactively. You can switch between the two views using the small icon at the upper-right corner of the widget.

      • API Resource Usage

        This table shows a resource-level breakdown of API traffic. Each row represents an API resource and it shows the API name, resource path, API method, and the hit count for that combination.

      "},{"location":"monitoring-and-insights/insights-overview/#errors","title":"Errors","text":"

      The Errors page shows information related to erroneous API calls that are received by your system. The errors are categorized based on the error type. You can further drill down using the error subtypes. Use this page as the starting point for debugging any API errors.

      You can filter the information displayed in the widgets as follows:

      Filtering Option Description By API In the API field, select the APIs for which you want to view analytics. By default, all APIs are selected. You can select one or multiple APIs from this selector and view the aggregated result. By Category The Category field is displayed when you click Category in the upper right corner of the page. In this field, you can select one or all of the following error categories:Authentication: Any kind of authentication error falls into this category including expired/missing/invalid credentials.Target Connectivity: Any kind of back-end error falls into this category including connection time-outs/other back-end errors (for example, 4xx and 5xx status codes).Throttling: Any request that fails due to rate-limiting falls into this category including application throttling/subscription throttling.Other: All other errors fall into this category including mediation errors/resource not found errors. By Status Code The Status Code field is displayed when you click Status Code in the upper right corner of the page. In this field, you can select all or any available HTTP status code categories (4xx, 5xx, etc.). These status codes represent the response status of the API Gateway. Viewing errors by category

      The following widgets are available for monitoring errors when you have selected Category in the upper-right corner of the page.

      • This graph shows the error by category over time for the selected period. Apply the required filters as explained above to select the APIs and the error categories to which this content applies. When you select multiple APIs, the error count is grouped by category.

      • This table provides further information about the errors such as application details and the error reason. For some authentication errors, the application name is not available. You can use this table to get more concrete information about the errors related to your APIs and then start the problem identification.

      Viewing errors by status code

      The following widgets are available for monitoring errors when you select Status Code in the upper-right corner of the page.

      • Errors by Status Code

        This graph shows the distribution of HTTP status codes received for errors over time for the selected period. Apply the required filters as explained above to select the APIs and status code groups to which this content applies. When you select multiple APIs, the error count is grouped by the status code.

      • Target Errors by Status Code

        This graph shows the distribution of target errors that have occurred during the selected time interval by HTTP status code. Apply the required filters as explained in the table above to view the APIs and status code groups to which this content applies. If you select multiple APIs, the widget groups the target error count by the status code.

      • Errors

        The Errors heat map shows the HTTP response codes of errors sent to the client by the API Gateway. Each row displays the number of times the system returned each status code for the selected APIs. The cell color is red for higher numbers and white for lower numbers. If required, you can further filter the results by the error code groups you identified with the Errors by Status Code graph.

      • Target Errors

        The Target errors heat map shows the HTTP response codes of errors that the API Gateway received from the backend. Each row displays the number of times the system returned each status code for the selected APIs. The cell color is red for higher numbers and white for lower numbers. If required, you can further filter the results by the error code groups you identified with the Target Errors by Status Code graph.

      "},{"location":"monitoring-and-insights/insights-overview/#latency","title":"Latency","text":"

      The Latency page shows information related to the latency of API calls within the API management deployment. You can view a summary of the slowest APIs and then drill down into the API view for further analysis. Use this page as a starting point to debug API slowness.

      The information displayed is as follows:

      • Top 10 Slowest APIs

        This widget allows you to identify the slowest APIs of the API management system at a glance. Since these are the APIs that contribute to the higher 95th percentile of the system, improving these APIs lowers the 95th percentile of latency in the API Management deployments.

      • Latencies By Category

        This widget allows you to further drill down details in the above chart. Use the API selector in this widget to select the slow API you identified in the earlier step and then analyze further. Use the charts available in the widget to view the 95th percentile and the median latency over the selected period of the following:

        • Backend
        • Request mediation
        • Response mediation

      You can use these charts to further drill down and analyze whether the latency occurs in the backend, request mediation, or response mediation. Also, because you can see both the median and 95th percentile, you can easily identify whether the slowness is occurring in each request or whether it is intermittent.

      "},{"location":"monitoring-and-insights/insights-overview/#cache","title":"Cache","text":"

      The Cache page shows statistics that indicate the efficiency with which response caching is carried out for the requests sent to your APIs.

      The page displays the following statistics:

      • Cache Hit Percentage

        This graph shows the percentage of requests the system has handled via the response cache over time and the total hits over time. This information allows you to assess how efficiently the backend handles API requests. For example, if the cache hit rate is low, it may indicate that the backend generates the same response each time a specific request is sent instead of returning the response via the cache. In such a scenario, there is scope to improve performance via response caching.

      • Latency

        This section shows the total latency reported during the same time interval applied to the Cache Hit Percentage graph above.

      "},{"location":"monitoring-and-insights/insights-overview/#devices","title":"Devices","text":"

      The Devices page displays information about operating systems and HTTP agents that end users use to invoke the APIs. You can use this page to get an idea of the distribution of your user base and improve your APIs to match the audience.

      To filter the information displayed on this page by API, select the required API(s) in the API field. All is selected by default.

      The information displayed is as follows:

      • Top Platforms

        This chart shows the breakdown of the API clients by the operating system. The pie chart only shows platforms with a significant amount of requests. Other platforms are grouped under the Other category.

      • Top User Agents

        This chart shows the breakdown of the API clients by user-agent. The pie chart only shows user agents with a significant amount of requests. Other platforms are grouped under the Other category.

      "},{"location":"monitoring-and-insights/insights-overview/#alerts","title":"Alerts","text":"

      The Alerts page shows information related to business alerts issued by Choreo for your currently selected environment and organization. You can use this page as a health monitoring dashboard and make it visible to your project team. Using this page you can drill down on each alert and discover possible anomalies in your published APIs. See the topics given below to get details of the available widgets and understand how to use them effectively.

      Prerequisites

      To use this page, be sure to configure alerts and have API invocations that trigger alerts.

      Note

      Alerts are retained only for a week.

      • Alert Summary

        This table lists each alert generated during the selected time interval. The message of the alert can be viewed by expanding the arrow icon on the details column. The drop-downs can be used to filter alerts based on the alert type and API.

      • Top APIs by Alert Count

        This shows a pie chart and a table to visualize the alert distribution during the selected time interval.

      "},{"location":"monitoring-and-insights/insights-overview/#reports","title":"Reports","text":"

      The Reports page allows you to download monthly usage reports for your system. There are preconfigured reports with system-wide statistics, and a custom report generator to generate reports based on a subset of APIs/applications.

      Download custom reports

      This widget allows you to generate a custom report for the statistics that have been generated up to now and download it.

      To generate a custom report, follow the steps below:

      1. In the API field, select one or more APIs for which you want to generate the report. If required, you can select all the APIs by selecting All.

      2. If you need to further filter the content printed in the report, select one or more applications in the Application field. By default, all the applications that have subscribed to one or more of the selected APIs are selected.

        Tip

        If you want to filter the report content by the API consumer instead of the application, click on the toggle switch to the right of the Application field, and then select the required consumer. Only consumers who have subscribed to one or more of the selected APIs are displayed in the list. You can either select one or all of them.

      3. Select the required year and the month in the Year and Month fields to specify the time interval for which you want to generate the report.

      4. Click Download, and select the required format.

      The report is downloaded in the specified format. The following is a sample report generated in PDF format.

      The contents of the report are as follows.

      Item Description Generated Time The date and the time the report was generated. Organization The organization to which the report applies. Each report always applies to a specific organization. Environment The environment to which the report applies. Each report always applies to a specific environment. Tenant The tenant to which the report applies. Each report always applies to a specific tenant. Reporting period The time interval for which the report is generated. Total request count The total request count received by all selected APIs during the report time interval.

      The table in the report contains the following rows.

      Item Description API The name of the API. Application The name of the application. The name of the subscriber is also provided within brackets. Usage The usage count. Download pregenerated reports

      These widgets allow you to download monthly reports for the last three months.

      To download a pregenerated report, click Download for the relevant month and then click on the required format.

      "},{"location":"monitoring-and-insights/insights-overview/#geo-map","title":"Geo Map","text":"

      The Geo Map page allows you to see a geographical representation of your API usage. You can use this page to make business decisions such as identifying growing regions, analyzing the impact of a region-specific marketing campaign, etc.

      To filter the information displayed on this page by API, select the required API(s) in the API field. The default value is All.

      This heat map highlights the countries with the appropriate color based on the hit count. It uses a relative color scale to depict the highest hit count to the lowest non-zero hit count.

      Viewing the number of requests by country

      You can hold the pointer over the highlighted countries to view the country name and the total number of hits from that location. You can also use the mouse to zoom the map or pan it. Optionally, you can download geo-map data in a tabular format using the PDF or CSV download options by clicking on the top right corner.

      Note

      • Currently, this feature is only available for on-premises environments.
      • The geo-map page utilizes the IP address of the incoming request to derive the geolocation. The actual source IP address can be replaced if there are intermediate hosts between the client and the gateway node. Therefore, the reverse proxy or the load balancer fronting the gateway node must add the x-forwarded-for header to each request to preserve the source IP address. If you do not configure this correctly, the Geo Map page will not show any data. To test this, you can manually add an x-forwarded-for header to the request.
      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/","title":"Integrate Choreo with Moesif","text":"

      Moesif is an API analytics and monetization service that helps you grow your API products. You can integrate Choreo with Moesif and gain valuable insights into your API's usage. While Moesif's API analytics capabilities empower you to make informed decision-making on behalf of your organization, its monetization options simplify revenue generation from your APIs, eliminating the need for complex coding.

      In this guide, you will:

      • Generate a key in Moesif.
      • Configure Choreo to connect to Moesif.
      • Invoke an API and observe the insights on the Moesif dashboard.
      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/#step-1-generate-an-api-key-in-moesif","title":"Step 1: Generate an API key in Moesif","text":"

      Let's generate an API key in Moesif. If you're an existing Moesif user with a registered organization, proceed to step 1.2.

      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/#step-11-generate-a-key-in-moesif-as-a-new-user","title":"Step 1.1: Generate a key in Moesif as a new user","text":"

      If you are a new user, follow the steps below to register an organization and generate a key:

      1. Go to https://www.moesif.com/.
      2. Click Sign Up and select an authentication option and proceed.
      3. On the Get Started page, enter meaningful values for the fields and create a new organization.

        Field Description Organization Name The name of your company or team. Application Name The name of your application that represents one project or environment.
      4. Click Next.

      5. On the Overview page, click Next.

        This opens the Quick Install page. As there is no data, you cannot proceed. Let's configure Moesif to receive data from Choreo.

      6. Select a WSO2 Choreo as the Server Integration

      7. Copy the Application Id.

      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/#step-12-access-the-api-key-in-moesif-as-an-existing-user","title":"Step 1.2: Access the API key in Moesif as an existing user","text":"

      If you are an existing user with a registered organization, or you do not have an API key for the organization you created, follow the steps below to access the generated API key:

      1. Go to https://www.moesif.com/.
      2. Click on your profile in the bottom left corner, and navigate to the API Keys page.
      3. Copy the Collection Application Id.
      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/#step-2-integrate-choreo-with-moesif","title":"Step 2: Integrate Choreo with Moesif","text":"

      Let's configure Choreo to publish events to Moesif.

      1. Go to https://console.choreo.dev/ and sign in.
      2. On the left navigation, click Settings.
      3. In the header, click the Organization list. This will open the organization level settings page.
      4. Click the API Management tab, and click Moesif Dashboard.
      5. Select the environment you want to publish data for.
      6. Paste the Application Id you copied.
      7. Click Add.

      Once you successfully add the key, you will see a delete option next to it. Currently, you can only configure one API key. If you need to add a new API key, you need to delete the existing key and add the new one.

      Note

      Once you configure the Moesif API key on Choreo, wait for five minutes before you publish any data to the Moesif API analytics platform.

      "},{"location":"monitoring-and-insights/integrate-choreo-with-moesif/#step-3-invoke-an-api-and-observe-the-data-on-the-moesif-dashboard","title":"Step 3: Invoke an API and observe the data on the Moesif Dashboard","text":"

      You have configured Choreo to publish data to Moesif. Let's see how you can view the insights on Moesif.

      Tip

      • If you have not created an API and deployed it on Choreo, you can follow the create and deploy a REST API guide to get started.
      1. Invoke your API by following the Test REST Endpoints via the OpenAPI Console guide.

      2. Once you publish data, your Moesif dashboard will receive events. Once Moesif receives events, you will see a notification on Moesif confirming that it received data.

      3. Click Next on the notification. This will take you to the final step, where you can opt to add team members. In this guide, let's skip this step.

      4. Click Finish.

      You can now view your API's insights in the Moesif dashboard.

      "},{"location":"monitoring-and-insights/observability-overview/","title":"Observability Overview","text":"

      The Choreo observability dashboard provides a comprehensive interface to visualize and monitor the performance of services deployed on Choreo.

      The Observability dashboard allows you to:

      • Observe the throughput and latencies of requests served over a given period.
      • Compare metrics side-by-side to facilitate efficient diagnosis.
      • Observe the diagnostics view generated over a given period.
      • View logs generated over a specific timeframe.

      Tip

      If you are a Choreo private data plane customer and you want to observe your private data plane using New Relic, see Observing Choreo Private Data Planes With New Relic.

      "},{"location":"monitoring-and-insights/observability-overview/#throughput-and-latency-graphs","title":"Throughput and latency graphs","text":"

      The throughput graph depicts the throughput of requests per second for a selected timestamp.

      By default, Choreo renders this graph for the data generated within the past 24 hours. You can change the default time window by selecting the time range and zone from the options bar. To expand the graph, click and drag the cursor over the period you want to drill down.

      You can view the Choreo service logs in the Logs pane below the throughput and latency graph. Clicking on a graph updates the Logs view to contain the corresponding log entries generated at that time. You can use these logs to identify the reasons for any latency and throughput anomalies you detect using the graph.

      "},{"location":"monitoring-and-insights/observability-overview/#diagnostics-view","title":"Diagnostics view","text":"

      The Diagnostics view allows you to simultaneously analyze errors, throughput, latencies, CPU usage, memory usage, and logs for a particular event. This facilitates detailed error detection and analysis.

      By default, the time range selected for the Throughput & Latency graphs is the same time range used for the Diagnostics view.

      Each horizontal section of the graph, termed a bin, represents a specific period and comprises:

      • Date/Time: Indicates when the log entries began to appear.
      • Logs: List of log entries and respective log counts within the bin's timeframe, sorted by precedence (error logs followed by info logs). Each bin displays a maximum of five log entries.
      • Error: The number of HTTP errors that occurred at the selected time.
      • TP: Throughput of the requests at the selected time (req/s).
      • Latency: Request latency at the selected time (ms).
      • CPU: CPU usage at the selected time (millicores).
      • Memory: Memory usage at the selected time (MiB).
      "},{"location":"monitoring-and-insights/observability-overview/#logs","title":"Logs","text":"

      The Logs pane serves as a centralized view to observe logs of the components you deploy on Choreo. This facilitates rigorous troubleshooting and analysis.

      "},{"location":"monitoring-and-insights/view-logs/","title":"View Logs","text":"

      The unified log view in Choreo allows you to view runtime and audit logs to gain application and user insights while ensuring data privacy.

      Choreo provides real-time insights through live logs and allows you to view historical logs for insights into the past. You also have the flexibility to define a required time range to view relevant log entries, where an intuitive scrolling capability facilitates easy viewing of appropriate logs within the selected time frame.

      The log view also provides advanced filtering capabilities that allow you to efficiently navigate through appropriate logs to expedite troubleshooting in distributed environments.

      Note

      All personally identifiable information (PII) gets resolved at the frontend service level, with only relevant UUIDs stored in logs.

      "},{"location":"monitoring-and-insights/view-logs/#runtime-logs","title":"Runtime logs","text":"

      Choreo runtime logs provide insights into both project and component-level logs, covering application and gateway logs. These logs streamline the debugging process by centralizing diverse log sources.

      In Choreo, any organization member can view runtime logs via the runtime logs page. Choreo allows you to apply filters based on parameters such as log level (error, warn, info, debug), log type (application, gateway), and environment (development, staging, production) to simplify the debugging process.

      To access runtime logs, follow the steps below:

      1. Sign in to Choreo.
      2. In the left navigation menu, click Observability and then click Runtime Logs. This displays runtime logs for the past 30 days by default.

        To view logs based on a specific time range and other requirements, you can apply the necessary filter criteria.

      "},{"location":"monitoring-and-insights/view-logs/#understand-runtime-logs","title":"Understand runtime logs","text":"

      When you view component-level logs on the Runtime Logs page, you will see both application and gateway logs.

      Application logs

      Each application log entry displays the following details:

      • timestamp: The time when the request is received by the component.
      • level: Indicates the severity of the log message. Possible values are Debug, Info, Warn, and Error.
      • componentVersion: The version of the invoked component.
      • componentVersionId: The identifier of the invoked component\u2019s version.
      • envName: The environment of the inbound request. For example, Development, Production, etc.
      Gateway logs

      Each gateway log entry displays the following details:

      • timestamp: The time when the request is received by the gateway component.
      • logLine: Contains the following details about the request, including inbound and outbound information from the gateway perspective.
        • Method: The HTTP method of the request.
        • RequestPath: The path of the inbound request.
        • ServicePath: The path of the outbound request.
        • UserAgent: The user-agent header of the request.
        • CorrelationID: The request identifier of the inbound request. This is useful to track a request.
        • ServiceHost: The host IP of the backend.
        • Duration: The time taken for the gateway to serve the request.\u00a0\u00a0
      • gatewayCode: Indicates the state of the request from the gateway perspective. Possible values are as follows:

        • BACKEND_RESPONSE: Indicates successful processing of the request by the gateway with a response to the client from the backend application.
        • CORS_RESPONSE: Denotes a CORS (Cross Origin Resource Sharing) request.
        • AUTH_FAILURE: Indicates a request failure at the gateway due to authentication or authorization issues, such as an invalid token.
        • NO_HEALTHY_BACKEND: Indicates a request failure at the gateway due to a non-existent backend.
        • RATE_LIMITED: Indicates a request failure at the gateway due to surpassing the rate limit enforced within the component.
        • RESOURCE_NOT_FOUND: Indicates a request failure at the gateway due to the absence of a matching API resource for the inbound request. This can be caused by a mismatch in the HTTP method, path, or host.
        • BACKEND_TIMEOUT: Indicates a request timeout when calling the backend application from the gateway.
        • GATEWAY_ERROR: Indicates a request failure due to an erroneous behavior in the gateway.

        Note

        Occasionally, a request may not fit into any of the above categories. In such instances, the gatewayCode is displayed as UNKNOWN.

      • statusCode: The HTTP status code returned to the client.

      • componentVersion: The version of the invoked component.
      • envName: The environment of the inbound request. For example, Development, Production, etc.
      "},{"location":"monitoring-and-insights/view-logs/#audit-logs","title":"Audit logs","text":"

      Audit logs, also called audit trails, enhance security, ensure compliance, provide operational insights, and help manage risks.

      In Choreo, an audit log records organization-level user-specific operations performed via the Choreo Console. It also captures the timestamp and the outcome of the action.

      As of now, Choreo captures the following user-specific operations as audit logs:

      • Project creation, update, and deletion.
      • Component creation, update, and deletion.
      • Component promotion initiation.
      • Component version creation.
      • Component deployment, redeployment, and undeployment initiation for all components other than REST API Proxy components.
      • Component API access mode update.
      • Enabling and disabling component auto-deployment on commit.
      • Component build configuration update.
      • Component endpoint creation, update, and deletion.
      • Organization user management.
      • On-premises key management.
      • Project-level configuration management.

      In Choreo, organization administrators are allowed to view audit logs by default. If other members need to access organization-specific audit logs, the administrator can create a role with the relevant permission and assign it to members. For step-by-step instructions on how to create and assign a role with relevant permission, see Manage audit log access.

      To view audit logs, follow these steps:

      1. Sign in to Choreo.
      2. In the Choreo Console, go to the top navigation menu and click Organization.

        Tip

        As of now, you can only view organization-level audit logs.

      3. In the left navigation menu, click DevOps and then click Audit Logs. This displays audit logs for the past 30 days by default.

        To view audit logs based on a specific time range and other requirements, you can apply the necessary filter criteria.

      "},{"location":"monitoring-and-insights/view-logs/#audit-log-retention","title":"Audit log retention","text":"

      Choreo retains audit logs for one year and archives them for an additional year. Therefore, the total retention period for audit logs is two years.

      "},{"location":"monitoring-and-insights/view-logs/#manage-audit-log-access","title":"Manage audit log access","text":"

      Follow the steps given below to create a role with audit log access permission and assign it to organization members who need access to audit logs:

      Note

      You must be the organization administrator to perform this action.

      Step 1: Create a role with audit log access permission
      1. In the Choreo Console, go to the top navigation menu and click Organization.
      2. In the left navigation menu, click Settings.
      3. On the Organization tab, click Roles and then click + Create Role.
      4. Enter a name and description for the role.

      5. Click Next.

      6. In the Create Role dialog, select LOG-MANAGEMENT under Permissions.

      7. Click Create.

      Step 2: Assign the created role to an organization member
      1. On the Organization tab, click Members. This lists the members of the organization with their respective details.
      2. Click on a member who needs to have access to audit logs, and then click + Add Role.

        Tip

        If you want to invite one or more members and assign them the audit log viewer role, follow the steps given below:

        1. Click + Invite Member and then click to expand the Roles list.
        2. Select the role you created in Step 1.
        3. In the Emails field, enter the email addresses of members you want to invite and grant permission to access audit logs.
        4. Click Invite. This sends an invitation email to each email address so that the members can accept and obtain access to view audit logs.
      3. Click to expand the Roles list and select the role you created in Step 1.

      4. Click Add. This assigns the selected role to the member.
      "},{"location":"monitoring-and-insights/alerts/configure-alerts/","title":"Configure Alerts","text":"

      This section explains how you can configure alerts for your API manager deployments. Setting up alerts allows you to proactively monitor your API ecosystem and take corrective measures when necessary.

      You can configure alerts for each environment within your organization. You can add, modify, or delete alerts per API. Optionally, you can specify a list of emails for each alert configuration.

      Alerts are subject to a suppression policy to prevent duplicate notifications within a specific time frame. By default, a 10-minute suppression window is applied, and this is not configurable. The suppression policy is specific to each alert configuration.

      Info

      • You can configure a maximum of 20 alerts per organization, environment, and tenant combination.
      • Adding email addresses to an alert configuration is optional. If necessary, you can add a maximum of 5 email addresses per alert.

      Alerts can be categorized as either latency alerts or traffic alerts.

      "},{"location":"monitoring-and-insights/alerts/configure-alerts/#latency-alerts","title":"Latency alerts","text":"

      Latency alerts notify you if the response latency of an API exceeds a predefined threshold. This is useful for APIs that need to meet specific SLAs and for proactively identifying slow APIs.

      To configure a new latency alert, follow the steps given below:

      1. Sign in to the Choreo Console.
      2. Ensure you are in the correct organization where you have a project with the API to configure a latency alert.
      3. In the Choreo Console left navigation menu, click Usage Insights.
      4. In the left navigation menu on the Usage Insights page, click Alerts.
      5. Click the Environment list and select the required environment.
      6. Click Alert Configuration.

        This opens the Alert Configuration pane with the Latency tab open by default.

      7. In the API Name field, select the API for which you want to configure the alert.

        Info

        Only the APIs that you have invoked at least once are listed here. For other APIs, you need to give the API name in the required format as instructed in the UI.

      8. In the Metric field, select the required metric against which you want to evaluate the alert configuration.

        Tip

        The list includes all available options. If there are multiple metrics, you can select the required metric. If there is only one metric to choose, that metric is selected by default, and the field is disabled.

      9. In the Latency field, specify the threshold in milliseconds.

        Info

        When the 95th percentile of the selected metric exceeds the threshold provided here, alerts are triggered.

      10. In the Emails field, specify the list of emails that should be notified when the alert is added.

      11. Click + Add.

      Once an alert is successfully added, the alert configuration is listed in the Alert Configuration pane. Each configuration can be edited and removed via this pane.

      "},{"location":"monitoring-and-insights/alerts/configure-alerts/#traffic-alerts","title":"Traffic alerts","text":"

      Traffic alerts notify you when the request count of an API exceeds a predefined threshold. This is useful for managing APIs with backend traffic limits or monetized backends that require proactive scaling based on incoming traffic.

      To configure a new traffic alert, follow the steps below:

      1. Sign in to the Choreo Console.
      2. Ensure you are in the correct organization where you have a project with the API to configure a latency alert.
      3. In the Choreo Console left navigation menu, click Usage Insights.
      4. In the left navigation menu on the Usage Insights page, click Alerts.
      5. Click the Environment list and select the required environment.
      6. Click Alert Configuration. This opens the Alert Configuration pane.
      7. Click the Traffic tab.
      8. In the API Name field, select the API for which you want to configure the alert.

        Info

        Only the APIs that you have invoked at least once are listed here. For other APIs, you need to give the API name in the required format as instructed in the UI.

      9. In the Metric field, select the required metric against which you want to evaluate the alert configuration.

        Tip

        The list includes all available options. If there are multiple metrics, you can select the required metric. If there is only one metric to choose, that metric is selected by default, and the field is disabled.

      10. In the Threshold field, specify the threshold number of requests per minute.

      11. If required, specify the list of emails that should be notified when the alert is generated in the Emails field.

      12. Click Add.

      Once an alert is successfully added, the alert configuration is listed in the Alert Configuration pane. Each configuration can be edited and removed via this pane.

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/","title":"Configure CIO Dashboard","text":"

      You can view DORA metrics in Choreo to use as KPIs to measure your organization's DevOps team's performance. Choreo enables this feature by default for all organizations. DORA includes the following four key metrics that are regarded as the most important metrics to indicate team performance:

      • Deployment Frequency: How often an organization successfully releases to production
      • Lead Time for Changes: The amount of time it takes a commit to get into production
      • Change Failure Rate: The percentage of deployments causing a failure in production
      • Time to Restore Service: How long it takes an organization to recover from a failure in production

      Choreo enables two DORA metrics by default; deployment frequency and lead time for change.

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#configure-the-cio-dashboard-with-all-metrics","title":"Configure the CIO Dashboard with all metrics","text":"

      To configure the CIO dashboard by enabling the other two metrics, follow the steps below:

      1. Sign in to Choreo using your Google, GitHub, or Microsoft account.
      2. On the left navigation menu, click Delivery Insights.
      3. Click on the DORA Metrics tab.
      4. Scroll to the bottom of the dashboard and click Configure.
      5. Select your incident management system. Currently, Choreo only supports GitHub.
      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#configuring-github-as-the-incident-management-system","title":"Configuring GitHub as the incident management system","text":"

      To configure GitHub as the incident management system, follow the steps below:

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#step-1-authorize","title":"Step 1: Authorize","text":"

      First, let's authorize Choreo to access the repositories used to record incidents.

      On the Add Integration page, select GitHub and click Authorize with GitHub.

      Once the authorization process is complete, you can start configuring the GitHub repository.

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#step-2-configure","title":"Step 2: Configure","text":"

      By default, Choreo collects incident details(issues) from all repositories containing Choreo components. However, you can configure a GitHub account and a GitHub repository to allow Choreo to read issues from a specific repository, and then click Next.

      Field Description Value Data Plane Choreo collects incident details by running a scheduled job which invokes the GitHub API periodically. This job runs on the user's data plane. This configuration allows users to specify a preferred data plane to run the job, especially when they have multiple data planes. Select a preferred data plane from the Data Plane list. GitHub Account The GitHub account you have your repositories in. Select your GitHub account that includes the repository used for incident collection. GitHub Repository By default, Choreo will collect incident details(issues) from all repositories that already have Choreo components."},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#step-3-filter-label","title":"Step 3: Filter label","text":"

      The filter label allows Choreo to scrape issues associated with that label.

      • Incident Label: The label Choreo uses to identify incidents. For example, Type/Incident.

      • Invalid incident label(Optional): Choreo will not scrape issues with this label and will proceed to skip these issues. For example, Resolution/Invalid. You can use this label when you want to ignore issues. For example, closing an issue after identifying that it doesn't qualify as an incident issue as it was due to a user error.

      Once you configure the labels, click Save.

      Choreo will enable incident data publishing in the background once you save. Once completed, DORA metric charts will appear in the CIO dashboard for Mean Time To Recover and Change Failure Rate. If there are any issues in the configuration, the configure banner will reappear, and the user can proceed to reconfigure.

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#step-4-enrich-incident-tickets-with-deployment-information","title":"Step 4: Enrich incident tickets with deployment information","text":"

      Choreo extracts deployment information from the relevant incident and generates DORA metrics that help you analyze the deployment statistics related to the incidents. Therefore, you must manually update the GitHub issue with the relevant deployment-related information. Follow the steps below to add the deployment information to the GitHub issue.

      Get deployment details
      1. On the Choreo Console header, select the project and the component for which the incident was reported.
      2. On the left navigation menu, click Deploy.
      3. On the Production Environment card, click Deployment History.
      4. On the right-hand side panel, select the relevant deployment, and click Release details to copy the deployment details to the clipboard.

      Add deployment information to the GitHub issue
      1. Edit the GitHub issue to add the deployment information.
      2. Paste the deployment information you copied (in step 4 under the section Get deployment details) at the end of the issue body.
      3. Click Save.

      That's it! You have successfully configured your CIO dashboard to include the DORA metrics.

      Note

      The CIO Dashboard is expected to reflect the latest statistics within approximately 30 minutes.

      "},{"location":"monitoring-and-insights/delivery-insights/configure-dora-metrics/#edit-configurations","title":"Edit configurations","text":"

      You can edit or override the configurations you made via the edit option in the dashboard.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/","title":"View DORA metrics","text":"

      DORA metrics comprise four key metrics. Let's explore what each metric represents in Choreo. Choreo displays a summary and graphical representation of each metric.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#snapshot-view","title":"Snapshot view","text":"

      The snapshot view includes four tiles on the top of the dashboard, summarizing DORA metrics for the entire time period you select. The snapshot view categorizes each metric into four performance levels: elite, high, medium, and low. The categorization is based on the 2020 DORA metric report.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#time-series-view","title":"Time series view","text":"

      The time series view provides a graphical representation of how the statistics have changed over a period of time. You can use this view to analyze team performance and identify trends.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#deployment-frequency","title":"Deployment frequency","text":"

      DORA team definition: The frequency at which an organization successfully releases to production.

      In Choreo, this translates to the number of times an organization deploys a component to the production environment. Choreo does not count the deployment done to the development or other lower environments.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#snapshot-view_1","title":"Snapshot view","text":"

      The snapshot view of the Deployment Frequency metric shows the deployment frequency for all components within the selected organization. The frequency is dynamically determined and rounded to the nearest measurement. For example, if there is more than one deployment daily, the deployment frequency is measured in deployments per day. If the deployment frequency is less, it is measured in a higher granularity. For example, deployments per week.

      A lower deployment frequency indicates that your organizational efficiency is low and that you need to evaluate and improve the processes to encourage frequent releases.

      Choreo also displays the total number of deployments for the selected time range and the percentage increase or decrease compared to the previous time range.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#time-series-view_1","title":"Time series view","text":"

      The time series view for the Deployment Frequency metric visualizes the deployment count as a bar chart for the selected time period. Deployment count is aggregated based on the \u2018view by\u2019 selector. Hovering over each bar shows the counts for the aggregated period. Using this chart, organizations can identify deployment patterns, such as days of the week/months of the year where more deployments are likely to happen (near quarterly release days) and periods with fewer deployments. Decision-makers can then take steps to investigate and improve performance. This chart displays the pattern before and after a process change so you can use it to evaluate the team's performance after a significant process change.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#lead-time-for-change","title":"Lead Time for Change","text":"

      DORA team definition: The time it takes for a commit to reach production.

      In Choreo, this translates into the time between committing and promoting a deployment to production. Although this approach may overlook any commits you push to production between two commits, it effectively assesses the efficiency of the review, approval, and CI/CD processes. Therefore, focusing on the production commits is adequate. If a team commits locally for extended periods without deploying to production, this gets reflected in the Deployment Frequency charts.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#snapshot-view_2","title":"Snapshot view","text":"

      The snapshot view of this metric displays the 95th percentile of the lead time for the selected time period. 95th percentile serves as a better representation as it filters out large outliers that can taint the average value. Lower lead times for change suggest that your organization has efficient processes for change review, approval, and CI/CD, while longer times suggest that the process needs to improve. Organizations can also use the categorization label to determine their standpoint on global standards.

      Additionally, Choreo also displays the percentage increase or decrease compared to the last time period.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#time-series-view_2","title":"Time series view","text":"

      The time series view of this metric visualizes the lead time as a bar chart for the selected time period. The time is summed based on the \u2018view by\u2019 selector. To handle outliers, the y-axis employs a log scale that represents values read dynamically. Hovering over each bar displays the actual counts for the aggregated period. Using this chart, organizations can identify trends in their release process. For example, organizations can identify the time of the year when lead time rises, such as summer break. Also, organizations can use this to benchmark and evaluate new process changes. For example, if you introduced a process to include peer programming and reviewing, this chart can be used to evaluate its effect on the lead time and provide leadership with factual information to proceed further.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#change-failure-rate","title":"Change failure rate","text":"

      The DORA team definition: The percentage of deployments causing a failure in production.

      In Choreo, this translates to the ratio of deployments causing production failures to the total number of deployments. If there is at least one incident reported against a deployment, Choreo considers that deployment as a failed deployment in production. Any deployment-time failures are not counted as production failures because such failures don't impact the end user. For this metric to be accurate, the organization is expected to open incidents adhering to the proper format as it is crucial for Choreo to identify production failures.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#snapshot-view_3","title":"Snapshot view","text":"

      The snapshot view of this metric visualizes the change failure rate as a percentage for the selected time period. This will be the absolute percentage for the entire time period. When deciding on the time, the time of deployment is considered instead of the incident reported time. For example, the change failure rate for January 2023 will reflect the following: - All deployments that happened within January. - Any incidents that were reported at any time (in or after January) against the January deployments.

      This view helps leadership assess the quality of deliverables and identify areas for improvement. Higher rates suggest that the organization needs to improve its processes to bring in more quality assurance aspects such as improved code coverage and end-to-end test coverage.

      Additionally, Choreo also shows the percentage increase or decrease compared to the previous time period.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#time-series-view_3","title":"Time series view","text":"

      The time series view of this metric displays it as a line chart with data points corresponding to the granularity selected by the \u2018view by\u2019 selector. The absolute percentage is shown for each granularity. Hovering over the line chart displays the actual counts for the aggregated period. This chart helps leadership identify timely trends in product quality aspects. For example, this view displays the months of the year where the failure rate is high (for example, close to quarterly release/announcement dates). Also, you can use this to measure the effectiveness of changes introduced to improve quality. For example, if the organization introduced an end-to-end test pipeline integration to the PR approval process, they can use this view to factually observe the timely impact of that change and determine how it decreases the failure rate.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#mean-time-to-recovermttr","title":"Mean Time to Recover(MTTR)","text":"

      The DORA team definition: The time it takes for an organization to recover from a production failure.

      In Choreo, this measures the time from identifying a production incident to resolving it. This metric reflects the responsiveness and agility of incident management teams.

      Choreo depends on the open and close times of incidents to gather the relevant information. Therefore, for the dashboards to be accurate, organizations must follow process guidelines to update and close incident tickets efficiently in their incident management system.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#snapshot-view_4","title":"Snapshot view","text":"

      The snapshot view for this metric displays the mean recovery time for the selected time period. Choreo dynamically adjusts the time unit to measure this metric for better readability. This chart helps organizations evaluate the response time and agility of their incident handling teams, which in turn is an indication of stability. Higher MTTR means the leadership should look at new ways of improving the efficiency and agility of the teams handling incidents.

      "},{"location":"monitoring-and-insights/delivery-insights/view-dora-metrics/#time-series-view_4","title":"Time series view","text":"

      The time series view of this metric shows how the mean time to recovery changes over time on a granularity based on the \u2018view by\u2019 selector. Each time the granularity mean would be used as the aggregation factor. Hovering over the line chart displays the actual counts for the aggregated period. This view helps leadership understand timely trends on mean time to recovery, such as higher values during holiday periods when there is less staff. Also, you can use this measurement to evaluate the effectiveness of process changes such as introducing an incident response plan. The trend view clearly shows the before and after statistics and the effectiveness of the process change.

      "},{"location":"monitoring-and-insights/logs/view-pdp-logs/","title":"View Private Data Plane (PDP) Logs","text":"

      Choreo offers the capability to access runtime logs through its console. However, in cases where viewing logs for your PDP is not supported by Choreo yet, you can still view the runtime logs of your components via the log analyzing solution provided by your cloud vendor as a workaround.

      "},{"location":"monitoring-and-insights/logs/view-pdp-logs/#prerequisites","title":"Prerequisites","text":"

      Before you try out this guide, complete the following:

      1. Go to https://console.choreo.dev/, and sign in using your preferred method.
      2. Select your component from Components Listing. This will open the Overview page of your component.
      3. In the left navigation menu, click Runtime under DevOps.
      4. Copy the Release ID and the Namespace. Save it for later.
      "},{"location":"monitoring-and-insights/logs/view-pdp-logs/#view-private-data-plane-pdp-logs-with-azure-log-analytics","title":"View Private Data Plane (PDP) logs with Azure Log Analytics","text":"

      You can view your PDP logs with Azure Log Analytics by following the steps below:

      1. Go to https://portal.azure.com/.
      2. Follow the Azure Log Analytics Tutorial and open log analytics of your relative log analytics workspace.
      3. Copy and paste the query below into the query editor.
      4. Replace the <START_TIME_STAMP EX: 2023-04-10T07:07:31.684Z> and <END_TIME_STAMP EX: 2023-04-21T07:27:31.684Z> values as required. Replace the '' and '' with the values you copied by following the steps in the prerequisites section. Replace the <OPTIONAL SEARCH PHRASE> with your search term, or leave it blank if you don't require any search filtering.
      5. Run the query to extract the relevant logs.
      6. let startDateTime = datetime('<START_TIME_STAMP EX: 2023-04-10T07:07:31.684Z>');\nlet endDateTime = datetime('<END_TIME_STAMP EX: 2023-04-21T07:27:31.684Z>');\nlet releaseId = '<RELEASE_ID>';\nlet namespace = '<NAMESPACE>';\nlet searchPhrase = '<OPTIONAL SEARCH PHRASE>';\nlet startDateTimeKPI = iff(datetime_diff('second', endDateTime, startDateTime) > 60, startDateTime, endDateTime - 2m);let endDateTimeKPI = iff(datetime_diff('second', endDateTime, startDateTime) > 60, endDateTime, startDateTime + 2m);let filteredLogLevels = dynamic([]);\nlet hasNoLevelFilter = array_length(filteredLogLevels) == 0;\nlet commonKeys = dynamic(['time', 'level', 'module', 'traceId', 'spanId', 'message']);\nlet ContainerIdList = KubePodInventory\n| where TimeGenerated > startDateTimeKPI and TimeGenerated < endDateTimeKPI\n| where Namespace == namespace\n| where extractjson('$.[0].release_id', PodLabel) == releaseId\n| distinct ContainerID;\nlet data = ContainerLog\n| where TimeGenerated > startDateTime and TimeGenerated < endDateTime\n| where ContainerID in (ContainerIdList)\n| where searchPhrase == \"\" or LogEntry contains searchPhrase\n| top 126 by TimeGenerated desc\n| extend logs = parse_json(LogEntry)\n| project TimeGenerated, LogLevel = iif(isempty(logs['level']), iff(LogEntrySource == 'stderr', 'ERROR', 'INFO'), logs['level']), LogEntry = iif(isempty(logs['message']), logs, logs['message']),\nKeyValuePair = bag_remove_keys(logs, commonKeys)\n| where hasNoLevelFilter or LogLevel in (filteredLogLevels);\nlet lastTimeStamp = data | top 1 by TimeGenerated asc | project TimeGenerated;\nlet trimmedData = data | where TimeGenerated > toscalar(lastTimeStamp)| sort by TimeGenerated desc;\nlet selected = iff(toscalar(data | count) == 126, 'trimmedData', 'data');\nlet choose = (selector:string){   union   (trimmedData | where selector == 'trimmedData'),    (data | where selector == 'data')};\nchoose(selected);\n
        "},{"location":"monitoring-and-insights/logs/view-pdp-logs/#view-private-data-plane-pdp-logs-with-amazon-cloudwatch","title":"View Private Data Plane (PDP) logs with Amazon CloudWatch","text":"
        1. Go to https://portal.azure.com/.
        2. Follow the AWS Analyzing Log Data documentation and open Log Insights.
        3. Select the relevant region and the relevant log group (the log group string has the cluster name and \u201c/application\u201d appended at the end).
        4. Select the required time range.
        5. Copy the query below and paste it into the query editor.
        6. Replace the <RELEASE_ID> with the values you copied by following the steps in the prerequisites section. Replace the <OPTIONAL SEARCH PHRASE> with your search term, or leave it blank if you don't require any search filtering.
        7. Run the query to extract the logs.
        fields @timestamp, @message\n| filter kubernetes.labels.release_id == \"<RELEASE_ID>\"\n| filter @message like \"<OPTIONAL SEARCH PHRASE>\"\n
        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/","title":"Access the Choreo Insights API","text":"

        The Usage Insights page in the Choreo Console displays data retrieved from the Insights API exposed over the Internet. However, in some scenarios, you may need to retrieve data from external systems and implement custom dashboards to display the data.

        Choreo provides a secure and user-friendly approach to accomplish this requirement. Follow the steps given below:

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/#become-a-member-of-the-choreo-system-organization","title":"Become a member of the Choreo System organization","text":"
        1. Access the Developer Portal of the Choreo System organization via https://devportal.choreo.dev/choreosystem/applications and sign in using your preferred method.

        2. To obtain access to the Choreo System organization, click Request Access.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/#create-an-application-and-generate-keys","title":"Create an application and generate keys","text":"

        To create an application and generate keys, follow the steps below:

        1. To create a new application in the Choreo System organization, click + Create Application.

        2. Enter a name for the application and click Create. This creates the application and takes you to the Overview page.

        3. To subscribe to the Insights API via the newly created application, follow the steps below:

          1. In the left navigation menu, click Subscriptions.
          2. In the Subscription Management pane, click + Add APIs.
          3. Search for Insights and click Add.
        4. To generate credentials for the application, follow the steps given below:

          1. In the left navigation menu, click Production under Credentials.
          2. Click Generate Credentials. Choreo generates tokens and populates the Consumer Key and Consumer Secret fields in the Application Keys pane.
        5. To specify an appropriate token expiry time for the application, follow the steps given below:

          1. In the Application Keys pane, click to expand Advanced Configurations.
          2. Specify an appropriate value in the Application access token expiry time field and click Update.

        6. Execute the following cURL command to generate an access token:

          curl --location --request POST 'https://sts.choreo.dev/oauth2/token' \\\n--header 'Authorization: Basic <BASE64_ENCODED_CONSUMER_KEY_AND_CONSUMER_SECRET_OF_YOUR_APP_HERE>' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'grant_type=client_credentials' \\\n--data-urlencode 'orgHandle=<YOUR_ORG_HANDLE_HERE>' \\\n--data-urlencode 'scope=apim:api_manage'\n

          Info

          To obtain your organization handle, follow the steps given below:

          1. Go to https://console.choreo.dev and sign in using your preferred method.
          2. In the Choreo Console, click your username in the top right corner.
          3. In the drop-down menu, click\u00a0Settings.
          4. In\u00a0the\u00a0Organization\u00a0pane, click Copy Handle.

          You can use the generated token to access the Insights API exposed via https://choreocontrolplane.choreo.dev/93tu/insights/1.0.0/query-api.

          The following is a sample cURL command to invoke the Insights API:

          curl --location --request POST 'https://choreocontrolplane.choreo.dev/93tu/insights/1.0.0/query-api' \\\n--header 'Content-Type: application/json' \\\n--header 'Authorization: Bearer <TOKEN_HERE>' \\\n--data-raw '{\"query\":\"query ($org: OrgFilter!) {listEnvironments(org: $org){id\\n name}}\",\"variables\":{\"org\":{\"orgId\":\"<ORG_UUID_HERE>\"}}}'\n

          Tip

          • When the token expires, you can generate a new token programmatically by making an API call to the token endpoint using the client credentials grant type.
          • If a token theft occurs, you can revoke the token by making an API call to the revoke endpoint.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/","title":"Choreo Insights API","text":"

        The Choreo Insights API is a GraphQL API that allows you to retrieve data from external systems based on specific criteria. This guide describes the operations and schema-defined types you can use to retrieve data via the Choreo Insights API.

        • Allowed operations: Queries
        • Schema-defined types: Objects, Inputs, Enums, and Scalars
        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#try-out","title":"Try out","text":"

        You can try out the Choreo Insights API with your data via GraphQL Explorer.

        Warning

        The GraphQL Explorer is currently not compatible with the Safari web browser due to a known issue.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#query","title":"Query","text":"

        The query root of the Choreo Insights GraphQL API.

        Field Argument Type Description listAllAPI [API] Fetches all the APIs with the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the provider parameter to further filter the APIs by a specific provider. provider String The name of the API provider. dataFilter DataFilter! The data filter. listApplications [Application] Fetches all the applications with the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the applicationFilter parameter to further filter the applications by a specific application filter. applicationFilter ApplicationFilter The application filter. dataFilter DataFilter! The data filter. listProviders [Provider] Fetches all the API providers with the given combination of tenant ID, environment ID, and organization ID. dataFilter DataFilter! The data filter. listSubscribers [Subscriber] Fetches all the API subscribers with the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the subscriberFilter parameter to further filter the subscribers. subscriberFilter SubscriberFilter The subscriber filter. dataFilter DataFilter! The data filter. listOrganizations [Organization] Fetches all the organizations of a user. listEnvironments [Environment] Fetches all the environments of an organization. org OrgFilter! The organization filter. projectId String The project ID by which the results need to be filtered. It is optional to specify a value for this parameter. Note that providing a project ID with an on-prem key is not allowed. listTenants [String] Fetches all the tenants with the given combination of environment ID and organization ID. tenantDataFilter TenantDataFilter! The tenant filter. getTotalTraffic Int Returns the total traffic during the given time range for the specified combination of tenant ID, environment ID, and organization ID. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. getTotalErrors Int Returns the total number of errors that occurred during the given time range for the specified combination of tenant ID, environment ID, and organization ID. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. getOverallLatency Float Returns the overall response latency (95th percentile value) during the given time range for the specified combination of tenant ID, environment ID, and organization ID. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. getLatencySummary LatencySummary Returns the response latency value (95th percentile value) for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the latencySummaryFilter parameter to further filter the results. filter TimeFilter! The time filter. latencySummaryFilter LatencySummaryFilter The latency summary filter. dataFilter DataFilter! The data filter. getSuccessSummary SuccessSummary Returns the number of successful (2xx response code) hit count for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the granularity parameter to override the default granularity value. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. granularity String The granularity value. getErrorSummary ErrorSummary Returns the number of unsuccessful hits (i.e., the total of both 4xx and 5xx response codes) for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the granularity parameter to override the default granularity value. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. granularity String The granularity value. getErrorsByCategory ErrorsByCategory Returns the number of proxy errors (i.e., the total of both 4xx and 5xx response codes) by each error category for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the errorsByCategoryFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. errorsByCategoryFilter ErrorsByCategoryFilter The errors by category filter. dataFilter DataFilter! The data filter. getErrorsDetails DetailsOfErrors Returns details of each proxy error (for both 4xx and 5xx response codes) within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the errorsDetailsFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. errorsDetailsFilter ErrorsDetailsFilter The error details filter. dataFilter DataFilter! The data filter. getProxyTargetErrorsOverTime [ErrorsByStatusCodeCategory] Returns a list of hit counts for proxy and target errors for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. The errors in each proxy and target result set are grouped as 4xx, 5xx, and total. Optionally, you can configure the errorsByStatusCodeFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. errorsByStatusCodeFilter ErrorsByStatusCodeFilter The errors by status code filter. dataFilter DataFilter! The data filter. getErrorsByStatusCode ErrorsByStatusCode Returns the hit count for each error response code (401, 404, and 500 etc.,) for each API within the specified time range for the given combination of tenant ID, environment ID, and organization ID. timeFilter TimeFilter! The time filter. errorCountByStatusCodeFilter ErrorCountByStatusCodeFilter! The error count by status code filter. dataFilter DataFilter! The data filter. getTotalErrorsByAPI TotalError Returns the total proxy error hit count for an API across for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the filter parameter to further filter the results by a given time range. filter TimeFilter The time filter. dataFilter DataFilter! The data filter. apiId ID! The API ID. getAPIUsageOverTime [APIUsageOverTime] Returns a list of details related to the usage of each API over time for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the apiUsageOvertimeFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. apiUsageOvertimeFilter APIUsageOverTimeFilter The API usage overtime filter. dataFilter DataFilter! The data filter. getAPIUsageByAppOverTime APIUsageByAppOverTime Returns API usage by each application over time for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the apiUsageOvertimeFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. apiUsageOvertimeFilter APIUsageOverTimeFilter The API usage overtime filter. dataFilter DataFilter! The data filter. getAPIUsageByBackendOverTime APIUsageByBackendOverTime Returns API usage by each backend over time for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the apiUsageByBackendOverTimeFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. apiUsageByBackendOverTimeFilter APIUsageByBackendOverTimeFilter The API usage by backend overtime filter. dataFilter DataFilter! The data filter. getResourceUsage ResourceUsages Returns API usage by resource within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the resourceUsageFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. resourceUsageFilter ResourceUsageFilter The resource usage filter. dataFilter DataFilter! The data filter. getTotalTrafficByAPI Int Returns the total hit count for an API for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the filter parameter to further filter the results by a given time range. filter TimeFilter The time filter. dataFilter DataFilter! The data filter. apiId ID! The API ID. topSlowestAPIs [SlowAPI] Returns a list of top slowest APIs based on the response latency (95th percentile value) within the specified time range for the given combination of tenant ID, environment ID, and organization ID. filter TimeFilter! The time filter. dataFilter DataFilter! The data filter. limit Int! The limit for the slow APIs list. getLatency APILatency Returns different latency category values (95th percentile values) for a given API over time for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. timeFilter TimeFilter! The time filter. latencyFilter LatencyFilter! The latency filter. dataFilter DataFilter! The data filter. getOverallLatencyByAPI OverallLatency Returns the overall response latency (95th percentile value) for an API for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the filter parameter to further filter the results by a given time range. filter TimeFilter The time filter. dataFilter DataFilter! The data filter. apiId ID! The API ID. getCacheHitsAndMisses CacheHits Return the total number of response cache hits, misses, and hit percentage for an API over time for each time granularity within the specified time range for the given combination of tenant ID, environment ID, and organization ID. timeFilter TimeFilter! The time filter. cacheFilter CacheFilter The cache filter. dataFilter DataFilter! The data filter. getTopPlatforms [Platform] Returns a list of top platforms ranked based on the hit count within the specified time range for the given combination of tenant ID, environment ID, and organization ID. The result list includes the top nine platforms with the respective hit count, and all the rest of the platforms are labeled as **Other** with the cumulated hit count. Optionally, you can configure the deviceFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. deviceFilter DeviceFilter The device filter. dataFilter DataFilter! The data filter. getTopUserAgents [UserAgent] Returns a list of top user agents ranked based on the hit count within the specified time range for the given combination of tenant ID, environment ID, and organization ID. The result list includes the top nine user agents with the respective hit count, and all the rest of the platforms are labeled as **Other** with the cumulated hit count. Optionally, you can configure the deviceFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. deviceFilter DeviceFilter The device filter. dataFilter DataFilter! The data filter. getAPIUsageByGeoLocation [UsageByGeoLocation] NOTE: Currently, this operation returns data only for on-premise environments. Returns API usage by country within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the geoLocationFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. geoLocationFilter GeoLocationFilter The geolocation filter. dataFilter DataFilter! The data filter. getAPIsUsageByApplications [APIUsageByApplication] Returns details relating to the usage of each API by application within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the apiUsageByAppFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. apiUsageByAppFilter APIUsageByAppFilter The API usage by app filter. dataFilter DataFilter! The data filter. getTopAPIsByAlertCount TopAPIsByAlertCount Returns top APIs ranked based on the alert count within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the topAPIsByAlertCountFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. topAPIsByAlertCountFilter TopAPIsByAlertCountFilter The top APIs by alert count filter. dataFilter DataFilter! The data filter. getAlertSummary AlertSummaries Returns a summary for each alert within the specified time range for the given combination of tenant ID, environment ID, and organization ID. Optionally, you can configure the alertSummaryFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. alertSummaryFilter AlertSummaryFilter The alert summary filter. dataFilter DataFilter! The data filter. getSuccessAPIsUsageByApplications [SuccessAPIUsageByApplication] NOTE: This operation can only be invoked via using an on-prem key as the authentication header. Returns a list of successful hit counts (i.e., 2xx response codes) within the specified time range for each API, grouped by each application. Optionally, you can configure the successAPIUsageByAppFilter parameter to further filter the results. timeFilter TimeFilter! The time filter. successAPIUsageByAppFilter SuccessAPIUsageByAppFilter The successful API usage by application filter. getSuccessAPIsUsageByApplicationsWithOnPremKey [SuccessAPIUsageByApplication] Returns a list of successful hit counts (i.e., 2xx response codes) within the specified time range for each API, grouped by each application. Optionally, you can configure the successAPIUsageByAppFilter parameter to further filter the results. onPremKey String! The value of the On-Prem key. timeFilter TimeFilter! The time filter. successAPIUsageByAppFilter SuccessAPIUsageByAppFilter The successful API usage by application filter. getCustomReportOvertime CustomReportOvertime Returns the summary of hits or latency data as specified for the selected time duration, grouped by time spans. dataFilter DataFilter! The data filter. timeFilter TimeFilter! The time filter. metric Metric! The metric for which data needs to be retrieved. groupByFields [GroupByField]! The column/field by which data needs to be retrieved. groupByValues [String]! The value used to filter by the groupByField. granularity String! The granularity value for which data is retrieved. getCustomReportTopOvertime CustomReportTopOvertime Returns the summary of hits or latency data as specified for the selected time duration, grouped by time spans for the top N values for the selected groupByField. dataFilter DataFilter! The data filter. timeFilter TimeFilter! The time filter. metric Metric! The metric for which data needs to be retrieved. groupByFields [GroupByField]! The column/field by which the data should be grouped. groupByValues [String]! The value used to filter by the groupByField. granularity String! The granularity value for which data is retrieved. getGroupByValues [[String]] Returns a list of value sets by which you can group the data available for the selected groupBy fields. dataFilter DataFilter! The data filter. groupByFields [GroupByField]! The column/field for which the API needs to retrieve distinct values. groupByValues [String]! The value used to filter by the groupByField."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#objects","title":"Objects","text":""},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#api","title":"API","text":"

        Represents API details.

        Field Argument Type Description id ID! The ID of the API. name String! The API name. version String! The API version. provider String! The API provider name."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apilatency","title":"APILatency","text":"

        Represents latency values for a single API over time.

        Field Argument Type Description summary [Latency] A list containing latency category values over time. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusage","title":"APIUsage","text":"

        Represents the API usage for a single timestamp. The timestamp is calculated based on the granularity value provided.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' count Int! The API usage count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebyapp","title":"APIUsageByApp","text":"

        Represents API usage across APIs by a single application.

        Field Argument Type Description applicationId ID! The application ID. applicationName String! The application name. applicationOwner String! The name of the application owner. usage [APIUsage] A list containing the APIs usage values. Returns an empty array if no data is available."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebyappovertime","title":"APIUsageByAppOverTime","text":"

        Represents API usage across APIs by applications over time.

        Field Argument Type Description usage [APIUsageByApp] A list containing the API usage values across APIs, grouped by the application. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebyapplication","title":"APIUsageByApplication","text":"

        Represents a single API usage by a single application.

        Field Argument Type Description apiId String! The ID of the API. applicationId String! The Application ID. applicationName String! The application name. applicationOwner String! The name of the application owner. count Int! The usage of the API by the application."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebybackend","title":"APIUsageByBackend","text":"

        Represents API usage across APIs by a single backend.

        Field Argument Type Description backend String! The name of the backend. usage [APIUsage] A list containing the APIs usage values. Returns an empty array if no data is available."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebybackendovertime","title":"APIUsageByBackendOverTime","text":"

        Represents API usage across APIs by each backend over time.

        Field Argument Type Description usage [APIUsageByBackend] A list containing the API usage values across APIs by each backend. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusageovertime","title":"APIUsageOverTime","text":"

        Represents a single API usage over time.

        Field Argument Type Description apiId ID The ID of the API. usage [APIUsage] A list containing the API usage values. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#alertsummaries","title":"AlertSummaries","text":"

        Represents alert summaries.

        Field Argument Type Description usage [AlertSummary] A list containing the alert summary for each alert. Returns an empty array if no data is available. pagination Pagination! The pagination details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#alertsummary","title":"AlertSummary","text":"

        Represents a summary for an alert.

        Field Argument Type Description apiId ID! The ID of the API. timestamp String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' category String! The alert category. Possible values are LATENCY and TRAFFIC. metric String! The alert metric. Possible values are RESPONSE_LATENCY and TOTAL_TRAFFIC. severity String! The severity level of the alert. Possible values are LOW, MEDIUM, and HIGH. message String! The alert details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#application","title":"Application","text":"

        Represents application details.

        Field Argument Type Description id ID! The Application ID. name String! The application name. owner String! The name of the application owner."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#cachehit","title":"CacheHit","text":"

        Represents the response cache hits and misses for a single timestamp. The timestamp is calculated based on the granularity value provided.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' hits Int! The number of times the response cache was hit. misses Int! The number of times the response cache was missed. hitPercentage Float! The response cache hits as a percentage of the sum of hits and misses."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#cachehits","title":"CacheHits","text":"

        Represents the response cache hits and misses over time.

        Field Argument Type Description summary [CacheHit] A list containing cache hits, misses, and the hit percentage over time. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#customreportgroupby","title":"CustomReportGroupBy","text":"

        Represents the usage data overtime for the selected parameters of a specific groupByValue.

        Field Argument Type Description groupByValue ID! The distinct group-by value that is used as an ID. usage [CustomReportUsage] A list containing the usage values. This returns an empty array if no data is available."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#customreportovertime","title":"CustomReportOvertime","text":"

        Represents usage data overtime for the selected parameters.

        Field Argument Type Description usage [CustomReportUsage] A list containing the usage values. This returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#customreporttopovertime","title":"CustomReportTopOvertime","text":"

        Represents usage data overtime for the selected parameters grouped by the top N groupByValues.

        Field Argument Type Description usage [CustomReportGroupBy] A list containing the usage values grouped by the selected groupByField. This returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#customreportusage","title":"CustomReportUsage","text":"

        Represents usage data for a single timestamp in CustomReports.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' value Int! The usage value (Hit Count/ Latency)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#detailsoferrors","title":"DetailsOfErrors","text":"

        Represents error details over time.

        Field Argument Type Description usage [ErrorDetails]! A list containing error details over time. Returns an empty array if no data is available. pagination Pagination! The pagination details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#environment","title":"Environment","text":"

        Represents an environment.

        Field Argument Type Description id String! The environment ID. externalEnvId String! The external environment ID. internalEnvId String The internal environment ID. sandboxEnvId String The sandbox environment ID. name String! The environment name. type EnvironmentType! The environment type. A Choreo environment is labeled as CHOREO, a private Choreo environment is labeled as CHOREO_PRIVATE, and the on-premise environment is labeled as ON_PREM."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorcountbycategory","title":"ErrorCountByCategory","text":"

        Represents the number of errors from each category for a single timestamp. The timestamp is calculated according to the provided granularity value. If you select some categories, the error counts are retrieved only for those categories, and a null value is shown for the other categories that are not selected.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' auth Int The count of authorization errors. targetConnectivity Int The count of target connectivity errors. throttled Int The count of throttling errors. other Int The count of other errors."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorcountbycode","title":"ErrorCountByCode","text":"

        Represents the error count for a single error status code.

        Field Argument Type Description statusCode String! The error status code. count Int! The error count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorcountbycodeforapi","title":"ErrorCountByCodeForAPI","text":"

        Represents the error count for each status code for a single API.

        Field Argument Type Description apiId ID! The ID of the API. errorCountByCode [ErrorCountByCode] A list containing the error count for each error status code. Returns an empty array if no data is available."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errordetails","title":"ErrorDetails","text":"

        Represents details of an error for a single timestamp. The timestamp is calculated according to the granularity value provided.

        Field Argument Type Description apiId ID The ID of the API. timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' applicationId String The Application ID. applicationName String The application name. applicationOwner String The name of the application owner. reason String! The reason for the error. count Int! The error count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorstatuscodecategorycounts","title":"ErrorStatusCodeCategoryCounts","text":"

        Represents errors by the main status code (4xx or 5xx) and the total error count.

        Field Argument Type Description _4xx Int The number of client errors. _5xx Int The number of server errors. total Int The total number of client and server errors."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsummary","title":"ErrorSummary","text":"

        Provides the unsuccessful usage (i.e., 4xx and 5xx response codes) summary across all APIs.

        Field Argument Type Description summary [ErrorValue]! A list containing unsuccessful usage values. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorvalue","title":"ErrorValue","text":"

        Represents the unsuccessful request count (i.e., 4xx and 5xx response codes) for a single timestamp. The timestamp is calculated based on the granularity value provided.

        Field Argument Type Description timeSpan String Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' errorCount Int Represents the error request count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsbycategory","title":"ErrorsByCategory","text":"

        Represents the errors by category over time.

        Field Argument Type Description errors [ErrorCountByCategory] A list containing the error count for each error category over time. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsbystatuscode","title":"ErrorsByStatusCode","text":"

        Represents the error counts grouped by status code for each API.

        Field Argument Type Description errors [ErrorCountByCodeForAPI]! A list containing the error count for each status code for each API. Returns an empty array if no data is available. pagination Pagination! Pagination details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsbystatuscodecategory","title":"ErrorsByStatusCodeCategory","text":"

        Represents the error category values (grouped as 4xx, 5xx, and total) for both proxy and target errors for a single timestamp. The timestamp is calculated based on the granularity value provided.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' proxy ErrorStatusCodeCategoryCounts Represents proxy-related errors categorized as client errors (4xx response codes) or server errors (5xx response codes), and the total of both categories. target ErrorStatusCodeCategoryCounts Represents target-related errors categorized as client errors (4xx response codes) or server errors (5xx response codes), and the total of both categories."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#latency","title":"Latency","text":"

        Represents latency values for each latency category for a single timestamp. The timestamp is calculated based on the granularity value provided.

        Field Argument Type Description timeSpan String Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' response Int The response latency (95th percentile) in milliseconds (ms). backend Int The backend latency (95th percentile) in milliseconds (ms). requestMediation Int The request mediation latency (95th percentile) in milliseconds (ms). responseMediation Int The response mediation latency (95th percentile) in milliseconds (ms). responseMedian Int The median (50th percentile) of the response latency in milliseconds (ms). backendMedian Int The median (50th percentile) of the backend latency in milliseconds (ms). requestMediationMedian Int The median (50th percentile) of the request mediation latency in milliseconds (ms). responseMediationMedian Int The median (50th percentile) of the response mediation latency in milliseconds (ms)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#latencysummary","title":"LatencySummary","text":"

        Provides the latency summary.

        Field Argument Type Description summary [LatencyValue]! A list containing latency values. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#latencyvalue","title":"LatencyValue","text":"

        Represents the latency value for a single timestamp. The timestamp is calculated according to the provided granularity value.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' latencyTime Float! Represents the latency (95th percentile) time in milliseconds (ms)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#organization","title":"Organization","text":"

        Represents an organization.

        Field Argument Type Description id String! The organization ID. uuid ID! The organization UUID. handle String! The organization handle name. name String! The organization name."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#overalllatency","title":"OverallLatency","text":"

        Represents the overall latency values.

        Field Argument Type Description response Float The response latency (95th percentile value) in milliseconds (ms)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#pagination","title":"Pagination","text":"

        Represents pagination details.

        Field Argument Type Description total Int! The total number of results. limit Int! The number of items in the result set. offset Int! The offset value for the result set. sortBy String! The sorting column name of the result set. sortOrder String! The sorting order of the result set. Possible values are asc and desc."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#platform","title":"Platform","text":"

        Represents a platform.

        Field Argument Type Description platform String! The name of the platform. count Int! The usage of the platform."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#provider","title":"Provider","text":"

        Represents API Provider details.

        Field Argument Type Description name String! The API provider name."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#resourceusage","title":"ResourceUsage","text":"

        Represents the usage of a single API resource.

        Field Argument Type Description apiId ID! The ID of the API. apiResourceTemplate String! The API resource template. apiMethod String! The API method. count Int! The usage of the API resource."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#resourceusages","title":"ResourceUsages","text":"

        Represents API resource usages.

        Field Argument Type Description usage [ResourceUsage] A list with the usage of each API resource. Returns an empty array if no data is available. pagination Pagination! Pagination details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#slowapi","title":"SlowAPI","text":"

        A slow API identified based on the response latency (95th percentile).

        Field Argument Type Description apiId ID! The ID of the API. latency Int! Represents the latency (95th percentile) time in milliseconds (ms)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#subscriber","title":"Subscriber","text":"

        Represents API Subscriber details.

        Field Argument Type Description name String! The name of the API subscriber."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#successapiusagebyapplication","title":"SuccessAPIUsageByApplication","text":"

        Represents successful usages(that have resulted in the 2xx response code) of an API by an application.

        Field Argument Type Description apiId String! The ID of the API. apiName String! The name of the API. apiVersion String! The version of the API. apiCreatorTenantDomain String! The tenant domain of the API creator. applicationId String! The application ID. applicationName String! The name of the application. applicationOwner String! The name of the application owner. count Int!"},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#successsummary","title":"SuccessSummary","text":"

        Provides the successful (2xx response code) usage summary across all the APIs.

        Field Argument Type Description summary [SuccessValue]! A list containing successful usage values. Returns an empty array if no data is available. granularity String! The granularity value for which data is retrieved."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#successvalue","title":"SuccessValue","text":"

        Represents the successful request count (i.e., requests that have received the 2xx response code) for a single timestamp. The timestamp is calculated according to the granularity value provided.

        Field Argument Type Description timeSpan String! Represents a timestamp value that is calculated based on the specified granularity value. For example, if the granularity value is 1d, the timestamp represents the start of the day calculated adhering to the timezone provided in the time filter. e.g., timeSpan: '2021-06-21T00:00:00.0000000+05:30' requestCount Int! Represents the successful request count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#topapibyalertcount","title":"TopAPIByAlertCount","text":"

        Represents a top API by alert count.

        Field Argument Type Description apiId ID! The ID of the API. count Int! The alert count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#topapisbyalertcount","title":"TopAPIsByAlertCount","text":"

        Represents the top APIs by alert count.

        Field Argument Type Description usage [TopAPIByAlertCount] A list containing top APIs by alert count. Returns an empty array if no data is available. pagination Pagination! The pagination details."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#totalerror","title":"TotalError","text":"

        Represents the total errors.

        Field Argument Type Description proxy Int The proxy-related error count."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#usagebygeolocation","title":"UsageByGeoLocation","text":"

        Represents the usage of a single API in a single country.

        Field Argument Type Description country String! The name of the country. count Int! The usage of the API."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#useragent","title":"UserAgent","text":"

        Represents a user agent.

        Field Argument Type Description userAgent String! The name of the user agent. count Int! The usage of the user agent."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#inputs","title":"Inputs","text":""},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebyappfilter","title":"APIUsageByAppFilter","text":"

        Filters the API usage by application results.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. appIds [String] The results are filtered for the list of applications you specify here. A maximum of five application IDs can be defined. subscribers [String] The results are filtered for the list of subscribers you specify here. A maximum of five subscriber IDs can be defined."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusagebybackendovertimefilter","title":"APIUsageByBackendOverTimeFilter","text":"

        Filters the results for API usage by backend over time.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#apiusageovertimefilter","title":"APIUsageOverTimeFilter","text":"

        Filters the results for API usage over time.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. appIds [String] The results are filtered for the list of applications you specify here. A maximum of five application IDs can be defined. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#alertsummaryfilter","title":"AlertSummaryFilter","text":"

        Filters the alerts summary results.

        Field Type Description paginationFilter PaginationFilter The pagination filter. searchFilter SearchFilter The search filter. apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined. category String The alert category by which the results need to be filtered. The available categories to select are TRAFFIC and LATENCY."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#applicationfilter","title":"ApplicationFilter","text":"

        Filters applications by the application owner and API IDs.

        Field Type Description owner String apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#cachefilter","title":"CacheFilter","text":"

        Filters response cache results.

        Field Type Description apiId String The results are filtered by the API ID specified here. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#datafilter","title":"DataFilter","text":"

        Filters results by the given combination of organization, environment, and tenant.

        Field Type Description orgId String! The organization by which the results need to be filtered. It is required to specify a value for this parameter. environmentId String The environment ID by which the results need to be filtered. It is required to specify a value for this parameter. environmentIds [String] The environment IDs by which the results need to be filtered. It is required to specify a value for this parameter. tenant String! The name of the tenant by which the results need to be filtered. It is required to specify a value for this parameter. projectId String The project ID by which the results need to be filtered. It is optional to specify a value for this parameter. Note that providing a project ID with an on-prem key is not allowed."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#devicefilter","title":"DeviceFilter","text":"

        Filters results related to devices.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorcountbystatuscodefilter","title":"ErrorCountByStatusCodeFilter","text":"

        Filters errors by status code results.

        Field Type Description apiId String The results are filtered by the API ID specified here. errorType ErrorType! The type of the error. It is required to specify a value for this parameter. errorCodeType ErrorCodeType The error code type. If this parameter is not configured, both client-related error response codes (401, 404, etc.) and server-related response codes (500, 501, etc.) are included in the result set. paginationFilter PaginationFilter The pagination filter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsbycategoryfilter","title":"ErrorsByCategoryFilter","text":"

        Filters errors by category results.

        Field Type Description apiId String The ID of the API. categories [String] The list of categories by which the results need to be filtered. Category values that you can specify here are AUTH, TARGET_CONNECTIVITY, THROTTLED, and OTHER. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsbystatuscodefilter","title":"ErrorsByStatusCodeFilter","text":"

        Filters errors by status code results.

        Field Type Description apiId String The results are filtered by the API ID specified here. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorsdetailsfilter","title":"ErrorsDetailsFilter","text":"

        Filters the results for error details.

        Field Type Description apiId String The results are filtered by the API ID specified here. appId String The application ID by which the results need to be filtered. category String The error category by which the results need to be filtered. The error category that you can specify here must be one of the AUTH TARGET_CONNECTIVITY, THROTTLED, and OTHER values. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d. paginationFilter PaginationFilter The pagination filter. searchFilter SearchFilter The search filter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#geolocationfilter","title":"GeoLocationFilter","text":"

        Filters the API usage by geolocation results.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#latencyfilter","title":"LatencyFilter","text":"

        Filters latency results.

        Field Type Description apiId String! The results are filtered by the API ID specified here. It is required to specify a value for this parameter. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#latencysummaryfilter","title":"LatencySummaryFilter","text":"

        Filters latency summary results.

        Field Type Description apiId String The results are filtered by the API ID specified here. granularity String The granularity value that is used for data retrieval. If the granularity value is not set, the default granularity for the related time range is applied. The possible granularity values that you can specify are 1m, 15m, 1h, 1d, and 7d."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#orgfilter","title":"OrgFilter","text":"

        Filters results for the given organization.

        Field Type Description orgId String! The ID of the organization by which the results need to be filtered. It is required to specify a value for this parameter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#paginationfilter","title":"PaginationFilter","text":"

        Filters related to pagination.

        Field Type Description limit Int The total number of rows in the result set. This value must be a positive integer. If this limit value is not set, the total number of rows is five by default. offset Int The offset value to set when filtering results. This value must be zero or a positive integer. If you do not specify an offset value, the default offset value (i.e., 0) applies. sortBy String The column name by which the results are sorted. If the sortBy value is not set, the default column of the related operation that is available for sorting purposes is used. sortOrder String The order in which the results are sorted. Possible values are asc (to sort in ascending order) and desc (to sort in descending order). If no value is specified, the results are sorted in ascending order by default (except for count-specific operations such as getTopAPIsByAlertCount where the results are always sorted in descending order)."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#resourceusagefilter","title":"ResourceUsageFilter","text":"

        Filters resource usage results.

        Field Type Description paginationFilter PaginationFilter The pagination filter. searchFilter SearchFilter The search filter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#searchfilter","title":"SearchFilter","text":"

        Filters results by searching matching results for the provided search text.

        Field Type Description apiIds [String] The list of API IDs that need to be searched with the given search text. Note that it is not possible to define API IDs without a search text in the search filter. searchText String! Text which needs to be searched among the results. It is required to specify a value for this parameter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#subscriberfilter","title":"SubscriberFilter","text":"

        Filters the subscriber results.

        Field Type Description apiIds [String] The results are filtered for the list of APIs you specify here. A maximum of five API IDs can be defined."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#successapiusagebyappfilter","title":"SuccessAPIUsageByAppFilter","text":"

        Filters successful API usage by application results.

        Field Type Description apiIds [String] The list of API IDs by which the results need to be filtered. tenantDomains [String] The tenant domain name by which the results need to be filtered."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#tenantdatafilter","title":"TenantDataFilter","text":"

        Filters results by the tenant.

        Field Type Description orgId String! The ID of the organization by which the results need to be filtered. It is required to specify a value for this parameter. envId String The ID of the environment by which the results need to be filtered. It is required to specify a value for this parameter. environmentIds [String] The environment IDs by which the results need to be filtered. It is required to specify a value for this parameter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#timefilter","title":"TimeFilter","text":"

        Filters results by the provided date range.

        Field Type Description from String! The start date of the time range. The date specified here must be a date earlier than the date specified via the to parameter. If the defined date and time entry do not have a timezone, the UTC time zone (z) is used. It is required to specify a value for this parameter. e.g., '2021-08-16T12:00:00.000+05:30'. to String! The end date of the time range. The date specified here must be a date later than the date specified via the from parameter. If the defined date and time entry do not have a timezone, the UTC time zone (z) is used. It is required to specify a value for this parameter. e.g., '2021-08-16T12:30:00.000+05:30'."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#topapisbyalertcountfilter","title":"TopAPIsByAlertCountFilter","text":"

        Filters the top APIs by alert count results.

        Field Type Description paginationFilter PaginationFilter The pagination filter. searchFilter SearchFilter The search filter."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#enums","title":"Enums","text":""},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#environmenttype","title":"EnvironmentType","text":"

        Represents an error type.

        Value Description CHOREO The Choreo environments. CHOREO_PRIVATE The private data-plane Choreo environments. ON_PREM The On-Premise environments."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errorcodetype","title":"ErrorCodeType","text":"

        Represents an error code type.

        Value Description _4XX The client-side errors. _5XX The server-side errors."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#errortype","title":"ErrorType","text":"

        Represents an error type.

        Value Description PROXY The proxy-related errors. TARGET The target-related errors."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#groupbyfield","title":"GroupByField","text":"

        Represents an groupByField used in CustomReports.

        Value Description API_NAME The API name. API_VERSION The API version. API_RESOURCE_TEMPLATE The API resource template. API_METHOD The API method. API_CREATOR The API creator. APPLICATION_NAME The name of the application. APPLICATION_OWNER The owner of the application. DESTINATION The destination. USER_AGENT The user Agent. PLATFORM The platform. TARGET_RESPONSE_CODE The target response code."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#metric","title":"Metric","text":"

        Represents a metric used in CustomReports.

        Value Description HIT_COUNT The number of API calls. RESPONSE_CACHE_HIT The number of API calls that used the response cache. REQUEST_MEDIATION_LATENCY The request mediation latency. RESPONSE_MEDIATION_LATENCY The response mediation latency. BACKEND_LATENCY The backend latency. TOTAL_LATENCY The total latency. API_ERRORS The number of hits for which API errors are returned. TARGET_ERRORS The number of hits for which target errors are returned."},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#scalars","title":"Scalars","text":""},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#boolean","title":"Boolean","text":"

        The Boolean scalar type represents true or false.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#float","title":"Float","text":"

        The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#id","title":"ID","text":"

        The ID scalar type represents a unique identifier, often used to re-fetch an object or as the key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as \"4\") or integer (such as 4) input value is accepted as an ID.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#int","title":"Int","text":"

        The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.

        "},{"location":"monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/#string","title":"String","text":"

        The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/","title":"Deploy a Web Application that Consumes a Backend Service","text":"

        Choreo is an Internal Developer Platform (IDevP) that streamlines the entire process of building, deploying, monitoring, and managing your cloud-native applications easily.

        In this quick start guide, you will explore how to expose a service endpoint via Choreo and securely consume the service from a web application. You will use a simple reading list web application with a sign-in page and functionality to interact with a secure backend service. You will also use Choreo's managed authentication to easily set up authentication for your web application without having to dive into the details of security protocols. The application will allow users to sign in and view their reading lists, add books to a reading list, delete books from the reading list, and sign out of the application effortlessly.

        This guide walks you through the following steps:

        • Deploy and test a service component.
        • Create a web application to consume the exposed service.
        • Create a connection to the deployed service.
        • Enable managed authentication and deploy the web application.
        • Consume the deployed service via the web application.
        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#prerequisites","title":"Prerequisites","text":"

        Before you try out this guide, complete the following:

        1. Create a GitHub repository to save the service implementation. For this guide, you can fork the Choreo sample book list app repository.

        2. If you are signing in to the Choreo Console for the first time, create an organization as follows:

          1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
          2. Enter a unique organization name. For example, Stark Industries.
          3. Read and accept the privacy policy and terms of use.
          4. Click Create.

          This creates the organization and opens the organization home page.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-1-create-a-project","title":"Step 1: Create a project","text":"

        Follow the steps given below to create a project:

        1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
        2. On the organization home page, click + Create Project.
        3. Enter a display name, unique name, and description for the project. You can enter the values given below:

          Tip

          In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

          Field Value Project Display Name Sample project Name sample-project Project Description My sample project
        4. Click Create. This creates the project and opens the project home page.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-2-connect-your-sample-repository-and-configure-the-sample-service","title":"Step 2: Connect your sample repository and configure the sample service","text":"

        To connect to the repository you forked in the prerequisites and configure the sample service, follow the steps given below:

        1. On the project home page, click Start under Create Multiple Components.
        2. Go to the GitHub tab.
        3. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

          Alternatively, you can paste the Choreo sample book list app repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

          Note

          The Choreo GitHub App requires the following permissions:

          • Read and write access to code and pull requests.
          • Read access to issues and metadata.

          You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

        4. Enter the following information:

          Field Value Organization Your GitHub account Repository choreo-sample-book-list-app Branch main
        5. In the Add Component Directories pane under Configure Components, click the + icon corresponding to reading-list-service.

        6. In the Component Configuration dialog that opens, specify values as follows for each of the fields:

          Field Value Component Display Name Reading List Service Component Name reading-list-service Path reading-list-service Component Type Service Buildpack NodeJS Language Version 20.x.x
        7. Click Save. This adds the Reading List Service component to the Configured Components pane.

        8. Click Finish. This initializes the service with the implementation from your GitHub repository and takes you to the project home page.

          You can see the Reading List Service component listed under Component Listing on the project home page.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-3-build-the-service","title":"Step 3: Build the service","text":"

        To build the service, follow the steps given below:

        1. On the project home page, click the Reading List Service component listed under Component Listing. This takes you to the component overview page.
        2. In the left navigation menu, click Build.
        3. In the Builds pane, click Build Latest.

        !!! note Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-4-deploy-the-service","title":"Step 4: Deploy the service","text":"

        For the REST endpoint of the service to be invokable, you need to deploy it. To deploy the service, follow the steps given below:

        1. In the left navigation menu, click Deploy.
        2. In the Set Up card, click Configure & Deploy.
        3. In the Environment Configurations pane that opens, click Next to skip the configuration.
        4. In the File Mount pane that opens, click Next to skip the configuration.
        5. In the Endpoint Details pane that opens, verify that the Network Visibility is set to Public. This setting securely exposes the endpoint for consumption.
        6. Click Deploy. This deploys the service to the development environment and lists the service in the Choreo Marketplace.
        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-5-test-the-service","title":"Step 5: Test the service","text":"

        To test the endpoint via the integrated OpenAPI Console in Choreo, follow the steps given below:

        1. In the Choreo Console left navigation menu, click Test and then click Console.
        2. In the OpenAPI Console that opens, select Development from the environment drop-down list.
        3. In the Endpoint list, select Books REST Endpoint.
        4. Expand the GET/books method, click Try it out, then click Execute.
        5. Click .
        6. Check the Server Response section. You will see an empty response. You can add an entry using the POST method and retry the GET/books method again.
        7. Expand the POST/books method and click Try it out.
        8. Update the request body so that the parameters have the values given below:

          Parameter Value author Bram Stoker status to_read title Dracula

          The request body should look as follows:

            {\n\"author\": \"Bram Stoker\",\n\"status\": \"to_read\",\n\"title\": \"Dracula\"\n}\n
          9. Click Execute.

          Check the Server Response section. On successful invocation, you will receive the 201 HTTP code.

        Similarly, you can expand and try out the GET and DELETE methods.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-6-consume-the-service","title":"Step 6: Consume the service","text":"

        Now that the Reading List Service is deployed and available in the Choreo Marketplace, application developers can discover the service via the Marketplace and consume it.

        In this section of the guide, you will deploy a sample front-end application to consume the service. This application will serve as the interface for users to interact with the reading list. The sample application used in this guide is designed to personalize the book lists based on the user ID that it obtains from its identity provider.

        To host the front-end application in Choreo, you will create a web application component, set up authentication for it, and deploy it. To establish a connection between your web application and the deployed service, you will create a Connection.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-61-create-a-web-application-to-consume-the-service","title":"Step 6.1: Create a web application to consume the service","text":"

        To create a web application component, follow the steps given below:

        1. In the Choreo Console header, click the Project list and select the project that you created in step 1.
        2. On the project home page, click + Create under Component Listing.
        3. Click the Web Application card.
        4. Enter a display name, unique name, and a description to create the web application. You can enter the values given below:

          Info

          In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

          Field Value Component Display Name Reading List Web App Component Name reading-list-web-app Description Front-end application for the reading list service
        5. Go to the GitHub tab.

        6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

          Alternatively, you can paste the Choreo sample Book List Service repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

          Note

          The Choreo GitHub App requires the following permissions:

          • Read and write access to code and pull requests.
          • Read access to issues and metadata.

          You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

        7. Enter the following information:

          Field Description Organization Your GitHub account Repository choreo-sample-book-list-app Branch main
        8. Select React as the buildpack because the sample front-end application is a React application built with Vite.

        9. Enter the following information:

          Field Value Project Directory /choreo-sample-book-list-app/reading-list-front-end-with-managed-auth Build Command npm install && npm run build Build Path dist Node Version 18
        10. Click Create. This initializes the component with the implementation from your GitHub repository and takes you to the Overview page of the component.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-62-create-a-connection-between-the-web-application-and-the-deployed-service","title":"Step 6.2: Create a connection between the web application and the deployed service","text":"

        A connection allows you to integrate the service you intend to deploy on Choreo with other services on Choreo or external resources. For more information on Choreo Connections refer to the Connection documentation.

        To establish a connection between the web application you created and the deployed service, follow the steps given below:

        1. In the left navigation menu, click Dependencies and then click Connections.
        2. Click + Create.
        3. In the Select a Service pane, click Reading List Service.`
        4. Specify values as follows for each of the fields:

          Field Value Name Reading List Connection Description Connection to the reading list
        5. Click Create. This creates the connection and displays the service URL of the connection for each environment the service is deployed in. In this guide, you will see the service URL for the Development environment. You can copy the service URL to use when you configure the web application before deploying it.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-63-build-the-web-application-component","title":"Step 6.3: Build the web application component","text":"

        To build the web application, follow the steps given below:

        1. In the left navigation menu, click Build.
        2. In the Builds pane, click Build Latest.

        !!! note Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-64-configure-and-deploy-the-web-application","title":"Step 6.4: Configure and deploy the web application","text":"

        In this step, you will configure managed authentication, create a user to access the web application, and then deploy the web application. For more information on Choreo's managed authentication capability, see the Managed Authentication documentation.

        To configure managed authentication, follow the steps given below:

        1. In the left navigation menu, click Deploy.
        2. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can specify values for the mount file.
        3. Specify the following in the config.js file mount.

          • You must replace <Service URL> with the value that you copied when creating a connection to the Reading List Service in step 6.2.

            window.configs = {\napiUrl: '<Service URL>',\n};\n

          Tip

          You can refer to the configuration file mounted at /app/public as ./public/config.js within your web application.

        4. Click Next. This opens the Authentication pane.

        5. Under Authentication Settings, make sure that you have the Managed authentication with Choreo toggle enabled.

          Tip

          Managed authentication is enabled by default when you create a web application using React, Angular, or Vue.js buildpacks.

        6. Specify values as follows for each of the fields:

          Field Value Post Login Path / Post Logout Path / Error Path /

        Next, you can create a user to access the web application.

        To create a user to access the readingListApp application, follow the steps given below:

        1. Under Manage Users, click + Create.
        2. To proceed with creating a user with the populated username and password, click Create. Make sure you copy the populated username and password to use when you test the front-end application.

          Tip

          • By default, your test user base consists of a demo user. For instructions on how to modify the test user base, see Configure a User Store with the Built-In Identity Provider.

        Now, you can deploy the web application.

        To deploy the web application and obtain the URL to access it, follow the steps given below:

        1. In the Authentication pane, click Deploy. The deployment may take a few minutes to complete.
        2. Once you deploy the web application, copy the Web App URL from the development environment card.
        3. Navigate to the web app URL. You can verify that you have successfully hosted the web application.
        "},{"location":"quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/#step-7-test-the-front-end-application","title":"Step 7: Test the front-end application","text":"

        To test the front-end application and send requests to the Reading List Service via it, follow the steps given below:

        1. Access the front-end application via its web URL that you copied in the above step.
        2. Click Login, and sign in with the credentials of the user that you created.

          The application opens as follows.

        3. Add three new reading items with different statuses.

          For example, the details can be as follows:

          Title Author Status The Museum of Innocence Orhan Pamuk reading The Remains of the Day Kazuo Ishiguro to_read David Copperfield Charles Dickens read

          To add each record, follow the steps given below:

          1. Click + Add New.
          2. Enter values for the Name, Author, and Status fields.
          3. Click Save.

          Three tabs open for each status. To delete a reading list item, you can click Delete.

        To verify whether the reading list is personalized for each user, you can sign in as a different user. The reading list items you entered above will not appear for the other user.

        Congratulations! You have successfully exposed a service endpoint via Choreo and securely consumed it from a web application.

        After you have successfully tested your service and web application, you can now try out various other Choreo features such as managing, observing, DevOps, etc., similar to any other component type within Choreo.

        "},{"location":"quick-start-guides/deploy-your-first-service/","title":"Deploy Your First Service","text":"

        Choreo, an Internal Developer Platform (IDevP), simplifies the deployment, monitoring, and management of your cloud-native services, allowing you to focus on innovation and implementation.

        Choreo allows you to easily deploy services you've created in your preferred programming language in just a few steps.

        In this guide, you will:

        • Use a pre-implemented service that has resources to maintain a book list.
        • Build and deploy the service in Choreo using the Nodejs buildpack. It runs on port 8080.
        • Test the service.

        For a video tutorial that walks you through these steps, see Deploy Your First Service with Choreo.

        "},{"location":"quick-start-guides/deploy-your-first-service/#prerequisites","title":"Prerequisites","text":"
        1. You must have a GitHub account with a repository that contains your service implementation. To proceed with the steps in this guide, you can fork the Choreo sample book list service repository, which contains the sample for this guide.

        2. If you are signing in to the Choreo Console for the first time, create an organization as follows:

          1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
          2. Enter a unique organization name. For example, Stark Industries.
          3. Read and accept the privacy policy and terms of use.
          4. Click Create.

          This creates the organization and opens the organization home page.

        "},{"location":"quick-start-guides/deploy-your-first-service/#learn-the-repository-file-structure","title":"Learn the repository file structure","text":"

        Let's familiarize ourselves with the key files in this sample application. The below table gives a brief overview of the important files in the sample book list service.

        Note

        The following file paths are relative to the path <choreo-sample-book-list-service>/.

        Filepath Description app.mjs The Node.js (JavaScript) based service code. .choreo/component.yaml Choreo-specific configuration that provides information about how Choreo exposes the service. openapi.yaml OpenAPI contract of the service. This is required to publish our service as a managed API. This openapi.yaml file is referenced by the .choreo/component.yaml.

        Let's get started!

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-1-create-a-project","title":"Step 1: Create a project","text":"

        Follow the steps given below to create a project:

        1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
        2. On the organization home page, click + Create Project.
        3. Enter a display name, unique name, and description for the project. You can enter the values given below:

          Info

          In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

          Field Value Project Display Name Book List Project Name book-list-project Project Description My sample project
        4. Click Create. This creates the project and takes you to the project home page.

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-2-create-a-service-component","title":"Step 2: Create a service component","text":"

        Let's create a service component by following these steps:

        1. On the project home page, click Service under Create a Component.
        2. Enter a unique name and a description for the service. For this guide, let's enter the following values:

          Field Value Component Display Name Book List Description Gets the book list
        3. Go to the GitHub tab.

        4. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

          Alternatively, you can paste the Choreo sample Book List Service repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

          Note

          The Choreo GitHub App requires the following permissions:

          • Read and write access to code and pull requests.
          • Read access to issues and metadata.

          You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

        5. Enter the following information:

          Field Description Organization Your GitHub account Repository choreo-sample-book-list-service Branch main
        6. Select the NodeJS buildpack.

        7. Enter the following information.

          Field Description NodeJS Project Directory / Language Version 20.x.x
        8. Click Create.

        You have successfully created a Service component with the NodeJS buildpack. Now let's build and deploy the service.

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-3-build-and-deploy","title":"Step 3: Build and deploy","text":"

        Now that the source repository is connected and Choreo has set up the endpoints based on the repository's configuration, it's time to proceed with building the service. Choreo will create a Docker image in the build process. You can then deploy the built Docker image and test the book list service.

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-31-build","title":"Step 3.1: Build","text":"

        To build the service, follow these steps:

        1. On the project home page, click the Book List component listed under Component Listing. This takes you to the component overview page.
        2. In the left navigation, click Build.
        3. Click Build Latest.

        !!! note Building the service component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-32-deploy","title":"Step 3.2: Deploy","text":"

        Now you are ready to deploy the service. Follow these steps:

        1. In the left navigation menu, click Deploy.
        2. On the Set Up card, click Configure & Deploy.
        3. In the Environment Configurations pane, click Next.
        4. In the File Mount pane, click Next.
        5. Review the Endpoint Details and click Deploy.

          Note

          Deploying the service component may take a while. You can track the progress by observing the logs. Once the deployment is complete, the build status changes to Active on the Development environment card.

        "},{"location":"quick-start-guides/deploy-your-first-service/#step-4-test-the-service","title":"Step 4: Test the service","text":"

        To test the Book List service via the integrated OpenAPI Console in Choreo, follow the steps given below:

        1. In the Choreo Console left navigation menu, click Test and then click Console.
        2. In the OpenAPI Console that opens, select Development from the environment drop-down list.
        3. In the Endpoint list, select Books REST Endpoint.
        4. Expand the GET /books method and click Try it out.
        5. Click Execute.
        6. Check the Server Response section.

        Similarly, you can expand and try out the other methods.

        After you have successfully tested your service, you can now try out various other Choreo features such as managing, observing, DevOps, etc., similar to any other component type within Choreo.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/","title":"Deploy Your First Static Web Application","text":"

        Choreo is an internal developer platform as a service that takes care of the complexities of building platforms, allowing application developers to focus on innovation and implementation. Choreo streamlines the entire process of building, deploying, monitoring, and managing your cloud-native applications.

        In this quick start guide, you will explore how easy it is to deploy a web application using Choreo. Here, you will use a simple web application designed to add tasks to a to-do list.

        This guide walks you through the following steps:

        • Create a project.
        • Create a Web Application component and connect it to the GitHub repository that includes the web application implementation.
        • Build the web application.
        • Deploy the web application and access it.

        For a video tutorial that walks you through these steps, see Deploy a Static Web App on Choreo.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/#prerequisites","title":"Prerequisites","text":"

        Before you try out this guide, complete the following:

        1. Fork the choreo-sample-todo-list-app repository, which contains the sample for this guide.
        2. If you are signing in to the Choreo Console for the first time, create an organization as follows:

          1. Go to https://console.choreo.dev/, and sign in using your Google, GitHub, or Microsoft account.
          2. Enter a unique organization name. For example, Stark Industries.
          3. Read and accept the privacy policy and terms of use.
          4. Click Create.

          This creates the organization and opens the organization home page.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/#step-1-create-a-project","title":"Step 1: Create a project","text":"

        Follow the steps given below to create a project:

        1. Go to https://console.choreo.dev/ and sign in. This opens the organization home page.
        2. On the organization home page, click + Create Project.
        3. Enter a display name, unique name, and description for the project. You can enter the values given below:

          Tip

          In the Name field, you must specify a name to uniquely identify your project in various contexts. The value is editable only at the time you create the project. You cannot change the name after you create the project.

          Field Value Project Display Name Sample project Name sample-project Project Description My sample project
        4. Click Create. This creates the project and opens the project home page.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/#step-2-create-a-web-application-component","title":"Step 2: Create a Web Application component","text":"

        To create a Web Application component, follow the steps given below:

        1. On the project home page, click Web Application under Create a Component.
        2. Enter a unique name and a description for the web application.
        3. Go to the GitHub tab.
        4. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

          Alternatively, you can paste the choreo-sample-todo-list-app repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

          Note

          The Choreo GitHub App requires the following permissions:

          • Read and write access to code and pull requests.
          • Read access to issues and metadata.

          You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

        5. Enter the following information:

          Field Value Organization Your GitHub account Repository choreo-sample-todo-list-app Branch main
        6. Select NodeJS as the Buildpack

        7. Enter the following information:

          Field Value NodeJS Project Directory / Language Version 20.x.x Port 8080
        8. Click Create. Choreo initializes the component with the sample implementation and opens the Overview page of the component.

        Now let's build and deploy the web application.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/#step-3-build-your-web-application","title":"Step 3: Build your web application","text":"

        To build the web application, follow the steps given below:

        1. In the left navigation menu, click Build.
        2. In the Builds pane, click Build Latest.

          Note

          Building the component may take a while. You can track the progress via the logs in the Build Details pane. Once the build process is complete, the build status changes to Success.

        Now you can proceed to deploy your web application.

        "},{"location":"quick-start-guides/deploy-your-first-static-web-application/#step-4-deploy-and-access-your-web-application","title":"Step 4: Deploy and access your web application","text":"
        1. In the left navigation menu, click Deploy.
        2. In the Set Up card, click Configure and Deploy. This opens the Configure & Deploy pane, where you can add a file mount if necessary. In this guide you will not add a file mount.
        3. Click Deploy. The deployment to the Development environment may take a few minutes to complete. On successful deployment, you will see the Deployment Status as Active in the Development card.
        4. To verify that you have successfully hosted the web application, click the Web App URL on the Development card. This takes you to the web application. You can try creating one or more new tasks by specifying an appropriate task ID and task label.

        After you have successfully tested your web application, you can now try out various other Choreo features such as observability, DevOps, etc., similar to any other component type within Choreo.

        "},{"location":"references/choreo-limitations/","title":"Choreo Limitations","text":"

        Explore key limitations in Choreo, covering areas like HTTP request parameters, components, applications, and API definition files. You can gain insights into the limitations to enhance your understanding and optimize your use of Choreo effectively.

        "},{"location":"references/choreo-limitations/#api-management-limits","title":"API management limits","text":"

        Below are key limitations when working with APIs in Choreo:

        Resource Limit Maximum request payload 10 MB URL size 2 KB Request header
        • Request Headers total: 40 KB
        • Max Single Request header: 10 KB
        Total request duration
        • Minimum: 10 seconds
        • Default: 1 minute
        • Maximum: 5 minutes
        Maximum connection duration (WebSocket APIs) 15 minutes Connection idle timeout (WebSocket APIs) 5 minutes Size for API definition (OpenAPI document) 10 Mb Number of APIs for PDP 1000 API deployments Number of APIs per organization (free tier) 5 APIs for free users Number of Developer Portal applications per organization (free tier) 10 applications for free users"},{"location":"references/choreo-limitations/#choreo-cloud-data-plane-limits","title":"Choreo cloud data plane limits","text":"

        Below are key limitations when working with web applications in the Choreo cloud data plane:

        Resource Limit Request size limit (including headers, cookies, and payloads) 256 KB Response body size limit 20 MB Number of open ports permitted per web application 1 While it is possible to have multiple ports open for project-level communication within a data plane, incoming internet traffic can only be directed to a single port. This contrasts with Service-type components, which allow for multiple endpoints."},{"location":"references/choreo-platform-services-billing/","title":"Choreo Platform Services Billing","text":"

        The platform services you create in your Choreo Organization, such as databases, caches, or Kafka services are billed as part of your existing Choreo subscription. The cost is determined by the usage and service plan of each resource you create.

        Key billing information:

        • Hourly billing: Usage is billed based on the number of hours a resource is active. For example, if you create a database, cache, or Kafka service and remove it within the same month, you only pay for the number of hours it was active.
        • Fixed pricing: Pricing is based on the selected service plan. Choreo does not charge extra for network bandwidth usage.

        Try out the free trial

        Choreo provides a 7-day free trial for all database types on the 'Hobbyist' service plan, available to free-tier users.

        "},{"location":"references/faq/","title":"Frequently Asked Questions","text":""},{"location":"references/faq/#general","title":"General","text":""},{"location":"references/faq/#q-what-is-choreo","title":"Q: What is Choreo?","text":"

        Choreo is an internal developer platform designed to accelerate the creation of digital experiences. With Choreo, you can effortlessly build, deploy, monitor, and manage your cloud native applications. Our goal is to enhance developer productivity and enable innovation.

        "},{"location":"references/faq/#q-what-is-an-organization-in-choreo","title":"Q: What is an organization in Choreo?","text":"

        An organization is a logical grouping of users and their resources. It may represent a company, community, or a single user. Users can belong to multiple organizations, and each organization can have different roles assigned to its users to control access to Choreo features.

        "},{"location":"references/faq/#q-what-is-a-project-in-choreo","title":"Q: What is a project in Choreo?","text":"

        A project is a logical grouping of related components to help you organize your work. Each project provides runtime isolation through namespaces when you deploy components.

        "},{"location":"references/faq/#q-what-is-a-component-in-choreo","title":"Q: What is a component in Choreo?","text":"

        A component is a workload designed to run on Choreo. Examples of components include integrations, APIs, microservices, manual/scheduled jobs, web apps, and triggers.

        "},{"location":"references/faq/#q-what-is-the-difference-between-an-internal-and-external-api","title":"Q: What is the difference between an internal and external API?","text":"

        In Choreo, you can publish an API as an internal or an external API. A user or an application can access an external API publicly over the internet, whereas an internal API is only accessible through other components within the same organization.

        "},{"location":"references/faq/#q-what-is-a-connector-in-choreo-marketplace","title":"Q: What is a connector in Choreo Marketplace?","text":"

        A connector is a reusable Ballerina package that simplifies connecting to external or internal systems and APIs, such as Salesforce, SAP, GitHub, and Twilio. You can use the connectors available in the Choreo marketplace to implement your integration use cases. Connectors can be created and published by both WSO2 and Choreo users.

        "},{"location":"references/faq/#q-what-is-a-trigger-in-choreo-marketplace","title":"Q: What is a trigger in Choreo Marketplace?","text":"

        A trigger is a construct that enables users to receive known event payloads from external systems, facilitating event-driven programming.

        "},{"location":"references/faq/#q-what-is-a-sampletemplate-in-choreo","title":"Q: What is a sample/template in Choreo?","text":"

        A sample or template is a prebuilt Ballerina program that covers a popular integration use case or pattern. Examples include connecting Salesforce to Slack or implementing content-based routing.

        "},{"location":"references/faq/#q-what-are-the-support-options-in-choreo","title":"Q: What are the support options in Choreo?","text":"

        You can find information about our support plans, including free, basic, and enterprise options at https://wso2.com/choreo/customer-support/.

        "},{"location":"references/faq/#q-how-can-i-perform-log-monitoring-or-analytics-for-the-azure-environment","title":"Q: How can I perform log monitoring or analytics for the Azure environment?","text":"

        If you have a log monitoring product or service, such as Azure Monitor, you can use it together with Choreo. Note: The log monitoring tool is not included in the infrastructure cost.

        "},{"location":"references/faq/#q-what-is-the-maximum-request-payload-size-supported-by-choreo","title":"Q: What is the maximum request payload size supported by Choreo?","text":"

        Choreo allows a maximum request payload size of 10 MB.

        "},{"location":"references/faq/#q-what-source-control-software-does-choreo-support","title":"Q: What source control software does Choreo support?","text":"

        Choreo now supports GitHub, Bitbucket and GitLab.

        "},{"location":"references/faq/#q-why-dont-i-see-the-undeployed-builds-for-my-component-in-choreo","title":"Q: Why don't I see the undeployed builds for my component in Choreo?","text":"

        You are allowed to build your component any number of times. However, Choreo has a limit on retaining undeployed builds. For users on the free-tier, Choreo will retain only one undeployed build. For those on any other tier, Choreo will retain the latest five undeployed builds.

        "},{"location":"references/faq/#q-what-is-ballerina","title":"Q: What is Ballerina?","text":"

        Ballerina is an open-source programming language designed for the cloud. It simplifies the process of using, combining, and creating network services. When you use Ballerina to write integrations in Choreo, you can save time and deliver 2-3x faster. To learn more, check out https://ballerina.io/.

        "},{"location":"references/faq/#q-what-is-asgardeo","title":"Q: What is Asgardeo?","text":"

        Asgardeo is an identity provider (IdP) that allows developers to secure access for consumers, business partners, employees, and APIs. Asgardeo is Choreo\u2019s default IDP. To learn more, visit https://wso2.com/asgardeo/.

        "},{"location":"references/faq/#q-why-dont-i-see-the-region-selector-on-the-project-creation-page","title":"Q: Why don\u2019t I see the region selector on the project creation page?","text":"

        If you are a Choreo cloud data plane user, you can create projects in multiple regions only if you have a paid subscription in Choreo. Otherwise, your projects will be created in the same region you selected when onboarding the organization.

        If you are a private data plane user, there will be no region selector in project creation at all.

        "},{"location":"references/faq/#q-as-a-cloud-data-plane-user-how-can-i-create-components-in-multiple-data-planes","title":"Q: As a Cloud Data Plane user, how can I create components in multiple data planes?","text":"

        When an organization admin onboards a new organization in Choreo, they can choose the preferred data plane. Choreo then sets the selected data plane as the default for the entire organization. Subsequently, users within the free tier of the cloud data plane can create components only in the set default data plane. If a free-tier user needs to create components in a different data plane, the user must get a paid subscription.

        "},{"location":"references/faq/#security-and-data-protection","title":"Security and data protection","text":""},{"location":"references/faq/#q-how-is-data-managed-in-choreo","title":"Q: How is data managed in Choreo?","text":"

        Choreo manages data using WSO2 containers and Kubernetes clusters, which provide scalability, resilience, and security. Find out more here.

        "},{"location":"references/faq/#q-what-is-the-wso2-subprocessor-list","title":"Q: What is the WSO2 Subprocessor list?","text":"

        This is a detailed list of all subprocessors used by WSO2, including their name, location, and purpose. This information is updated frequently to ensure compliance with data protection regulations and is found here.

        "},{"location":"references/faq/#q-how-do-we-secure-wso2-private-and-public-clouds","title":"Q: How do we secure WSO2 Private and Public Clouds?","text":"

        WSO2 uses a range of security controls and design patterns to protect against several threats, including internal attacks, software supply chain attacks, service and platform attacks, and more. Find out more regarding this here.

        "},{"location":"references/faq/#q-how-can-i-connect-a-choreo-component-with-a-protected-third-party-application","title":"Q: How can I connect a Choreo component with a protected third-party application?","text":"

        To connect a Choreo component with a third-party application, it is necessary to establish seamless communication between the component and the protected third-party application, especially when connecting to external databases like MySQL, MSSQL, PGSQL, Oracle DB, etc. To ensure this, the requests coming from the Choreo data plane must be allowed by adding the specific data plane IP ranges to your allowlist.

        • If your component is deployed in the Choreo US data plane, add the following IP range to your allowlist:

          • 20.22.170.144/28
        • If your component is deployed in the Choreo EU data plane, add the following IP range to your allowlist:

          • 20.166.183.112/28
        • If you are working on the Cybertruck Challenge, add the following IP range to your allowlist:

          • 20.190.30.48/28
        "},{"location":"references/faq/#data-planes","title":"Data planes","text":""},{"location":"references/faq/#q-what-is-a-choreo-control-plane","title":"Q: What is a Choreo control plane?","text":"

        The Choreo control plane is a centralized management component that oversees and coordinates the workloads deployed by customers. It provides a unified point of control and visibility for the organization, allowing administrators to manage, monitor, and orchestrate the organization\u2019s resources efficiently.

        "},{"location":"references/faq/#q-what-is-a-data-plane","title":"Q: What is a data plane?","text":"

        A data plane in Choreo is a computing environment designed for running customer workloads. These environments are hosted in either a dedicated cloud infrastructure owned by the customer (private data planes) or on public cloud infrastructure owned by WSO2, also known as the Choreo data plane.

        "},{"location":"references/faq/#q-which-regions-support-the-choreo-data-planecdp","title":"Q: Which regions support the Choreo data plane(CDP)?","text":"

        The Choreo data plane is currently supported in the US East 2 and North Europe. However, WSO2 is planning to add support for additional regions as needed.

        "},{"location":"references/faq/#q-which-regions-support-private-data-planespdps","title":"Q: Which regions support private data planes(PDPs)?","text":"

        Private data planes can be deployed in any region where Azure and AWS are available and meet the requirements for PDPs.

        "},{"location":"references/faq/#q-if-i-want-to-use-my-azure-aks-instances-as-the-private-data-plane-what-are-the-minimum-requirements-i-should-meet","title":"Q: If I want to use my Azure AKS instances as the private data plane, what are the minimum requirements I should meet?","text":"

        We recommend using a minimum of two (2) workload nodes to ensure high availability.

        "},{"location":"references/faq/#q-are-the-choreo-control-plane-and-data-planes-highly-available-are-they-running-on-multiple-clusters","title":"Q: Are the Choreo control plane and data planes highly available? Are they running on multiple clusters?","text":"

        The Choreo control plane and data plane are designed for high availability using Azure components like AKS, MSSQL, ACR, KV, Service Bus, and so on, with a high availability of 99.99%, which allows at least three workload nodes. In the event of a node failure or upgrade, this setup provides reliable failover. WSO2 also has a backup and recovery strategy in place, including continuous restore drills. If you require AKS cluster-level redundancy, we can consider multiple zones. In this case, the cost will include an additional infrastructure cost.

        "},{"location":"references/faq/#environments","title":"Environments","text":""},{"location":"references/faq/#q-as-a-choreo-cloud-data-plane-user-why-cant-i-create-environments","title":"Q: As a Choreo cloud data plane user, why can't I create environments?","text":"

        You can create environments only if you have a paid subscription in Choreo. It can be either Pay-as-you-Go (PAYG) or an Enterprise plan.

        "},{"location":"references/faq/#q-i-am-a-pay-as-you-go-payg-customer-using-the-choreo-cloud-data-plane-how-many-environments-can-i-create","title":"Q: I am a Pay-As-You-Go (PAYG) customer using the Choreo cloud data plane. How many environments can I create?","text":"

        You can create up to 5 environments at the organization level, including the existing Development & Production environments by default. If you have projects in both data planes (US & EU), there will be 4 environments already created in total, and you will only be allowed to create one additional environment either in the US or EU data plane.

        "},{"location":"references/faq/#q-i-am-an-enterprise-subscription-customer-using-the-choreo-private-data-plane-how-many-environments-do-i-get","title":"Q: I am an Enterprise subscription customer using the Choreo private data plane. How many environments do I get?","text":"

        As an Enterprise subscription customer, the number of environments you can use is not limited. However, the more environments you use, the more resources you will consume in the data plane for the workload you deploy. This may result in higher infrastructure costs for the private data plane.

        "},{"location":"references/faq/#q-as-a-choreo-cloud-data-plane-user-why-dont-i-see-both-us-eu-data-planes-in-the-data-plane-selector-when-creating-an-environment","title":"Q: As a Choreo cloud data plane user, why don\u2019t I see both US & EU data planes in the data plane selector when creating an environment?","text":"

        You will see both US & EU data planes only if you have a paid subscription and have created projects in both US & EU data planes.

        "},{"location":"references/faq/#q-i-am-a-customer-who-use-choreo-in-a-private-data-plane-how-many-environments-can-i-create","title":"Q: I am a customer who use Choreo in a private data plane. How many environments can I create?","text":"

        Initially, you will receive the requested number of environments when establishing your private data plane. Subsequently, you can create additional environments as needed.

        "},{"location":"references/faq/#billing-and-support","title":"Billing and support","text":""},{"location":"references/faq/#q-whom-do-i-reach-out-to-if-i-have-a-billing-question","title":"Q: Whom do I reach out to if I have a billing question?","text":"

        You can reach out to cloud-billing-support@wso2.com or create a support ticket via our support portal.

        "},{"location":"references/faq/#q-whats-a-developer-plan","title":"Q: What's a Developer plan?","text":"

        A Developer plan allows you to try out Choreo\u2019s capabilities at no cost. It\u2019s ideal for proof of concept (PoC) tasks or workloads with limited transactions. This plan allows you to experiment with up to 5 components and provides US$1,000/year of Choreo data plane (CDP) credits.

        "},{"location":"references/faq/#q-how-do-i-calculate-the-infrastructure-costs","title":"Q: How do I calculate the infrastructure costs?","text":"

        Calculating infrastructure costs depends on the type of workload you want to manage. Here are a few examples:

        • Example 1: Managing existing APIs as an API proxy with simple mediation; no additional infrastructure costs.
        • Example 2: Managing existing APIs as an API proxy with complex mediation and policies; Choreo will deploy 1 x container to handle these mediation and policies at approximately US$57.25 per month per API.
        • Example 3: Creating, deploying, and managing a new API or integration within Choreo; pay for 1 x component + infrastructure cost. Each container deployed will be approximately US$57.25 per month on the default configuration provided by Choreo. Additional resources will be charged based on the type of resource required.
        • Example 4: Creating, deploying, and managing a microservice; the same approach as example 3.
        "},{"location":"references/faq/#q-what-are-the-component-limitations","title":"Q: What are the component limitations?","text":"
        • Developer plan: Allows up to a maximum of five free components and unlimited paid components.
        • PAYG plan: Allows unlimited paid components.
        • Enterprise plan: Allows unlimited paid components.
        "},{"location":"references/faq/#q-how-do-i-read-the-bill","title":"Q: How do I read the bill?","text":"

        Your bill will detail the number of components used, infrastructure consumed, support plans used, and any additional services you may have purchased. If you are unsure about any charges on your bill, reach out to choreo-support@wso2.com for clarification.

        "},{"location":"references/faq/#q-is-support-included-in-the-choreo-enterprise-plan","title":"Q: Is support included in the Choreo Enterprise plan?","text":"

        The Choreo Enterprise plan does not automatically include support; however, you can purchase support plans in addition to the Enterprise plan at any time. Find out more at https://wso2.com/choreo/customer-support/.

        "},{"location":"references/faq/#q-i-am-an-enterprise-subscription-customer-who-wants-to-use-the-choreo-private-data-plane-what-costs-will-i-incur-in-addition-to-the-subscription-and-support-plan","title":"Q: I am an Enterprise subscription customer who wants to use the Choreo private data plane. What costs will I incur in addition to the subscription and support plan?","text":"

        You can start by using a basic plan or contact us for an Enterprise support plan.

        "},{"location":"references/faq/#q-i-want-to-upgrade-from-payg-to-an-enterprise-subscription-will-there-be-an-outage-during-the-upgrade","title":"Q: I want to upgrade from PAYG to an Enterprise subscription. Will there be an outage during the upgrade?","text":"

        No, there are no outages when upgrading a plan.

        "},{"location":"references/faq/#choreo-cli","title":"Choreo CLI","text":""},{"location":"references/faq/#q-how-do-i-uninstall-the-cli","title":"Q: How do I uninstall the CLI?","text":"

        If you didn't download the binary directly, you can uninstall the CLI by deleting the .choreo directory in the home directory of your operating system.

        "},{"location":"references/faq/#q-how-do-i-update-the-cli","title":"Q: How do I update the CLI?","text":"

        You can update the CLI by running the following command:

        curl -o- https://cli.choreo.dev/install.sh | bash\n

        "},{"location":"references/faq/#q-what-are-the-supported-component-types-in-the-cli","title":"Q: What are the supported component types in the CLI?","text":"

        The Choreo CLI currently supports the following component types: - Service - Web Application - Webhook - Scheduled Task - Manual Task

        "},{"location":"references/faq/#q-how-do-i-get-help-with-a-specific-command-in-the-cli","title":"Q: How do I get help with a specific command in the CLI?","text":"

        You can get help with a specific command by running the following command:

        choreo <command> --help\n

        "},{"location":"references/faq/#q-what-are-the-build-configurations-required-when-creating-components-using-the-cli","title":"Q: What are the build configurations required when creating components using the CLI?","text":"

        You can configure the component build configurations depending on the component type as follows:

        choreo create component <name> --project <name> --build-configs='key1=value1,key2=value2'\nchoreo create component <name> --project <name> --build-configs='key1=value1' --build-configs='key2=value2'\n

        The build configurations required for existing buildpacks are as follows:

        Component Type Buildpack Required Configurations Service Python
        • buildPackLangVersion: Language Version
        Node.js
        • buildPackLangVersion: Language Version
        Java
        • buildPackLangVersion: Language Version
        Go
        • buildPackLangVersion: Language Version
        PHP
        • buildPackLangVersion: Language Version
        Ruby
        • buildPackLangVersion: Language Version
        Docker
        • dockerFilePath: Path to the docker file
        Ballerina
        • Not Applicable
          • WSO2 MI
            • Not Applicable
              • .Net
                • buildPackLangVersion: Language Version
                  • Webapp Python
                    • buildPackLangVersion: Language Version
                    • port: Port
                    Node.js
                    • buildPackLangVersion: Language Version
                    • port: Port
                    Go
                    • buildPackLangVersion: Language Version
                    • port: Port
                    PHP
                    • buildPackLangVersion: Language Version
                    • port: Port
                    Ruby
                    • buildPackLangVersion: Language Version
                    • port: Port
                    .Net
                    • buildPackLangVersion: Language Version
                    • port: Port
                    Docker
                    • dockerFilePath: Path to the docker file
                    • port: Port
                    Static website
                    • Not Applicable
                      • React
                        • buildCommand: Command to be used for building the component
                        • outputDirectory: Output directory for the component build artifacts
                        • nodeVersion: Node.js version used
                        Angular
                        • buildCommand: Command to be used for building the component
                        • outputDirectory: Output directory for the component build artifacts
                        • nodeVersion: Node.js version used
                        Vue
                        • buildCommand: Command to be used for building the component
                        • outputDirectory: Output directory for the component build artifacts
                        • nodeVersion: Node.js version used
                        Webhook Python
                        • buildPackLangVersion: Language Version
                        Node.js
                        • buildPackLangVersion: Language Version
                        Java
                        • buildPackLangVersion: Language Version
                        Go
                        • buildPackLangVersion: Language Version
                        PHP
                        • buildPackLangVersion: Language Version
                        Ruby
                        • buildPackLangVersion: Language Version
                        Docker
                        • dockerFilePath: Path to the docker file
                        Ballerina
                        • Not Applicable
                          • WSO2 MI
                            • Not Applicable
                              • Scheduled Task Python
                                • buildPackLangVersion: Language Version
                                Node.js
                                • buildPackLangVersion: Language Version
                                Java
                                • buildPackLangVersion: Language Version
                                Go
                                • buildPackLangVersion: Language Version
                                .Net
                                • buildPackLangVersion: Language Version
                                PHP
                                • buildPackLangVersion: Language Version
                                Ruby
                                • buildPackLangVersion: Language Version
                                Docker
                                • dockerFilePath: Path to the docker file
                                Ballerina
                                • Not Applicable
                                  • WSO2 MI
                                    • Not Applicable
                                      • Manual Task Python
                                        • buildPackLangVersion: Language Version
                                        Node.JS
                                        • buildPackLangVersion: Language Version
                                        Java
                                        • buildPackLangVersion: Language Version
                                        Go
                                        • buildPackLangVersion: Language Version
                                        .Net
                                        • buildPackLangVersion: Language Version
                                        PHP
                                        • buildPackLangVersion: Language Version
                                        Ruby
                                        • buildPackLangVersion: Language Version
                                        Docker
                                        • dockerFilePath: Path to the docker file
                                        Ballerina
                                        • Not Applicable
                                          • WSO2 MI
                                            • Not Applicable
                                              • "},{"location":"references/private-data-plane-management-models/","title":"Private Data Plane Management Models","text":"

                                                Choreo supports various management models for private data planes (PDPs), fostering collaboration between WSO2 and customers across diverse scenarios. The following sections provide insights into WSO2's fully managed solutions and shared responsibility models, allowing you to make informed decisions regarding cloud-based operations and security.

                                                "},{"location":"references/private-data-plane-management-models/#wso2-fully-managed-infrastructure-and-pdp-in-wso2-subscription-model","title":"WSO2 fully managed (infrastructure and PDP in WSO2 subscription) model","text":"

                                                WSO2 fully managed private data planes are supported only on Azure, AWS, and GCP cloud providers.

                                                Task Task description Responsible party Accountable Consulted Informed Subscription prerequisites - Create subscriptions - Check quota and service limits - Run the Choreo compatibility prerequisite script WSO2 WSO2 Customer (If required) Customer (If required) Remote access for installation Provide owner access WSO2 WSO2 WSO2 WSO2 Network management - Obtain customers backend CIDR in case of VPN/peering - Check end-to-end connectivity (primary and failover) WSO2/Customer WSO2/Customer Customer Customer Firewall rules/access control Set up firewall and required rules depending on the security tier WSO2 WSO2 Customer Customer Infrastructure provisioning - Provision Bastion - Provision Kubernetes clusters WSO2 WSO2 - Customer(If required) Kubernetes cluster management - Manage Kubernetes versions - Increase node pool size WSO2 WSO2 Customer Customer Infrastructure monitoring Set up alerts WSO2 WSO2 - Customer(If required) DNS management for Choreo system - Manage DNS infrastructure - Manage SSL certificates for Choreo system components WSO2/Customer WSO2/Customer Customer Customer Choreo system components deployment Set up PDP agents via Helm WSO2 WSO2 - - Choreo system components management Upgrade/patch/debug versions WSO2 WSO2 - Customer(If required) Choreo system components monitoring - Set up continuous monitoring 24x7 - Provide monthly uptime reports WSO2 WSO2 - Customer Choreo system security monitoring If basic tier - CSPM - Apply security patches - Manage supply chain security (Image scanning, SAST) - Manage security incidents If standard tier/premium tier - CSPM - Apply security patches - Manage supply chain security - Monitor runtime security alerts (Azure Defender) - Monitor security incident and event management (SIEM) alerts - Manage security incidents - Adhere to compliance standards WSO2/Customer WSO2/Customer WSO2/Customer WSO2/Customer Choreo application creation/deployment Customer Customer Customer Customer Choreo application management Customer Customer Customer Customer Choreo application monitoring Customer Customer Customer Customer Choreo application logs Customer Customer Customer Customer"},{"location":"references/private-data-plane-management-models/#wso2-fully-managed-infrastructure-and-pdp-in-customer-subscription-model","title":"WSO2 fully managed (infrastructure and PDP in customer subscription) model","text":"Task Task description Responsible party Accountable Consulted Informed Subscription prerequisites - Create subscriptions - Check quota and service limits - Run the Choreo compatibility prerequisite script Customer Customer WSO2 - Remote access for installation Provide access Customer Customer WSO2 WSO2 Network management - Obtain customers backend CIDR in case of VPN/peering - Check end-to-end connectivity (primary and failover) WSO2/Customer WSO2/Customer Customer Customer Firewall rules/access control Set up firewall and required rules depending on the security tier WSO2/Customer WSO2/Customer Customer Customer Infrastructure provisioning - Provision Bastion - Provision Kubernetes clusters WSO2 WSO2 Customer Customer Kubernetes cluster management - Manage Kubernetes versions - Increase node pool size WSO2 WSO2 Customer Customer Infrastructure monitoring Set up alerts WSO2 WSO2 - Customer(If required) DNS management for Choreo system - Manage DNS infrastructure - Manage SSL certificates for Choreo system components WSO2/Customer WSO2/Customer Customer Customer Choreo system components deployment Set up PDP agents via Helm WSO2 WSO2 Customer - Choreo system components management Upgrade/patch/debug versions WSO2 WSO2 - Customer(If required) Choreo system components monitoring - Set up continuous monitoring 24x7 - Provide monthly uptime reports WSO2 WSO2 - Customer Choreo system security monitoring If basic tier - CSPM - Apply security patches - Manage supply chain security (Image scanning, SAST) - Manage security incidents If standard tier/premium tier - CSPM - Apply security patches - Manage supply chain security - Monitor runtime security alerts (Azure Defender) - Monitor security incident and event management (SIEM) alerts - Manage security incidents - Adhere to compliance standards WSO2/Customer WSO2/Customer WSO2/Customer WSO2/Customer Choreo application creation/deployment Customer Customer Customer Customer Choreo application management Customer Customer Customer Customer Choreo application monitoring Customer Customer Customer Customer Choreo application logs Customer Customer Customer Customer"},{"location":"references/private-data-plane-management-models/#customer-self-managed-wso2-provides-installation-script-and-updates-model","title":"Customer self-managed (WSO2 provides installation script and updates) model","text":"Task Task description Responsible party Accountable Consulted Informed Subscription prerequisites - Create subscriptions - Check quota and service limits - Run the Choreo compatibility prerequisite script Customer Customer WSO2 WSO2 Remote access for installation Provide owner access Customer Customer WSO2 - Network management - Obtain customers backend CIDR in case of VPN/peering - Check end-to-end connectivity (primary and failover) Customer Customer WSO2 WSO2 Firewall rules/access control Set up firewall and required rules depending on the security tier Customer Customer WSO2 WSO2 Infrastructure provisioning - Provision Bastion - Provision Kubernetes clusters Customer Customer WSO2 WSO2(If required) Kubernetes cluster management - Manage Kubernetes versions - Increase node pool size Customer Customer WSO2 WSO2(If required) Infrastructure monitoring Set up alerts Customer Customer WSO2 - DNS management for Choreo system - Manage DNS infrastructure - Manage SSL certificates for Choreo system components Customer Customer WSO2 - Choreo system components deployment Set up PDP agents via Helm Customer Customer WSO2 - Choreo system components management Upgrade/patch/debug versions Customer Customer WSO2 - Choreo system components monitoring - Set up continuous monitoring 24x7 - Provide monthly uptime reports Customer Customer WSO2 - Choreo system security monitoring If basic tier - CSPM - Apply security patches - Manage supply chain security (Image scanning, SAST) - Manage security incidents If standard tier/premium tier - CSPM - Apply security patches - Manage supply chain security - Monitor runtime security alerts (Azure Defender) - Monitor security incident and event management (SIEM) alerts - Manage security incidents - Adhere to compliance standards WSO2/Customer WSO2/Customer WSO2/Customer WSO2/Customer Choreo application creation/deployment Customer Customer Customer Customer Choreo application management Customer Customer Customer Customer Choreo application monitoring Customer Customer Customer Customer Choreo application logs Customer Customer Customer Customer"},{"location":"references/private-data-plane-security-levels/","title":"Private Data Plane Security Levels","text":"

                                                The following table outlines the private data plane security levels supported in Choreo:

                                                Basic tier Standard tier Premium tier Distributed denial-of-service (DDoS) protection basic * Distributed denial-of-service (DDoS) protection basic * Distributed denial-of-service (DDoS) protection premium * Controlled admin access * Controlled admin access * Controlled admin access * End-to-end data encryption in transit End-to-end data encryption in transit End-to-end data encryption in transit Data encryption at rest * Data encryption at rest * Data encryption at rest * Secret management Secret management Secret management Foundational CSPM * Foundational CSPM * Premium CSPM * Static application security testing (SAST) Static application security testing (SAST) Static application security testing (SAST) Infrastructure as code (IaC) scanning Infrastructure as code (IaC) scanning Infrastructure as code (IaC) scanning Software composition analysis Software composition analysis Software composition analysis Docker image security scanning Docker image security scanning Docker image security scanning N/A Kubernetes runtime protection * Kubernetes runtime protection * N/A Web application firewall (WAF) * Web application firewall (WAF) * N/A N/A Network firewall *

                                                * Not available in the on-premises private data plane.

                                                Tip

                                                Available add-ons: - Security incident and event management (SIEM). - 24/7 security operation center.

                                                "},{"location":"references/troubleshoot-choreo/","title":"Troubleshoot Choreo","text":"

                                                This page walks you through common problems you may encounter when building and deploying components with Choreo, along with the recommended solutions to resolve each issue.

                                                "},{"location":"references/troubleshoot-choreo/#troubleshoot-component-build-errors","title":"Troubleshoot component build errors","text":""},{"location":"references/troubleshoot-choreo/#deploying-an-angular-web-application-displays-the-nginx-welcome-page-instead-of-the-applications-homepage","title":"Deploying an Angular web application displays the Nginx welcome page instead of the application's homepage.","text":"

                                                This occurs due to specifying an incorrect build output directory when you set up your Angular application in Choreo. To resolve the issue, follow the guidelines given below:

                                                • Ensure that the build output directory correctly points to where your Angular build script outputs the files. The deafult output directory is dist/<project-name>.
                                                • Make sure to reconfigure the build settings if the current configuration is incorrect.
                                                "},{"location":"references/troubleshoot-choreo/#an-error-occurs-in-the-container-trivy-scan-when-building-a-byoc-component","title":"An error occurs in the container Trivy scan when building a BYOC component.","text":"

                                                The recommended approach to address this issue is to fix the identified vulnerability and rebuild the component.

                                                However, if you want to add a .trivyignore file to overcome the issue, ensure to add it to the Docker build context path specified when creating the component. For example, {buildContextPath}./trivyignore.

                                                "},{"location":"references/troubleshoot-choreo/#the-configjs-file-is-not-properly-mounted-in-a-web-application","title":"The config.js file is not properly mounted in a web application.","text":"

                                                To resolve this issue, follow the steps given below:

                                                1. Add the config.js file to the app/public directory in your repository.
                                                2. Reference it from the index.html file by adding a script tag as follows:

                                                  <script src=\"public/config.js\"></script>

                                                "},{"location":"references/troubleshoot-choreo/#troubleshoot-component-deployment-errors","title":"Troubleshoot component deployment errors","text":""},{"location":"references/troubleshoot-choreo/#the-configjs-file-is-not-properly-integrated-during-the-deployment-of-a-react-application-causing-it-to-render-with-unexpected-html-instead-of-the-expected-javascript-configuration","title":"The config.js file is not properly integrated during the deployment of a React application, causing it to render with unexpected HTML instead of the expected JavaScript configuration.","text":"

                                                To ensure correct loading of the config.js file, follow the steps given below:

                                                • Reference the config.js file from the index.html file of your application by adding a script tag as follows:

                                                  <script src=\"public/config.js\"></script>

                                                • Verify that the path in the script tag matches the location where the config.js file is stored in your repository.

                                                • Make sure the script tag is placed within the <body> tag in your index.html file. You must ensure that it is not mistakenly placed within another HTML element.
                                                "},{"location":"references/troubleshoot-choreo/#im-not-aware-of-the-commits-that-can-trigger-an-automatic-build-in-choreo","title":"I'm not aware of the commits that can trigger an automatic build in Choreo.","text":"

                                                Merge commits and commits pushed directly to the branch can trigger a build in Choreo.

                                                "},{"location":"references/troubleshoot-choreo/#troubleshoot-web-application-issues","title":"Troubleshoot web application issues","text":""},{"location":"references/troubleshoot-choreo/#after-building-a-web-application-the-nginx-welcome-page-is-displayed-instead-of-the-web-application-home-page","title":"After building a web application, the Nginx welcome page is displayed instead of the web application home page.","text":"

                                                This can happen if an incorrect build output directory is specified during component creation.

                                                During the build process, output files including the index.html are copied to the Nginx root directory. To ensure that the correct files are copied during the build process, you must check the Docker build logs.

                                                "},{"location":"references/troubleshoot-choreo/#the-language-i-prefer-to-use-is-not-available-as-a-buildpack","title":"The language I prefer to use is not available as a buildpack.","text":"

                                                In such scenarios, you can use the Dockerfile buildpack to create the component.

                                                "},{"location":"references/troubleshoot-choreo/#i-mistakenly-used-an-incorrect-build-command-when-creating-a-web-application-how-can-i-update-it-before-triggering-a-build","title":"I mistakenly used an incorrect build command when creating a web application. How can I update it before triggering a build?","text":"

                                                You can go to the build page of the component and update the build command in the build configurations section.

                                                "},{"location":"references/troubleshoot-choreo/#troubleshoot-managed-authentication-issues","title":"Troubleshoot managed-authentication issues","text":""},{"location":"references/troubleshoot-choreo/#after-securing-a-web-application-with-managed-authentication-im-not-able-to-add-users-who-can-sign-in-to-the-application","title":"After securing a web application with managed authentication, I\u2019m not able to add users who can sign in to the application.","text":"

                                                For step-by-step instructions on how to manage users with Choreo's built-in identity provider (IdP), see Configure a User Store with the Built-In IdP.

                                                For details on setting up other OpenID Connect (OIDC) supported IdPs, see Manage OAuth Keys.

                                                "},{"location":"references/troubleshoot-choreo/#troubleshoot-tailscale-proxy-issues","title":"Troubleshoot Tailscale proxy issues","text":""},{"location":"references/troubleshoot-choreo/#where-can-i-find-logs-to-troubleshoot-tailscale-proxy-issues","title":"Where can I find logs to troubleshoot Tailscale proxy issues?","text":"

                                                To troubleshoot Tailscale proxy issues, you can view the Runtime Logs of the running container for your Tailscale proxy deployment. These logs can help you diagnose most of the issues. You can also view real-time container logs via the Runtime page under DevOps. For more details, see Observe real-time container logs.

                                                "},{"location":"references/troubleshoot-choreo/#im-not-able-to-connect-the-tailscale-proxy-node-to-my-tailscale-network-due-to-an-authentication-failure","title":"I'm not able to connect the Tailscale proxy node to my Tailscale network due to an authentication failure.","text":"
                                                • If you encounter the following log lines in your Tailscale proxy deployment, it indicates a misconfiguration of the TS_AUTH_KEY:

                                                  2024-06-04T10:38:53.885800940Z To authenticate, visit:\n2024-06-04T10:38:53.885802684Z \n2024-06-04T10:38:53.885815708Z https://login.tailscale.com/a/696841f011517\n2024-06-04T10:38:53.885817457Z \n2024-06-04T10:38:55.194344862Z Waiting for tailscale up to complete...\n2024-06-04T10:38:57.198970796Z Waiting for tailscale up to complete...\n2024-06-04T10:38:59.203265659Z Waiting for tailscale up to complete...\n
                                                  To resolve this, you must re-check your authentication key and ensure you have entered the correct key.

                                                • If you encounter the following log lines in your Tailscale proxy deployment, it indicates that your authentication key is invalid or expired.

                                                  2024-06-04T11:33:58.762363181Z 2024/06/04 11:33:58 Received error: invalid key: unable to validate API key\n2024-06-04T11:33:58.762458209Z backend error: invalid key: unable to validate API key\n

                                                  To resolve this, you must verify the correctness of your authentication key. If the key has expired, you must generate a new key from Tailscale admin console.

                                                "},{"location":"references/troubleshoot-choreo/#im-not-able-to-access-private-endpoints-although-the-tailscale-proxy-is-properly-connected-to-my-tailscale-network","title":"I'm not able to access private endpoints although the Tailscale proxy is properly connected to my Tailscale network.","text":"

                                                To resolve this, do the following:

                                                • Ensure your on-premises setup is properly connected to the Tailscale network and that specific services, database servers, etc., are running as expected in your on-premises setup.
                                                • Verify that the IP addresses and ports specified in your Config.yaml file (mounted to Tailscale proxy during deployment) match the IP addresses in your Tailscale network.
                                                • Cross-check the ports defined in the endpoints.yaml file with the port mappings in the Config.yaml file.
                                                "},{"location":"resources/kubernetes-upgrade-notice/","title":"Choreo Kubernetes Infrastructure Upgrade Notice","text":"

                                                Upgrade Date: September 4, 2023, from 3:00 a.m. to 6:00 a.m. UTC

                                                An upcoming upgrade to the Choreo Kubernetes infrastructure is scheduled to take place on September 4, 2023.

                                                "},{"location":"resources/kubernetes-upgrade-notice/#impact-on-java-based-components","title":"Impact on Java-based Components","text":"

                                                This upgrade is geared towards enhancing the performance and capabilities of our platform. However, it's important to note that there might be an impact on Java-based components in terms of memory usage. Specifically, applications relying on Java Runtime versions older than jdk8u372 or 11.0.16 could experience out-of-memory errors due to potential memory consumption increases resulting from the upgrade.

                                                "},{"location":"resources/kubernetes-upgrade-notice/#affected-component-types","title":"Affected Component Types","text":"

                                                The following Choreo component types could be affected:

                                                • Components created using the Ballerina preset (For example, Service, Webhook, Scheduled trigger, Manual Trigger components).
                                                • Integration components created using the WSO2 Micro Integrator preset (For example, Integration as an API, Event-triggered integration, Manually-triggered integration, and Scheduled integration components).
                                                • REST API Proxies that include mediation policies.
                                                • Components created using the Dockerfile preset (Components created with containerized applications utilizing the Java Runtime).
                                                "},{"location":"resources/kubernetes-upgrade-notice/#action-required","title":"Action Required","text":"

                                                Recommended action date: Before September 4, 2023, 3:00 a.m. UTC

                                                To ensure a smooth transition and compatibility with the updated Java Runtime version, follow the steps below:

                                                • Ballerina or Micro Integrator-based components: If you have created components using the Ballerina preset or the MI preset, we strongly advise you to redeploy your components before we initiate the upgrade. In the deployment pipeline, we will build your component using the latest Java version.

                                                • REST API Proxy components that include mediation policies: If you have created REST API Proxy components and attached a mediation policy, we strongly advise you to redeploy your components before we initiate the upgrade. In the deployment pipeline, we will build your component using the latest Java version.

                                                • Other Java-based containerized components: If you have components created using the Dockerfile preset that includes containerized applications utilizing the Java Runtime, follow the steps below:

                                                  1. Upgrade your Java version to OpenJDK / HotSpot - jdk8u372, 11.0.16, 15, or later.
                                                  2. Rebuild your containerized application.
                                                  3. Redeploy your containerized component.
                                                "},{"location":"resources/kubernetes-upgrade-notice/#redeploy-a-component-in-choreo","title":"Redeploy a component in Choreo","text":"

                                                To redeploy your component, follow the steps given below:

                                                1. Go to https://console.choreo.dev/, and sign in using your preferred login method.
                                                2. Select your component from Components Listing. This will open the overview page of your component.
                                                3. In the left navigation menu, click Deploy.
                                                4. Deploy your component via the Build Area card.

                                                For more information, refer to this document.

                                                "},{"location":"testing/test-apis-with-choreo-apichat/","title":"Test APIs with Choreo API Chat","text":"

                                                Testing APIs is an essential step in the API development process. Choreo simplifies the testing task by allowing you to engage with your APIs using natural language through Choreo API Chat. It eliminates manual test scenario creation and JSON payload accuracy concerns. It enables easy API communication using human language and requires no coding for handling sequences with multiple resource calls. This makes your API testing efficient and user-friendly.

                                                Info

                                                This feature is available for REST API Proxy components and Service components with REST endpoints.

                                                "},{"location":"testing/test-apis-with-choreo-apichat/#prerequisites","title":"Prerequisites","text":"

                                                Before you try out this guide, be sure that you have the following:

                                                • A REST API Proxy component or a Service component that exposes a REST API with a valid OpenAPI specification.

                                                  Info

                                                  • If you are creating a REST API Proxy component, you can create it either by using a valid OpenAPI specification or by defining the resources manually.
                                                  • If you are creating a service component with the Dockerfile preset, make sure to expose the OpenAPI specification from your component.
                                                  • If you do not already have a component, you can choose to create one from the following sources:
                                                  Component type Sample source Reference documentation REST API Proxy https://raw.githubusercontent.com/wso2/choreo-sample-apps/main/rest-api-proxy/pet-store/openapi.yaml Develop an API Proxy Service (Exposing a REST API endpoint) https://github.com/wso2/choreo-sample-apps/tree/main/java/pet-store Develop a Service
                                                "},{"location":"testing/test-apis-with-choreo-apichat/#test-your-apis","title":"Test your APIs","text":"

                                                Follow the steps below to test an API with API Chat:

                                                1. Sign in to the Choreo Console.
                                                2. In the Component Listing pane, click on the component you want to test.
                                                3. On the left navigation, click Test and then click API Chat. This opens the API Chat pane.
                                                4. You can enter your query in natural language and execute it. For example, if you have a resource like \"/pet/findByStatus,\" you can input the query, such as \"Get the pets that are available,\" and execute it to obtain results. The resources are executed sequentially based on your query. Alternatively, you can use the sample queries available to try out API Chat.
                                                "},{"location":"testing/test-apis-with-curl/","title":"Test APIs with cURL","text":"

                                                Testing APIs is an essential step in the API development process. Choreo simplifies the testing task by allowing you to use cURL commands generated by Choreo.

                                                You can follow the steps below to generate a cURL command and test your API method:

                                                1. Sign in to the Choreo Console.

                                                2. In the Component Listing pane, click on the component you want to test.

                                                3. Click Test in the left navigation menu and then click cURL. This opens the cURL pane.

                                                4. In the cURL pane, select the environment from the drop-down list.

                                                5. Select an appropriate HTTP method from the Method list.

                                                6. Click the Parameters tab and add the necessary parameters for the API method.

                                                7. Click the Headers tab and add the required header values.

                                                8. Click the Body tab and select the message body type to invoke the API method.

                                                9. Copy the generated cURL command.

                                                10. Use the copied cURL command via a cURL client to test your API method.

                                                "},{"location":"testing/test-components-with-test-runner/","title":"Test Components with Test Runner","text":"

                                                Test Runner is a component type in Choreo that simplifies the process of running automated tests against your components deployed in Choreo. This capability helps developers evaluate applications in different setups and environments, leading to more confidence and improved visibility into the application's status.

                                                You can create tests using popular programming languages like Go, Java, JavaScript, Python, and more. Additionally, you have the option to build a test runner component by supplying a Dockerfile containing a series of test scripts or by offering a set of Postman Collections.

                                                "},{"location":"testing/test-components-with-test-runner/#prerequisites","title":"Prerequisites","text":"

                                                Before you try out the steps in this guide, complete the following:

                                                • If you are signing in to the Choreo Console for the first time, create an organization as follows:
                                                  1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                  2. Enter a unique organization name. For example, Stark Industries.
                                                  3. Read and accept the privacy policy and terms of use.
                                                  4. Click Create. This creates the organization and opens the Project Home page of the default project created for you.
                                                • Fork the Choreo examples repository, which contains the test runner sample for this guide.

                                                You can develop tests in a language of your choice and execute them within the Choreo platform.

                                                "},{"location":"testing/test-components-with-test-runner/#create-a-test-runner-component-using-a-buildpack","title":"Create a test runner component using a buildpack","text":"
                                                1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                2. Click +Create in the Component Listing section.
                                                3. Click the Test Runner card.
                                                4. Enter a display name, unique name, and description for the test runner component. For this guide, enter the following values:

                                                  Info

                                                  In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

                                                  Field Value Component Display Name Go Test Runner Component Name go-test-runner Description Test Runner implemented in Go
                                                5. Go to the GitHub tab.

                                                6. To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

                                                  Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

                                                  Note

                                                  The Choreo GitHub App requires the following permissions:

                                                  • Read and write access to code and pull requests.
                                                  • Read access to issues and metadata.

                                                  You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

                                                7. Under Connect Your Repository, enter the following information:

                                                  Field Value Organization Your GitHub account GitHub Repository choreo-samples Branch main
                                                8. Under Buildpack, select a buildpack based on the language of your choice.

                                                9. Based on the buildpack you chose, go to the relevant tab below and enter the respective values for the Project directory and Language version fields:

                                                  GoJavaScriptPythonJavaDockerfilePostman Field Value Go Project Directory /test-runner-go Language Version 1.x Field Value Project Directory /test-runner-javascript Language Version 18.x.x Field Value Project Directory /test-runner-python Language Version 3.10.x Field Value Project Directory /test-runner-java Language Version 17

                                                  For programming languages that doesn't support buildpacks or for advanced use cases, you can define your own Dockerfile and run test workloads. Refer to for more information. Field Value Postman Directory /postman-collection-dir

                                                10. Click Create.

                                                11. You have successfully created a Test Runner component using a buildpack of your choice. Now let's build and run the tests.

                                                  "},{"location":"testing/test-components-with-test-runner/#build-and-deploy-the-test-runner-component-to-execute-the-tests","title":"Build and deploy the test runner component to execute the tests","text":"
                                                  1. In the left navigation menu, click Build.
                                                  2. In the Builds pane, click Build Latest.
                                                  3. On the left navigation, click Deploy.
                                                  4. In the Set Up card, click Deploy to deploy the test runner component. If you want to provide additional configuration or secrets, use the Configure and Deploy option from the list.
                                                  5. Once the deployment is successful, click Execute in the left navigation menu.
                                                  6. Select the environment from the environment list and click Run Now to trigger a test execution.
                                                  7. Once the execution is completed it is listed on the execution page. This may take some time. Once the execution is listed, you can click on a particular execution to view the test result(s).

                                                    Inject dynamic values into your application as command-line arguments

                                                    If you want to inject dynamic values into your application as command-line arguments when you run a test runner component, follow the steps given below:

                                                    1. Click the drop-down icon next to Run Now and then click Run with Arguments.
                                                    2. In the Runtime Arguments pane that opens, enter the arguments you want to pass to your application.
                                                    3. Click Execute. This triggers the test runner with the specified arguments.

                                                    Tip

                                                    For Postman Collections:

                                                    • The default behavior is to run all the collections in the specified directory.
                                                    • To run specific collections in the directory, use -f or --files as the first argument, followed by a comma-separated list of collections.
                                                    • Since Choreo uses Newman internally to run Postman Collections, you can pass any valid Newman arguments.
                                                  "},{"location":"testing/test-graphql-endpoints-via-the-graphql-console/","title":"Test GraphQL Endpoints via the GraphQL Console","text":"

                                                  Choreo provides an integrated GraphQL Console to test publicly exposed GraphQL endpoints of Service components you create and deploy. The GraphQL Console allows you to write queries and mutations interactively. As Choreo uses OAuth2.0 authentication by default to secure GraphQL APIs, the GraphQL Console generates test keys to test APIs.

                                                  Follow the steps below to test a GraphQL endpoint via the GraphQL Console:

                                                  1. Sign in to the Choreo Console.

                                                  2. In the Component Listing pane, click on the component you want to test.

                                                  3. Click Test in the left navigation menu and then click Console. This opens the GraphQL Console pane.

                                                  4. In the GraphQL Console pane, select the environment from the drop-down list.

                                                  5. Select the required endpoint from the Endpoint list.

                                                    Note

                                                    • The Network Visibilities of an endpoint are set in the component.yaml. You can set any combination of Public, Organization, or Project.
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Public, continue with step 7.
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Organization, the GraphQL endpoint will not be invokable from outside the organization. In this instance, for testing purposes, Choreo allows you to generate a temporay test URL that will be active for 15 minutes. Execute step 6 to generate the temporary URL.
                                                  6. If the Network Visibilities of the endpoint contains Organization, click on Generate URL to generate a temporary test URL that will be active for 15 minutes. Else, skip this step.

                                                    Note

                                                    The temporay test URL will be available only for 15 minutes and it will get expired after. You can deactivate the test URL by clicking on the Deactivate URL button.

                                                  7. Enter the API path and the query or mutation you want to test.

                                                  8. Click the play icon.

                                                    Tip

                                                    If you want to generate a required query or mutation for testing via the GraphQL Explorer, click Explorer to open the GraphQL Explorer.

                                                    Note

                                                    GraphQL Explorer has a known issue causing improper construction of list inputs. To work around this, you must manually update the list input in the generated query before executing it.

                                                  "},{"location":"testing/test-rest-endpoints-via-the-openapi-console/","title":"Test REST Endpoints via the OpenAPI Console","text":"

                                                  Choreo provides an integrated OpenAPI Console to test REST endpoints of Service components that you create and deploy. As Choreo uses OAuth2.0 authentication to secure REST APIs, the OpenAPI Console generates test keys to test APIs.

                                                  Follow the steps below to test a REST endpoint via the integrated OpenAPI Console:

                                                  1. Sign in to the Choreo Console.

                                                  2. In the Component Listing pane, click on the component you want to test.

                                                  3. Click Test in the left navigation menu and then click Console. This opens the OpenAPI Console pane.

                                                  4. In the OpenAPI Console pane, select the environment from the drop-down list.

                                                  5. Select the required endpoint from the Endpoint list.

                                                    Note

                                                    • The Network Visibilities of an endpoint is set in the component.yaml. You can set it to Public, Organization, or Project.
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Public, go to step 7.
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Organization, the endpoint will not be publicly accessible. However, for testing purposes, Choreo offers the ability to create a temporary test URL that is publicly accessible (secured with OAuth 2.0) and remains active for 15 minutes. To generate the temporary URL, proceed with step 6.
                                                  6. If the Network Visibilities of the endpoint contains Organization, click on Generate URL to generate a temporary test URL that will be active for 15 minutes. Else, skip this step.

                                                    Note

                                                    The temporary test URL will be available only for 15 minutes and it will get expired after. You can deactivate the test URL by clicking on the Deactivate URL button.

                                                  7. Expand the resource you want to test.

                                                  8. Click Try it out.

                                                  9. Enter values for parameters if applicable.

                                                  10. Click Execute. You can see the response body under Responses.

                                                  "},{"location":"testing/test-websocket-endpoints-via-the-websocket-console/","title":"Test WebSocket Endpoints via the WebSocket Console","text":"

                                                  Choreo provides an integrated WebSocket Console to test publicly exposed WebSocket endpoints of Service components you create and deploy. The WebSocket Console allows you to connect to your service and exchange messages interactively. Choreo secures WebSocket APIs with OAuth2.0 by default, and the console automatically generates test keys for authenticated API testing.

                                                  Follow the steps below to test a WebSocket endpoint via the WebSocket Console:

                                                  1. Sign in to the Choreo Console.

                                                  2. In the Component Listing pane, click on the component you want to test.

                                                  3. Click Test in the left navigation menu and then click Console. This opens the WebSocket Console pane.

                                                  4. In the WebSocket Console pane, select the environment from the drop-down list.

                                                  5. Select the required endpoint from the Endpoint list.

                                                    Note

                                                    • The Network Visibility of an endpoint is set in the endpoints.yaml file. You can set it to Public, Organization, or Project.
                                                    • If you have set the Network Visibility of the endpoint to Public, proceed to step 7.
                                                    • If you have set the Network Visibility of the endpoint to Organization, it won't be accessible from outside the organization. For testing, Choreo allows you to generate a temporary URL that remains active for 15 minutes. Follow step 6 to generate the URL.
                                                  6. If the Network Visibility of the endpoint is set to Organization, click Generate URL to generate a temporary test URL valid for 15 minutes. Otherwise, skip this step.

                                                    Note

                                                    The temporary test URL is valid for 15 minutes and will expire after that. If you want to manually deactivate it, click Deactivate URL.

                                                  7. Expand the channel you want to test.

                                                  8. Click Connect to establish a connection. The connection status will be displayed in the output logs.

                                                  9. Send and receive messages to and from the deployed service.

                                                    Note

                                                    The maximum connection duration is 15 minutes. After that, the connection terminates. To reconnect, click Connect again.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/","title":"Expose a Service as a Managed API","text":"

                                                  Choreo simplifies securely exposing existing services as managed APIs. It also allows you to effectively manage all aspects of an API's lifecycle, security, throttling, and governance so that you can focus more on service development.

                                                  In this tutorial, you will use Choreo to expose a service as an API proxy and publish it to the Choreo Developer Portal for application developers to consume.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#prerequisites","title":"Prerequisites","text":"

                                                  Before you try out this tutorial, complete the following:

                                                  • If you are signing in to the Choreo Console for the first time, create an organization as follows:

                                                    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                    2. Enter a unique organization name. For example, Stark Industries.
                                                    3. Read and accept the privacy policy and terms of use.
                                                    4. Click Create.

                                                    This creates the organization and opens the Project Home page of the default project created for you.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-1-create-an-api-proxy","title":"Step 1: Create an API proxy","text":"

                                                  To create an API proxy, you can either upload an OpenAPI specification or provide an OpenAPI specification URL. In this tutorial, you will use a URL of a sample OpenAPI specification.

                                                  Follow the steps given below:

                                                  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                  2. If you already have one or more components in your project, click + Create under Component Listing. Otherwise, proceed to the next step.
                                                  3. Click the API Proxy card.
                                                  4. In the Create an API Proxy pane that opens, click Try with sample URL.
                                                  5. Click Next.
                                                  6. Update the populated API proxy details with the values given in the following table:

                                                    Info

                                                    In the Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

                                                    Field Value Display Name Swagger Petstore Name swagger-petstore Context api/v3 Version 1.0 Target https://petstore3.swagger.io/api/v3 Access Mode External: API is publicly accessible
                                                  7. Click Create. This creates the component and takes you to the Overview page of the component.

                                                  To see the resources of the API proxy, go to the left navigation menu, click Develop, and then click Resources.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-2-deploy-the-api-proxy","title":"Step 2: Deploy the API proxy","text":"

                                                  To deploy the API proxy to the development environment, follow the steps given below:

                                                  1. In the left navigation menu, click Deploy.
                                                  2. In the Build Area card, click Configure & Deploy. This opens the Configure & Deploy pane, where you can select the API access mode depending on how you want the API to be accessible.

                                                    Here, you can select External to make the API publicly accessible, and then click Deploy.

                                                    Once the deployment is complete, the Development card indicates the Deployment Status as Active.

                                                  Now you are ready to test the API proxy.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-3-test-the-api-proxy","title":"Step 3: Test the API proxy","text":"

                                                  You can test the API proxy in the development environment before promoting it to production. Choreo provides the following options to test your API proxy: - OpenAPI Console - cURL

                                                  In this guide, you will use the OpenAPI Console.

                                                  To test the API proxy via the OpenAPI Console, follow the steps given below:

                                                  1. In the left navigation menu, click Test and then click OpenAPI Console.

                                                    Tip

                                                    Since the API proxy is secured when it is deployed, you will need a key to invoke it. Choreo automatically generates a key when you navigate to the OpenAPI Console pane.

                                                  2. In the OpenAPI Console pane, select Development from the environment drop-down list.

                                                  3. Expand the GET /pet/findByStatus method and click Try it Out to test it.
                                                  4. Select available as the status and click Execute. You will see a response similar to the following:

                                                  This indicates that your API proxy is working as expected.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-4-promote-the-api-proxy-to-production","title":"Step 4: Promote the API proxy to production","text":"

                                                  Once you verify that the API proxy is working as expected in the development environment, you can follow the steps given below to promote it to production:

                                                  1. In the left navigation menu, click Deploy.
                                                  2. In the Development card, click Promote.
                                                  3. In the Configure & Deploy pane that opens, click Next.

                                                    Tip

                                                    If you want to specify a different endpoint for your production environment, you can make the change in the Configure & Deploy pane.

                                                  The Production card indicates the Deployment Status as Active when the API proxy is successfully deployed to production.

                                                  If you want to verify that the API proxy is working as expected in production, you can test the API in the production environment.

                                                  Now that your API is deployed in both development and production environments and can be invoked, the next step is to publish it so that consumers can discover and subscribe to it.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-5-publish-the-api-proxy","title":"Step 5: Publish the API proxy","text":"

                                                  To publish the API to the Choreo Developer Portal, follow the steps given below:

                                                  1. In the left navigation menu, click Manage and then click Lifecycle. This opens the Lifecycle page, where you can see the different lifecycle stages that an API can be in. You can see that the current lifecycle stage is Created.
                                                  2. Click Publish.
                                                  3. In the Publish API dialog that opens, click Confirm to proceed publishing the API with the specified display name. If you want to change the display name, make the necessary changes and then click Confirm. This changes the API lifecycle state to Published.

                                                  You can observe that the API lifecycle stage has changed to Published. Now the API is available for consumption. API consumers can consume the API via the Choreo Developer Portal.

                                                  "},{"location":"tutorials/expose-a-service-as-a-managed-api/#step-6-invoke-the-api","title":"Step 6: Invoke the API","text":"

                                                  To generate credentials for the published API and to invoke it via the Developer Portal, follow the steps below:

                                                  1. In the Lifecycle Management pane, click Go to DevPortal. This takes you to the Petstore API published to the Choreo Developer Portal.

                                                  2. To generate credentials for testing the API, follow the steps given below:

                                                    1. In the Developer Portal left navigation menu, click Production under Credentials.
                                                    2. Click Generate Credentials. Choreo generates new tokens and populates the Consumer Key and Consumer Secret fields.
                                                  3. To invoke the API, follow the steps given below:

                                                    1. In the Developer Portal left navigation menu, click Try Out.
                                                    2. In the Endpoint list, select Development as the environment to try out the API.
                                                    3. Click Get Test Key. This generates an access token.
                                                    4. Expand the GET /pet/findByStatus operation and click Try it out.
                                                    5. Select available as the status and click Execute.

                                                  Now you have successfully created, deployed, tested, and published an API proxy using Choreo.

                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/","title":"Secure an API with Role-Based Access Control","text":"

                                                  Role-based access control is a flexible and scalable approach to manage access to API resources. In this approach, each user or group is assigned a specific role that determines the permission granted to perform operations on an API resource.

                                                  This tutorial explains how to implement role-based access control using Choreo and Asgardeo. It includes a real-world scenario with instructions to create and publish an API proxy component in Choreo and apply role-based access control.

                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#scenario","title":"Scenario","text":"

                                                  An organization needs to implement a user management service to keep track of users. The service needs to perform the following four operations:

                                                  • List existing users
                                                  • List a user
                                                  • Create new users
                                                  • Delete a user

                                                  There are two types of users in the organization:

                                                  • Human Resource Manager (HR manager)
                                                  • Human Resource Officer (HR officer)

                                                  Each user type requires different levels of access to the user management service.

                                                  • The HR manager must have permission to perform the following operations: list existing users, list a user, create new users, and delete a user.
                                                  • The HR officer must have permission to perform the following operations: list existing users and list a user.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#implement-role-based-access-control-with-choreo-and-asgardeo","title":"Implement role-based access control with Choreo and Asgardeo","text":"

                                                  Let\u2019s take a look at the steps to follow to implement the scenario described above using Choreo and Asgardeo.

                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#prerequisites","title":"Prerequisites","text":"

                                                  Before you try out this guide, complete the following:

                                                  If you are signing in to the Choreo Console for the first time, create an organization as follows:

                                                  1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                  2. Enter a unique organization name. For example, Stark Industries.
                                                  3. Read and accept the privacy policy and terms of use.
                                                  4. Click Create.

                                                  This creates the organization and opens the home page of the default project created for you.

                                                  Enable Asgardeo as the key manager

                                                  If you created your organization in Choreo before the 21st of February 2023, and you have not already enabled Asgardeo as the key manager, follow these steps to enable Asgardeo as the default key manager:

                                                  1. In the Choreo Console, go to the top navigation menu and click Organization. This takes you to the organization's home page.
                                                  2. In the left navigation menu, click Settings.
                                                  3. In the header, click the Organization list. This will open the organization level settings page.
                                                  4. Click the API Management tab and then click Enable Asgardeo Key Manager.
                                                  5. In the confirmation dialog that opens, click Yes.

                                                    Tip

                                                    Enabling Asgardeo as the default key manager has the following effects:

                                                    • Once the Asgardeo Key Manager is enabled, it will act as the default key manager. You cannot disable, change, or remove it.
                                                    • Existing applications created via the Developer Portal in your organization will continue to function as usual. However, any new application you create within the organization will use Asgardeo as the key manager.
                                                    • New grant types such as Password, Authorization Code, PKCE, and Implicit, which were not available in Choreo will become available.
                                                    • The capability to add an external IdP will be disabled because Asgardeo does not support token exchange. However, you can use the federation capabilities of Asgardeo to achieve similar functionality.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-1-create-an-api-proxy-component-and-deploy-it","title":"Step 1: Create an API proxy component and deploy it","text":"

                                                  Follow these steps to create an API proxy component, add resources, and deploy it:

                                                  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                  2. To create an API proxy component, follow the instructions in Develop an API Proxy: Step 1. This opens the Resources pane, where you can define resources for the API proxy.
                                                  3. In the Resources pane, follow the steps given below to add resources:

                                                    • Select GET as the HTTP Verb, enter /users as the URI Pattern, and click + to add the resource.
                                                    • Select GET as the HTTP Verb, enter /users/{userID} as the URI Pattern, and click + to add the resource.
                                                    • Select POST as the HTTP Verb, enter /users as the URI Pattern, and click + to add the resource.
                                                    • Select DELETE as the HTTP Verb, enter /users/{userID} as the URI Pattern, and click + to add the resource.
                                                  4. To remove the five default resources that start with /*, click the delete icon corresponding to each resource. This marks the resources for deletion.

                                                  5. Click Save. The API resources will be as follows:

                                                  6. In the left navigation menu, click Deploy.

                                                  7. Go to the Build Area card and click Configure & Deploy.
                                                  8. In the Configure API Access Mode pane that opens, select either External or Internal, depending on how you want the API to be accessible. In this tutorial, select External.
                                                  9. Click Deploy.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-2-apply-permission-to-resources-and-publish-the-api","title":"Step 2: Apply permission to resources and publish the API","text":"

                                                  Follow these steps:

                                                  1. On the Deploy page, go to the Build Area card and click Security Settings.
                                                  2. In the Security Settings pane, go to the Permissions List section and click + Add Permission(Scope).
                                                  3. To add necessary permission values to the permission list, follow the steps given below:
                                                    1. In the Permissions List section, enter get_user_list as the permission value and click +Add New.
                                                    2. Similarly, add get_user, create_user, and delete_user as permission values.
                                                  4. In the Permissions section, expand each resource and select the permission values as follows for each:

                                                    Resource Permission GET/users get_user_list GET/users/{userID} get_user POST/users create_user DELETE/users/{userID} delete_user
                                                  5. Click Apply.

                                                  6. To apply the latest permissions to the deployed component, you must redeploy it. Follow the steps below to redeploy:
                                                    1. Go to the Build Area card and click Configure & Deploy.
                                                    2. In the Configure API Access Mode pane that opens, select either External or Internal, depending on how you want the API to be accessible. In this tutorial, select External.
                                                    3. Click Deploy.

                                                  Now you are ready to promote the API to production.

                                                  1. In the left navigation menu, click Deploy.
                                                  2. Go to the Development card and click Promote. The Configure & Deploy pane opens with the Use Development endpoint configuration option selected by default.
                                                  3. Click Next to promote the API to production. Now you can publish the API
                                                  4. In the left navigation menu, click Manage and then click Lifecycle.
                                                  5. In the Lifecycle Management pane, click Publish. This changes the status of the API to Published.

                                                  Now, an application developer can discover the API, subscribe to it and then invoke it.

                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-3-subscribe-to-the-published-api","title":"Step 3: Subscribe to the Published API","text":"

                                                  In this step, you take the role of an application developer who consumes the published API. To consume the API, you must create an application, generate keys, and subscribe to the API.

                                                  Follow these steps:

                                                  1. Go to the API Developer Portal and click Applications on the top menu.
                                                  2. Click +Create.
                                                  3. Enter User Management App as the Application Name and click Create. This creates the application and takes you to the application overview page.
                                                  4. In the Developer Portal left navigation menu, click Production under Credentials.
                                                  5. Click to expand Advanced Configurations and follow these steps to generate credentials for the application:
                                                    1. Select Code as the grant type.
                                                    2. Enter the hosted URL of the application as the Callback URL.
                                                    3. Click Generate Credentials.
                                                  6. To subscribe to the API follow these steps:
                                                    1. In the Developer Portal left navigation menu, click Subscriptions.
                                                    2. In the Subscription Management pane, click Add APIs.
                                                    3. In the Add APIs list, go to the API you created, and click Add.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-4-define-roles-and-assign-them-to-groups","title":"Step 4: Define roles and assign them to groups","text":"

                                                  In this step, you define roles, create necessary groups and assign appropriate roles to groups so that you can easily manage user permission.

                                                  Follow these steps:

                                                  1. In the Developer Portal left navigation menu, click Production under Credentials.
                                                  2. In the Permissions section, click Manage Permissions. This takes you to the Roles tab of the User Management App application in Asgardeo, where you can add applicable roles.

                                                  3. Follow these steps to add roles:

                                                    1. Click + New Role, enter admin as the Role Name, and click Next.
                                                    2. Select get_user_list, get_user, create_user, and delete_useras Role Permissions.
                                                    3. Click Finish.
                                                    4. Similarly, add another role with user as the Role Name and get_user_list, and get_user as Role Permissions.

                                                    Now you can proceed to create groups and assign applicable roles to the groups.

                                                  4. In the Asgardeo Console left navigation menu, click User Management and then click Groups.

                                                  5. In the Groups pane, follow these steps to add groups and assign roles:
                                                    1. Click + New Group, enter HR-Manager as the Group Name, and click Finish.
                                                    2. Click the Roles tab in the HR-Manager group you created and then click + Assign Roles.
                                                    3. Click the arrow corresponding to the User Management App to view applicable roles and select admin.
                                                    4. Click Save.
                                                    5. Similarly, add another group with HR-Officer as the Group Name and assign the user role to it.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-5-define-users-and-assign-them-to-groups","title":"Step 5: Define users and assign them to groups","text":"

                                                  In this step, you define users and assign them to groups depending on the job function of the user. This allows you to manage permission at the group level instead of for individual users.

                                                  Follow these steps:

                                                  1. Define two users named Cameron and Alex. For step-by-step instructions on adding a user, see Manage users in the Asgardeo documentation.
                                                  2. Assign Cameron to the HR-Manager group and assign Alex to the HR-Officer group. For step-by-step instructions on assigning a user to a group, see Assign groups in the Asgardeo documentation.
                                                  "},{"location":"tutorials/secure-an-api-with-role-based-access-control/#step-6-obtain-an-access-token-and-try-out-the-api","title":"Step 6: Obtain an access token and try out the API","text":"

                                                  Follow these steps:

                                                  1. Construct the authorization URL as follows by replacing the placeholders with appropriate values:

                                                    <authorize_URL>?response_type=code&client_id=<clientID>&redirect_uri=<redirect_URL>&scope=<scopes>\n
                                                    • Replace <authorize URL> with the URL populated as the Authorize Endpoint in the Application Keys pane.

                                                    • Replace <redirect_URL> with the value specified as the Callback URL under Advanced Configurations in the Application Keys pane.

                                                    • Replace <scopes> with the permission(scopes) applicable to the user. You can copy the applicable permission(scopes) from the API Overview page. Here let\u2019s copy the permission(scopes) applicable to the user Alex.

                                                    • Replace <clientID> with the value populated as Consumer Key in the Application Keys pane.

                                                  2. Open the constructed URL via a web browser. This will take you to a sign-in page provided by Asgardeo.

                                                  3. Sign in with credentials of Alex and click Allow to approve the consent.

                                                    This redirects you to the callback URL of the application. The URL includes a code as a query parameter.

                                                  4. Copy the code and use it to replace <code> in the following cURL command to invoke the authorization code grant token request:

                                                    curl <token_url> -d \"grant_type=authorization_code&code=<code>&redirect_uri=<redirect_uri>\" -H \"Authorization: Basic <base64(clientId:clientSecret)>\"\n
                                                    • Replace <token_url> with the URL populated as the Token Endpoint in the Application Keys pane.

                                                    • Replace <redirect_uri> with the value specified as the Callback URL under Advanced Configurations in the Application Keys pane.

                                                    • Use a Base64 encoder to encode your client ID and client secret in the following format and replace <base64(clientId:clientSecret)> with the encoded value:

                                                      <clientId>:<clientSecret>

                                                      Note

                                                      WSO2 does not recommend the use of online Base64 encoders for this purpose.

                                                  5. Extract the access token from the response that you get.

                                                  6. Go to the API Developer Portal, try out the HR API using the access token you extracted, and observe the responses.

                                                    You\u2019ll observe that it is only possible to access the following resources because the access token only contains the permission(scopes) to invoke those resources:

                                                    • GET /users
                                                    • GET /users/{userID}

                                                    Invoking any other resource gives you a scope validation failed response because the token doesn't include the required scopes to invoke them.

                                                  Similarly, if you use Cameron\u2019s credentials and sign in to obtain an access token, you'll observe that you can invoke all four resources because it would contain all the required permission(scopes).

                                                  Now you have gained hands-on experience in implementing role-based access control with Choreo and Asgardeo.

                                                  "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..2dfc7fd3b --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,703 @@ + + + + https://wso2.com/choreo/docs/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/page-not-found/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/what-is-choreo/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-a-custom-domain-for-your-organization/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-a-user-store-with-built-in-idp/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-approvals-for-choreo-workflows/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-enterprise-login/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-self-sign-up/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/control-access-in-the-choreo-console/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/create-api-subscription-plans/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/customize-the-developer-portal/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/inviting-members/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/manage-members-of-an-organization/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/review-workflow-approval-requests/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-an-external-idp/configure-asgardeo-as-an-external-idp/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/administer/configure-an-external-idp/configure-azure-ad-as-an-external-idp/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-rate-limiting/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/control-api-visibility/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/documents/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/lifecycle-management/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/rename-api-display-name/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-governance/default-rulesets/owasp_top_10_doc/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-governance/default-rulesets/wso2_api_design_guidelines_doc/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-governance/default-rulesets/wso2_style_guidelines_doc/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-policies/about-api-policies/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-policies/apply-advanced-settings-on-mediation-policies/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/api-policies/attach-and-manage-policies/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/manage-api-traffic/assign-subscription-plans-to-apis/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/api-management/manage-api-traffic/subscribe-to-an-api-with-a-subscription-plan/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/configure-mutual-tls-between-components/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/pass-end-user-attributes-to-upstream-services/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/secure-api-access-with-asgardeo/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/secure-api-access-with-azure-ad/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/secure-communication-between-the-choreo-gateway-and-your-backend-with-mutual-tls/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/secure-web-applications-with-managed-authentication/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/authentication-and-authorization/test-secure-api-access-with-choreo-built-in-security-token-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-cli/choreo-cli-overview/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-cli/get-started-with-the-choreo-cli/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/choreo-marketplace/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/ci-cd/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/component/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/connections/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/data-planes/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/deployment-tracks/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/endpoint/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/environments/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/organization/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/project/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/choreo-concepts/resource-hierarchy/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/consuming-a-sevice/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/create-a-subscription/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/create-an-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/generate-an-access-token/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/manage-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/manage-subscription/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/consuming-services/share-applications/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/bring-your-own-image/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/configure-endpoints-body/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/configure-endpoints/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/deploy-a-containerized-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/deploy-an-application-with-buildpacks/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-a-webhook/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-an-api-proxy/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-components-using-vs-code/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-components-with-git/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/manage-component-source-configurations/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/manage-deployment-tracks-for-choreo-components/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/manage-the-micro-integrator-runtime-version-in-your-integration-project/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/submit-and-manage-workflow-approval-requests/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/work-with-the-micro-integrator-runtime-in-choreo/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-integrations/develop-a-manual-task/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-integrations/develop-a-scheduled-task/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-integrations/develop-an-event-handler/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-integrations/develop-an-integration-with-integration-studio/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/develop-a-ballerina-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/develop-a-service-with-docker/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/develop-a-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-ballerina-graphql-endpoint-via-a-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-grpc-endpoint-via-a-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-prism-based-mock-server-using-an-openapi-specification/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-tcp-server-via-a-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-udp-server-via-a-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/expose-a-websocket-endpoint-via-a-nodejs-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-services/service-component-overview/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-web-applications/build-and-deploy-a-single-page-web-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/develop-web-applications/develop-web-applications-locally-with-managed-authentication/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/sharing-and-reusing/create-a-connection/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/sharing-and-reusing/use-a-connection-in-your-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/sharing-and-reusing/use-a-connection-in-your-web-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/develop-components/sharing-and-reusing/use-a-database-connection-in-your-component/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/configure-container-resources-commands-and-arguments/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/configure-storage/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/configure-vpns-on-the-choreo-cloud-data-plane/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/manage-configurations-and-secrets/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/manage-environments/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/set-up-health-checks/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/view-runtime-details/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/autoscale/autoscale-component-replicas/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/devops-and-ci-cd/autoscale/autoscale-components-with-scale-to-zero/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/integrate-and-manage-external-services/integrate-and-manage-gen-ai-services/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/integrate-and-manage-external-services/integrate-and-manage-third-party-services/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/add-choreo-managed-databases-and-caches-to-the-marketplace/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/billing-for-platform-services/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/choreo-managed-caches/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/choreo-managed-databases-and-caches/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/choreo-managed-mysql-databases/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-databases-and-caches/choreo-managed-postgresql-databases/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-message-brokers/choreo-managed-message-brokers/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-message-brokers/configure-a-kafka-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-message-brokers/create-choreo-managed-kafka-services/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/manage-message-brokers/monitor-a-kafka-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/generate-custom-reports/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/insights-overview/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/integrate-choreo-with-moesif/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/observability-overview/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/view-logs/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/alerts/configure-alerts/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/delivery-insights/configure-dora-metrics/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/delivery-insights/view-dora-metrics/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/logs/view-pdp-logs/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/work-with-choreo-insights-api/access-the-choreo-insights-api/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/monitoring-and-insights/work-with-choreo-insights-api/choreo-insights-api/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/quick-start-guides/deploy-a-web-application-that-consumes-a-backend-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/quick-start-guides/deploy-your-first-service/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/quick-start-guides/deploy-your-first-static-web-application/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/choreo-limitations/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/choreo-platform-services-billing/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/faq/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/private-data-plane-management-models/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/private-data-plane-security-levels/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/references/troubleshoot-choreo/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/resources/kubernetes-upgrade-notice/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-apis-with-choreo-apichat/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-apis-with-curl/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-components-with-test-runner/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-graphql-endpoints-via-the-graphql-console/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-rest-endpoints-via-the-openapi-console/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/testing/test-websocket-endpoints-via-the-websocket-console/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/tutorials/expose-a-service-as-a-managed-api/ + 2024-11-04 + daily + + + https://wso2.com/choreo/docs/tutorials/secure-an-api-with-role-based-access-control/ + 2024-11-04 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 000000000..a23db658d Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/test/curl/index.html b/test/curl/index.html new file mode 100644 index 000000000..abb2b9867 --- /dev/null +++ b/test/curl/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/test/graphql-console/index.html b/test/graphql-console/index.html new file mode 100644 index 000000000..8a527d7c7 --- /dev/null +++ b/test/graphql-console/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/test/invoke-apis-via-console/index.html b/test/invoke-apis-via-console/index.html new file mode 100644 index 000000000..5c4fb5a46 --- /dev/null +++ b/test/invoke-apis-via-console/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/test/open-api-console/index.html b/test/open-api-console/index.html new file mode 100644 index 000000000..5c4fb5a46 --- /dev/null +++ b/test/open-api-console/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/testing/test-apis-with-choreo-apichat/index.html b/testing/test-apis-with-choreo-apichat/index.html new file mode 100644 index 000000000..850efe3e1 --- /dev/null +++ b/testing/test-apis-with-choreo-apichat/index.html @@ -0,0 +1,3556 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test APIs with Choreo API Chat - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test APIs with Choreo API Chat

                                                  +

                                                  Testing APIs is an essential step in the API development process. Choreo simplifies the testing task by allowing you to engage with your APIs using natural language through Choreo API Chat. It eliminates manual test scenario creation and JSON payload accuracy concerns. It enables easy API communication using human language and requires no coding for handling sequences with multiple resource calls. This makes your API testing efficient and user-friendly.

                                                  +
                                                  +

                                                  Info

                                                  +

                                                  This feature is available for REST API Proxy components and Service components with REST endpoints.

                                                  +
                                                  +

                                                  Prerequisites

                                                  +

                                                  Before you try out this guide, be sure that you have the following:

                                                  + +

                                                  Test your APIs

                                                  +

                                                  Follow the steps below to test an API with API Chat:

                                                  +
                                                    +
                                                  1. Sign in to the Choreo Console.
                                                  2. +
                                                  3. In the Component Listing pane, click on the component you want to test.
                                                  4. +
                                                  5. On the left navigation, click Test and then click API Chat. This opens the API Chat pane.
                                                  6. +
                                                  7. You can enter your query in natural language and execute it. For example, if you have a resource like "/pet/findByStatus," you can input the query, such as "Get the pets that are available," and execute it to obtain results. The resources are executed sequentially based on your query. Alternatively, you can use the sample queries available to try out API Chat.
                                                  8. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/test-apis-with-choreo-testgpt/index.html b/testing/test-apis-with-choreo-testgpt/index.html new file mode 100644 index 000000000..d63c3fb45 --- /dev/null +++ b/testing/test-apis-with-choreo-testgpt/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/testing/test-apis-with-curl/index.html b/testing/test-apis-with-curl/index.html new file mode 100644 index 000000000..678b848fd --- /dev/null +++ b/testing/test-apis-with-curl/index.html @@ -0,0 +1,3479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test APIs with cURL - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test APIs with cURL

                                                  +

                                                  Testing APIs is an essential step in the API development process. Choreo simplifies the testing task by allowing you to use cURL commands generated by Choreo.

                                                  +

                                                  You can follow the steps below to generate a cURL command and test your API method:

                                                  +
                                                    +
                                                  1. +

                                                    Sign in to the Choreo Console.

                                                    +
                                                  2. +
                                                  3. +

                                                    In the Component Listing pane, click on the component you want to test.

                                                    +
                                                  4. +
                                                  5. +

                                                    Click Test in the left navigation menu and then click cURL. This opens the cURL pane.

                                                    +
                                                  6. +
                                                  7. +

                                                    In the cURL pane, select the environment from the drop-down list.

                                                    +
                                                  8. +
                                                  9. +

                                                    Select an appropriate HTTP method from the Method list.

                                                    +
                                                  10. +
                                                  11. +

                                                    Click the Parameters tab and add the necessary parameters for the API method.

                                                    +
                                                  12. +
                                                  13. +

                                                    Click the Headers tab and add the required header values.

                                                    +
                                                  14. +
                                                  15. +

                                                    Click the Body tab and select the message body type to invoke the API method.

                                                    +
                                                  16. +
                                                  17. +

                                                    Copy the generated cURL command.

                                                    +
                                                  18. +
                                                  19. +

                                                    Use the copied cURL command via a cURL client to test your API method.

                                                    +
                                                  20. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/test-components-with-test-runner/index.html b/testing/test-components-with-test-runner/index.html new file mode 100644 index 000000000..2451af436 --- /dev/null +++ b/testing/test-components-with-test-runner/index.html @@ -0,0 +1,3754 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test Components with Test Runner - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + + + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test Components with Test Runner

                                                  +

                                                  Test Runner is a component type in Choreo that simplifies the process of running automated tests against your components deployed in Choreo. This capability helps developers evaluate applications in different setups and environments, leading to more confidence and improved visibility into the application's status.

                                                  +

                                                  You can create tests using popular programming languages like Go, Java, JavaScript, Python, and more. Additionally, you have the option to build a test runner component by supplying a Dockerfile containing a series of test scripts or by offering a set of Postman Collections.

                                                  +

                                                  Prerequisites

                                                  +

                                                  Before you try out the steps in this guide, complete the following:

                                                  +
                                                    +
                                                  • If you are signing in to the Choreo Console for the first time, create an organization as follows:
                                                      +
                                                    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                    2. +
                                                    3. Enter a unique organization name. For example, Stark Industries.
                                                    4. +
                                                    5. Read and accept the privacy policy and terms of use.
                                                    6. +
                                                    7. Click Create. + This creates the organization and opens the Project Home page of the default project created for you.
                                                    8. +
                                                    +
                                                  • +
                                                  • Fork the Choreo examples repository, which contains the test runner sample for this guide.
                                                  • +
                                                  +

                                                  You can develop tests in a language of your choice and execute them within the Choreo platform.

                                                  +

                                                  Create a test runner component using a buildpack

                                                  +
                                                    +
                                                  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                  2. +
                                                  3. Click +Create in the Component Listing section.
                                                  4. +
                                                  5. Click the Test Runner card.
                                                  6. +
                                                  7. +

                                                    Enter a display name, unique name, and description for the test runner component. For this guide, enter the following values:

                                                    +
                                                    +

                                                    Info

                                                    +

                                                    In the Component Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

                                                    +
                                                    + + + + + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Component Display NameGo Test Runner
                                                    Component Namego-test-runner
                                                    DescriptionTest Runner implemented in Go
                                                    +
                                                  8. +
                                                  9. +

                                                    Go to the GitHub tab.

                                                    +
                                                  10. +
                                                  11. +

                                                    To allow Choreo to connect to your GitHub account, click Authorize with GitHub. If you have not already connected your GitHub repository to Choreo, enter your GitHub credentials and select the repository you created in the prerequisites section to install the Choreo GitHub App.

                                                    +

                                                    Alternatively, you can paste the Choreo samples repository URL in the Provide Repository URL field to connect to it without requiring authorization from the Choreo Apps GitHub application. However, authorizing the repository with the Choreo GitHub App is necessary if you want to enable Auto Deploy for the component.

                                                    +
                                                    +

                                                    Note

                                                    +

                                                    The Choreo GitHub App requires the following permissions:

                                                    +
                                                      +
                                                    • Read and write access to code and pull requests.
                                                    • +
                                                    • Read access to issues and metadata.
                                                    • +
                                                    +

                                                    You can revoke access if you do not want Choreo to have access to your GitHub account. However, write access is exclusively utilized for sending pull requests to a user repository. Choreo will not directly push any changes to a repository.

                                                    +
                                                    +
                                                  12. +
                                                  13. +

                                                    Under Connect Your Repository, enter the following information:

                                                    + + + + + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    OrganizationYour GitHub account
                                                    GitHub Repositorychoreo-samples
                                                    Branchmain
                                                    +
                                                  14. +
                                                  15. +

                                                    Under Buildpack, select a buildpack based on the language of your choice.

                                                    +
                                                  16. +
                                                  17. +

                                                    Based on the buildpack you chose, go to the relevant tab below and enter the respective values for the Project directory and Language version fields:

                                                    +
                                                    +
                                                    +
                                                    + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Go Project Directory/test-runner-go
                                                    Language Version1.x
                                                    +
                                                    +
                                                    + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Project Directory/test-runner-javascript
                                                    Language Version18.x.x
                                                    +
                                                    +
                                                    + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Project Directory/test-runner-python
                                                    Language Version3.10.x
                                                    +
                                                    +
                                                    + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Project Directory/test-runner-java
                                                    Language Version17
                                                    +
                                                    +
                                                    +

                                                    For programming languages that doesn't support buildpacks or for advanced use cases, you can define your own Dockerfile and run test workloads. Refer to for more information.

                                                    +
                                                    +
                                                    + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Postman Directory/postman-collection-dir
                                                    +
                                                    +
                                                    +
                                                    +
                                                  18. +
                                                  19. +

                                                    Click Create.

                                                    +
                                                  20. +
                                                  +

                                                  You have successfully created a Test Runner component using a buildpack of your choice. Now let's build and run the tests.

                                                  +

                                                  Build and deploy the test runner component to execute the tests

                                                  +
                                                    +
                                                  1. In the left navigation menu, click Build.
                                                  2. +
                                                  3. In the Builds pane, click Build Latest.
                                                  4. +
                                                  5. On the left navigation, click Deploy.
                                                  6. +
                                                  7. In the Set Up card, click Deploy to deploy the test runner component. If you want to provide additional configuration or secrets, use the Configure and Deploy option from the list.
                                                  8. +
                                                  9. Once the deployment is successful, click Execute in the left navigation menu.
                                                  10. +
                                                  11. Select the environment from the environment list and click Run Now to trigger a test execution.
                                                  12. +
                                                  13. +

                                                    Once the execution is completed it is listed on the execution page. This may take some time. Once the execution is listed, you can click on a particular execution to view the test result(s).

                                                    +
                                                    +

                                                    Inject dynamic values into your application as command-line arguments

                                                    +

                                                    If you want to inject dynamic values into your application as command-line arguments when you run a test runner component, follow the steps given below:

                                                    +
                                                      +
                                                    1. Click the drop-down icon next to Run Now and then click Run with Arguments.
                                                    2. +
                                                    3. In the Runtime Arguments pane that opens, enter the arguments you want to pass to your application.
                                                    4. +
                                                    5. Click Execute. This triggers the test runner with the specified arguments.
                                                    6. +
                                                    +
                                                    +

                                                    Tip

                                                    +

                                                    For Postman Collections:

                                                    +
                                                      +
                                                    • The default behavior is to run all the collections in the specified directory.
                                                    • +
                                                    • To run specific collections in the directory, use -f or --files as the first argument, followed by a comma-separated list of collections.
                                                    • +
                                                    • Since Choreo uses Newman internally to run Postman Collections, you can pass any valid Newman arguments.
                                                    • +
                                                    +
                                                    +
                                                    +
                                                  14. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/test-graphql-endpoints-via-the-graphql-console/index.html b/testing/test-graphql-endpoints-via-the-graphql-console/index.html new file mode 100644 index 000000000..4503b5187 --- /dev/null +++ b/testing/test-graphql-endpoints-via-the-graphql-console/index.html @@ -0,0 +1,3495 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test GraphQL Endpoints via the GraphQL Console - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test GraphQL Endpoints via the GraphQL Console

                                                  +

                                                  Choreo provides an integrated GraphQL Console to test publicly exposed GraphQL endpoints of Service components you create and deploy. The GraphQL Console allows you to write queries and mutations interactively. As Choreo uses OAuth2.0 authentication by default to secure GraphQL APIs, the GraphQL Console generates test keys to test APIs.

                                                  +

                                                  Follow the steps below to test a GraphQL endpoint via the GraphQL Console:

                                                  +
                                                    +
                                                  1. +

                                                    Sign in to the Choreo Console.

                                                    +
                                                  2. +
                                                  3. +

                                                    In the Component Listing pane, click on the component you want to test.

                                                    +
                                                  4. +
                                                  5. +

                                                    Click Test in the left navigation menu and then click Console. This opens the GraphQL Console pane.

                                                    +
                                                  6. +
                                                  7. +

                                                    In the GraphQL Console pane, select the environment from the drop-down list.

                                                    +
                                                  8. +
                                                  9. +

                                                    Select the required endpoint from the Endpoint list.

                                                    +
                                                    +

                                                    Note

                                                    +
                                                      +
                                                    • The Network Visibilities of an endpoint are set in the component.yaml. You can set any combination of Public, Organization, or Project.
                                                    • +
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Public, continue with step 7.
                                                    • +
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Organization, the GraphQL endpoint will not be invokable from outside the organization. In this instance, for testing purposes, Choreo allows you to generate a temporay test URL that will be active for 15 minutes. Execute step 6 to generate the temporary URL.
                                                    • +
                                                    +
                                                    +
                                                  10. +
                                                  11. +

                                                    If the Network Visibilities of the endpoint contains Organization, click on Generate URL to generate a temporary test URL that will be active for 15 minutes. Else, skip this step.

                                                    +
                                                    +

                                                    Note

                                                    +

                                                    The temporay test URL will be available only for 15 minutes and it will get expired after. You can deactivate the test URL by clicking on the Deactivate URL button.

                                                    +
                                                    +

                                                    OpenAPI Console

                                                    +
                                                  12. +
                                                  13. +

                                                    Enter the API path and the query or mutation you want to test.

                                                    +
                                                  14. +
                                                  15. +

                                                    Click the play icon.

                                                    +
                                                    +

                                                    Tip

                                                    +

                                                    If you want to generate a required query or mutation for testing via the GraphQL Explorer, click Explorer to open the GraphQL Explorer.

                                                    +
                                                    +
                                                    +

                                                    Note

                                                    +

                                                    GraphQL Explorer has a known issue causing improper construction of list inputs. To work around this, you must manually update the list input in the generated query before executing it.

                                                    +
                                                    +

                                                    GraphQL Console

                                                    +
                                                  16. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/test-rest-endpoints-via-the-openapi-console/index.html b/testing/test-rest-endpoints-via-the-openapi-console/index.html new file mode 100644 index 000000000..4293a8508 --- /dev/null +++ b/testing/test-rest-endpoints-via-the-openapi-console/index.html @@ -0,0 +1,3494 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test REST Endpoints via the OpenAPI Console - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test REST Endpoints via the OpenAPI Console

                                                  +

                                                  Choreo provides an integrated OpenAPI Console to test REST endpoints of Service components that you create and deploy. +As Choreo uses OAuth2.0 authentication to secure REST APIs, the OpenAPI Console generates test keys to test APIs.

                                                  +

                                                  Follow the steps below to test a REST endpoint via the integrated OpenAPI Console:

                                                  +
                                                    +
                                                  1. +

                                                    Sign in to the Choreo Console.

                                                    +
                                                  2. +
                                                  3. +

                                                    In the Component Listing pane, click on the component you want to test.

                                                    +
                                                  4. +
                                                  5. +

                                                    Click Test in the left navigation menu and then click Console. This opens the OpenAPI Console pane.

                                                    +
                                                  6. +
                                                  7. +

                                                    In the OpenAPI Console pane, select the environment from the drop-down list.

                                                    +
                                                  8. +
                                                  9. +

                                                    Select the required endpoint from the Endpoint list.

                                                    +
                                                    +

                                                    Note

                                                    +
                                                      +
                                                    • The Network Visibilities of an endpoint is set in the component.yaml. You can set it to Public, Organization, or Project.
                                                    • +
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Public, go to step 7.
                                                    • +
                                                    • If you have set the Network Visibilities of the endpoint in the component.yaml to Organization, the endpoint will not be publicly accessible. However, for testing purposes, Choreo offers the ability to create a temporary test URL that is publicly accessible (secured with OAuth 2.0) and remains active for 15 minutes. To generate the temporary URL, proceed with step 6.
                                                    • +
                                                    +
                                                    +
                                                  10. +
                                                  11. +

                                                    If the Network Visibilities of the endpoint contains Organization, click on Generate URL to generate a temporary test URL that will be active for 15 minutes. Else, skip this step.

                                                    +
                                                    +

                                                    Note

                                                    +

                                                    The temporary test URL will be available only for 15 minutes and it will get expired after. You can deactivate the test URL by clicking on the Deactivate URL button.

                                                    +
                                                    +

                                                    OpenAPI Console

                                                    +
                                                  12. +
                                                  13. +

                                                    Expand the resource you want to test.

                                                    +
                                                  14. +
                                                  15. +

                                                    Click Try it out.

                                                    +
                                                  16. +
                                                  17. +

                                                    Enter values for parameters if applicable.

                                                    +
                                                  18. +
                                                  19. +

                                                    Click Execute. You can see the response body under Responses.

                                                    +

                                                    OpenAPI Console

                                                    +
                                                  20. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/test-websocket-endpoints-via-the-websocket-console/index.html b/testing/test-websocket-endpoints-via-the-websocket-console/index.html new file mode 100644 index 000000000..39196756b --- /dev/null +++ b/testing/test-websocket-endpoints-via-the-websocket-console/index.html @@ -0,0 +1,3493 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test WebSocket Endpoints via the WebSocket Console - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Test WebSocket Endpoints via the WebSocket Console

                                                  +

                                                  Choreo provides an integrated WebSocket Console to test publicly exposed WebSocket endpoints of Service components you create and deploy. The WebSocket Console allows you to connect to your service and exchange messages interactively. Choreo secures WebSocket APIs with OAuth2.0 by default, and the console automatically generates test keys for authenticated API testing.

                                                  +

                                                  Follow the steps below to test a WebSocket endpoint via the WebSocket Console:

                                                  +
                                                    +
                                                  1. +

                                                    Sign in to the Choreo Console.

                                                    +
                                                  2. +
                                                  3. +

                                                    In the Component Listing pane, click on the component you want to test.

                                                    +
                                                  4. +
                                                  5. +

                                                    Click Test in the left navigation menu and then click Console. This opens the WebSocket Console pane.

                                                    +
                                                  6. +
                                                  7. +

                                                    In the WebSocket Console pane, select the environment from the drop-down list.

                                                    +
                                                  8. +
                                                  9. +

                                                    Select the required endpoint from the Endpoint list.

                                                    +
                                                    +

                                                    Note

                                                    +
                                                      +
                                                    • The Network Visibility of an endpoint is set in the endpoints.yaml file. You can set it to Public, Organization, or Project.
                                                    • +
                                                    • If you have set the Network Visibility of the endpoint to Public, proceed to step 7.
                                                    • +
                                                    • If you have set the Network Visibility of the endpoint to Organization, it won't be accessible from outside the organization. For testing, Choreo allows you to generate a temporary URL that remains active for 15 minutes. Follow step 6 to generate the URL.
                                                    • +
                                                    +
                                                    +
                                                  10. +
                                                  11. +

                                                    If the Network Visibility of the endpoint is set to Organization, click Generate URL to generate a temporary test URL valid for 15 minutes. Otherwise, skip this step.

                                                    +
                                                    +

                                                    Note

                                                    +

                                                    The temporary test URL is valid for 15 minutes and will expire after that. If you want to manually deactivate it, click Deactivate URL.

                                                    +
                                                    +

                                                    WebSocket Console

                                                    +
                                                  12. +
                                                  13. +

                                                    Expand the channel you want to test.

                                                    +
                                                  14. +
                                                  15. +

                                                    Click Connect to establish a connection. The connection status will be displayed in the output logs.

                                                    +
                                                  16. +
                                                  17. +

                                                    Send and receive messages to and from the deployed service.

                                                    +
                                                    +

                                                    Note

                                                    +

                                                    The maximum connection duration is 15 minutes. After that, the connection terminates. To reconnect, click Connect again.

                                                    +
                                                    +
                                                  18. +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/troubleshoot/faq/index.html b/troubleshoot/faq/index.html new file mode 100644 index 000000000..426317852 --- /dev/null +++ b/troubleshoot/faq/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/configure-automatic-deployment/index.html b/tutorials/configure-automatic-deployment/index.html new file mode 100644 index 000000000..84ba09b6e --- /dev/null +++ b/tutorials/configure-automatic-deployment/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/connect-your-existing-ballerina-project-to-choreo/index.html b/tutorials/connect-your-existing-ballerina-project-to-choreo/index.html new file mode 100644 index 000000000..8bb3fe766 --- /dev/null +++ b/tutorials/connect-your-existing-ballerina-project-to-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/connect-your-own-github-repository-to-choreo/index.html b/tutorials/connect-your-own-github-repository-to-choreo/index.html new file mode 100644 index 000000000..8992d9f11 --- /dev/null +++ b/tutorials/connect-your-own-github-repository-to-choreo/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/construct-statements/index.html b/tutorials/construct-statements/index.html new file mode 100644 index 000000000..7a123ea5d --- /dev/null +++ b/tutorials/construct-statements/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/create-your-first-rest-api/index.html b/tutorials/create-your-first-rest-api/index.html new file mode 100644 index 000000000..349745712 --- /dev/null +++ b/tutorials/create-your-first-rest-api/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/expose-a-service-as-a-managed-api/index.html b/tutorials/expose-a-service-as-a-managed-api/index.html new file mode 100644 index 000000000..9c075c7ce --- /dev/null +++ b/tutorials/expose-a-service-as-a-managed-api/index.html @@ -0,0 +1,3730 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Expose a Service as a Managed API - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + + + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Expose a Service as a Managed API

                                                  +

                                                  Choreo simplifies securely exposing existing services as managed APIs. It also allows you to effectively manage all aspects of an API's lifecycle, security, throttling, and governance so that you can focus more on service development.

                                                  +

                                                  In this tutorial, you will use Choreo to expose a service as an API proxy and publish it to the Choreo Developer Portal for application developers to consume.

                                                  +

                                                  Prerequisites

                                                  +

                                                  Before you try out this tutorial, complete the following:

                                                  +
                                                    +
                                                  • +

                                                    If you are signing in to the Choreo Console for the first time, create an organization as follows:

                                                    +
                                                      +
                                                    1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                    2. +
                                                    3. Enter a unique organization name. For example, Stark Industries.
                                                    4. +
                                                    5. Read and accept the privacy policy and terms of use.
                                                    6. +
                                                    7. Click Create.
                                                    8. +
                                                    +

                                                    This creates the organization and opens the Project Home page of the default project created for you.

                                                    +
                                                  • +
                                                  +

                                                  Step 1: Create an API proxy

                                                  +

                                                  To create an API proxy, you can either upload an OpenAPI specification or provide an OpenAPI specification URL. In this tutorial, you will use a URL of a sample OpenAPI specification.

                                                  +

                                                  Follow the steps given below:

                                                  +
                                                    +
                                                  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                  2. +
                                                  3. If you already have one or more components in your project, click + Create under Component Listing. Otherwise, proceed to the next step.
                                                  4. +
                                                  5. Click the API Proxy card.
                                                  6. +
                                                  7. In the Create an API Proxy pane that opens, click Try with sample URL.
                                                  8. +
                                                  9. Click Next.
                                                  10. +
                                                  11. +

                                                    Update the populated API proxy details with the values given in the following table:

                                                    +
                                                    +

                                                    Info

                                                    +

                                                    In the Name field, you must specify a name to uniquely identify the component in various contexts. The value is editable only at the time you create the component. You cannot change the name after you create the component.

                                                    +
                                                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                    FieldValue
                                                    Display NameSwagger Petstore
                                                    Nameswagger-petstore
                                                    Contextapi/v3
                                                    Version1.0
                                                    Targethttps://petstore3.swagger.io/api/v3
                                                    Access ModeExternal: API is publicly accessible
                                                    +
                                                  12. +
                                                  13. +

                                                    Click Create. This creates the component and takes you to the Overview page of the component.

                                                    +
                                                  14. +
                                                  +

                                                  To see the resources of the API proxy, go to the left navigation menu, click Develop, and then click Resources.

                                                  +

                                                  Step 2: Deploy the API proxy

                                                  +

                                                  To deploy the API proxy to the development environment, follow the steps given below:

                                                  +
                                                    +
                                                  1. In the left navigation menu, click Deploy.
                                                  2. +
                                                  3. +

                                                    In the Build Area card, click Configure & Deploy. This opens the Configure & Deploy pane, where you can select the API access mode depending on how you want the API to be accessible.

                                                    +

                                                    Here, you can select External to make the API publicly accessible, and then click Deploy.

                                                    +

                                                    Once the deployment is complete, the Development card indicates the Deployment Status as Active.

                                                    +
                                                  4. +
                                                  +

                                                  Now you are ready to test the API proxy.

                                                  +

                                                  Step 3: Test the API proxy

                                                  +

                                                  You can test the API proxy in the development environment before promoting it to production. Choreo provides the following options to test your API proxy: +- OpenAPI Console +- cURL

                                                  +

                                                  In this guide, you will use the OpenAPI Console.

                                                  +

                                                  To test the API proxy via the OpenAPI Console, follow the steps given below:

                                                  +
                                                    +
                                                  1. +

                                                    In the left navigation menu, click Test and then click OpenAPI Console.

                                                    +
                                                    +

                                                    Tip

                                                    +

                                                    Since the API proxy is secured when it is deployed, you will need a key to invoke it. Choreo automatically generates a key when you navigate to the OpenAPI Console pane.

                                                    +
                                                    +
                                                  2. +
                                                  3. +

                                                    In the OpenAPI Console pane, select Development from the environment drop-down list.

                                                    +
                                                  4. +
                                                  5. Expand the GET /pet/findByStatus method and click Try it Out to test it.
                                                  6. +
                                                  7. +

                                                    Select available as the status and click Execute. You will see a response similar to the following:

                                                    +

                                                    API proxy response

                                                    +
                                                  8. +
                                                  +

                                                  This indicates that your API proxy is working as expected.

                                                  +

                                                  Step 4: Promote the API proxy to production

                                                  +

                                                  Once you verify that the API proxy is working as expected in the development environment, you can follow the steps given below to promote it to production:

                                                  +
                                                    +
                                                  1. In the left navigation menu, click Deploy.
                                                  2. +
                                                  3. In the Development card, click Promote.
                                                  4. +
                                                  5. +

                                                    In the Configure & Deploy pane that opens, click Next.

                                                    +
                                                    +

                                                    Tip

                                                    +

                                                    If you want to specify a different endpoint for your production environment, you can make the change in the Configure & Deploy pane.

                                                    +
                                                    +
                                                  6. +
                                                  +

                                                  The Production card indicates the Deployment Status as Active when the API proxy is successfully deployed to production.

                                                  +

                                                  If you want to verify that the API proxy is working as expected in production, you can test the API in the production environment.

                                                  +

                                                  Now that your API is deployed in both development and production environments and can be invoked, the next step is to publish it so that consumers can discover and subscribe to it.

                                                  +

                                                  Step 5: Publish the API proxy

                                                  +

                                                  To publish the API to the Choreo Developer Portal, follow the steps given below:

                                                  +
                                                    +
                                                  1. In the left navigation menu, click Manage and then click Lifecycle. This opens the Lifecycle page, where you can see the different lifecycle stages that an API can be in. You can see that the current lifecycle stage is Created.
                                                  2. +
                                                  3. Click Publish.
                                                  4. +
                                                  5. In the Publish API dialog that opens, click Confirm to proceed publishing the API with the specified display name. If you want to change the display name, make the necessary changes and then click Confirm. This changes the API lifecycle state to Published.
                                                  6. +
                                                  +

                                                  You can observe that the API lifecycle stage has changed to Published. Now the API is available for consumption. API consumers can consume the API via the Choreo Developer Portal.

                                                  +

                                                  Step 6: Invoke the API

                                                  +

                                                  To generate credentials for the published API and to invoke it via the Developer Portal, follow the steps below:

                                                  +
                                                    +
                                                  1. +

                                                    In the Lifecycle Management pane, click Go to DevPortal. This takes you to the Petstore API published to the Choreo Developer Portal.

                                                    +
                                                  2. +
                                                  3. +

                                                    To generate credentials for testing the API, follow the steps given below:

                                                    +
                                                      +
                                                    1. In the Developer Portal left navigation menu, click Production under Credentials.
                                                    2. +
                                                    3. Click Generate Credentials. Choreo generates new tokens and populates the Consumer Key and Consumer Secret fields.
                                                    4. +
                                                    +
                                                  4. +
                                                  5. +

                                                    To invoke the API, follow the steps given below:

                                                    +
                                                      +
                                                    1. In the Developer Portal left navigation menu, click Try Out.
                                                    2. +
                                                    3. In the Endpoint list, select Development as the environment to try out the API.
                                                    4. +
                                                    5. Click Get Test Key. This generates an access token.
                                                    6. +
                                                    7. Expand the GET /pet/findByStatus operation and click Try it out.
                                                    8. +
                                                    9. Select available as the status and click Execute.
                                                    10. +
                                                    +
                                                  6. +
                                                  +

                                                  Now you have successfully created, deployed, tested, and published an API proxy using Choreo.

                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tutorials/map-data/index.html b/tutorials/map-data/index.html new file mode 100644 index 000000000..c58674663 --- /dev/null +++ b/tutorials/map-data/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/tutorials/secure-an-api-with-role-based-access-control/index.html b/tutorials/secure-an-api-with-role-based-access-control/index.html new file mode 100644 index 000000000..523b89f9d --- /dev/null +++ b/tutorials/secure-an-api-with-role-based-access-control/index.html @@ -0,0 +1,3892 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Secure an API with Role-Based Access Control - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + + + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  Secure an API with Role-Based Access Control

                                                  +

                                                  Role-based access control is a flexible and scalable approach to manage access to API resources. In this approach, each user or group is assigned a specific role that determines the permission granted to perform operations on an API resource.

                                                  +

                                                  This tutorial explains how to implement role-based access control using Choreo and Asgardeo. It includes a real-world scenario with instructions to create and publish an API proxy component in Choreo and apply role-based access control.

                                                  +

                                                  Scenario

                                                  +

                                                  An organization needs to implement a user management service to keep track of users. The service needs to perform the following four operations:

                                                  +
                                                    +
                                                  • List existing users
                                                  • +
                                                  • List a user
                                                  • +
                                                  • Create new users
                                                  • +
                                                  • Delete a user
                                                  • +
                                                  +

                                                  There are two types of users in the organization:

                                                  +
                                                    +
                                                  • Human Resource Manager (HR manager)
                                                  • +
                                                  • Human Resource Officer (HR officer)
                                                  • +
                                                  +

                                                  Each user type requires different levels of access to the user management service.

                                                  +
                                                    +
                                                  • The HR manager must have permission to perform the following operations: list existing users, list a user, create new users, and delete a user.
                                                  • +
                                                  • The HR officer must have permission to perform the following operations: list existing users and list a user.
                                                  • +
                                                  +

                                                  Implement role-based access control with Choreo and Asgardeo

                                                  +

                                                  Let’s take a look at the steps to follow to implement the scenario described above using Choreo and Asgardeo.

                                                  +

                                                  Prerequisites

                                                  +

                                                  Before you try out this guide, complete the following:

                                                  +

                                                  If you are signing in to the Choreo Console for the first time, create an organization as follows:

                                                  +
                                                    +
                                                  1. Go to https://console.choreo.dev/, and sign in using your preferred method.
                                                  2. +
                                                  3. Enter a unique organization name. For example, Stark Industries.
                                                  4. +
                                                  5. Read and accept the privacy policy and terms of use.
                                                  6. +
                                                  7. Click Create.
                                                  8. +
                                                  +

                                                  This creates the organization and opens the home page of the default project created for you.

                                                  +
                                                  +

                                                  Enable Asgardeo as the key manager

                                                  +

                                                  If you created your organization in Choreo before the 21st of February 2023, and you have not already enabled Asgardeo as the key manager, follow these steps to enable Asgardeo as the default key manager:

                                                  +
                                                    +
                                                  1. In the Choreo Console, go to the top navigation menu and click Organization. This takes you to the organization's home page.
                                                  2. +
                                                  3. In the left navigation menu, click Settings.
                                                  4. +
                                                  5. In the header, click the Organization list. This will open the organization level settings page.
                                                  6. +
                                                  7. Click the API Management tab and then click Enable Asgardeo Key Manager.
                                                  8. +
                                                  9. +

                                                    In the confirmation dialog that opens, click Yes.

                                                    +
                                                    +

                                                    Tip

                                                    +

                                                    Enabling Asgardeo as the default key manager has the following effects:

                                                    +
                                                      +
                                                    • Once the Asgardeo Key Manager is enabled, it will act as the default key manager. You cannot disable, change, or remove it.
                                                    • +
                                                    • Existing applications created via the Developer Portal in your organization will continue to function as usual. However, any new application you create within the organization will use Asgardeo as the key manager.
                                                    • +
                                                    • New grant types such as Password, Authorization Code, PKCE, and Implicit, which were not available in Choreo will become available.
                                                    • +
                                                    • The capability to add an external IdP will be disabled because Asgardeo does not support token exchange. However, you can use the federation capabilities of Asgardeo to achieve similar functionality.
                                                    • +
                                                    +
                                                    +
                                                  10. +
                                                  +
                                                  +

                                                  Step 1: Create an API proxy component and deploy it

                                                  +

                                                  Follow these steps to create an API proxy component, add resources, and deploy it:

                                                  +
                                                    +
                                                  1. Go to https://console.choreo.dev/ and sign in. This opens the project home page.
                                                  2. +
                                                  3. To create an API proxy component, follow the instructions in Develop an API Proxy: Step 1. This opens the Resources pane, where you can define resources for the API proxy.
                                                  4. +
                                                  5. +

                                                    In the Resources pane, follow the steps given below to add resources:

                                                    +
                                                      +
                                                    • Select GET as the HTTP Verb, enter /users as the URI Pattern, and click + to add the resource.
                                                    • +
                                                    • Select GET as the HTTP Verb, enter /users/{userID} as the URI Pattern, and click + to add the resource.
                                                    • +
                                                    • Select POST as the HTTP Verb, enter /users as the URI Pattern, and click + to add the resource.
                                                    • +
                                                    • Select DELETE as the HTTP Verb, enter /users/{userID} as the URI Pattern, and click + to add the resource.
                                                    • +
                                                    +
                                                  6. +
                                                  7. +

                                                    To remove the five default resources that start with /*, click the delete icon corresponding to each resource. This marks the resources for deletion.

                                                    +
                                                  8. +
                                                  9. +

                                                    Click Save. The API resources will be as follows:

                                                    +

                                                    API resources

                                                    +
                                                  10. +
                                                  11. +

                                                    In the left navigation menu, click Deploy.

                                                    +
                                                  12. +
                                                  13. Go to the Build Area card and click Configure & Deploy.
                                                  14. +
                                                  15. In the Configure API Access Mode pane that opens, select either External or Internal, depending on how you want the API to be accessible. In this tutorial, select External.
                                                  16. +
                                                  17. Click Deploy.
                                                  18. +
                                                  +

                                                  Step 2: Apply permission to resources and publish the API

                                                  +

                                                  Follow these steps:

                                                  +
                                                    +
                                                  1. On the Deploy page, go to the Build Area card and click Security Settings.
                                                  2. +
                                                  3. In the Security Settings pane, go to the Permissions List section and click + Add Permission(Scope).
                                                  4. +
                                                  5. To add necessary permission values to the permission list, follow the steps given below:
                                                      +
                                                    1. In the Permissions List section, enter get_user_list as the permission value and click +Add New.
                                                    2. +
                                                    3. Similarly, add get_user, create_user, and delete_user as permission values.
                                                    4. +
                                                    +
                                                  6. +
                                                  7. +

                                                    In the Permissions section, expand each resource and select the permission values as follows for each:

                                                    + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                    ResourcePermission
                                                    GET/usersget_user_list
                                                    GET/users/{userID}get_user
                                                    POST/userscreate_user
                                                    DELETE/users/{userID}delete_user
                                                    +
                                                  8. +
                                                  9. +

                                                    Click Apply.

                                                    +
                                                  10. +
                                                  11. To apply the latest permissions to the deployed component, you must redeploy it. Follow the steps below to redeploy:
                                                      +
                                                    1. Go to the Build Area card and click Configure & Deploy.
                                                    2. +
                                                    3. In the Configure API Access Mode pane that opens, select either External or Internal, depending on how you want the API to be accessible. In this tutorial, select External.
                                                    4. +
                                                    5. Click Deploy.
                                                    6. +
                                                    +
                                                  12. +
                                                  +

                                                  Now you are ready to promote the API to production.

                                                  +
                                                    +
                                                  1. In the left navigation menu, click Deploy.
                                                  2. +
                                                  3. Go to the Development card and click Promote. The Configure & Deploy pane opens with the Use Development endpoint configuration option selected by default.
                                                  4. +
                                                  5. Click Next to promote the API to production. Now you can publish the API
                                                  6. +
                                                  7. In the left navigation menu, click Manage and then click Lifecycle.
                                                  8. +
                                                  9. In the Lifecycle Management pane, click Publish. This changes the status of the API to Published.
                                                  10. +
                                                  +

                                                  Now, an application developer can discover the API, subscribe to it and then invoke it.

                                                  +

                                                  Step 3: Subscribe to the Published API

                                                  +

                                                  In this step, you take the role of an application developer who consumes the published API. +To consume the API, you must create an application, generate keys, and subscribe to the API.

                                                  +

                                                  Follow these steps:

                                                  +
                                                    +
                                                  1. Go to the API Developer Portal and click Applications on the top menu.
                                                  2. +
                                                  3. Click +Create.
                                                  4. +
                                                  5. Enter User Management App as the Application Name and click Create. This creates the application and takes you to the application overview page.
                                                  6. +
                                                  7. In the Developer Portal left navigation menu, click Production under Credentials.
                                                  8. +
                                                  9. Click to expand Advanced Configurations and follow these steps to generate credentials for the application:
                                                      +
                                                    1. Select Code as the grant type.
                                                    2. +
                                                    3. Enter the hosted URL of the application as the Callback URL.
                                                    4. +
                                                    5. Click Generate Credentials.
                                                    6. +
                                                    +
                                                  10. +
                                                  11. To subscribe to the API follow these steps:
                                                      +
                                                    1. In the Developer Portal left navigation menu, click Subscriptions.
                                                    2. +
                                                    3. In the Subscription Management pane, click Add APIs.
                                                    4. +
                                                    5. In the Add APIs list, go to the API you created, and click Add.
                                                    6. +
                                                    +
                                                  12. +
                                                  +

                                                  Step 4: Define roles and assign them to groups

                                                  +

                                                  In this step, you define roles, create necessary groups and assign appropriate roles to groups so that you can easily manage user permission.

                                                  +

                                                  Follow these steps:

                                                  +
                                                    +
                                                  1. In the Developer Portal left navigation menu, click Production under Credentials.
                                                  2. +
                                                  3. +

                                                    In the Permissions section, click Manage Permissions. This takes you to the Roles tab of the User Management App application in Asgardeo, where you can add applicable roles.

                                                    +

                                                    Manage permissions

                                                    +
                                                  4. +
                                                  5. +

                                                    Follow these steps to add roles:

                                                    +
                                                      +
                                                    1. Click + New Role, enter admin as the Role Name, and click Next.
                                                    2. +
                                                    3. Select get_user_list, get_user, create_user, and delete_useras Role Permissions.
                                                    4. +
                                                    5. Click Finish.
                                                    6. +
                                                    7. Similarly, add another role with user as the Role Name and get_user_list, and get_user as Role Permissions.
                                                    8. +
                                                    +

                                                    Now you can proceed to create groups and assign applicable roles to the groups.

                                                    +
                                                  6. +
                                                  7. +

                                                    In the Asgardeo Console left navigation menu, click User Management and then click Groups.

                                                    +
                                                  8. +
                                                  9. In the Groups pane, follow these steps to add groups and assign roles:
                                                      +
                                                    1. Click + New Group, enter HR-Manager as the Group Name, and click Finish.
                                                    2. +
                                                    3. Click the Roles tab in the HR-Manager group you created and then click + Assign Roles.
                                                    4. +
                                                    5. Click the arrow corresponding to the User Management App to view applicable roles and select admin.
                                                    6. +
                                                    7. Click Save.
                                                    8. +
                                                    9. Similarly, add another group with HR-Officer as the Group Name and assign the user role to it.
                                                    10. +
                                                    +
                                                  10. +
                                                  +

                                                  Step 5: Define users and assign them to groups

                                                  +

                                                  In this step, you define users and assign them to groups depending on the job function of the user. This allows you to manage permission at the group level instead of for individual users.

                                                  +

                                                  Follow these steps:

                                                  +
                                                    +
                                                  1. Define two users named Cameron and Alex. For step-by-step instructions on adding a user, see Manage users in the Asgardeo documentation.
                                                  2. +
                                                  3. Assign Cameron to the HR-Manager group and assign Alex to the HR-Officer group. For step-by-step instructions on assigning a user to a group, see Assign groups in the Asgardeo documentation.
                                                  4. +
                                                  +

                                                  Step 6: Obtain an access token and try out the API

                                                  +

                                                  Follow these steps:

                                                  +
                                                    +
                                                  1. +

                                                    Construct the authorization URL as follows by replacing the placeholders with appropriate values:

                                                    +
                                                    <authorize_URL>?response_type=code&client_id=<clientID>&redirect_uri=<redirect_URL>&scope=<scopes>
                                                    +
                                                    + +
                                                      +
                                                    • +

                                                      Replace <authorize URL> with the URL populated as the Authorize Endpoint in the Application Keys pane.

                                                      +

                                                      Authorize endpoint

                                                      +
                                                    • +
                                                    • +

                                                      Replace <redirect_URL> with the value specified as the Callback URL under Advanced Configurations in the Application Keys pane.

                                                      +

                                                      Callback URL

                                                      +
                                                    • +
                                                    • +

                                                      Replace <scopes> with the permission(scopes) applicable to the user. You can copy the applicable permission(scopes) from the API Overview page. Here let’s copy the permission(scopes) applicable to the user Alex.

                                                      +

                                                      Scopes

                                                      +
                                                    • +
                                                    • +

                                                      Replace <clientID> with the value populated as Consumer Key in the Application Keys pane.

                                                      +

                                                      Consumer key

                                                      +
                                                    • +
                                                    +
                                                  2. +
                                                  3. +

                                                    Open the constructed URL via a web browser. This will take you to a sign-in page provided by Asgardeo.

                                                    +
                                                  4. +
                                                  5. +

                                                    Sign in with credentials of Alex and click Allow to approve the consent.

                                                    +

                                                    Approve consent

                                                    +

                                                    This redirects you to the callback URL of the application. The URL includes a code as a query parameter.

                                                    +

                                                    Code

                                                    +
                                                  6. +
                                                  7. +

                                                    Copy the code and use it to replace <code> in the following cURL command to invoke the authorization code grant token request:

                                                    +
                                                    curl <token_url> -d "grant_type=authorization_code&code=<code>&redirect_uri=<redirect_uri>" -H "Authorization: Basic <base64(clientId:clientSecret)>"
                                                    +
                                                    + +
                                                      +
                                                    • +

                                                      Replace <token_url> with the URL populated as the Token Endpoint in the Application Keys pane.

                                                      +

                                                      Token endpoint

                                                      +
                                                    • +
                                                    • +

                                                      Replace <redirect_uri> with the value specified as the Callback URL under Advanced Configurations in the Application Keys pane.

                                                      +
                                                    • +
                                                    • +

                                                      Use a Base64 encoder to encode your client ID and client secret in the following format and replace <base64(clientId:clientSecret)> with the encoded value:

                                                      +

                                                      <clientId>:<clientSecret>

                                                      +
                                                      +

                                                      Note

                                                      WSO2 does not recommend the use of online Base64 encoders for this purpose.

                                                      +

                                                      +
                                                      +
                                                    • +
                                                    +
                                                  8. +
                                                  9. +

                                                    Extract the access token from the response that you get.

                                                    +

                                                    Access token

                                                    +
                                                  10. +
                                                  11. +

                                                    Go to the API Developer Portal, try out the HR API using the access token you extracted, and observe the responses.

                                                    +

                                                    You’ll observe that it is only possible to access the following resources because the access token only contains the permission(scopes) to invoke those resources:

                                                    +
                                                      +
                                                    • GET /users
                                                    • +
                                                    • GET /users/{userID}
                                                    • +
                                                    +

                                                    Invoking any other resource gives you a scope validation failed response because the token doesn't include the required scopes to invoke them. + Scope validation failed

                                                    +
                                                  12. +
                                                  +

                                                  Similarly, if you use Cameron’s credentials and sign in to obtain an access token, you'll observe that you can invoke all four resources because it would contain all the required permission(scopes).

                                                  +

                                                  Now you have gained hands-on experience in implementing role-based access control with Choreo and Asgardeo.

                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webhook/index.html b/webhook/index.html new file mode 100644 index 000000000..7b4b54dd2 --- /dev/null +++ b/webhook/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/what-is-choreo/index.html b/what-is-choreo/index.html new file mode 100644 index 000000000..0f545896e --- /dev/null +++ b/what-is-choreo/index.html @@ -0,0 +1,3502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + What is Choreo? - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  + + + +
                                                  + + + + + + +
                                                  + + +
                                                  + +
                                                  + + + + + + + +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + +
                                                  +
                                                  + + + + + + + + + + + + + + + + + + + + +

                                                  What is Choreo?

                                                  +

                                                  Choreo is an internal developer platform that redefines how you create digital experiences. Choreo empowers you to seamlessly design, develop, deploy, and govern your cloud native applications, unlocking innovation while reducing time-to-market.

                                                  +

                                                  The following are some of the cutting-edge capabilities of Choreo:

                                                  +
                                                    +
                                                  • +

                                                    Design that leads to end-to-end security, governance, and operational efficiency:

                                                    +
                                                      +
                                                    • Domain-driven design: Organize your enterprise systems into domains, exposing managed APIs, events, and data through projects., A project consists of components representing units of deployment.
                                                    • +
                                                    • Application security design: Cell-based architecture, where projects become governable units from development to deployment, ensuring managed access via APIs, events, and data.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Efficient and effective development:

                                                    +
                                                      +
                                                    • Code in any language: Develop applications in your team's preferred programming language, harnessing existing skill sets to build powerful polyglot APIs, services, events, tasks, and more.
                                                    • +
                                                    • Native support for VS Code: Seamlessly collaborate and manage code using VS Code in a feature-rich, visually-enhanced development environment.
                                                    • +
                                                    • Git repository integration: Effortlessly connect to Git-based platforms like GitHub, Bitbucket, or GitLab to develop components by linking an existing repository.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Seamless deployment:

                                                    +
                                                      +
                                                    • CI/CD: Eliminate manual builds and unreliable deployments with Choreo's industry-standard CI/CD tooling, providing complete control and flexibility.
                                                    • +
                                                    • Multi-cloud Kubernetes: Easily deliver cloud native applications across Azure, AWS, GCP, or your Kubernetes clusters.
                                                    • +
                                                    • Configuration management: Centralize configuration parameters, sensitive credentials, and secrets across deployment environments via an intuitive interface.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Effortless management of APIs, integrations, microservices, and web applications:

                                                    +
                                                      +
                                                    • Enable security: Empower security teams to manage data flows, ensuring seamless control over sensitive information like access credentials.
                                                    • +
                                                    • Scale up or down: Kubernetes handles scaling automatically, optimizing costs by scaling services based on demand.
                                                    • +
                                                    • Ensure reliability: DevOps and SRE teams can easily manage deployed components with built-in insights and observability.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Reusable digital assets:

                                                    +
                                                      +
                                                    • Control visibility and sharing: Publish your digital assets to a shared marketplace for consumption by internal or external stakeholders, managed by role-based access control.
                                                    • +
                                                    • Internal Marketplace: Choreo's secure internal marketplace fosters transparency and efficiency with granular access control for publishers and consumers.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Comprehensive observability:

                                                    +
                                                      +
                                                    • Anomaly detection: Stay ahead of issues with prompt notifications, ensuring balanced scaling and immediate action during unexpected mishaps.
                                                    • +
                                                    • Troubleshoot and debug: Quickly pinpoint and address root causes using detailed logs and data aligned in the same timeline, down to the machine-level details.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Robust governance:

                                                    +
                                                      +
                                                    • DORA metrics: Monitor your DevOps efficiency with Choreo DORA metrics, experiencing rapid improvements in time from deployment to production safely and robustly.
                                                    • +
                                                    • Engineering insights: Gain visibility into engineering insights and advanced data analytics to make data-driven decisions, optimize processes, and improve efficiency.
                                                    • +
                                                    • API analytics: Understand API performance and adoption patterns to identify and resolve operational bottlenecks.
                                                    • +
                                                    +
                                                  • +
                                                  + + + + + + +
                                                  +
                                                  + + +
                                                  + + + +
                                                  + + +
                                                  + + + +
                                                  +
                                                  +
                                                  + + + + + + + + + + + + + + + + + \ No newline at end of file