+}
+
+export const PluginPresetsDataGrid = ({ filterSettings, pluginPresetsPromise }: PluginPresetsDataGridProps) => {
+ return (
+
+
+
+
+
+
+ Instances
+ Name
+ Plugin Definition
+ Message
+ Actions
+
+
+
+ }>
+
+
+
+
+
+ )
+}
diff --git a/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsFilter.tsx b/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsFilter.tsx
new file mode 100644
index 0000000000..a6c41aaa2a
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/PluginPresets/PluginPresetsFilter.tsx
@@ -0,0 +1,44 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { useCallback } from "react"
+import { useLoaderData, useNavigate } from "@tanstack/react-router"
+import { Stack, SearchInput, InputGroup } from "@cloudoperators/juno-ui-components"
+
+export type FilterSettings = {
+ searchTerm?: string
+}
+
+export const PluginPresetsFilter = () => {
+ const navigate = useNavigate()
+ const { filterSettings } = useLoaderData({ from: "/admin/plugin-presets" })
+
+ const handleSearchChange = useCallback(
+ (value?: string) => {
+ navigate({
+ to: "/admin/plugin-presets",
+ search: (prev) => ({
+ ...prev,
+ searchTerm: value,
+ }),
+ })
+ },
+ [navigate]
+ )
+
+ return (
+
+
+ handleSearchChange(undefined)}
+ />
+
+
+ )
+}
diff --git a/apps/greenhouse/src/components/admin/PluginPresets/index.tsx b/apps/greenhouse/src/components/admin/PluginPresets/index.tsx
new file mode 100644
index 0000000000..1e523116d7
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/PluginPresets/index.tsx
@@ -0,0 +1,27 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { Container, ContentHeading } from "@cloudoperators/juno-ui-components"
+import { useLoaderData } from "@tanstack/react-router"
+import { PluginPresetsDataGrid } from "./PluginPresetsDataGrid"
+import { PluginPresetsFilter } from "./PluginPresetsFilter"
+
+export const PluginPresets = () => {
+ const { pluginPresetsPromise, filterSettings } = useLoaderData({ from: "/admin/plugin-presets" })
+
+ return (
+ <>
+
+ Plugin Presets Overview
+ Manage and monitor plugin preset configurations across all clusters
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/greenhouse/src/components/admin/api/plugin-presets.ts b/apps/greenhouse/src/components/admin/api/plugin-presets.ts
new file mode 100644
index 0000000000..784aef8616
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/api/plugin-presets.ts
@@ -0,0 +1,12 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { PluginPreset } from "../types/k8sTypes"
+
+export const fetchPluginPresets = async (client: any, namespace: string): Promise => {
+ const response = await client.get(`/apis/greenhouse.sap/v1alpha1/namespaces/${namespace}/pluginpresets`)
+
+ return response.items || []
+}
diff --git a/apps/greenhouse/src/components/admin/common/EmptyDataGridRow.tsx b/apps/greenhouse/src/components/admin/common/EmptyDataGridRow.tsx
new file mode 100644
index 0000000000..608acea9f2
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/EmptyDataGridRow.tsx
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { DataGridCell, DataGridRow } from "@cloudoperators/juno-ui-components"
+
+type EmptyDataGridRowProps = {
+ colSpan: number
+ children: React.ReactNode
+}
+
+export const EmptyDataGridRow = ({ colSpan, children }: EmptyDataGridRowProps) => (
+
+ {children}
+
+)
diff --git a/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.test.tsx b/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.test.tsx
new file mode 100644
index 0000000000..953dffdcdd
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.test.tsx
@@ -0,0 +1,34 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { render, screen } from "@testing-library/react"
+import { ErrorMessage } from "./ErrorMessage"
+
+describe("ErrorMessage", () => {
+ it("renders error message with name and message", () => {
+ const error = new Error("Something went wrong")
+ error.name = "TestError"
+ render()
+ const errorText = screen.getByText("TestError: Something went wrong")
+ expect(errorText).toBeInTheDocument()
+ })
+
+ it("renders error message with default name", () => {
+ const error = new Error("Something went wrong")
+ error.name = ""
+ render()
+ const errorText = screen.getByText("Error: Something went wrong")
+ expect(errorText).toBeInTheDocument()
+ })
+
+ it("renders default message when error message is empty", () => {
+ const error = new Error("")
+ error.name = "TestError"
+ render()
+ const errorText = screen.getByText("TestError: Something went wrong")
+ expect(errorText).toBeInTheDocument()
+ })
+})
diff --git a/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.tsx b/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.tsx
new file mode 100644
index 0000000000..371c51e2b4
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/ErrorBoundary/ErrorMessage.tsx
@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { Icon, Stack } from "@cloudoperators/juno-ui-components"
+
+type ErrorMessageProps = {
+ error: Error
+}
+
+export const ErrorMessage = ({ error }: ErrorMessageProps) => {
+ const errorName = error.name ? `${error.name}: ` : "Error: "
+ const errorMessage = error.message || "Something went wrong"
+
+ return (
+
+
+
+ {errorName}
+ {errorMessage}
+
+
+ )
+}
diff --git a/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.test.tsx b/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.test.tsx
new file mode 100644
index 0000000000..7eaa62809a
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.test.tsx
@@ -0,0 +1,96 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { useEffect } from "react"
+import { render, screen } from "@testing-library/react"
+import { FallbackProps } from "react-error-boundary"
+import { ErrorBoundary } from "./index"
+
+const Component = () => Some Component
+const ComponentThatThrows = () => {
+ useEffect(() => {
+ throw new Error("Test error message")
+ }, [])
+ return Will not render
+}
+
+const CustomFallback = ({ error }: FallbackProps) => Custom fallback: {error?.message}
+
+describe("ErrorBoundary", () => {
+ let consoleSpy: any
+
+ beforeEach(() => {
+ // mock console.error to suppress the error message being printed to the console
+ consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {})
+ })
+
+ afterEach(() => {
+ // restore console.error to its original implementation
+ consoleSpy.mockRestore()
+ })
+
+ it("should render children when no error occurs", () => {
+ render(
+
+
+
+ )
+ expect(screen.getByText("Some Component")).toBeInTheDocument()
+ })
+
+ describe("when error occurs", () => {
+ it("should render null when displayErrorMessage is false", () => {
+ const { container } = render(
+
+
+
+ )
+ expect(container.firstChild).toBeNull()
+ expect(screen.queryByText("Some Component")).not.toBeInTheDocument()
+ })
+
+ it("should render null when displayErrorMessage is undefined", () => {
+ const { container } = render(
+
+
+
+ )
+ expect(container.firstChild).toBeNull()
+ expect(screen.queryByText("Some Component")).not.toBeInTheDocument()
+ })
+
+ it("should render default ErrorMessage when displayErrorMessage is true and no fallback provided", () => {
+ render(
+
+
+
+ )
+ expect(screen.getByText("Error: Test error message")).toBeInTheDocument()
+ expect(screen.queryByText("Some Component")).not.toBeInTheDocument()
+ })
+
+ it("should render custom fallback when displayErrorMessage is true and fallback is provided", () => {
+ render(
+
+
+
+ )
+ expect(screen.getByText("Custom fallback: Test error message")).toBeInTheDocument()
+ expect(screen.queryByText("Error: Test error message")).not.toBeInTheDocument()
+ expect(screen.queryByText("Some Component")).not.toBeInTheDocument()
+ })
+
+ it("should render null when displayErrorMessage is false even if fallback is provided", () => {
+ const { container } = render(
+
+
+
+ )
+ expect(container.firstChild).toBeNull()
+ expect(screen.queryByText("Custom fallback: Test error message")).not.toBeInTheDocument()
+ expect(screen.queryByText("Some Component")).not.toBeInTheDocument()
+ })
+ })
+})
diff --git a/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.tsx b/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.tsx
new file mode 100644
index 0000000000..b7e91398e9
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/ErrorBoundary/index.tsx
@@ -0,0 +1,27 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { ReactNode } from "react"
+import { ErrorBoundary as ReactErrorBoundary, FallbackProps } from "react-error-boundary"
+import { ErrorMessage } from "./ErrorMessage"
+
+export const ErrorBoundary = ({
+ children,
+ displayErrorMessage,
+ fallbackRender,
+ resetKeys,
+}: {
+ children: ReactNode
+ displayErrorMessage?: boolean
+ fallbackRender?: (props: FallbackProps) => ReactNode
+ resetKeys?: any
+}) => (
+ null}
+ >
+ {children}
+
+)
diff --git a/apps/greenhouse/src/components/admin/common/LoadingDataRow.test.tsx b/apps/greenhouse/src/components/admin/common/LoadingDataRow.test.tsx
new file mode 100644
index 0000000000..967e3a50eb
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/LoadingDataRow.test.tsx
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { render, screen } from "@testing-library/react"
+import { LoadingDataRow } from "./LoadingDataRow"
+
+describe("LoadingDataRow", () => {
+ it("should correctly render", () => {
+ render()
+ const loadingText = screen.getByText("Loading...")
+ expect(loadingText).toBeInTheDocument()
+ })
+})
diff --git a/apps/greenhouse/src/components/admin/common/LoadingDataRow.tsx b/apps/greenhouse/src/components/admin/common/LoadingDataRow.tsx
new file mode 100644
index 0000000000..de0045d201
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/LoadingDataRow.tsx
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { Stack } from "@cloudoperators/juno-ui-components/index"
+import { EmptyDataGridRow } from "./EmptyDataGridRow"
+
+export const LoadingDataRow = ({ colSpan }: { colSpan: number }) => (
+
+
+ Loading...
+
+
+)
diff --git a/apps/greenhouse/src/components/admin/common/getErrorDataRow.tsx b/apps/greenhouse/src/components/admin/common/getErrorDataRow.tsx
new file mode 100644
index 0000000000..0b46d52945
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/common/getErrorDataRow.tsx
@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { Stack } from "@cloudoperators/juno-ui-components/index"
+import { EmptyDataGridRow } from "./EmptyDataGridRow"
+import { ErrorMessage } from "./ErrorBoundary/ErrorMessage"
+
+export const getErrorDataRowComponent = ({ colspan }: { colspan: number }) => {
+ const ErrorDataRow = ({ error }: { error: Error }) => (
+
+
+
+
+
+ )
+ ErrorDataRow.displayName = "ErrorDataRow"
+ return ErrorDataRow
+}
diff --git a/apps/greenhouse/src/components/admin/types/k8sTypes.ts b/apps/greenhouse/src/components/admin/types/k8sTypes.ts
new file mode 100644
index 0000000000..cc8e01bbe3
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/types/k8sTypes.ts
@@ -0,0 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import type { components } from "./schema"
+
+export type PluginPreset = components["schemas"]["PluginPreset"]
diff --git a/apps/greenhouse/src/components/admin/types/schema.d.ts b/apps/greenhouse/src/components/admin/types/schema.d.ts
new file mode 100644
index 0000000000..20235210b6
--- /dev/null
+++ b/apps/greenhouse/src/components/admin/types/schema.d.ts
@@ -0,0 +1,1556 @@
+/*
+ * SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Juno contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This file was auto-generated by openapi-typescript.
+ * Do not make direct changes to the file.
+ */
+
+export type paths = Record
+export type webhooks = Record
+export interface components {
+ schemas: {
+ /**
+ * Catalog
+ * @description Catalog is the Schema for the catalogs API.
+ */
+ Catalog: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description CatalogSpec defines the desired state of Catalog. */
+ spec?: {
+ /** @description Sources contains the list of Git Repository source to resolve PluginDefinitions / ClusterPluginDefinitions from */
+ sources: {
+ /** @description Interval defines how often to reconcile the Git repository source */
+ interval?: string
+ /** @description Overrides are the PluginDefinition overrides to be applied */
+ overrides?: {
+ /**
+ * @description Alias is the alias to apply to the PluginDefinition Name via Kustomize patches
+ * For SourceType Helm, this field is passed to postRender Kustomize patch
+ */
+ alias?: string
+ /** @description Name is the name of the PluginDefinition to patch with an alias */
+ name: string
+ /** @description Repository is the repository to override in the PluginDefinition .spec.helmChart.repository */
+ repository?: string
+ }[]
+ /**
+ * @description Ref is the git reference (branch, tag, or SHA) to resolve PluginDefinitions from
+ * precedence: SHA > Tag > Branch
+ * if not specified, defaults to the branch "main"
+ */
+ ref?: {
+ branch?: string
+ sha?: string
+ tag?: string
+ }
+ /** @description Repository - the Git repository URL */
+ repository: string
+ /**
+ * @description Resources contains the list of path to PluginDefinition files
+ * e.g. ["plugins/plugin-a.yaml", "plugins/plugin-b.yaml"]
+ * glob patterns are supported, e.g. ["plugins/*.yaml", "more-plugins/**\/plugindefinition.yaml"]
+ */
+ resources: string[]
+ /**
+ * @description SecretName is the name of v1.Secret containing credentials to access the Git repository
+ * the secret must be in the same namespace as the Catalog resource
+ *
+ * GitHub App Example:
+ */
+ secretName?: string
+ }[]
+ }
+ /** @description CatalogStatus defines the observed state of Catalog. */
+ status?: {
+ /** @description Inventory contains list of internal artifacts generated by Catalog */
+ inventory?: {
+ [key: string]: {
+ kind: string
+ message?: string
+ name: string
+ ready?: string
+ }[]
+ }
+ /** @description LastReconciledAt contains the value when the reconcile was last triggered via annotation. */
+ lastReconciledAt?: string
+ /** @description StatusConditions contain the different conditions that constitute the status of the Catalog */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * ClusterKubeconfig
+ * @description ClusterKubeconfig is the Schema for the clusterkubeconfigs API
+ * ObjectMeta.OwnerReferences is used to link the ClusterKubeconfig to the Cluster
+ * ObjectMeta.Generation is used to detect changes in the ClusterKubeconfig and sync local kubeconfig files
+ * ObjectMeta.Name is designed to be the same with the Cluster name
+ */
+ ClusterKubeconfig: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /**
+ * @description ClusterKubeconfigSpec stores the kubeconfig data for the cluster
+ * The idea is to use kubeconfig data locally with minimum effort (with local tools or plain kubectl):
+ * kubectl get cluster-kubeconfig $NAME -o yaml | yq -y .spec.kubeconfig
+ */
+ spec?: {
+ /**
+ * @description ClusterKubeconfigData stores the kubeconfig data ready to use kubectl or other local tooling
+ * It is a simplified version of clientcmdapi.Config: https://pkg.go.dev/k8s.io/client-go/tools/clientcmd/api#Config
+ */
+ kubeconfig?: {
+ apiVersion?: string
+ clusters?: {
+ cluster: {
+ /** Format: byte */
+ "certificate-authority-data"?: string
+ server?: string
+ }
+ name: string
+ }[]
+ contexts?: {
+ context?: {
+ cluster: string
+ namespace?: string
+ user: string
+ }
+ name: string
+ }[]
+ "current-context"?: string
+ kind?: string
+ preferences?: Record
+ users?: {
+ name: string
+ user?: {
+ /** @description AuthProviderConfig holds the configuration for a specified auth provider. */
+ "auth-provider"?: {
+ config?: {
+ [key: string]: string
+ }
+ name: string
+ }
+ /** Format: byte */
+ "client-certificate-data"?: string
+ /** Format: byte */
+ "client-key-data"?: string
+ }
+ }[]
+ }
+ }
+ status?: {
+ /**
+ * @description A StatusConditions contains a list of conditions.
+ * Only one condition of a given type may exist in the list.
+ */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * ClusterPluginDefinition
+ * @description ClusterPluginDefinition is the Schema for the clusterplugindefinitions API.
+ */
+ ClusterPluginDefinition: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description PluginDefinitionSpec defines the desired state of PluginDefinitionSpec */
+ spec?: {
+ /** @description Description provides additional details of the pluginDefinition. */
+ description?: string
+ /** @description DisplayName provides a human-readable label for the pluginDefinition. */
+ displayName?: string
+ /**
+ * @description DocMarkDownUrl specifies the URL to the markdown documentation file for this plugin.
+ * Source needs to allow all CORS origins.
+ */
+ docMarkDownUrl?: string
+ /** @description HelmChart specifies where the Helm Chart for this pluginDefinition can be found. */
+ helmChart?: {
+ /** @description Name of the HelmChart chart. */
+ name: string
+ /** @description Repository of the HelmChart chart. */
+ repository: string
+ /** @description Version of the HelmChart chart. */
+ version: string
+ }
+ /**
+ * @description Icon specifies the icon to be used for this plugin in the Greenhouse UI.
+ * Icons can be either:
+ * - A string representing a juno icon in camel case from this list: https://github.com/sapcc/juno/blob/main/libs/juno-ui-components/src/components/Icon/Icon.component.js#L6-L52
+ * - A publicly accessible image reference to a .png file. Will be displayed 100x100px
+ */
+ icon?: string
+ /** @description RequiredValues is a list of values required to create an instance of this PluginDefinition. */
+ options?: {
+ /** @description Default provides a default value for the option */
+ default?: unknown
+ /** @description Description provides a human-readable text for the value as shown in the UI. */
+ description?: string
+ /** @description DisplayName provides a human-readable label for the configuration option */
+ displayName?: string
+ /** @description Name/Key of the config option. */
+ name: string
+ /** @description Regex specifies a match rule for validating configuration options. */
+ regex?: string
+ /** @description Required indicates that this config option is required */
+ required: boolean
+ /**
+ * @description Type of this configuration option.
+ * @enum {string}
+ */
+ type: "string" | "secret" | "bool" | "int" | "list" | "map"
+ }[]
+ /** @description UIApplication specifies a reference to a UI application */
+ uiApplication?: {
+ /** @description Name of the UI application. */
+ name: string
+ /**
+ * @description URL specifies the url to a built javascript asset.
+ * By default, assets are loaded from the Juno asset server using the provided name and version.
+ */
+ url?: string
+ /** @description Version of the frontend application. */
+ version: string
+ }
+ /** @description Version of this pluginDefinition */
+ version: string
+ /**
+ * Format: int32
+ * @description Weight configures the order in which Plugins are shown in the Greenhouse UI.
+ * Defaults to alphabetical sorting if not provided or on conflict.
+ */
+ weight?: number
+ }
+ /** @description ClusterPluginDefinitionStatus defines the observed state of ClusterPluginDefinition. */
+ status?: {
+ /** @description StatusConditions contain the different conditions that constitute the status of the Plugin. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * Cluster
+ * @description Cluster is the Schema for the clusters API
+ */
+ Cluster: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description ClusterSpec defines the desired state of the Cluster. */
+ spec?: {
+ /**
+ * @description AccessMode configures how the cluster is accessed from the Greenhouse operator.
+ * @enum {string}
+ */
+ accessMode: "direct"
+ /** @description KubeConfig contains specific values for `KubeConfig` for the cluster. */
+ kubeConfig?: {
+ /**
+ * Format: int32
+ * @description MaxTokenValidity specifies the maximum duration for which a token remains valid in hours.
+ * @default 72
+ */
+ maxTokenValidity: number
+ }
+ }
+ /** @description ClusterStatus defines the observed state of Cluster */
+ status?: {
+ /**
+ * Format: date-time
+ * @description BearerTokenExpirationTimestamp reflects the expiration timestamp of the bearer token used to access the cluster.
+ */
+ bearerTokenExpirationTimestamp?: string
+ /** @description KubernetesVersion reflects the detected Kubernetes version of the cluster. */
+ kubernetesVersion?: string
+ /** @description Nodes contain a short summary of nodes count and not ready nodes status. */
+ nodes?: {
+ /** @description NotReady is slice of non-ready nodes status details. */
+ notReady?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime represents latest transition time of status.
+ */
+ lastTransitionTime?: string
+ /** @description Message represents the error message. */
+ message?: string
+ /** @description Name of the node. */
+ name: string
+ }[]
+ /**
+ * Format: int32
+ * @description ReadyNodes represent the number of ready nodes in the cluster.
+ */
+ ready?: number
+ /**
+ * Format: int32
+ * @description Total represent the number of all the nodes in the cluster.
+ */
+ total?: number
+ }
+ /** @description StatusConditions contain the different conditions that constitute the status of the Cluster. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * Organization
+ * @description Organization is the Schema for the organizations API
+ */
+ Organization: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description OrganizationSpec defines the desired state of Organization */
+ spec?: {
+ /** @description Authentication configures the organizations authentication mechanism. */
+ authentication?: {
+ /** @description OIDConfig configures the OIDC provider. */
+ oidc?: {
+ /** @description ClientIDReference references the Kubernetes secret containing the client id. */
+ clientIDReference: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ /** @description ClientSecretReference references the Kubernetes secret containing the client secret. */
+ clientSecretReference: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ /** @description Issuer is the URL of the identity service. */
+ issuer: string
+ /**
+ * @description OAuth2ClientRedirectURIs are a registered set of redirect URIs. When redirecting from the idproxy to
+ * the client application, the URI requested to redirect to must be contained in this list.
+ */
+ oauth2ClientRedirectURIs?: string[]
+ /**
+ * @description RedirectURI is the redirect URI to be used for the OIDC flow against the upstream IdP.
+ * If none is specified, the Greenhouse ID proxy will be used.
+ */
+ redirectURI?: string
+ }
+ /** @description SCIMConfig configures the SCIM client. */
+ scim?: {
+ /**
+ * @description AuthType defined possible authentication type
+ * @default basic
+ * @enum {string}
+ */
+ authType: "basic" | "token"
+ /** @description URL to the SCIM server. */
+ baseURL: string
+ /** @description Password to be used for basic authentication. */
+ basicAuthPw?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ /** @description User to be used for basic authentication. */
+ basicAuthUser?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ /** @description BearerHeader to be used to defined bearer token header */
+ bearerHeader?: string
+ /** @description BearerPrefix to be used to defined bearer token prefix */
+ bearerPrefix?: string
+ /** @description BearerToken to be used for bearer token authorization */
+ bearerToken?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ }
+ }
+ /** @description ConfigMapRef allows to reference organizational config map. */
+ configMapRef?: string
+ /** @description Description provides additional details of the organization. */
+ description?: string
+ /**
+ * @description DisplayName is an optional name for the organization to be displayed in the Greenhouse UI.
+ * Defaults to a normalized version of metadata.name.
+ */
+ displayName?: string
+ /** @description MappedOrgAdminIDPGroup is the IDP group ID identifying org admins */
+ mappedOrgAdminIdPGroup?: string
+ }
+ /** @description OrganizationStatus defines the observed state of an Organization */
+ status?: {
+ /** @description StatusConditions contain the different conditions that constitute the status of the Organization. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * PluginDefinition
+ * @description PluginDefinition is the Schema for the PluginDefinitions API
+ */
+ PluginDefinition: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description PluginDefinitionSpec defines the desired state of PluginDefinitionSpec */
+ spec?: {
+ /** @description Description provides additional details of the pluginDefinition. */
+ description?: string
+ /** @description DisplayName provides a human-readable label for the pluginDefinition. */
+ displayName?: string
+ /**
+ * @description DocMarkDownUrl specifies the URL to the markdown documentation file for this plugin.
+ * Source needs to allow all CORS origins.
+ */
+ docMarkDownUrl?: string
+ /** @description HelmChart specifies where the Helm Chart for this pluginDefinition can be found. */
+ helmChart?: {
+ /** @description Name of the HelmChart chart. */
+ name: string
+ /** @description Repository of the HelmChart chart. */
+ repository: string
+ /** @description Version of the HelmChart chart. */
+ version: string
+ }
+ /**
+ * @description Icon specifies the icon to be used for this plugin in the Greenhouse UI.
+ * Icons can be either:
+ * - A string representing a juno icon in camel case from this list: https://github.com/sapcc/juno/blob/main/libs/juno-ui-components/src/components/Icon/Icon.component.js#L6-L52
+ * - A publicly accessible image reference to a .png file. Will be displayed 100x100px
+ */
+ icon?: string
+ /** @description RequiredValues is a list of values required to create an instance of this PluginDefinition. */
+ options?: {
+ /** @description Default provides a default value for the option */
+ default?: unknown
+ /** @description Description provides a human-readable text for the value as shown in the UI. */
+ description?: string
+ /** @description DisplayName provides a human-readable label for the configuration option */
+ displayName?: string
+ /** @description Name/Key of the config option. */
+ name: string
+ /** @description Regex specifies a match rule for validating configuration options. */
+ regex?: string
+ /** @description Required indicates that this config option is required */
+ required: boolean
+ /**
+ * @description Type of this configuration option.
+ * @enum {string}
+ */
+ type: "string" | "secret" | "bool" | "int" | "list" | "map"
+ }[]
+ /** @description UIApplication specifies a reference to a UI application */
+ uiApplication?: {
+ /** @description Name of the UI application. */
+ name: string
+ /**
+ * @description URL specifies the url to a built javascript asset.
+ * By default, assets are loaded from the Juno asset server using the provided name and version.
+ */
+ url?: string
+ /** @description Version of the frontend application. */
+ version: string
+ }
+ /** @description Version of this pluginDefinition */
+ version: string
+ /**
+ * Format: int32
+ * @description Weight configures the order in which Plugins are shown in the Greenhouse UI.
+ * Defaults to alphabetical sorting if not provided or on conflict.
+ */
+ weight?: number
+ }
+ /** @description PluginDefinitionStatus defines the observed state of PluginDefinition */
+ status?: {
+ /** @description StatusConditions contain the different conditions that constitute the status of the Plugin. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * PluginPreset
+ * @description PluginPreset is the Schema for the PluginPresets API
+ */
+ PluginPreset: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description PluginPresetSpec defines the desired state of PluginPreset */
+ spec?: {
+ /** @description ClusterOptionOverrides define plugin option values to override by the PluginPreset */
+ clusterOptionOverrides?: {
+ clusterName: string
+ overrides: {
+ /** @description Name of the values. */
+ name: string
+ /**
+ * @description Template is a Go string template that will be dynamically resolved for cluster-specific values.
+ * Only PluginOptionValues declared as template will be templated by the PluginController for Flux.
+ */
+ template?: string
+ /** @description Value is the actual value in plain text. */
+ value?: unknown
+ /** @description ValueFrom references a potentially confidential value in another source. */
+ valueFrom?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ }[]
+ }[]
+ /** @description ClusterSelector is a label selector to select the clusters the plugin bundle should be deployed to. */
+ clusterSelector: {
+ /** @description matchExpressions is a list of label selector requirements. The requirements are ANDed. */
+ matchExpressions?: {
+ /** @description key is the label key that the selector applies to. */
+ key: string
+ /**
+ * @description operator represents a key's relationship to a set of values.
+ * Valid operators are In, NotIn, Exists and DoesNotExist.
+ */
+ operator: string
+ /**
+ * @description values is an array of string values. If the operator is In or NotIn,
+ * the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ * the values array must be empty. This array is replaced during a strategic
+ * merge patch.
+ */
+ values?: string[]
+ }[]
+ /**
+ * @description matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ * map is equivalent to an element of matchExpressions, whose key field is "key", the
+ * operator is "In", and the values array contains only "value". The requirements are ANDed.
+ */
+ matchLabels?: {
+ [key: string]: string
+ }
+ }
+ /**
+ * @description DeletionPolicy defines how Plugins owned by a PluginPreset are handled on deletion of the PluginPreset.
+ * Supported values are "Delete" and "Retain". If not set, defaults to "Delete".
+ * @default Delete
+ * @enum {string}
+ */
+ deletionPolicy: "Delete" | "Retain"
+ /** @description PluginSpec is the spec of the plugin to be deployed by the PluginPreset. */
+ plugin: {
+ /** @description ClusterName is the name of the cluster the plugin is deployed to. If not set, the plugin is deployed to the greenhouse cluster. */
+ clusterName?: string
+ /**
+ * @description DeletionPolicy defines how Helm Releases created by a Plugin are handled upon deletion of the Plugin.
+ * Supported values are "Delete" and "Retain". If not set, defaults to "Delete".
+ * @default Delete
+ * @enum {string}
+ */
+ deletionPolicy: "Delete" | "Retain"
+ /**
+ * @description DisplayName is an optional name for the Plugin to be displayed in the Greenhouse UI.
+ * This is especially helpful to distinguish multiple instances of a PluginDefinition in the same context.
+ * Defaults to a normalized version of metadata.name.
+ */
+ displayName?: string
+ /** @description IgnoreDifferences defines paths to ignore when detecting drift between desired and actual state. */
+ ignoreDifferences?: {
+ /** @description Group matches the APIVersion group of the resources to ignore. */
+ group?: string
+ /** @description Kind matches the Kind of the resources to ignore. */
+ kind?: string
+ /** @description Name matches the name of the resources to ignore. */
+ name?: string
+ /** @description Paths is a list of JSON paths to ignore when detecting drifts. */
+ paths: string[]
+ /** @description Version matches the APIVersion version of the resources to ignore. */
+ version?: string
+ }[]
+ /** @description Values are the values for a PluginDefinition instance. */
+ optionValues?: {
+ /** @description Name of the values. */
+ name: string
+ /**
+ * @description Template is a Go string template that will be dynamically resolved for cluster-specific values.
+ * Only PluginOptionValues declared as template will be templated by the PluginController for Flux.
+ */
+ template?: string
+ /** @description Value is the actual value in plain text. */
+ value?: unknown
+ /** @description ValueFrom references a potentially confidential value in another source. */
+ valueFrom?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ }[]
+ /**
+ * @description PluginDefinition is the name of the PluginDefinition this instance is for.
+ *
+ * Deprecated: Use PluginDefinitionRef instead. Future releases of greenhouse will remove this field.
+ */
+ pluginDefinition: string
+ /** @description PluginDefinitionRef is the reference to the (Cluster-)PluginDefinition. */
+ pluginDefinitionRef: {
+ /**
+ * @description Kind of the referent. Supported values: PluginDefinition, ClusterPluginDefinition.
+ * @enum {string}
+ */
+ kind?: "PluginDefinition" | "ClusterPluginDefinition"
+ /** @description Name of the referenced PluginDefinition or ClusterPluginDefinition resource. */
+ name?: string
+ }
+ /**
+ * @description ReleaseName is the name of the helm release in the remote cluster to which the backend is deployed.
+ * If the Plugin was already deployed, the Plugin's name is used as the release name.
+ * If this Plugin is newly created, the releaseName is defaulted to the PluginDefinitions HelmChart name.
+ */
+ releaseName?: string
+ /**
+ * @description ReleaseNamespace is the namespace in the remote cluster to which the backend is deployed.
+ * Defaults to the Greenhouse managed namespace if not set.
+ */
+ releaseNamespace?: string
+ /** @description WaitFor defines other Plugins to wait for before installing this Plugin. */
+ waitFor?: {
+ /** @description PluginRef defines a reference to the Plugin. */
+ pluginRef: {
+ /** @description Name of the Plugin. */
+ name?: string
+ /** @description PluginPreset is the name of the PluginPreset which creates the Plugin. */
+ pluginPreset?: string
+ }
+ }[]
+ }
+ /** @description WaitFor defines other Plugins to wait for before creating the Plugin. */
+ waitFor?: {
+ /** @description PluginRef defines a reference to the Plugin. */
+ pluginRef: {
+ /** @description Name of the Plugin. */
+ name?: string
+ /** @description PluginPreset is the name of the PluginPreset which creates the Plugin. */
+ pluginPreset?: string
+ }
+ }[]
+ }
+ /** @description PluginPresetStatus defines the observed state of PluginPreset */
+ status?: {
+ /** @description FailedPlugins is the number of failed Plugins managed by the PluginPreset. */
+ failedPlugins?: number
+ /** @description PluginStatuses contains statuses of Plugins managed by the PluginPreset. */
+ pluginStatuses?: {
+ pluginName?: string
+ /** @description Condition contains additional information on the state of a resource. */
+ readyCondition?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }
+ }[]
+ /** @description ReadyPlugins is the number of ready Plugins managed by the PluginPreset. */
+ readyPlugins?: number
+ /** @description StatusConditions contain the different conditions that constitute the status of the PluginPreset. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ /** @description TotalPlugins is the number of Plugins in total managed by the PluginPreset. */
+ totalPlugins?: number
+ }
+ }
+ /**
+ * Plugin
+ * @description Plugin is the Schema for the plugins API
+ */
+ Plugin: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description PluginSpec defines the desired state of Plugin */
+ spec?: {
+ /** @description ClusterName is the name of the cluster the plugin is deployed to. If not set, the plugin is deployed to the greenhouse cluster. */
+ clusterName?: string
+ /**
+ * @description DeletionPolicy defines how Helm Releases created by a Plugin are handled upon deletion of the Plugin.
+ * Supported values are "Delete" and "Retain". If not set, defaults to "Delete".
+ * @default Delete
+ * @enum {string}
+ */
+ deletionPolicy: "Delete" | "Retain"
+ /**
+ * @description DisplayName is an optional name for the Plugin to be displayed in the Greenhouse UI.
+ * This is especially helpful to distinguish multiple instances of a PluginDefinition in the same context.
+ * Defaults to a normalized version of metadata.name.
+ */
+ displayName?: string
+ /** @description IgnoreDifferences defines paths to ignore when detecting drift between desired and actual state. */
+ ignoreDifferences?: {
+ /** @description Group matches the APIVersion group of the resources to ignore. */
+ group?: string
+ /** @description Kind matches the Kind of the resources to ignore. */
+ kind?: string
+ /** @description Name matches the name of the resources to ignore. */
+ name?: string
+ /** @description Paths is a list of JSON paths to ignore when detecting drifts. */
+ paths: string[]
+ /** @description Version matches the APIVersion version of the resources to ignore. */
+ version?: string
+ }[]
+ /** @description Values are the values for a PluginDefinition instance. */
+ optionValues?: {
+ /** @description Name of the values. */
+ name: string
+ /**
+ * @description Template is a Go string template that will be dynamically resolved for cluster-specific values.
+ * Only PluginOptionValues declared as template will be templated by the PluginController for Flux.
+ */
+ template?: string
+ /** @description Value is the actual value in plain text. */
+ value?: unknown
+ /** @description ValueFrom references a potentially confidential value in another source. */
+ valueFrom?: {
+ /** @description Secret references the secret containing the value. */
+ secret?: {
+ /** @description Key in the secret to select the value from. */
+ key: string
+ /** @description Name of the secret in the same namespace. */
+ name: string
+ }
+ }
+ }[]
+ /**
+ * @description PluginDefinition is the name of the PluginDefinition this instance is for.
+ *
+ * Deprecated: Use PluginDefinitionRef instead. Future releases of greenhouse will remove this field.
+ */
+ pluginDefinition: string
+ /** @description PluginDefinitionRef is the reference to the (Cluster-)PluginDefinition. */
+ pluginDefinitionRef: {
+ /**
+ * @description Kind of the referent. Supported values: PluginDefinition, ClusterPluginDefinition.
+ * @enum {string}
+ */
+ kind?: "PluginDefinition" | "ClusterPluginDefinition"
+ /** @description Name of the referenced PluginDefinition or ClusterPluginDefinition resource. */
+ name?: string
+ }
+ /**
+ * @description ReleaseName is the name of the helm release in the remote cluster to which the backend is deployed.
+ * If the Plugin was already deployed, the Plugin's name is used as the release name.
+ * If this Plugin is newly created, the releaseName is defaulted to the PluginDefinitions HelmChart name.
+ */
+ releaseName?: string
+ /**
+ * @description ReleaseNamespace is the namespace in the remote cluster to which the backend is deployed.
+ * Defaults to the Greenhouse managed namespace if not set.
+ */
+ releaseNamespace?: string
+ /** @description WaitFor defines other Plugins to wait for before installing this Plugin. */
+ waitFor?: {
+ /** @description PluginRef defines a reference to the Plugin. */
+ pluginRef: {
+ /** @description Name of the Plugin. */
+ name?: string
+ /** @description PluginPreset is the name of the PluginPreset which creates the Plugin. */
+ pluginPreset?: string
+ }
+ }[]
+ }
+ /** @description PluginStatus defines the observed state of Plugin */
+ status?: {
+ /** @description Description provides additional details of the plugin. */
+ description?: string
+ /**
+ * @description ExposedServices provides an overview of the Plugins services that are centrally exposed.
+ * It maps the exposed URL to the service found in the manifest.
+ */
+ exposedServices?: {
+ [key: string]: {
+ /** @description Name is the name of the service in the target cluster. */
+ name: string
+ /** @description Namespace is the namespace of the service in the target cluster. */
+ namespace: string
+ /**
+ * Format: int32
+ * @description Port is the port of the service. Zero for ingresses where port is not applicable.
+ */
+ port?: number
+ /** @description Protocol is the protocol of the service. */
+ protocol?: string
+ /**
+ * @description Type is the type of exposed service.
+ * @default service
+ * @enum {string}
+ */
+ type: "service" | "ingress"
+ }
+ }
+ /** @description HelmChart contains a reference the helm chart used for the deployed pluginDefinition version. */
+ helmChart?: {
+ /** @description Name of the HelmChart chart. */
+ name: string
+ /** @description Repository of the HelmChart chart. */
+ repository: string
+ /** @description Version of the HelmChart chart. */
+ version: string
+ }
+ /**
+ * @description HelmReleaseStatus reflects the status of the latest HelmChart release.
+ * This is only configured if the pluginDefinition is backed by HelmChart.
+ */
+ helmReleaseStatus?: {
+ /** @description Diff contains the difference between the deployed helm chart and the helm chart in the last reconciliation */
+ diff?: string
+ /**
+ * Format: date-time
+ * @description FirstDeployed is the timestamp of the first deployment of the release.
+ */
+ firstDeployed?: string
+ /**
+ * Format: date-time
+ * @description LastDeployed is the timestamp of the last deployment of the release.
+ */
+ lastDeployed?: string
+ /** @description PluginOptionChecksum is the checksum of plugin option values. */
+ pluginOptionChecksum?: string
+ /** @description Status is the status of a HelmChart release. */
+ status: string
+ }
+ /** @description LastReconciledAt contains the value when the reconcile was last triggered via annotation. */
+ lastReconciledAt?: string
+ /** @description StatusConditions contain the different conditions that constitute the status of the Plugin. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ /** @description UIApplication contains a reference to the frontend that is used for the deployed pluginDefinition version. */
+ uiApplication?: {
+ /** @description Name of the UI application. */
+ name: string
+ /**
+ * @description URL specifies the url to a built javascript asset.
+ * By default, assets are loaded from the Juno asset server using the provided name and version.
+ */
+ url?: string
+ /** @description Version of the frontend application. */
+ version: string
+ }
+ /** @description Version contains the latest pluginDefinition version the config was last applied with successfully. */
+ version?: string
+ /**
+ * Format: int32
+ * @description Weight configures the order in which Plugins are shown in the Greenhouse UI.
+ */
+ weight?: number
+ }
+ }
+ /**
+ * TeamRoleBinding
+ * @description TeamRoleBinding is the Schema for the rolebindings API
+ */
+ TeamRoleBinding: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description TeamRoleBindingSpec defines the desired state of a TeamRoleBinding */
+ spec?: {
+ /** @description ClusterSelector is used to select a Cluster or Clusters the TeamRoleBinding should be deployed to. */
+ clusterSelector?: {
+ /** @description Name of a single Cluster to select. */
+ clusterName?: string
+ /** @description LabelSelector is a label query over a set of Clusters. */
+ labelSelector?: {
+ /** @description matchExpressions is a list of label selector requirements. The requirements are ANDed. */
+ matchExpressions?: {
+ /** @description key is the label key that the selector applies to. */
+ key: string
+ /**
+ * @description operator represents a key's relationship to a set of values.
+ * Valid operators are In, NotIn, Exists and DoesNotExist.
+ */
+ operator: string
+ /**
+ * @description values is an array of string values. If the operator is In or NotIn,
+ * the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ * the values array must be empty. This array is replaced during a strategic
+ * merge patch.
+ */
+ values?: string[]
+ }[]
+ /**
+ * @description matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ * map is equivalent to an element of matchExpressions, whose key field is "key", the
+ * operator is "In", and the values array contains only "value". The requirements are ANDed.
+ */
+ matchLabels?: {
+ [key: string]: string
+ }
+ }
+ }
+ /**
+ * @description CreateNamespaces when enabled the controller will create namespaces for RoleBindings if they do not exist.
+ * @default false
+ */
+ createNamespaces: boolean
+ /**
+ * @description Namespaces is a list of namespaces in the Greenhouse Clusters to apply the RoleBinding to.
+ * If empty, a ClusterRoleBinding will be created on the remote cluster, otherwise a RoleBinding per namespace.
+ */
+ namespaces?: string[]
+ /** @description TeamRef references a Greenhouse Team by name */
+ teamRef?: string
+ /** @description TeamRoleRef references a Greenhouse TeamRole by name */
+ teamRoleRef?: string
+ /** @description Usernames defines list of users to add to the (Cluster-)RoleBindings */
+ usernames?: string[]
+ }
+ /** @description TeamRoleBindingStatus defines the observed state of the TeamRoleBinding */
+ status?: {
+ /** @description PropagationStatus is the list of clusters the TeamRoleBinding is applied to */
+ clusters?: {
+ /** @description ClusterName is the name of the cluster the rbacv1 resources are created on. */
+ clusterName: string
+ /** @description Condition is the overall Status of the rbacv1 resources created on the cluster */
+ condition?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }
+ }[]
+ /** @description StatusConditions contain the different conditions that constitute the status of the TeamRoleBinding. */
+ statusConditions?: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ /**
+ * TeamRole
+ * @description TeamRole is the Schema for the TeamRoles API
+ */
+ TeamRole: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description TeamRoleSpec defines the desired state of a TeamRole */
+ spec?: {
+ /** @description AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole on the remote cluster */
+ aggregationRule?: {
+ /**
+ * @description ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules.
+ * If any of the selectors match, then the ClusterRole's permissions will be added
+ */
+ clusterRoleSelectors?: {
+ /** @description matchExpressions is a list of label selector requirements. The requirements are ANDed. */
+ matchExpressions?: {
+ /** @description key is the label key that the selector applies to. */
+ key: string
+ /**
+ * @description operator represents a key's relationship to a set of values.
+ * Valid operators are In, NotIn, Exists and DoesNotExist.
+ */
+ operator: string
+ /**
+ * @description values is an array of string values. If the operator is In or NotIn,
+ * the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ * the values array must be empty. This array is replaced during a strategic
+ * merge patch.
+ */
+ values?: string[]
+ }[]
+ /**
+ * @description matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ * map is equivalent to an element of matchExpressions, whose key field is "key", the
+ * operator is "In", and the values array contains only "value". The requirements are ANDed.
+ */
+ matchLabels?: {
+ [key: string]: string
+ }
+ }[]
+ }
+ /**
+ * @description Labels are applied to the ClusterRole created on the remote cluster.
+ * This allows using TeamRoles as part of AggregationRules by other TeamRoles
+ */
+ labels?: {
+ [key: string]: string
+ }
+ /** @description Rules is a list of rbacv1.PolicyRules used on a managed RBAC (Cluster)Role */
+ rules?: {
+ /**
+ * @description APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
+ * the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
+ */
+ apiGroups?: string[]
+ /**
+ * @description NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
+ * Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
+ * Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
+ */
+ nonResourceURLs?: string[]
+ /** @description ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. */
+ resourceNames?: string[]
+ /** @description Resources is a list of resources this rule applies to. '*' represents all resources. */
+ resources?: string[]
+ /** @description Verbs is a list of Verbs that apply to ALL the ResourceKinds contained in this rule. '*' represents all verbs. */
+ verbs: string[]
+ }[]
+ }
+ /** @description TeamRoleStatus defines the observed state of a TeamRole */
+ status?: Record
+ }
+ /**
+ * Team
+ * @description Team is the Schema for the teams API
+ */
+ Team: {
+ /**
+ * @description APIVersion defines the versioned schema of this representation of an object.
+ * Servers should convert recognized schemas to the latest internal value, and
+ * may reject unrecognized values.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ */
+ apiVersion?: string
+ /**
+ * @description Kind is a string value representing the REST resource this object represents.
+ * Servers may infer this from the endpoint the client submits requests to.
+ * Cannot be updated.
+ * In CamelCase.
+ * More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ */
+ kind?: string
+ metadata?: {
+ name?: string
+ namespace?: string
+ /** Format: uuid */
+ uid?: string
+ resourceVersion?: string
+ /** Format: date-time */
+ creationTimestamp?: string
+ /** Format: date-time */
+ deletionTimestamp?: string
+ labels?: {
+ [key: string]: string
+ }
+ annotations?: {
+ [key: string]: string
+ }
+ }
+ /** @description TeamSpec defines the desired state of Team */
+ spec?: {
+ /** @description Description provides additional details of the team. */
+ description?: string
+ /** @description URL to join the IdP group. */
+ joinUrl?: string
+ /** @description IdP group id matching team. */
+ mappedIdPGroup?: string
+ }
+ /** @description TeamStatus defines the observed state of Team */
+ status?: {
+ members?: {
+ /** @description Email of the user. */
+ email: string
+ /** @description FirstName of the user. */
+ firstName: string
+ /** @description ID is the unique identifier of the user. */
+ id: string
+ /** @description LastName of the user. */
+ lastName: string
+ }[]
+ /**
+ * @description A StatusConditions contains a list of conditions.
+ * Only one condition of a given type may exist in the list.
+ */
+ statusConditions: {
+ conditions?: {
+ /**
+ * Format: date-time
+ * @description LastTransitionTime is the last time the condition transitioned from one status to another.
+ */
+ lastTransitionTime: string
+ /** @description Message is an optional human-readable message indicating details about the last transition. */
+ message?: string
+ /** @description Reason is a one-word, CamelCase reason for the condition's last transition. */
+ reason?: string
+ /** @description Status of the condition. */
+ status: string
+ /** @description Type of the condition. */
+ type: string
+ }[]
+ }
+ }
+ }
+ }
+ responses: never
+ parameters: never
+ requestBodies: never
+ headers: never
+ pathItems: never
+}
+export type $defs = Record
+export type operations = Record
diff --git a/apps/greenhouse/src/routes/__root.tsx b/apps/greenhouse/src/routes/__root.tsx
index 4ac9c63f60..b1538c5e48 100644
--- a/apps/greenhouse/src/routes/__root.tsx
+++ b/apps/greenhouse/src/routes/__root.tsx
@@ -6,6 +6,7 @@
import React, { useEffect } from "react"
import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"
import { useActions } from "@cloudoperators/juno-messages-provider"
+import type { createClient } from "@cloudoperators/juno-k8s-client"
import { AppProps } from "../Shell"
import ShellLayout from "../components/layout/ShellLayout"
import useApi from "../hooks/useApi"
@@ -13,6 +14,8 @@ import { usePlugin } from "../components/StoreProvider"
export type RouteContext = {
appProps: AppProps
+ apiClient: ReturnType | null
+ organization: string
}
export const Route = createRootRouteWithContext()({
diff --git a/apps/greenhouse/src/routes/admin/index.tsx b/apps/greenhouse/src/routes/admin/index.tsx
index af27dcf659..edc72b23fb 100644
--- a/apps/greenhouse/src/routes/admin/index.tsx
+++ b/apps/greenhouse/src/routes/admin/index.tsx
@@ -9,7 +9,7 @@ export const Route = createFileRoute("/admin/")({
beforeLoad: () => {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw redirect({
- to: "/admin/clusters",
+ to: "/admin/plugin-presets",
search: (prev) => ({ ...prev }),
})
},
diff --git a/apps/greenhouse/src/routes/admin/plugin-presets.tsx b/apps/greenhouse/src/routes/admin/plugin-presets.tsx
index b63c95eabf..3df4c4ce39 100644
--- a/apps/greenhouse/src/routes/admin/plugin-presets.tsx
+++ b/apps/greenhouse/src/routes/admin/plugin-presets.tsx
@@ -3,22 +3,37 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import React from "react"
import { createFileRoute } from "@tanstack/react-router"
+import { z } from "zod"
import { Crumb } from "../-types"
+import { PluginPresets } from "../../components/admin/PluginPresets"
+import { fetchPluginPresets } from "../../components/admin/api/plugin-presets"
+
+const searchParamsSchema = z.object({
+ searchTerm: z.string().optional(),
+})
export const Route = createFileRoute("/admin/plugin-presets")({
- component: RouteComponent,
- loader: async () => {
+ component: PluginPresets,
+ validateSearch: (search: Record) => {
+ return searchParamsSchema.parse(search)
+ },
+ loaderDeps: (search) => ({
+ ...search,
+ }),
+ loader: async ({ context: { apiClient, organization }, deps: { search } }) => {
const crumb: Crumb = {
label: "Plugin Presets",
}
+ const pluginPresetsPromise = fetchPluginPresets(apiClient, organization)
+ const filterSettings = {
+ searchTerm: search.searchTerm,
+ }
+
return {
crumb,
+ pluginPresetsPromise: pluginPresetsPromise,
+ filterSettings,
}
},
})
-
-function RouteComponent() {
- return Hello "/admin/plugins-presets"!
-}
diff --git a/apps/greenhouse/src/routes/admin/route.tsx b/apps/greenhouse/src/routes/admin/route.tsx
index 18cea9a413..8da15a7322 100644
--- a/apps/greenhouse/src/routes/admin/route.tsx
+++ b/apps/greenhouse/src/routes/admin/route.tsx
@@ -3,13 +3,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import React from "react"
-import { createFileRoute, Outlet } from "@tanstack/react-router"
-import { Layout as AdminLayout } from "../../components/admin/Layout"
+import { createFileRoute } from "@tanstack/react-router"
+import { Layout } from "../../components/admin/Layout"
import { Crumb } from "../-types"
export const Route = createFileRoute("/admin")({
- component: RouteComponent,
+ component: Layout,
+ errorComponent: Layout,
loader: () => {
const crumb: Crumb = {
label: "Admin",
@@ -20,11 +20,3 @@ export const Route = createFileRoute("/admin")({
}
},
})
-
-function RouteComponent() {
- return (
-
-
-
- )
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e84495133a..cf0ee142fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -373,6 +373,9 @@ importers:
react-dom:
specifier: 19.2.1
version: 19.2.1(react@19.2.1)
+ react-error-boundary:
+ specifier: 6.0.0
+ version: 6.0.0(react@19.2.1)
react-markdown:
specifier: 10.1.0
version: 10.1.0(@types/react@19.2.7)(react@19.2.1)
@@ -766,10 +769,10 @@ importers:
version: 7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
vite-plugin-dts:
specifier: 4.5.4
- version: 4.5.4(@types/node@24.10.1)(rollup@4.50.1)(typescript@5.9.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))
+ version: 4.5.4(@types/node@24.10.1)(rollup@4.50.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.2))(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
packages/messages-provider:
dependencies:
@@ -915,7 +918,7 @@ importers:
version: 4.7.0(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))
eslint-plugin-storybook:
specifier: 9.1.16
- version: 9.1.16(eslint@9.35.0(jiti@2.6.1))(storybook@9.1.16(@testing-library/dom@10.4.0)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(prettier@3.6.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)))(typescript@5.9.3)
+ version: 9.1.16(eslint@9.39.1(jiti@2.6.1))(storybook@9.1.16(@testing-library/dom@10.4.0)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(prettier@3.6.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)))(typescript@5.9.3)
flatpickr:
specifier: 4.6.13
version: 4.6.13
@@ -3461,8 +3464,8 @@ packages:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/project-service@8.46.2':
- resolution: {integrity: sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==}
+ '@typescript-eslint/project-service@8.46.4':
+ resolution: {integrity: sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
@@ -3477,20 +3480,14 @@ packages:
resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==}
engines: {node: ^16.0.0 || >=18.0.0}
- '@typescript-eslint/scope-manager@8.46.2':
- resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==}
+ '@typescript-eslint/scope-manager@8.46.4':
+ resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.47.0':
resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.46.2':
- resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
'@typescript-eslint/tsconfig-utils@8.46.4':
resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3524,10 +3521,6 @@ packages:
resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==}
engines: {node: ^16.0.0 || >=18.0.0}
- '@typescript-eslint/types@8.46.2':
- resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
'@typescript-eslint/types@8.46.4':
resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3545,8 +3538,8 @@ packages:
typescript:
optional: true
- '@typescript-eslint/typescript-estree@8.46.2':
- resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==}
+ '@typescript-eslint/typescript-estree@8.46.4':
+ resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
@@ -3563,8 +3556,8 @@ packages:
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
- '@typescript-eslint/utils@8.46.2':
- resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==}
+ '@typescript-eslint/utils@8.46.4':
+ resolution: {integrity: sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -3581,8 +3574,8 @@ packages:
resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==}
engines: {node: ^16.0.0 || >=18.0.0}
- '@typescript-eslint/visitor-keys@8.46.2':
- resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==}
+ '@typescript-eslint/visitor-keys@8.46.4':
+ resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.47.0':
@@ -10433,10 +10426,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.46.2(typescript@5.9.3)':
+ '@typescript-eslint/project-service@8.46.4(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3)
- '@typescript-eslint/types': 8.46.4
+ '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.47.0
debug: 4.4.1
typescript: 5.9.3
transitivePeerDependencies:
@@ -10456,20 +10449,16 @@ snapshots:
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/visitor-keys': 6.21.0
- '@typescript-eslint/scope-manager@8.46.2':
+ '@typescript-eslint/scope-manager@8.46.4':
dependencies:
- '@typescript-eslint/types': 8.46.2
- '@typescript-eslint/visitor-keys': 8.46.2
+ '@typescript-eslint/types': 8.46.4
+ '@typescript-eslint/visitor-keys': 8.46.4
'@typescript-eslint/scope-manager@8.47.0':
dependencies:
'@typescript-eslint/types': 8.47.0
'@typescript-eslint/visitor-keys': 8.47.0
- '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.9.3)':
- dependencies:
- typescript: 5.9.3
-
'@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
@@ -10504,8 +10493,6 @@ snapshots:
'@typescript-eslint/types@6.21.0': {}
- '@typescript-eslint/types@8.46.2': {}
-
'@typescript-eslint/types@8.46.4': {}
'@typescript-eslint/types@8.47.0': {}
@@ -10525,12 +10512,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.46.2(typescript@5.9.3)':
+ '@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/project-service': 8.46.2(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.9.3)
- '@typescript-eslint/types': 8.46.2
- '@typescript-eslint/visitor-keys': 8.46.2
+ '@typescript-eslint/project-service': 8.46.4(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3)
+ '@typescript-eslint/types': 8.46.4
+ '@typescript-eslint/visitor-keys': 8.46.4
debug: 4.4.1
fast-glob: 3.3.3
is-glob: 4.0.3
@@ -10571,13 +10558,13 @@ snapshots:
- supports-color
- typescript
- '@typescript-eslint/utils@8.46.2(eslint@9.35.0(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/utils@8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.46.2
- '@typescript-eslint/types': 8.46.2
- '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3)
- eslint: 9.35.0(jiti@2.6.1)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1))
+ '@typescript-eslint/scope-manager': 8.46.4
+ '@typescript-eslint/types': 8.46.4
+ '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3)
+ eslint: 9.39.1(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -10598,9 +10585,9 @@ snapshots:
'@typescript-eslint/types': 6.21.0
eslint-visitor-keys: 3.4.3
- '@typescript-eslint/visitor-keys@8.46.2':
+ '@typescript-eslint/visitor-keys@8.46.4':
dependencies:
- '@typescript-eslint/types': 8.46.2
+ '@typescript-eslint/types': 8.46.4
eslint-visitor-keys: 4.2.1
'@typescript-eslint/visitor-keys@8.47.0':
@@ -10638,15 +10625,6 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.2))(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))':
- dependencies:
- '@vitest/spy': 3.2.4
- estree-walker: 3.0.3
- magic-string: 0.30.19
- optionalDependencies:
- msw: 2.12.4(@types/node@24.10.1)(typescript@5.9.2)
- vite: 7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
-
'@vitest/mocker@3.2.4(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))':
dependencies:
'@vitest/spy': 3.2.4
@@ -10723,19 +10701,6 @@ snapshots:
de-indent: 1.0.2
he: 1.2.0
- '@vue/language-core@2.2.0(typescript@5.9.2)':
- dependencies:
- '@volar/language-core': 2.4.14
- '@vue/compiler-dom': 3.5.14
- '@vue/compiler-vue2': 2.7.16
- '@vue/shared': 3.5.14
- alien-signals: 0.4.14
- minimatch: 9.0.5
- muggle-string: 0.4.1
- path-browserify: 1.0.1
- optionalDependencies:
- typescript: 5.9.2
-
'@vue/language-core@2.2.0(typescript@5.9.3)':
dependencies:
'@volar/language-core': 2.4.14
@@ -11815,10 +11780,10 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
- eslint-plugin-storybook@9.1.16(eslint@9.35.0(jiti@2.6.1))(storybook@9.1.16(@testing-library/dom@10.4.0)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(prettier@3.6.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)))(typescript@5.9.3):
+ eslint-plugin-storybook@9.1.16(eslint@9.39.1(jiti@2.6.1))(storybook@9.1.16(@testing-library/dom@10.4.0)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(prettier@3.6.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/utils': 8.46.2(eslint@9.35.0(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.35.0(jiti@2.6.1)
+ '@typescript-eslint/utils': 8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.39.1(jiti@2.6.1)
storybook: 9.1.16(@testing-library/dom@10.4.0)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(prettier@3.6.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))
transitivePeerDependencies:
- supports-color
@@ -13344,32 +13309,6 @@ snapshots:
ms@2.1.3: {}
- msw@2.12.4(@types/node@24.10.1)(typescript@5.9.2):
- dependencies:
- '@inquirer/confirm': 5.1.10(@types/node@24.10.1)
- '@mswjs/interceptors': 0.40.0
- '@open-draft/deferred-promise': 2.2.0
- '@types/statuses': 2.0.6
- cookie: 1.0.2
- graphql: 16.12.0
- headers-polyfill: 4.0.3
- is-node-process: 1.2.0
- outvariant: 1.4.3
- path-to-regexp: 6.3.0
- picocolors: 1.1.1
- rettime: 0.7.0
- statuses: 2.0.2
- strict-event-emitter: 0.5.1
- tough-cookie: 6.0.0
- type-fest: 5.3.0
- until-async: 3.0.2
- yargs: 17.7.2
- optionalDependencies:
- typescript: 5.9.2
- transitivePeerDependencies:
- - '@types/node'
- optional: true
-
msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3):
dependencies:
'@inquirer/confirm': 5.1.10(@types/node@24.10.1)
@@ -14806,25 +14745,6 @@ snapshots:
- tsx
- yaml
- vite-plugin-dts@4.5.4(@types/node@24.10.1)(rollup@4.50.1)(typescript@5.9.2)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)):
- dependencies:
- '@microsoft/api-extractor': 7.52.8(@types/node@24.10.1)
- '@rollup/pluginutils': 5.3.0(rollup@4.50.1)
- '@volar/typescript': 2.4.14
- '@vue/language-core': 2.2.0(typescript@5.9.2)
- compare-versions: 6.1.1
- debug: 4.4.1
- kolorist: 1.8.0
- local-pkg: 1.1.1
- magic-string: 0.30.19
- typescript: 5.9.2
- optionalDependencies:
- vite: 7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
- transitivePeerDependencies:
- - '@types/node'
- - rollup
- - supports-color
-
vite-plugin-dts@4.5.4(@types/node@24.10.1)(rollup@4.50.1)(typescript@5.9.3)(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)):
dependencies:
'@microsoft/api-extractor': 7.52.8(@types/node@24.10.1)
@@ -14892,50 +14812,6 @@ snapshots:
tsx: 4.19.4
yaml: 2.8.0
- vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.2))(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0):
- dependencies:
- '@types/chai': 5.2.2
- '@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.2))(vite@7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))
- '@vitest/pretty-format': 3.2.4
- '@vitest/runner': 3.2.4
- '@vitest/snapshot': 3.2.4
- '@vitest/spy': 3.2.4
- '@vitest/utils': 3.2.4
- chai: 5.2.0
- debug: 4.4.1
- expect-type: 1.2.1
- magic-string: 0.30.19
- pathe: 2.0.3
- picomatch: 4.0.3
- std-env: 3.9.0
- tinybench: 2.9.0
- tinyexec: 0.3.2
- tinyglobby: 0.2.15
- tinypool: 1.1.1
- tinyrainbow: 2.0.0
- vite: 7.2.7(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
- vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)
- why-is-node-running: 2.3.0
- optionalDependencies:
- '@types/debug': 4.1.12
- '@types/node': 24.10.1
- '@vitest/ui': 3.2.4(vitest@3.2.4)
- jsdom: 26.1.0
- transitivePeerDependencies:
- - jiti
- - less
- - lightningcss
- - msw
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - yaml
-
vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@24.10.1)(typescript@5.9.3))(sass@1.81.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0):
dependencies:
'@types/chai': 5.2.2