This is an automated email from the ASF dual-hosted git repository.

jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 353919045aa Add service endpoint to provide hook meta data for UI 
(#47588)
353919045aa is described below

commit 353919045aa83fd6fe9e5b1d9f93873f139610f6
Author: Jens Scheffler <[email protected]>
AuthorDate: Wed Mar 12 23:28:19 2025 +0100

    Add service endpoint to provide hook meta data for UI (#47588)
    
    * Add service endpoint to provide hook meta data for UI
    
    * Review Feedback
    
    * Add pytest, re-wire ui connection endpoint
    
    * Re-naming class feedback
    
    * Revert import formatting change
    
    * Make test as DB test for FAB auth
---
 .../api_fastapi/core_api/datamodels/connections.py |  48 +++
 .../api_fastapi/core_api/openapi/v1-generated.yaml | 124 ++++++
 airflow/api_fastapi/core_api/routes/ui/__init__.py |   2 +
 .../api_fastapi/core_api/routes/ui/connections.py  |  40 ++
 .../core_api/services/ui/connections.py            | 210 ++++++++++
 airflow/ui/openapi-gen/queries/common.ts           | 106 ++---
 airflow/ui/openapi-gen/queries/prefetch.ts         | 109 ++---
 airflow/ui/openapi-gen/queries/queries.ts          | 249 +++++------
 airflow/ui/openapi-gen/queries/suspense.ts         | 147 ++++---
 airflow/ui/openapi-gen/requests/schemas.gen.ts     | 185 +++++++++
 airflow/ui/openapi-gen/requests/services.gen.ts    | 444 ++++++++++----------
 airflow/ui/openapi-gen/requests/types.gen.ts       | 453 ++++++++++++---------
 .../core_api/routes/ui/test_connections.py         |  41 ++
 13 files changed, 1471 insertions(+), 687 deletions(-)

diff --git a/airflow/api_fastapi/core_api/datamodels/connections.py 
b/airflow/api_fastapi/core_api/datamodels/connections.py
index 19a50eac79b..fee330e1fd1 100644
--- a/airflow/api_fastapi/core_api/datamodels/connections.py
+++ b/airflow/api_fastapi/core_api/datamodels/connections.py
@@ -18,6 +18,8 @@
 from __future__ import annotations
 
 import json
+from collections import abc
+from typing import Annotated
 
 from pydantic import Field, field_validator
 from pydantic_core.core_schema import ValidationInfo
@@ -75,6 +77,52 @@ class ConnectionTestResponse(BaseModel):
     message: str
 
 
+class ConnectionHookFieldBehavior(BaseModel):
+    """A class to store the behavior of each standard field of a Hook."""
+
+    hidden: Annotated[
+        bool,
+        Field(description="Flag if the form field should be hidden."),
+    ] = False
+    title: Annotated[
+        str | None,
+        Field(
+            description="Label / title for the field that should be displayed, 
if re-labelling is needed. Use `None` to display standard title."
+        ),
+    ] = None
+    placeholder: Annotated[
+        str | None,
+        Field(description="Placeholder text that should be populated to the 
form."),
+    ] = None
+
+
+class StandardHookFields(BaseModel):
+    """Standard fields of a Hook that a form will render."""
+
+    description: ConnectionHookFieldBehavior | None
+    url_schema: ConnectionHookFieldBehavior | None
+    host: ConnectionHookFieldBehavior | None
+    port: ConnectionHookFieldBehavior | None
+    login: ConnectionHookFieldBehavior | None
+    password: ConnectionHookFieldBehavior | None
+
+
+class ConnectionHookMetaData(BaseModel):
+    """
+    Response model for Hook information == Connection type meta data.
+
+    It is used to transfer providers information loaded by providers_manager 
such that
+    the API server/Web UI can use this data to render connection form UI.
+    """
+
+    connection_type: str | None
+    hook_class_name: str | None
+    default_conn_name: str | None
+    hook_name: str
+    standard_fields: StandardHookFields | None
+    extra_fields: abc.MutableMapping | None
+
+
 # Request Models
 class ConnectionBody(StrictBaseModel):
     """Connection Serializer for requests body."""
diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml 
b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
index 0eab45da497..984a40ff228 100644
--- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
+++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
@@ -58,6 +58,26 @@ paths:
                 $ref: '#/components/schemas/HTTPExceptionResponse'
       security:
       - OAuth2PasswordBearer: []
+  /ui/connections/hook_meta:
+    get:
+      tags:
+      - Connection
+      summary: Hook Meta Data
+      description: Retrieve information about available connection types (hook 
classes)
+        and their parameters.
+      operationId: hook_meta_data
+      responses:
+        '200':
+          description: Successful Response
+          content:
+            application/json:
+              schema:
+                items:
+                  $ref: '#/components/schemas/ConnectionHookMetaData'
+                type: array
+                title: Response Hook Meta Data
+      security:
+      - OAuth2PasswordBearer: []
   /ui/dags/recent_dag_runs:
     get:
       tags:
@@ -8121,6 +8141,74 @@ components:
       - total_entries
       title: ConnectionCollectionResponse
       description: Connection Collection serializer for responses.
+    ConnectionHookFieldBehavior:
+      properties:
+        hidden:
+          type: boolean
+          title: Hidden
+          description: Flag if the form field should be hidden.
+          default: false
+        title:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Title
+          description: Label / title for the field that should be displayed, 
if re-labelling
+            is needed. Use `None` to display standard title.
+        placeholder:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Placeholder
+          description: Placeholder text that should be populated to the form.
+      type: object
+      title: ConnectionHookFieldBehavior
+      description: A class to store the behavior of each standard field of a 
Hook.
+    ConnectionHookMetaData:
+      properties:
+        connection_type:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Connection Type
+        hook_class_name:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Hook Class Name
+        default_conn_name:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Default Conn Name
+        hook_name:
+          type: string
+          title: Hook Name
+        standard_fields:
+          anyOf:
+          - $ref: '#/components/schemas/StandardHookFields'
+          - type: 'null'
+        extra_fields:
+          anyOf:
+          - type: object
+          - type: 'null'
+          title: Extra Fields
+      type: object
+      required:
+      - connection_type
+      - hook_class_name
+      - default_conn_name
+      - hook_name
+      - standard_fields
+      - extra_fields
+      title: ConnectionHookMetaData
+      description: 'Response model for Hook information == Connection type 
meta data.
+
+
+        It is used to transfer providers information loaded by 
providers_manager such
+        that
+
+        the API server/Web UI can use this data to render connection form UI.'
     ConnectionResponse:
       properties:
         connection_id:
@@ -10228,6 +10316,42 @@ components:
       - latest_scheduler_heartbeat
       title: SchedulerInfoResponse
       description: Scheduler info serializer for responses.
+    StandardHookFields:
+      properties:
+        description:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+        url_schema:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+        host:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+        port:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+        login:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+        password:
+          anyOf:
+          - $ref: '#/components/schemas/ConnectionHookFieldBehavior'
+          - type: 'null'
+      type: object
+      required:
+      - description
+      - url_schema
+      - host
+      - port
+      - login
+      - password
+      title: StandardHookFields
+      description: Standard fields of a Hook that a form will render.
     StructureDataResponse:
       properties:
         edges:
diff --git a/airflow/api_fastapi/core_api/routes/ui/__init__.py 
b/airflow/api_fastapi/core_api/routes/ui/__init__.py
index cd01ee44232..b43b4141b9d 100644
--- a/airflow/api_fastapi/core_api/routes/ui/__init__.py
+++ b/airflow/api_fastapi/core_api/routes/ui/__init__.py
@@ -20,6 +20,7 @@ from airflow.api_fastapi.common.router import AirflowRouter
 from airflow.api_fastapi.core_api.routes.ui.assets import assets_router
 from airflow.api_fastapi.core_api.routes.ui.backfills import backfills_router
 from airflow.api_fastapi.core_api.routes.ui.config import config_router
+from airflow.api_fastapi.core_api.routes.ui.connections import 
connections_router
 from airflow.api_fastapi.core_api.routes.ui.dags import dags_router
 from airflow.api_fastapi.core_api.routes.ui.dashboard import dashboard_router
 from airflow.api_fastapi.core_api.routes.ui.dependencies import 
dependencies_router
@@ -30,6 +31,7 @@ ui_router = AirflowRouter(prefix="/ui", 
include_in_schema=False)
 
 ui_router.include_router(assets_router)
 ui_router.include_router(config_router)
+ui_router.include_router(connections_router)
 ui_router.include_router(dags_router)
 ui_router.include_router(dependencies_router)
 ui_router.include_router(dashboard_router)
diff --git a/airflow/api_fastapi/core_api/routes/ui/connections.py 
b/airflow/api_fastapi/core_api/routes/ui/connections.py
new file mode 100644
index 00000000000..2ce95265e04
--- /dev/null
+++ b/airflow/api_fastapi/core_api/routes/ui/connections.py
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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.
+from __future__ import annotations
+
+from fastapi import Depends
+
+from airflow.api_fastapi.common.router import AirflowRouter
+from airflow.api_fastapi.core_api.datamodels.connections import 
ConnectionHookMetaData
+from airflow.api_fastapi.core_api.security import requires_access_connection
+from airflow.api_fastapi.core_api.services.ui.connections import 
HookMetaService
+
+connections_router = AirflowRouter(tags=["Connection"], prefix="/connections")
+
+
+@connections_router.get(
+    "/hook_meta",
+    dependencies=[Depends(requires_access_connection(method="GET"))],
+)
+def hook_meta_data() -> list[ConnectionHookMetaData]:
+    """Retrieve information about available connection types (hook classes) 
and their parameters."""
+    # Note:
+    # This endpoint is implemented to serve the connections form in the UI. It 
is building on providers
+    # manager and hooks being loaded in the API server. Target should be that 
the API server reads the
+    # information from a database table to un-bundle the dependency for 
provider package install from
+    # the API server.
+    return HookMetaService.hook_meta_data()
diff --git a/airflow/api_fastapi/core_api/services/ui/connections.py 
b/airflow/api_fastapi/core_api/services/ui/connections.py
new file mode 100644
index 00000000000..482b3a6b5cb
--- /dev/null
+++ b/airflow/api_fastapi/core_api/services/ui/connections.py
@@ -0,0 +1,210 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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.
+
+from __future__ import annotations
+
+import logging
+from collections.abc import MutableMapping
+from functools import cache
+from typing import TYPE_CHECKING
+
+from airflow.api_fastapi.core_api.datamodels.connections import (
+    ConnectionHookFieldBehavior,
+    ConnectionHookMetaData,
+    StandardHookFields,
+)
+from airflow.sdk import Param
+
+if TYPE_CHECKING:
+    from airflow.providers_manager import ConnectionFormWidgetInfo, HookInfo
+
+log = logging.getLogger(__name__)
+
+
+class HookMetaService:
+    """Service for retrieving details about hooks to render UI."""
+
+    class MockOptional:
+        """Mock for wtforms.validators.Optional."""
+
+        def __init__(
+            self,
+            *args,
+            **kwargs,
+        ):
+            pass
+
+    class MockEnum:
+        """Mock for wtforms.validators.Optional."""
+
+        def __init__(self, allowed_values):
+            self.allowed_values = allowed_values
+
+    class MockBaseField:
+        """Mock of WTForms Field."""
+
+        param_type: str = "UNDEFINED"
+        param_format: str | None = None
+        widget = None
+
+        def __init__(
+            self,
+            label: str | None = None,
+            validators=None,
+            description: str = "",
+            default: str | None = None,
+            widget=None,
+        ):
+            type: str | list[str] = self.param_type
+            enum = {}
+            format = {"format": self.param_format} if self.param_format else {}
+            if validators:
+                if any(isinstance(v, HookMetaService.MockOptional) for v in 
validators):
+                    type = [self.param_type, "null"]
+                for v in validators:
+                    if isinstance(v, HookMetaService.MockEnum):
+                        enum = {"enum": v.allowed_values}
+            self.param = Param(
+                default=default,
+                title=label,
+                description=description or None,
+                type=type,
+                **format,
+                **enum,
+            )
+            self.widget = widget
+            self.field_class = self.__class__
+
+    class MockStringField(MockBaseField):
+        """Mock of WTForms StringField."""
+
+        param_type: str = "string"
+
+    class MockIntegerField(MockBaseField):
+        """Mock of WTForms IntegerField."""
+
+        param_type: str = "integer"
+
+    class MockPasswordField(MockBaseField):
+        """Mock of WTForms PasswordField."""
+
+        param_type: str = "string"
+        param_format: str | None = "password"
+
+    class MockBooleanField(MockBaseField):
+        """Mock of WTForms BooleanField."""
+
+        param_type: str = "boolean"
+
+    class MockAnyWidget:
+        """Mock any flask appbuilder widget."""
+
+    @staticmethod
+    def _get_hooks_with_mocked_fab() -> (
+        tuple[MutableMapping[str, HookInfo | None], dict[str, 
ConnectionFormWidgetInfo], dict[str, dict]]
+    ):
+        """Get hooks with all details w/o FAB needing to be installed."""
+        from unittest import mock
+
+        from airflow.providers_manager import ProvidersManager
+
+        def mock_lazy_gettext(txt: str) -> str:
+            """Mock for flask_babel.lazy_gettext."""
+            return txt
+
+        def mock_any_of(allowed_values: list) -> HookMetaService.MockEnum:
+            """Mock for wtforms.validators.any_of."""
+            return HookMetaService.MockEnum(allowed_values)
+
+        with (
+            mock.patch("wtforms.StringField", HookMetaService.MockStringField),
+            mock.patch("wtforms.fields.StringField", 
HookMetaService.MockStringField),
+            mock.patch("wtforms.fields.simple.StringField", 
HookMetaService.MockStringField),
+            mock.patch("wtforms.IntegerField", 
HookMetaService.MockIntegerField),
+            mock.patch("wtforms.fields.IntegerField", 
HookMetaService.MockIntegerField),
+            mock.patch("wtforms.PasswordField", 
HookMetaService.MockPasswordField),
+            mock.patch("wtforms.BooleanField", 
HookMetaService.MockBooleanField),
+            mock.patch("wtforms.fields.BooleanField", 
HookMetaService.MockBooleanField),
+            mock.patch("wtforms.fields.simple.BooleanField", 
HookMetaService.MockBooleanField),
+            mock.patch("flask_babel.lazy_gettext", mock_lazy_gettext),
+            mock.patch("flask_appbuilder.fieldwidgets.BS3TextFieldWidget", 
HookMetaService.MockAnyWidget),
+            mock.patch("flask_appbuilder.fieldwidgets.BS3TextAreaFieldWidget", 
HookMetaService.MockAnyWidget),
+            mock.patch("flask_appbuilder.fieldwidgets.BS3PasswordFieldWidget", 
HookMetaService.MockAnyWidget),
+            mock.patch("wtforms.validators.Optional", 
HookMetaService.MockOptional),
+            mock.patch("wtforms.validators.any_of", mock_any_of),
+        ):
+            pm = ProvidersManager()
+            return pm.hooks, pm.connection_form_widgets, pm.field_behaviours
+
+    @staticmethod
+    def _make_standard_fields(field_behaviour: dict | None) -> 
StandardHookFields | None:
+        if not field_behaviour:
+            return None
+
+        def make_field(field_name: str, field_behaviour: dict) -> 
ConnectionHookFieldBehavior | None:
+            hidden_fields = field_behaviour.get("hidden_fields", [])
+            relabeling = field_behaviour.get("relabeling", {}).get(field_name)
+            placeholder = field_behaviour.get("placeholders", 
{}).get(field_name)
+            if any([field_name in hidden_fields, relabeling, placeholder]):
+                return ConnectionHookFieldBehavior(
+                    hidden=field_name in hidden_fields,
+                    title=relabeling,
+                    placeholder=placeholder,
+                )
+            return None
+
+        return StandardHookFields(
+            description=make_field("description", field_behaviour),
+            url_schema=make_field("schema", field_behaviour),
+            host=make_field("host", field_behaviour),
+            port=make_field("port", field_behaviour),
+            login=make_field("login", field_behaviour),
+            password=make_field("password", field_behaviour),
+        )
+
+    @staticmethod
+    def _convert_extra_fields(form_widgets: dict[str, 
ConnectionFormWidgetInfo]) -> dict[str, MutableMapping]:
+        result: dict[str, MutableMapping] = {}
+        for key, form_widget in form_widgets.items():
+            hook_key = key.split("__")[1]
+            if isinstance(form_widget.field, HookMetaService.MockBaseField):
+                hook_widgets = result.get(hook_key, {})
+                hook_widgets[form_widget.field_name] = 
form_widget.field.param.dump()
+                result[hook_key] = hook_widgets
+            else:
+                log.error("Unknown form widget in %s: %s", hook_key, 
form_widget)
+        return result
+
+    @staticmethod
+    @cache
+    def hook_meta_data() -> list[ConnectionHookMetaData]:
+        hooks, connection_form_widgets, field_behaviours = 
HookMetaService._get_hooks_with_mocked_fab()
+        result: list[ConnectionHookMetaData] = []
+        widgets = 
HookMetaService._convert_extra_fields(connection_form_widgets)
+        for hook_key, hook_info in hooks.items():
+            if not hook_info:
+                continue
+            hook_meta = ConnectionHookMetaData(
+                connection_type=hook_key,
+                hook_class_name=hook_info.hook_class_name,
+                default_conn_name=None,  # TODO: later
+                hook_name=hook_info.hook_name,
+                
standard_fields=HookMetaService._make_standard_fields(field_behaviours.get(hook_key)),
+                extra_fields=widgets.get(hook_key),
+            )
+            result.append(hook_meta)
+        return result
diff --git a/airflow/ui/openapi-gen/queries/common.ts 
b/airflow/ui/openapi-gen/queries/common.ts
index e16aef39170..728d3e8fcda 100644
--- a/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow/ui/openapi-gen/queries/common.ts
@@ -279,6 +279,59 @@ export const UseConfigServiceGetConfigValueKeyFn = (
   },
   queryKey?: Array<unknown>,
 ) => [useConfigServiceGetConfigValueKey, ...(queryKey ?? [{ accept, option, 
section }])];
+export type ConnectionServiceHookMetaDataDefaultResponse = Awaited<
+  ReturnType<typeof ConnectionService.hookMetaData>
+>;
+export type ConnectionServiceHookMetaDataQueryResult<
+  TData = ConnectionServiceHookMetaDataDefaultResponse,
+  TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useConnectionServiceHookMetaDataKey = 
"ConnectionServiceHookMetaData";
+export const UseConnectionServiceHookMetaDataKeyFn = (queryKey?: 
Array<unknown>) => [
+  useConnectionServiceHookMetaDataKey,
+  ...(queryKey ?? []),
+];
+export type ConnectionServiceGetConnectionDefaultResponse = Awaited<
+  ReturnType<typeof ConnectionService.getConnection>
+>;
+export type ConnectionServiceGetConnectionQueryResult<
+  TData = ConnectionServiceGetConnectionDefaultResponse,
+  TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useConnectionServiceGetConnectionKey = 
"ConnectionServiceGetConnection";
+export const UseConnectionServiceGetConnectionKeyFn = (
+  {
+    connectionId,
+  }: {
+    connectionId: string;
+  },
+  queryKey?: Array<unknown>,
+) => [useConnectionServiceGetConnectionKey, ...(queryKey ?? [{ connectionId 
}])];
+export type ConnectionServiceGetConnectionsDefaultResponse = Awaited<
+  ReturnType<typeof ConnectionService.getConnections>
+>;
+export type ConnectionServiceGetConnectionsQueryResult<
+  TData = ConnectionServiceGetConnectionsDefaultResponse,
+  TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useConnectionServiceGetConnectionsKey = 
"ConnectionServiceGetConnections";
+export const UseConnectionServiceGetConnectionsKeyFn = (
+  {
+    connectionIdPattern,
+    limit,
+    offset,
+    orderBy,
+  }: {
+    connectionIdPattern?: string;
+    limit?: number;
+    offset?: number;
+    orderBy?: string;
+  } = {},
+  queryKey?: Array<unknown>,
+) => [
+  useConnectionServiceGetConnectionsKey,
+  ...(queryKey ?? [{ connectionIdPattern, limit, offset, orderBy }]),
+];
 export type DagsServiceRecentDagRunsDefaultResponse = 
Awaited<ReturnType<typeof DagsService.recentDagRuns>>;
 export type DagsServiceRecentDagRunsQueryResult<
   TData = DagsServiceRecentDagRunsDefaultResponse,
@@ -515,47 +568,6 @@ export const UseGridServiceGridDataKeyFn = (
     },
   ]),
 ];
-export type ConnectionServiceGetConnectionDefaultResponse = Awaited<
-  ReturnType<typeof ConnectionService.getConnection>
->;
-export type ConnectionServiceGetConnectionQueryResult<
-  TData = ConnectionServiceGetConnectionDefaultResponse,
-  TError = unknown,
-> = UseQueryResult<TData, TError>;
-export const useConnectionServiceGetConnectionKey = 
"ConnectionServiceGetConnection";
-export const UseConnectionServiceGetConnectionKeyFn = (
-  {
-    connectionId,
-  }: {
-    connectionId: string;
-  },
-  queryKey?: Array<unknown>,
-) => [useConnectionServiceGetConnectionKey, ...(queryKey ?? [{ connectionId 
}])];
-export type ConnectionServiceGetConnectionsDefaultResponse = Awaited<
-  ReturnType<typeof ConnectionService.getConnections>
->;
-export type ConnectionServiceGetConnectionsQueryResult<
-  TData = ConnectionServiceGetConnectionsDefaultResponse,
-  TError = unknown,
-> = UseQueryResult<TData, TError>;
-export const useConnectionServiceGetConnectionsKey = 
"ConnectionServiceGetConnections";
-export const UseConnectionServiceGetConnectionsKeyFn = (
-  {
-    connectionIdPattern,
-    limit,
-    offset,
-    orderBy,
-  }: {
-    connectionIdPattern?: string;
-    limit?: number;
-    offset?: number;
-    orderBy?: string;
-  } = {},
-  queryKey?: Array<unknown>,
-) => [
-  useConnectionServiceGetConnectionsKey,
-  ...(queryKey ?? [{ connectionIdPattern, limit, offset, orderBy }]),
-];
 export type DagRunServiceGetDagRunDefaultResponse = Awaited<ReturnType<typeof 
DagRunService.getDagRun>>;
 export type DagRunServiceGetDagRunQueryResult<
   TData = DagRunServiceGetDagRunDefaultResponse,
@@ -1759,12 +1771,6 @@ export type AssetServiceCreateAssetEventMutationResult = 
Awaited<
 export type AssetServiceMaterializeAssetMutationResult = Awaited<
   ReturnType<typeof AssetService.materializeAsset>
 >;
-export type BackfillServiceCreateBackfillMutationResult = Awaited<
-  ReturnType<typeof BackfillService.createBackfill>
->;
-export type BackfillServiceCreateBackfillDryRunMutationResult = Awaited<
-  ReturnType<typeof BackfillService.createBackfillDryRun>
->;
 export type ConnectionServicePostConnectionMutationResult = Awaited<
   ReturnType<typeof ConnectionService.postConnection>
 >;
@@ -1774,6 +1780,12 @@ export type 
ConnectionServiceTestConnectionMutationResult = Awaited<
 export type ConnectionServiceCreateDefaultConnectionsMutationResult = Awaited<
   ReturnType<typeof ConnectionService.createDefaultConnections>
 >;
+export type BackfillServiceCreateBackfillMutationResult = Awaited<
+  ReturnType<typeof BackfillService.createBackfill>
+>;
+export type BackfillServiceCreateBackfillDryRunMutationResult = Awaited<
+  ReturnType<typeof BackfillService.createBackfillDryRun>
+>;
 export type DagRunServiceClearDagRunMutationResult = Awaited<ReturnType<typeof 
DagRunService.clearDagRun>>;
 export type DagRunServiceTriggerDagRunMutationResult = Awaited<
   ReturnType<typeof DagRunService.triggerDagRun>
diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts 
b/airflow/ui/openapi-gen/queries/prefetch.ts
index 8f50495dbda..ef029329f6b 100644
--- a/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -366,6 +366,66 @@ export const prefetchUseConfigServiceGetConfigValue = (
     queryKey: Common.UseConfigServiceGetConfigValueKeyFn({ accept, option, 
section }),
     queryFn: () => ConfigService.getConfigValue({ accept, option, section }),
   });
+/**
+ * Hook Meta Data
+ * Retrieve information about available connection types (hook classes) and 
their parameters.
+ * @returns ConnectionHookMetaData Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseConnectionServiceHookMetaData = (queryClient: 
QueryClient) =>
+  queryClient.prefetchQuery({
+    queryKey: Common.UseConnectionServiceHookMetaDataKeyFn(),
+    queryFn: () => ConnectionService.hookMetaData(),
+  });
+/**
+ * Get Connection
+ * Get a connection entry.
+ * @param data The data for the request.
+ * @param data.connectionId
+ * @returns ConnectionResponse Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseConnectionServiceGetConnection = (
+  queryClient: QueryClient,
+  {
+    connectionId,
+  }: {
+    connectionId: string;
+  },
+) =>
+  queryClient.prefetchQuery({
+    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }),
+    queryFn: () => ConnectionService.getConnection({ connectionId }),
+  });
+/**
+ * Get Connections
+ * Get all connection entries.
+ * @param data The data for the request.
+ * @param data.limit
+ * @param data.offset
+ * @param data.orderBy
+ * @param data.connectionIdPattern
+ * @returns ConnectionCollectionResponse Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseConnectionServiceGetConnections = (
+  queryClient: QueryClient,
+  {
+    connectionIdPattern,
+    limit,
+    offset,
+    orderBy,
+  }: {
+    connectionIdPattern?: string;
+    limit?: number;
+    offset?: number;
+    orderBy?: string;
+  } = {},
+) =>
+  queryClient.prefetchQuery({
+    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ 
connectionIdPattern, limit, offset, orderBy }),
+    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }),
+  });
 /**
  * Recent Dag Runs
  * Get recent DAG runs.
@@ -702,55 +762,6 @@ export const prefetchUseGridServiceGridData = (
         state,
       }),
   });
-/**
- * Get Connection
- * Get a connection entry.
- * @param data The data for the request.
- * @param data.connectionId
- * @returns ConnectionResponse Successful Response
- * @throws ApiError
- */
-export const prefetchUseConnectionServiceGetConnection = (
-  queryClient: QueryClient,
-  {
-    connectionId,
-  }: {
-    connectionId: string;
-  },
-) =>
-  queryClient.prefetchQuery({
-    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }),
-    queryFn: () => ConnectionService.getConnection({ connectionId }),
-  });
-/**
- * Get Connections
- * Get all connection entries.
- * @param data The data for the request.
- * @param data.limit
- * @param data.offset
- * @param data.orderBy
- * @param data.connectionIdPattern
- * @returns ConnectionCollectionResponse Successful Response
- * @throws ApiError
- */
-export const prefetchUseConnectionServiceGetConnections = (
-  queryClient: QueryClient,
-  {
-    connectionIdPattern,
-    limit,
-    offset,
-    orderBy,
-  }: {
-    connectionIdPattern?: string;
-    limit?: number;
-    offset?: number;
-    orderBy?: string;
-  } = {},
-) =>
-  queryClient.prefetchQuery({
-    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ 
connectionIdPattern, limit, offset, orderBy }),
-    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }),
-  });
 /**
  * Get Dag Run
  * @param data The data for the request.
diff --git a/airflow/ui/openapi-gen/queries/queries.ts 
b/airflow/ui/openapi-gen/queries/queries.ts
index 02b647cdfa1..8aac17090b3 100644
--- a/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow/ui/openapi-gen/queries/queries.ts
@@ -463,6 +463,89 @@ export const useConfigServiceGetConfigValue = <
     queryFn: () => ConfigService.getConfigValue({ accept, option, section }) 
as TData,
     ...options,
   });
+/**
+ * Hook Meta Data
+ * Retrieve information about available connection types (hook classes) and 
their parameters.
+ * @returns ConnectionHookMetaData Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceHookMetaData = <
+  TData = Common.ConnectionServiceHookMetaDataDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceHookMetaDataKeyFn(queryKey),
+    queryFn: () => ConnectionService.hookMetaData() as TData,
+    ...options,
+  });
+/**
+ * Get Connection
+ * Get a connection entry.
+ * @param data The data for the request.
+ * @param data.connectionId
+ * @returns ConnectionResponse Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceGetConnection = <
+  TData = Common.ConnectionServiceGetConnectionDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  {
+    connectionId,
+  }: {
+    connectionId: string;
+  },
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }, 
queryKey),
+    queryFn: () => ConnectionService.getConnection({ connectionId }) as TData,
+    ...options,
+  });
+/**
+ * Get Connections
+ * Get all connection entries.
+ * @param data The data for the request.
+ * @param data.limit
+ * @param data.offset
+ * @param data.orderBy
+ * @param data.connectionIdPattern
+ * @returns ConnectionCollectionResponse Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceGetConnections = <
+  TData = Common.ConnectionServiceGetConnectionsDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  {
+    connectionIdPattern,
+    limit,
+    offset,
+    orderBy,
+  }: {
+    connectionIdPattern?: string;
+    limit?: number;
+    offset?: number;
+    orderBy?: string;
+  } = {},
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn(
+      { connectionIdPattern, limit, offset, orderBy },
+      queryKey,
+    ),
+    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }) as TData,
+    ...options,
+  });
 /**
  * Recent Dag Runs
  * Get recent DAG runs.
@@ -852,70 +935,6 @@ export const useGridServiceGridData = <
       }) as TData,
     ...options,
   });
-/**
- * Get Connection
- * Get a connection entry.
- * @param data The data for the request.
- * @param data.connectionId
- * @returns ConnectionResponse Successful Response
- * @throws ApiError
- */
-export const useConnectionServiceGetConnection = <
-  TData = Common.ConnectionServiceGetConnectionDefaultResponse,
-  TError = unknown,
-  TQueryKey extends Array<unknown> = unknown[],
->(
-  {
-    connectionId,
-  }: {
-    connectionId: string;
-  },
-  queryKey?: TQueryKey,
-  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
-) =>
-  useQuery<TData, TError>({
-    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }, 
queryKey),
-    queryFn: () => ConnectionService.getConnection({ connectionId }) as TData,
-    ...options,
-  });
-/**
- * Get Connections
- * Get all connection entries.
- * @param data The data for the request.
- * @param data.limit
- * @param data.offset
- * @param data.orderBy
- * @param data.connectionIdPattern
- * @returns ConnectionCollectionResponse Successful Response
- * @throws ApiError
- */
-export const useConnectionServiceGetConnections = <
-  TData = Common.ConnectionServiceGetConnectionsDefaultResponse,
-  TError = unknown,
-  TQueryKey extends Array<unknown> = unknown[],
->(
-  {
-    connectionIdPattern,
-    limit,
-    offset,
-    orderBy,
-  }: {
-    connectionIdPattern?: string;
-    limit?: number;
-    offset?: number;
-    orderBy?: string;
-  } = {},
-  queryKey?: TQueryKey,
-  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
-) =>
-  useQuery<TData, TError>({
-    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn(
-      { connectionIdPattern, limit, offset, orderBy },
-      queryKey,
-    ),
-    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }) as TData,
-    ...options,
-  });
 /**
  * Get Dag Run
  * @param data The data for the request.
@@ -2989,14 +3008,15 @@ export const useAssetServiceMaterializeAsset = <
     ...options,
   });
 /**
- * Create Backfill
+ * Post Connection
+ * Create connection entry.
  * @param data The data for the request.
  * @param data.requestBody
- * @returns BackfillResponse Successful Response
+ * @returns ConnectionResponse Successful Response
  * @throws ApiError
  */
-export const useBackfillServiceCreateBackfill = <
-  TData = Common.BackfillServiceCreateBackfillMutationResult,
+export const useConnectionServicePostConnection = <
+  TData = Common.ConnectionServicePostConnectionMutationResult,
   TError = unknown,
   TContext = unknown,
 >(
@@ -3005,7 +3025,7 @@ export const useBackfillServiceCreateBackfill = <
       TData,
       TError,
       {
-        requestBody: BackfillPostBody;
+        requestBody: ConnectionBody;
       },
       TContext
     >,
@@ -3016,23 +3036,28 @@ export const useBackfillServiceCreateBackfill = <
     TData,
     TError,
     {
-      requestBody: BackfillPostBody;
+      requestBody: ConnectionBody;
     },
     TContext
   >({
     mutationFn: ({ requestBody }) =>
-      BackfillService.createBackfill({ requestBody }) as unknown as 
Promise<TData>,
+      ConnectionService.postConnection({ requestBody }) as unknown as 
Promise<TData>,
     ...options,
   });
 /**
- * Create Backfill Dry Run
+ * Test Connection
+ * Test an API connection.
+ *
+ * This method first creates an in-memory transient conn_id & exports that to 
an env var,
+ * as some hook classes tries to find out the `conn` from their __init__ 
method & errors out if not found.
+ * It also deletes the conn id env connection after the test.
  * @param data The data for the request.
  * @param data.requestBody
- * @returns DryRunBackfillCollectionResponse Successful Response
+ * @returns ConnectionTestResponse Successful Response
  * @throws ApiError
  */
-export const useBackfillServiceCreateBackfillDryRun = <
-  TData = Common.BackfillServiceCreateBackfillDryRunMutationResult,
+export const useConnectionServiceTestConnection = <
+  TData = Common.ConnectionServiceTestConnectionMutationResult,
   TError = unknown,
   TContext = unknown,
 >(
@@ -3041,7 +3066,7 @@ export const useBackfillServiceCreateBackfillDryRun = <
       TData,
       TError,
       {
-        requestBody: BackfillPostBody;
+        requestBody: ConnectionBody;
       },
       TContext
     >,
@@ -3052,24 +3077,40 @@ export const useBackfillServiceCreateBackfillDryRun = <
     TData,
     TError,
     {
-      requestBody: BackfillPostBody;
+      requestBody: ConnectionBody;
     },
     TContext
   >({
     mutationFn: ({ requestBody }) =>
-      BackfillService.createBackfillDryRun({ requestBody }) as unknown as 
Promise<TData>,
+      ConnectionService.testConnection({ requestBody }) as unknown as 
Promise<TData>,
     ...options,
   });
 /**
- * Post Connection
- * Create connection entry.
+ * Create Default Connections
+ * Create default connections.
+ * @returns void Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceCreateDefaultConnections = <
+  TData = Common.ConnectionServiceCreateDefaultConnectionsMutationResult,
+  TError = unknown,
+  TContext = unknown,
+>(
+  options?: Omit<UseMutationOptions<TData, TError, void, TContext>, 
"mutationFn">,
+) =>
+  useMutation<TData, TError, void, TContext>({
+    mutationFn: () => ConnectionService.createDefaultConnections() as unknown 
as Promise<TData>,
+    ...options,
+  });
+/**
+ * Create Backfill
  * @param data The data for the request.
  * @param data.requestBody
- * @returns ConnectionResponse Successful Response
+ * @returns BackfillResponse Successful Response
  * @throws ApiError
  */
-export const useConnectionServicePostConnection = <
-  TData = Common.ConnectionServicePostConnectionMutationResult,
+export const useBackfillServiceCreateBackfill = <
+  TData = Common.BackfillServiceCreateBackfillMutationResult,
   TError = unknown,
   TContext = unknown,
 >(
@@ -3078,7 +3119,7 @@ export const useConnectionServicePostConnection = <
       TData,
       TError,
       {
-        requestBody: ConnectionBody;
+        requestBody: BackfillPostBody;
       },
       TContext
     >,
@@ -3089,28 +3130,23 @@ export const useConnectionServicePostConnection = <
     TData,
     TError,
     {
-      requestBody: ConnectionBody;
+      requestBody: BackfillPostBody;
     },
     TContext
   >({
     mutationFn: ({ requestBody }) =>
-      ConnectionService.postConnection({ requestBody }) as unknown as 
Promise<TData>,
+      BackfillService.createBackfill({ requestBody }) as unknown as 
Promise<TData>,
     ...options,
   });
 /**
- * Test Connection
- * Test an API connection.
- *
- * This method first creates an in-memory transient conn_id & exports that to 
an env var,
- * as some hook classes tries to find out the `conn` from their __init__ 
method & errors out if not found.
- * It also deletes the conn id env connection after the test.
+ * Create Backfill Dry Run
  * @param data The data for the request.
  * @param data.requestBody
- * @returns ConnectionTestResponse Successful Response
+ * @returns DryRunBackfillCollectionResponse Successful Response
  * @throws ApiError
  */
-export const useConnectionServiceTestConnection = <
-  TData = Common.ConnectionServiceTestConnectionMutationResult,
+export const useBackfillServiceCreateBackfillDryRun = <
+  TData = Common.BackfillServiceCreateBackfillDryRunMutationResult,
   TError = unknown,
   TContext = unknown,
 >(
@@ -3119,7 +3155,7 @@ export const useConnectionServiceTestConnection = <
       TData,
       TError,
       {
-        requestBody: ConnectionBody;
+        requestBody: BackfillPostBody;
       },
       TContext
     >,
@@ -3130,29 +3166,12 @@ export const useConnectionServiceTestConnection = <
     TData,
     TError,
     {
-      requestBody: ConnectionBody;
+      requestBody: BackfillPostBody;
     },
     TContext
   >({
     mutationFn: ({ requestBody }) =>
-      ConnectionService.testConnection({ requestBody }) as unknown as 
Promise<TData>,
-    ...options,
-  });
-/**
- * Create Default Connections
- * Create default connections.
- * @returns void Successful Response
- * @throws ApiError
- */
-export const useConnectionServiceCreateDefaultConnections = <
-  TData = Common.ConnectionServiceCreateDefaultConnectionsMutationResult,
-  TError = unknown,
-  TContext = unknown,
->(
-  options?: Omit<UseMutationOptions<TData, TError, void, TContext>, 
"mutationFn">,
-) =>
-  useMutation<TData, TError, void, TContext>({
-    mutationFn: () => ConnectionService.createDefaultConnections() as unknown 
as Promise<TData>,
+      BackfillService.createBackfillDryRun({ requestBody }) as unknown as 
Promise<TData>,
     ...options,
   });
 /**
diff --git a/airflow/ui/openapi-gen/queries/suspense.ts 
b/airflow/ui/openapi-gen/queries/suspense.ts
index dd2c5fe4fcc..3e5ff4194bc 100644
--- a/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow/ui/openapi-gen/queries/suspense.ts
@@ -440,6 +440,89 @@ export const useConfigServiceGetConfigValueSuspense = <
     queryFn: () => ConfigService.getConfigValue({ accept, option, section }) 
as TData,
     ...options,
   });
+/**
+ * Hook Meta Data
+ * Retrieve information about available connection types (hook classes) and 
their parameters.
+ * @returns ConnectionHookMetaData Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceHookMetaDataSuspense = <
+  TData = Common.ConnectionServiceHookMetaDataDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useSuspenseQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceHookMetaDataKeyFn(queryKey),
+    queryFn: () => ConnectionService.hookMetaData() as TData,
+    ...options,
+  });
+/**
+ * Get Connection
+ * Get a connection entry.
+ * @param data The data for the request.
+ * @param data.connectionId
+ * @returns ConnectionResponse Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceGetConnectionSuspense = <
+  TData = Common.ConnectionServiceGetConnectionDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  {
+    connectionId,
+  }: {
+    connectionId: string;
+  },
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useSuspenseQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }, 
queryKey),
+    queryFn: () => ConnectionService.getConnection({ connectionId }) as TData,
+    ...options,
+  });
+/**
+ * Get Connections
+ * Get all connection entries.
+ * @param data The data for the request.
+ * @param data.limit
+ * @param data.offset
+ * @param data.orderBy
+ * @param data.connectionIdPattern
+ * @returns ConnectionCollectionResponse Successful Response
+ * @throws ApiError
+ */
+export const useConnectionServiceGetConnectionsSuspense = <
+  TData = Common.ConnectionServiceGetConnectionsDefaultResponse,
+  TError = unknown,
+  TQueryKey extends Array<unknown> = unknown[],
+>(
+  {
+    connectionIdPattern,
+    limit,
+    offset,
+    orderBy,
+  }: {
+    connectionIdPattern?: string;
+    limit?: number;
+    offset?: number;
+    orderBy?: string;
+  } = {},
+  queryKey?: TQueryKey,
+  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+  useSuspenseQuery<TData, TError>({
+    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn(
+      { connectionIdPattern, limit, offset, orderBy },
+      queryKey,
+    ),
+    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }) as TData,
+    ...options,
+  });
 /**
  * Recent Dag Runs
  * Get recent DAG runs.
@@ -829,70 +912,6 @@ export const useGridServiceGridDataSuspense = <
       }) as TData,
     ...options,
   });
-/**
- * Get Connection
- * Get a connection entry.
- * @param data The data for the request.
- * @param data.connectionId
- * @returns ConnectionResponse Successful Response
- * @throws ApiError
- */
-export const useConnectionServiceGetConnectionSuspense = <
-  TData = Common.ConnectionServiceGetConnectionDefaultResponse,
-  TError = unknown,
-  TQueryKey extends Array<unknown> = unknown[],
->(
-  {
-    connectionId,
-  }: {
-    connectionId: string;
-  },
-  queryKey?: TQueryKey,
-  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
-) =>
-  useSuspenseQuery<TData, TError>({
-    queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }, 
queryKey),
-    queryFn: () => ConnectionService.getConnection({ connectionId }) as TData,
-    ...options,
-  });
-/**
- * Get Connections
- * Get all connection entries.
- * @param data The data for the request.
- * @param data.limit
- * @param data.offset
- * @param data.orderBy
- * @param data.connectionIdPattern
- * @returns ConnectionCollectionResponse Successful Response
- * @throws ApiError
- */
-export const useConnectionServiceGetConnectionsSuspense = <
-  TData = Common.ConnectionServiceGetConnectionsDefaultResponse,
-  TError = unknown,
-  TQueryKey extends Array<unknown> = unknown[],
->(
-  {
-    connectionIdPattern,
-    limit,
-    offset,
-    orderBy,
-  }: {
-    connectionIdPattern?: string;
-    limit?: number;
-    offset?: number;
-    orderBy?: string;
-  } = {},
-  queryKey?: TQueryKey,
-  options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
-) =>
-  useSuspenseQuery<TData, TError>({
-    queryKey: Common.UseConnectionServiceGetConnectionsKeyFn(
-      { connectionIdPattern, limit, offset, orderBy },
-      queryKey,
-    ),
-    queryFn: () => ConnectionService.getConnections({ connectionIdPattern, 
limit, offset, orderBy }) as TData,
-    ...options,
-  });
 /**
  * Get Dag Run
  * @param data The data for the request.
diff --git a/airflow/ui/openapi-gen/requests/schemas.gen.ts 
b/airflow/ui/openapi-gen/requests/schemas.gen.ts
index 6756181f8f8..acaf4580c32 100644
--- a/airflow/ui/openapi-gen/requests/schemas.gen.ts
+++ b/airflow/ui/openapi-gen/requests/schemas.gen.ts
@@ -1388,6 +1388,122 @@ export const $ConnectionCollectionResponse = {
   description: "Connection Collection serializer for responses.",
 } as const;
 
+export const $ConnectionHookFieldBehavior = {
+  properties: {
+    hidden: {
+      type: "boolean",
+      title: "Hidden",
+      description: "Flag if the form field should be hidden.",
+      default: false,
+    },
+    title: {
+      anyOf: [
+        {
+          type: "string",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Title",
+      description:
+        "Label / title for the field that should be displayed, if re-labelling 
is needed. Use `None` to display standard title.",
+    },
+    placeholder: {
+      anyOf: [
+        {
+          type: "string",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Placeholder",
+      description: "Placeholder text that should be populated to the form.",
+    },
+  },
+  type: "object",
+  title: "ConnectionHookFieldBehavior",
+  description: "A class to store the behavior of each standard field of a 
Hook.",
+} as const;
+
+export const $ConnectionHookMetaData = {
+  properties: {
+    connection_type: {
+      anyOf: [
+        {
+          type: "string",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Connection Type",
+    },
+    hook_class_name: {
+      anyOf: [
+        {
+          type: "string",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Hook Class Name",
+    },
+    default_conn_name: {
+      anyOf: [
+        {
+          type: "string",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Default Conn Name",
+    },
+    hook_name: {
+      type: "string",
+      title: "Hook Name",
+    },
+    standard_fields: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/StandardHookFields",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    extra_fields: {
+      anyOf: [
+        {
+          type: "object",
+        },
+        {
+          type: "null",
+        },
+      ],
+      title: "Extra Fields",
+    },
+  },
+  type: "object",
+  required: [
+    "connection_type",
+    "hook_class_name",
+    "default_conn_name",
+    "hook_name",
+    "standard_fields",
+    "extra_fields",
+  ],
+  title: "ConnectionHookMetaData",
+  description: `Response model for Hook information == Connection type meta 
data.
+
+It is used to transfer providers information loaded by providers_manager such 
that
+the API server/Web UI can use this data to render connection form UI.`,
+} as const;
+
 export const $ConnectionResponse = {
   properties: {
     connection_id: {
@@ -4588,6 +4704,75 @@ export const $SchedulerInfoResponse = {
   description: "Scheduler info serializer for responses.",
 } as const;
 
+export const $StandardHookFields = {
+  properties: {
+    description: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    url_schema: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    host: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    port: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    login: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+    password: {
+      anyOf: [
+        {
+          $ref: "#/components/schemas/ConnectionHookFieldBehavior",
+        },
+        {
+          type: "null",
+        },
+      ],
+    },
+  },
+  type: "object",
+  required: ["description", "url_schema", "host", "port", "login", "password"],
+  title: "StandardHookFields",
+  description: "Standard fields of a Hook that a form will render.",
+} as const;
+
 export const $StructureDataResponse = {
   properties: {
     edges: {
diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts 
b/airflow/ui/openapi-gen/requests/services.gen.ts
index 11b54997040..ef8a2d833af 100644
--- a/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -36,6 +36,22 @@ import type {
   GetConfigResponse,
   GetConfigValueData,
   GetConfigValueResponse,
+  HookMetaDataResponse,
+  DeleteConnectionData,
+  DeleteConnectionResponse,
+  GetConnectionData,
+  GetConnectionResponse,
+  PatchConnectionData,
+  PatchConnectionResponse,
+  GetConnectionsData,
+  GetConnectionsResponse,
+  PostConnectionData,
+  PostConnectionResponse,
+  BulkConnectionsData,
+  BulkConnectionsResponse,
+  TestConnectionData,
+  TestConnectionResponse,
+  CreateDefaultConnectionsResponse,
   RecentDagRunsData,
   RecentDagRunsResponse,
   GetDependenciesData,
@@ -62,21 +78,6 @@ import type {
   CreateBackfillDryRunResponse,
   GridDataData,
   GridDataResponse,
-  DeleteConnectionData,
-  DeleteConnectionResponse,
-  GetConnectionData,
-  GetConnectionResponse,
-  PatchConnectionData,
-  PatchConnectionResponse,
-  GetConnectionsData,
-  GetConnectionsResponse,
-  PostConnectionData,
-  PostConnectionResponse,
-  BulkConnectionsData,
-  BulkConnectionsResponse,
-  TestConnectionData,
-  TestConnectionResponse,
-  CreateDefaultConnectionsResponse,
   GetDagRunData,
   GetDagRunResponse,
   DeleteDagRunData,
@@ -698,6 +699,219 @@ export class ConfigService {
   }
 }
 
+export class ConnectionService {
+  /**
+   * Hook Meta Data
+   * Retrieve information about available connection types (hook classes) and 
their parameters.
+   * @returns ConnectionHookMetaData Successful Response
+   * @throws ApiError
+   */
+  public static hookMetaData(): CancelablePromise<HookMetaDataResponse> {
+    return __request(OpenAPI, {
+      method: "GET",
+      url: "/ui/connections/hook_meta",
+    });
+  }
+
+  /**
+   * Delete Connection
+   * Delete a connection entry.
+   * @param data The data for the request.
+   * @param data.connectionId
+   * @returns void Successful Response
+   * @throws ApiError
+   */
+  public static deleteConnection(data: DeleteConnectionData): 
CancelablePromise<DeleteConnectionResponse> {
+    return __request(OpenAPI, {
+      method: "DELETE",
+      url: "/public/connections/{connection_id}",
+      path: {
+        connection_id: data.connectionId,
+      },
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        404: "Not Found",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Get Connection
+   * Get a connection entry.
+   * @param data The data for the request.
+   * @param data.connectionId
+   * @returns ConnectionResponse Successful Response
+   * @throws ApiError
+   */
+  public static getConnection(data: GetConnectionData): 
CancelablePromise<GetConnectionResponse> {
+    return __request(OpenAPI, {
+      method: "GET",
+      url: "/public/connections/{connection_id}",
+      path: {
+        connection_id: data.connectionId,
+      },
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        404: "Not Found",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Patch Connection
+   * Update a connection entry.
+   * @param data The data for the request.
+   * @param data.connectionId
+   * @param data.requestBody
+   * @param data.updateMask
+   * @returns ConnectionResponse Successful Response
+   * @throws ApiError
+   */
+  public static patchConnection(data: PatchConnectionData): 
CancelablePromise<PatchConnectionResponse> {
+    return __request(OpenAPI, {
+      method: "PATCH",
+      url: "/public/connections/{connection_id}",
+      path: {
+        connection_id: data.connectionId,
+      },
+      query: {
+        update_mask: data.updateMask,
+      },
+      body: data.requestBody,
+      mediaType: "application/json",
+      errors: {
+        400: "Bad Request",
+        401: "Unauthorized",
+        403: "Forbidden",
+        404: "Not Found",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Get Connections
+   * Get all connection entries.
+   * @param data The data for the request.
+   * @param data.limit
+   * @param data.offset
+   * @param data.orderBy
+   * @param data.connectionIdPattern
+   * @returns ConnectionCollectionResponse Successful Response
+   * @throws ApiError
+   */
+  public static getConnections(data: GetConnectionsData = {}): 
CancelablePromise<GetConnectionsResponse> {
+    return __request(OpenAPI, {
+      method: "GET",
+      url: "/public/connections",
+      query: {
+        limit: data.limit,
+        offset: data.offset,
+        order_by: data.orderBy,
+        connection_id_pattern: data.connectionIdPattern,
+      },
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        404: "Not Found",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Post Connection
+   * Create connection entry.
+   * @param data The data for the request.
+   * @param data.requestBody
+   * @returns ConnectionResponse Successful Response
+   * @throws ApiError
+   */
+  public static postConnection(data: PostConnectionData): 
CancelablePromise<PostConnectionResponse> {
+    return __request(OpenAPI, {
+      method: "POST",
+      url: "/public/connections",
+      body: data.requestBody,
+      mediaType: "application/json",
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        409: "Conflict",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Bulk Connections
+   * Bulk create, update, and delete connections.
+   * @param data The data for the request.
+   * @param data.requestBody
+   * @returns BulkResponse Successful Response
+   * @throws ApiError
+   */
+  public static bulkConnections(data: BulkConnectionsData): 
CancelablePromise<BulkConnectionsResponse> {
+    return __request(OpenAPI, {
+      method: "PATCH",
+      url: "/public/connections",
+      body: data.requestBody,
+      mediaType: "application/json",
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Test Connection
+   * Test an API connection.
+   *
+   * This method first creates an in-memory transient conn_id & exports that 
to an env var,
+   * as some hook classes tries to find out the `conn` from their __init__ 
method & errors out if not found.
+   * It also deletes the conn id env connection after the test.
+   * @param data The data for the request.
+   * @param data.requestBody
+   * @returns ConnectionTestResponse Successful Response
+   * @throws ApiError
+   */
+  public static testConnection(data: TestConnectionData): 
CancelablePromise<TestConnectionResponse> {
+    return __request(OpenAPI, {
+      method: "POST",
+      url: "/public/connections/test",
+      body: data.requestBody,
+      mediaType: "application/json",
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+        422: "Validation Error",
+      },
+    });
+  }
+
+  /**
+   * Create Default Connections
+   * Create default connections.
+   * @returns void Successful Response
+   * @throws ApiError
+   */
+  public static createDefaultConnections(): 
CancelablePromise<CreateDefaultConnectionsResponse> {
+    return __request(OpenAPI, {
+      method: "POST",
+      url: "/public/connections/defaults",
+      errors: {
+        401: "Unauthorized",
+        403: "Forbidden",
+      },
+    });
+  }
+}
+
 export class DagsService {
   /**
    * Recent Dag Runs
@@ -1080,206 +1294,6 @@ export class GridService {
   }
 }
 
-export class ConnectionService {
-  /**
-   * Delete Connection
-   * Delete a connection entry.
-   * @param data The data for the request.
-   * @param data.connectionId
-   * @returns void Successful Response
-   * @throws ApiError
-   */
-  public static deleteConnection(data: DeleteConnectionData): 
CancelablePromise<DeleteConnectionResponse> {
-    return __request(OpenAPI, {
-      method: "DELETE",
-      url: "/public/connections/{connection_id}",
-      path: {
-        connection_id: data.connectionId,
-      },
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        404: "Not Found",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Get Connection
-   * Get a connection entry.
-   * @param data The data for the request.
-   * @param data.connectionId
-   * @returns ConnectionResponse Successful Response
-   * @throws ApiError
-   */
-  public static getConnection(data: GetConnectionData): 
CancelablePromise<GetConnectionResponse> {
-    return __request(OpenAPI, {
-      method: "GET",
-      url: "/public/connections/{connection_id}",
-      path: {
-        connection_id: data.connectionId,
-      },
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        404: "Not Found",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Patch Connection
-   * Update a connection entry.
-   * @param data The data for the request.
-   * @param data.connectionId
-   * @param data.requestBody
-   * @param data.updateMask
-   * @returns ConnectionResponse Successful Response
-   * @throws ApiError
-   */
-  public static patchConnection(data: PatchConnectionData): 
CancelablePromise<PatchConnectionResponse> {
-    return __request(OpenAPI, {
-      method: "PATCH",
-      url: "/public/connections/{connection_id}",
-      path: {
-        connection_id: data.connectionId,
-      },
-      query: {
-        update_mask: data.updateMask,
-      },
-      body: data.requestBody,
-      mediaType: "application/json",
-      errors: {
-        400: "Bad Request",
-        401: "Unauthorized",
-        403: "Forbidden",
-        404: "Not Found",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Get Connections
-   * Get all connection entries.
-   * @param data The data for the request.
-   * @param data.limit
-   * @param data.offset
-   * @param data.orderBy
-   * @param data.connectionIdPattern
-   * @returns ConnectionCollectionResponse Successful Response
-   * @throws ApiError
-   */
-  public static getConnections(data: GetConnectionsData = {}): 
CancelablePromise<GetConnectionsResponse> {
-    return __request(OpenAPI, {
-      method: "GET",
-      url: "/public/connections",
-      query: {
-        limit: data.limit,
-        offset: data.offset,
-        order_by: data.orderBy,
-        connection_id_pattern: data.connectionIdPattern,
-      },
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        404: "Not Found",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Post Connection
-   * Create connection entry.
-   * @param data The data for the request.
-   * @param data.requestBody
-   * @returns ConnectionResponse Successful Response
-   * @throws ApiError
-   */
-  public static postConnection(data: PostConnectionData): 
CancelablePromise<PostConnectionResponse> {
-    return __request(OpenAPI, {
-      method: "POST",
-      url: "/public/connections",
-      body: data.requestBody,
-      mediaType: "application/json",
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        409: "Conflict",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Bulk Connections
-   * Bulk create, update, and delete connections.
-   * @param data The data for the request.
-   * @param data.requestBody
-   * @returns BulkResponse Successful Response
-   * @throws ApiError
-   */
-  public static bulkConnections(data: BulkConnectionsData): 
CancelablePromise<BulkConnectionsResponse> {
-    return __request(OpenAPI, {
-      method: "PATCH",
-      url: "/public/connections",
-      body: data.requestBody,
-      mediaType: "application/json",
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Test Connection
-   * Test an API connection.
-   *
-   * This method first creates an in-memory transient conn_id & exports that 
to an env var,
-   * as some hook classes tries to find out the `conn` from their __init__ 
method & errors out if not found.
-   * It also deletes the conn id env connection after the test.
-   * @param data The data for the request.
-   * @param data.requestBody
-   * @returns ConnectionTestResponse Successful Response
-   * @throws ApiError
-   */
-  public static testConnection(data: TestConnectionData): 
CancelablePromise<TestConnectionResponse> {
-    return __request(OpenAPI, {
-      method: "POST",
-      url: "/public/connections/test",
-      body: data.requestBody,
-      mediaType: "application/json",
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-        422: "Validation Error",
-      },
-    });
-  }
-
-  /**
-   * Create Default Connections
-   * Create default connections.
-   * @returns void Successful Response
-   * @throws ApiError
-   */
-  public static createDefaultConnections(): 
CancelablePromise<CreateDefaultConnectionsResponse> {
-    return __request(OpenAPI, {
-      method: "POST",
-      url: "/public/connections/defaults",
-      errors: {
-        401: "Unauthorized",
-        403: "Forbidden",
-      },
-    });
-  }
-}
-
 export class DagRunService {
   /**
    * Get Dag Run
diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts 
b/airflow/ui/openapi-gen/requests/types.gen.ts
index 1ed2a13c959..ce1b31a13ea 100644
--- a/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -448,6 +448,41 @@ export type ConnectionCollectionResponse = {
   total_entries: number;
 };
 
+/**
+ * A class to store the behavior of each standard field of a Hook.
+ */
+export type ConnectionHookFieldBehavior = {
+  /**
+   * Flag if the form field should be hidden.
+   */
+  hidden?: boolean;
+  /**
+   * Label / title for the field that should be displayed, if re-labelling is 
needed. Use `None` to display standard title.
+   */
+  title?: string | null;
+  /**
+   * Placeholder text that should be populated to the form.
+   */
+  placeholder?: string | null;
+};
+
+/**
+ * Response model for Hook information == Connection type meta data.
+ *
+ * It is used to transfer providers information loaded by providers_manager 
such that
+ * the API server/Web UI can use this data to render connection form UI.
+ */
+export type ConnectionHookMetaData = {
+  connection_type: string | null;
+  hook_class_name: string | null;
+  default_conn_name: string | null;
+  hook_name: string;
+  standard_fields: StandardHookFields | null;
+  extra_fields: {
+    [key: string]: unknown;
+  } | null;
+};
+
 /**
  * Connection serializer for responses.
  */
@@ -1204,6 +1239,18 @@ export type SchedulerInfoResponse = {
   latest_scheduler_heartbeat: string | null;
 };
 
+/**
+ * Standard fields of a Hook that a form will render.
+ */
+export type StandardHookFields = {
+  description: ConnectionHookFieldBehavior | null;
+  url_schema: ConnectionHookFieldBehavior | null;
+  host: ConnectionHookFieldBehavior | null;
+  port: ConnectionHookFieldBehavior | null;
+  login: ConnectionHookFieldBehavior | null;
+  password: ConnectionHookFieldBehavior | null;
+};
+
 /**
  * Structure Data serializer for responses.
  */
@@ -1734,6 +1781,57 @@ export type GetConfigValueData = {
 
 export type GetConfigValueResponse = Config;
 
+export type HookMetaDataResponse = Array<ConnectionHookMetaData>;
+
+export type DeleteConnectionData = {
+  connectionId: string;
+};
+
+export type DeleteConnectionResponse = void;
+
+export type GetConnectionData = {
+  connectionId: string;
+};
+
+export type GetConnectionResponse = ConnectionResponse;
+
+export type PatchConnectionData = {
+  connectionId: string;
+  requestBody: ConnectionBody;
+  updateMask?: Array<string> | null;
+};
+
+export type PatchConnectionResponse = ConnectionResponse;
+
+export type GetConnectionsData = {
+  connectionIdPattern?: string | null;
+  limit?: number;
+  offset?: number;
+  orderBy?: string;
+};
+
+export type GetConnectionsResponse = ConnectionCollectionResponse;
+
+export type PostConnectionData = {
+  requestBody: ConnectionBody;
+};
+
+export type PostConnectionResponse = ConnectionResponse;
+
+export type BulkConnectionsData = {
+  requestBody: BulkBody_ConnectionBody_;
+};
+
+export type BulkConnectionsResponse = BulkResponse;
+
+export type TestConnectionData = {
+  requestBody: ConnectionBody;
+};
+
+export type TestConnectionResponse = ConnectionTestResponse;
+
+export type CreateDefaultConnectionsResponse = void;
+
 export type RecentDagRunsData = {
   dagDisplayNamePattern?: string | null;
   dagIdPattern?: string | null;
@@ -1848,55 +1946,6 @@ export type GridDataData = {
 
 export type GridDataResponse = GridResponse;
 
-export type DeleteConnectionData = {
-  connectionId: string;
-};
-
-export type DeleteConnectionResponse = void;
-
-export type GetConnectionData = {
-  connectionId: string;
-};
-
-export type GetConnectionResponse = ConnectionResponse;
-
-export type PatchConnectionData = {
-  connectionId: string;
-  requestBody: ConnectionBody;
-  updateMask?: Array<string> | null;
-};
-
-export type PatchConnectionResponse = ConnectionResponse;
-
-export type GetConnectionsData = {
-  connectionIdPattern?: string | null;
-  limit?: number;
-  offset?: number;
-  orderBy?: string;
-};
-
-export type GetConnectionsResponse = ConnectionCollectionResponse;
-
-export type PostConnectionData = {
-  requestBody: ConnectionBody;
-};
-
-export type PostConnectionResponse = ConnectionResponse;
-
-export type BulkConnectionsData = {
-  requestBody: BulkBody_ConnectionBody_;
-};
-
-export type BulkConnectionsResponse = BulkResponse;
-
-export type TestConnectionData = {
-  requestBody: ConnectionBody;
-};
-
-export type TestConnectionResponse = ConnectionTestResponse;
-
-export type CreateDefaultConnectionsResponse = void;
-
 export type GetDagRunData = {
   dagId: string;
   dagRunId: string;
@@ -2975,29 +3024,32 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/ui/dags/recent_dag_runs": {
+  "/ui/connections/hook_meta": {
     get: {
-      req: RecentDagRunsData;
       res: {
         /**
          * Successful Response
          */
-        200: DAGWithLatestDagRunsCollectionResponse;
-        /**
-         * Validation Error
-         */
-        422: HTTPValidationError;
+        200: Array<ConnectionHookMetaData>;
       };
     };
   };
-  "/ui/dependencies": {
-    get: {
-      req: GetDependenciesData;
+  "/public/connections/{connection_id}": {
+    delete: {
+      req: DeleteConnectionData;
       res: {
         /**
          * Successful Response
          */
-        200: BaseGraphResponse;
+        204: void;
+        /**
+         * Unauthorized
+         */
+        401: HTTPExceptionResponse;
+        /**
+         * Forbidden
+         */
+        403: HTTPExceptionResponse;
         /**
          * Not Found
          */
@@ -3008,34 +3060,21 @@ export type $OpenApiTs = {
         422: HTTPValidationError;
       };
     };
-  };
-  "/ui/dashboard/historical_metrics_data": {
     get: {
-      req: HistoricalMetricsData;
+      req: GetConnectionData;
       res: {
         /**
          * Successful Response
          */
-        200: HistoricalMetricDataResponse;
-        /**
-         * Bad Request
-         */
-        400: HTTPExceptionResponse;
+        200: ConnectionResponse;
         /**
-         * Validation Error
+         * Unauthorized
          */
-        422: HTTPValidationError;
-      };
-    };
-  };
-  "/ui/structure/structure_data": {
-    get: {
-      req: StructureDataData;
-      res: {
+        401: HTTPExceptionResponse;
         /**
-         * Successful Response
+         * Forbidden
          */
-        200: StructureDataResponse;
+        403: HTTPExceptionResponse;
         /**
          * Not Found
          */
@@ -3046,15 +3085,25 @@ export type $OpenApiTs = {
         422: HTTPValidationError;
       };
     };
-  };
-  "/ui/backfills": {
-    get: {
-      req: ListBackfillsData;
+    patch: {
+      req: PatchConnectionData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillCollectionResponse;
+        200: ConnectionResponse;
+        /**
+         * Bad Request
+         */
+        400: HTTPExceptionResponse;
+        /**
+         * Unauthorized
+         */
+        401: HTTPExceptionResponse;
+        /**
+         * Forbidden
+         */
+        403: HTTPExceptionResponse;
         /**
          * Not Found
          */
@@ -3066,14 +3115,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/backfills": {
+  "/public/connections": {
     get: {
-      req: ListBackfills1Data;
+      req: GetConnectionsData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillCollectionResponse;
+        200: ConnectionCollectionResponse;
         /**
          * Unauthorized
          */
@@ -3082,6 +3131,10 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
+        /**
+         * Not Found
+         */
+        404: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3089,12 +3142,12 @@ export type $OpenApiTs = {
       };
     };
     post: {
-      req: CreateBackfillData;
+      req: PostConnectionData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillResponse;
+        201: ConnectionResponse;
         /**
          * Unauthorized
          */
@@ -3103,10 +3156,6 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
-        /**
-         * Not Found
-         */
-        404: HTTPExceptionResponse;
         /**
          * Conflict
          */
@@ -3117,15 +3166,13 @@ export type $OpenApiTs = {
         422: HTTPValidationError;
       };
     };
-  };
-  "/public/backfills/{backfill_id}": {
-    get: {
-      req: GetBackfillData;
+    patch: {
+      req: BulkConnectionsData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillResponse;
+        200: BulkResponse;
         /**
          * Unauthorized
          */
@@ -3134,10 +3181,6 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
-        /**
-         * Not Found
-         */
-        404: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3145,14 +3188,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/backfills/{backfill_id}/pause": {
-    put: {
-      req: PauseBackfillData;
+  "/public/connections/test": {
+    post: {
+      req: TestConnectionData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillResponse;
+        200: ConnectionTestResponse;
         /**
          * Unauthorized
          */
@@ -3161,14 +3204,6 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
-        /**
-         * Not Found
-         */
-        404: HTTPExceptionResponse;
-        /**
-         * Conflict
-         */
-        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3176,14 +3211,13 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/backfills/{backfill_id}/unpause": {
-    put: {
-      req: UnpauseBackfillData;
+  "/public/connections/defaults": {
+    post: {
       res: {
         /**
          * Successful Response
          */
-        200: BackfillResponse;
+        204: void;
         /**
          * Unauthorized
          */
@@ -3192,14 +3226,17 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
+      };
+    };
+  };
+  "/ui/dags/recent_dag_runs": {
+    get: {
+      req: RecentDagRunsData;
+      res: {
         /**
-         * Not Found
-         */
-        404: HTTPExceptionResponse;
-        /**
-         * Conflict
+         * Successful Response
          */
-        409: HTTPExceptionResponse;
+        200: DAGWithLatestDagRunsCollectionResponse;
         /**
          * Validation Error
          */
@@ -3207,30 +3244,18 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/backfills/{backfill_id}/cancel": {
-    put: {
-      req: CancelBackfillData;
+  "/ui/dependencies": {
+    get: {
+      req: GetDependenciesData;
       res: {
         /**
          * Successful Response
          */
-        200: BackfillResponse;
-        /**
-         * Unauthorized
-         */
-        401: HTTPExceptionResponse;
-        /**
-         * Forbidden
-         */
-        403: HTTPExceptionResponse;
+        200: BaseGraphResponse;
         /**
          * Not Found
          */
         404: HTTPExceptionResponse;
-        /**
-         * Conflict
-         */
-        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3238,30 +3263,37 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/backfills/dry_run": {
-    post: {
-      req: CreateBackfillDryRunData;
+  "/ui/dashboard/historical_metrics_data": {
+    get: {
+      req: HistoricalMetricsData;
       res: {
         /**
          * Successful Response
          */
-        200: DryRunBackfillCollectionResponse;
+        200: HistoricalMetricDataResponse;
         /**
-         * Unauthorized
+         * Bad Request
          */
-        401: HTTPExceptionResponse;
+        400: HTTPExceptionResponse;
         /**
-         * Forbidden
+         * Validation Error
          */
-        403: HTTPExceptionResponse;
+        422: HTTPValidationError;
+      };
+    };
+  };
+  "/ui/structure/structure_data": {
+    get: {
+      req: StructureDataData;
+      res: {
         /**
-         * Not Found
+         * Successful Response
          */
-        404: HTTPExceptionResponse;
+        200: StructureDataResponse;
         /**
-         * Conflict
+         * Not Found
          */
-        409: HTTPExceptionResponse;
+        404: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3269,18 +3301,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/ui/grid/{dag_id}": {
+  "/ui/backfills": {
     get: {
-      req: GridDataData;
+      req: ListBackfillsData;
       res: {
         /**
          * Successful Response
          */
-        200: GridResponse;
-        /**
-         * Bad Request
-         */
-        400: HTTPExceptionResponse;
+        200: BackfillCollectionResponse;
         /**
          * Not Found
          */
@@ -3292,14 +3320,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/connections/{connection_id}": {
-    delete: {
-      req: DeleteConnectionData;
+  "/public/backfills": {
+    get: {
+      req: ListBackfills1Data;
       res: {
         /**
          * Successful Response
          */
-        204: void;
+        200: BackfillCollectionResponse;
         /**
          * Unauthorized
          */
@@ -3308,23 +3336,19 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
-        /**
-         * Not Found
-         */
-        404: HTTPExceptionResponse;
         /**
          * Validation Error
          */
         422: HTTPValidationError;
       };
     };
-    get: {
-      req: GetConnectionData;
+    post: {
+      req: CreateBackfillData;
       res: {
         /**
          * Successful Response
          */
-        200: ConnectionResponse;
+        200: BackfillResponse;
         /**
          * Unauthorized
          */
@@ -3337,23 +3361,25 @@ export type $OpenApiTs = {
          * Not Found
          */
         404: HTTPExceptionResponse;
+        /**
+         * Conflict
+         */
+        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
         422: HTTPValidationError;
       };
     };
-    patch: {
-      req: PatchConnectionData;
+  };
+  "/public/backfills/{backfill_id}": {
+    get: {
+      req: GetBackfillData;
       res: {
         /**
          * Successful Response
          */
-        200: ConnectionResponse;
-        /**
-         * Bad Request
-         */
-        400: HTTPExceptionResponse;
+        200: BackfillResponse;
         /**
          * Unauthorized
          */
@@ -3373,14 +3399,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/connections": {
-    get: {
-      req: GetConnectionsData;
+  "/public/backfills/{backfill_id}/pause": {
+    put: {
+      req: PauseBackfillData;
       res: {
         /**
          * Successful Response
          */
-        200: ConnectionCollectionResponse;
+        200: BackfillResponse;
         /**
          * Unauthorized
          */
@@ -3393,19 +3419,25 @@ export type $OpenApiTs = {
          * Not Found
          */
         404: HTTPExceptionResponse;
+        /**
+         * Conflict
+         */
+        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
         422: HTTPValidationError;
       };
     };
-    post: {
-      req: PostConnectionData;
+  };
+  "/public/backfills/{backfill_id}/unpause": {
+    put: {
+      req: UnpauseBackfillData;
       res: {
         /**
          * Successful Response
          */
-        201: ConnectionResponse;
+        200: BackfillResponse;
         /**
          * Unauthorized
          */
@@ -3414,6 +3446,10 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
+        /**
+         * Not Found
+         */
+        404: HTTPExceptionResponse;
         /**
          * Conflict
          */
@@ -3424,13 +3460,15 @@ export type $OpenApiTs = {
         422: HTTPValidationError;
       };
     };
-    patch: {
-      req: BulkConnectionsData;
+  };
+  "/public/backfills/{backfill_id}/cancel": {
+    put: {
+      req: CancelBackfillData;
       res: {
         /**
          * Successful Response
          */
-        200: BulkResponse;
+        200: BackfillResponse;
         /**
          * Unauthorized
          */
@@ -3439,6 +3477,14 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
+        /**
+         * Not Found
+         */
+        404: HTTPExceptionResponse;
+        /**
+         * Conflict
+         */
+        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3446,14 +3492,14 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/connections/test": {
+  "/public/backfills/dry_run": {
     post: {
-      req: TestConnectionData;
+      req: CreateBackfillDryRunData;
       res: {
         /**
          * Successful Response
          */
-        200: ConnectionTestResponse;
+        200: DryRunBackfillCollectionResponse;
         /**
          * Unauthorized
          */
@@ -3462,6 +3508,14 @@ export type $OpenApiTs = {
          * Forbidden
          */
         403: HTTPExceptionResponse;
+        /**
+         * Not Found
+         */
+        404: HTTPExceptionResponse;
+        /**
+         * Conflict
+         */
+        409: HTTPExceptionResponse;
         /**
          * Validation Error
          */
@@ -3469,21 +3523,26 @@ export type $OpenApiTs = {
       };
     };
   };
-  "/public/connections/defaults": {
-    post: {
+  "/ui/grid/{dag_id}": {
+    get: {
+      req: GridDataData;
       res: {
         /**
          * Successful Response
          */
-        204: void;
+        200: GridResponse;
         /**
-         * Unauthorized
+         * Bad Request
          */
-        401: HTTPExceptionResponse;
+        400: HTTPExceptionResponse;
         /**
-         * Forbidden
+         * Not Found
          */
-        403: HTTPExceptionResponse;
+        404: HTTPExceptionResponse;
+        /**
+         * Validation Error
+         */
+        422: HTTPValidationError;
       };
     };
   };
diff --git a/tests/api_fastapi/core_api/routes/ui/test_connections.py 
b/tests/api_fastapi/core_api/routes/ui/test_connections.py
new file mode 100644
index 00000000000..68ad0e5e90c
--- /dev/null
+++ b/tests/api_fastapi/core_api/routes/ui/test_connections.py
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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.
+from __future__ import annotations
+
+import pytest
+
+pytestmark = pytest.mark.db_test
+
+
+class TestHookMetaData:
+    def test_hook_meta_data(self, test_client):
+        response = test_client.get("/ui/connections/hook_meta")
+        response_data = response.json()
+        assert any(hook_data["connection_type"] == "generic" for hook_data in 
response_data)
+        assert any(hook_data["connection_type"] == "fs" for hook_data in 
response_data)
+
+        for hook_data in response_data:
+            if hook_data["connection_type"] == "fs":
+                assert hook_data["hook_name"] == "File (path)"
+
+    def test_should_respond_401(self, unauthenticated_test_client):
+        response = unauthenticated_test_client.get("/ui/connections/hook_meta")
+        assert response.status_code == 401
+
+    def test_should_respond_403(self, unauthorized_test_client):
+        response = unauthorized_test_client.get("/ui/connections/hook_meta")
+        assert response.status_code == 403

Reply via email to