diff --git a/.changeset/many-jars-obey.md b/.changeset/many-jars-obey.md
new file mode 100644
index 000000000..e29a6396a
--- /dev/null
+++ b/.changeset/many-jars-obey.md
@@ -0,0 +1,5 @@
+---
+"heureka-next": minor
+---
+
+The app is now able to communicate with the GraphQL backend.
diff --git a/.github/workflows/deploy-pr-preview.yaml b/.github/workflows/deploy-pr-preview.yaml
index 2b0a95983..a35914a70 100644
--- a/.github/workflows/deploy-pr-preview.yaml
+++ b/.github/workflows/deploy-pr-preview.yaml
@@ -155,7 +155,7 @@ jobs:
env:
PACKAGE_PATH: apps/heureka-next
TARGET_FOLDER: heureka_next
- APP_PROPS_BASE64: ${{ secrets.HEUREKA_NEXT_APP_PROPS_BASE64 }}
+ APP_PROPS_BASE64: ${{ secrets.HEUREKA_APP_PROPS_BASE64 }}
continue-on-error: true
- name: Generate index.html for Deployed Apps
diff --git a/apps/heureka-next/.env.template b/apps/heureka-next/.env.template
new file mode 100644
index 000000000..fb4bb7b4a
--- /dev/null
+++ b/apps/heureka-next/.env.template
@@ -0,0 +1,6 @@
+#
+# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
+# SPDX-License-Identifier: Apache-2.0
+#
+
+API_ENDPOINT=SOME_URL
diff --git a/apps/heureka-next/README.md b/apps/heureka-next/README.md
index c766d74ca..3ae20a200 100644
--- a/apps/heureka-next/README.md
+++ b/apps/heureka-next/README.md
@@ -4,6 +4,52 @@
This app will eventually become a successor to the existing Heureka app.
+## How to run locally?
+
+1. Go to app directory:
+ ```bash
+ cd apps/heureka-next
+ ```
+2. If you are running the app for the first time, follow these steps. Otherwise, skip to step 3:
+ 1. Create `appProps.json` and change the configurations accordingly:
+ ```bash
+ cp appProps.template.json appProps.json
+ ```
+ 2. Create `.env` file and change configurations accordingly:
+ ```bash
+ cp .env.template .env
+ ```
+3. Install dependencies:
+ ```bash
+ npm i
+ ```
+4. Run the development server:
+ ```bash
+ npm run dev
+ ```
+
+## How to update GraphQL types?
+
+1. Go to app directory:
+ ```bash
+ cd apps/heureka-next
+ ```
+2. Update GraphQL types from the latest GraphQL schema:
+ ```bash
+ npm run generate:types
+ ```
+
+## How to run tests?
+
+1. Go to app directory:
+ ```bash
+ cd apps/heureka-next
+ ```
+2. Run tests:
+ ```bash
+ npm run test
+ ```
+
## Contributing
We welcome contributions from the community. Please follow our [contribution guidelines] to contribute to this project.
diff --git a/apps/heureka-next/appProps.template.json b/apps/heureka-next/appProps.template.json
new file mode 100644
index 000000000..1da480a0f
--- /dev/null
+++ b/apps/heureka-next/appProps.template.json
@@ -0,0 +1,5 @@
+{
+ "apiEndpoint": "YOUR_GRAPHQL_API_ENDPOINT",
+ "embedded": false,
+ "theme": "light"
+}
diff --git a/apps/heureka-next/codegen.ts b/apps/heureka-next/codegen.ts
new file mode 100644
index 000000000..84fcd2221
--- /dev/null
+++ b/apps/heureka-next/codegen.ts
@@ -0,0 +1,23 @@
+import { CodegenConfig } from "@graphql-codegen/cli"
+import * as dotenv from "dotenv"
+
+// Load environment variables from .env file
+dotenv.config()
+
+const config: CodegenConfig = {
+ schema: process.env.API_ENDPOINT,
+ documents: "src/**/*.graphql",
+
+ generates: {
+ "src/generated/graphql.tsx": {
+ plugins: ["typescript", "typescript-operations", "typescript-react-apollo"],
+ config: {
+ withHooks: true,
+ withHOC: false,
+ withComponent: false,
+ },
+ },
+ },
+}
+
+export default config
diff --git a/apps/heureka-next/index.html b/apps/heureka-next/index.html
index ecbf0f5d8..d00de00ad 100644
--- a/apps/heureka-next/index.html
+++ b/apps/heureka-next/index.html
@@ -7,6 +7,19 @@
Heureka Next
+
diff --git a/apps/heureka-next/package.json b/apps/heureka-next/package.json
index c996166ca..91eedd02f 100644
--- a/apps/heureka-next/package.json
+++ b/apps/heureka-next/package.json
@@ -17,6 +17,7 @@
"dev": "vite",
"build": "vite build",
"build:static": "vite build --mode static",
+ "generate:types": "graphql-codegen --config codegen.ts",
"serve": "vite preview",
"test": "vitest run",
"lint": "eslint",
@@ -31,6 +32,11 @@
"react-dom": "18.3.1"
},
"devDependencies": {
+ "@apollo/client": "^3.11.10",
+ "@graphql-codegen/cli": "^5.0.3",
+ "@graphql-codegen/typescript": "^4.1.2",
+ "@graphql-codegen/typescript-operations": "^4.4.0",
+ "@graphql-codegen/typescript-react-apollo": "^4.3.2",
"@cloudoperators/juno-config": "*",
"@testing-library/jest-dom": "6.6.3",
"@testing-library/react": "16.2.0",
diff --git a/apps/heureka-next/src/App.tsx b/apps/heureka-next/src/App.tsx
index b85b74823..3966ffc38 100644
--- a/apps/heureka-next/src/App.tsx
+++ b/apps/heureka-next/src/App.tsx
@@ -7,16 +7,23 @@ import React from "react"
import { AppShellProvider } from "@cloudoperators/juno-ui-components"
import { ErrorBoundary } from "./components/ErrorBoundary"
import { Shell } from "./components/Shell"
+import { ApolloProvider } from "@apollo/client"
+import { getClient } from "./apollo-client"
export type AppProps = {
theme?: "theme-dark" | "theme-light"
+ apiEndpoint?: string
embedded?: boolean
}
-export const App = (props: AppProps) => (
-
-
-
-
-
+const App = (props: AppProps) => (
+
+
+
+
+
+
+
)
+
+export default App
diff --git a/apps/heureka-next/src/apollo-client.ts b/apps/heureka-next/src/apollo-client.ts
new file mode 100644
index 000000000..415948fb9
--- /dev/null
+++ b/apps/heureka-next/src/apollo-client.ts
@@ -0,0 +1,15 @@
+import { ApolloClient, InMemoryCache } from "@apollo/client"
+
+type ClientOptions = {
+ uri?: string
+}
+
+export const getClient = ({ uri }: ClientOptions) => {
+ if (typeof uri === "undefined") {
+ throw new Error("No API endpoint provided.")
+ }
+ return new ApolloClient({
+ uri,
+ cache: new InMemoryCache(),
+ })
+}
diff --git a/apps/heureka-next/src/components/Services/Services.test.tsx b/apps/heureka-next/src/components/Services/Services.test.tsx
index dc443c2fb..56bd1f50a 100644
--- a/apps/heureka-next/src/components/Services/Services.test.tsx
+++ b/apps/heureka-next/src/components/Services/Services.test.tsx
@@ -5,11 +5,42 @@
import React from "react"
import { render, screen } from "@testing-library/react"
+import { MockedProvider } from "@apollo/client/testing"
import { Services } from "./Services"
+import { GetServicesDocument } from "../../generated/graphql"
+
+const mocks = [
+ {
+ request: {
+ query: GetServicesDocument,
+ },
+ result: {
+ data: {
+ Services: {
+ edges: [
+ {
+ node: {
+ id: "some-id",
+ ccrn: "some-ccrn",
+ __typename: "Service",
+ },
+ __typename: "ServiceEdge",
+ },
+ ],
+ __typename: "ServiceConnection",
+ },
+ },
+ },
+ },
+]
describe("Services", () => {
- it("should render correctly", () => {
- render()
- expect(screen.getByText("render services here...")).toBeInTheDocument()
+ it("should render correctly", async () => {
+ render(
+
+
+
+ )
+ expect(await screen.findByText("some-ccrn")).toBeInTheDocument()
})
})
diff --git a/apps/heureka-next/src/components/Services/Services.tsx b/apps/heureka-next/src/components/Services/Services.tsx
index 76a9d9d55..4e2d4577f 100644
--- a/apps/heureka-next/src/components/Services/Services.tsx
+++ b/apps/heureka-next/src/components/Services/Services.tsx
@@ -4,5 +4,12 @@
*/
import React from "react"
+import { useGetServicesQuery } from "../../generated/graphql"
-export const Services = () => render services here...
+export const Services = () => {
+ const { data, loading, error } = useGetServicesQuery()
+ if (loading) return Loading...
+ if (error) return Error
+
+ return {data?.Services?.edges?.map((service) =>
{service?.node.ccrn}
)}
+}
diff --git a/apps/heureka-next/src/components/Shell/Shell.test.tsx b/apps/heureka-next/src/components/Shell/Shell.test.tsx
index 16574646f..094431628 100644
--- a/apps/heureka-next/src/components/Shell/Shell.test.tsx
+++ b/apps/heureka-next/src/components/Shell/Shell.test.tsx
@@ -6,15 +6,46 @@
import React from "react"
import { render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
+import { MockedProvider } from "@apollo/client/testing"
import { Shell } from "./Shell"
+import { GetServicesDocument } from "../../generated/graphql"
+
+const mocks = [
+ {
+ request: {
+ query: GetServicesDocument,
+ },
+ result: {
+ data: {
+ Services: {
+ edges: [
+ {
+ node: {
+ id: "some-id",
+ ccrn: "some-ccrn",
+ __typename: "Service",
+ },
+ __typename: "ServiceEdge",
+ },
+ ],
+ __typename: "ServiceConnection",
+ },
+ },
+ },
+ },
+]
const renderShell = () => ({
user: userEvent.setup(),
- ...render(),
+ ...render(
+
+
+
+ ),
})
describe("Shell", () => {
- it("should render correctly", () => {
+ it("should render correctly", async () => {
renderShell()
// assert that page header is rendered
expect(screen.getByText("Heureka")).toBeInTheDocument()
@@ -22,17 +53,13 @@ describe("Shell", () => {
expect(screen.getByText("Services")).toBeInTheDocument()
expect(screen.getByText("Vulnerabilities")).toBeInTheDocument()
expect(screen.getByText("Images")).toBeInTheDocument()
- })
-
- it("should render services view by default", () => {
- renderShell()
- expect(screen.getByText("render services here...")).toBeInTheDocument()
+ // assert that the default view 'Services' is rendered
+ expect(await screen.findByText("some-ccrn")).toBeInTheDocument()
})
it("should allow switching to other view", async () => {
const { user } = renderShell()
await user.click(screen.getByText("Vulnerabilities"))
expect(screen.getByText("render vulnerabilities here...")).toBeInTheDocument()
- expect(screen.queryByText("render services here...")).not.toBeInTheDocument()
})
})
diff --git a/apps/heureka-next/src/components/Shell/Shell.tsx b/apps/heureka-next/src/components/Shell/Shell.tsx
index 936bcad06..136fa2063 100644
--- a/apps/heureka-next/src/components/Shell/Shell.tsx
+++ b/apps/heureka-next/src/components/Shell/Shell.tsx
@@ -6,14 +6,34 @@
import React, { useState, ReactNode } from "react"
import { AppShell, Container, PageHeader } from "@cloudoperators/juno-ui-components"
import { MessagesProvider, Messages } from "@cloudoperators/juno-messages-provider"
-import { Navigation } from "../Navigation"
-import { ShellContent } from "./ShellContent"
-import { AppProps } from "../../App"
-import { SERVICES } from "../../constants"
import styles from "../../styles.scss?inline"
+import { Navigation } from "../Navigation"
+import { IMAGES, SERVICES, VULNERABILITIES } from "../../constants"
+import { Services } from "../Services"
+import { Vulnerabilities } from "../Vulnerabilities"
+import { Images } from "../Images"
+
+const getViewComponent = (selectedView: ReactNode) => {
+ switch (selectedView) {
+ case SERVICES:
+ return Services
+ case VULNERABILITIES:
+ return Vulnerabilities
+ case IMAGES:
+ return Images
+ default:
+ return () => null
+ }
+}
+
+type ShellProps = {
+ embedded?: boolean
+ defaultSelectedView?: ReactNode
+}
-export const Shell = ({ embedded }: AppProps) => {
- const [selectedView, setSelectedView] = useState(SERVICES)
+export const Shell = ({ embedded, defaultSelectedView = SERVICES }: ShellProps) => {
+ const [selectedView, setSelectedView] = useState(defaultSelectedView)
+ const SelectedViewComponent = getViewComponent(selectedView)
return (
{
-
+
>
diff --git a/apps/heureka-next/src/components/Shell/ShellContent/ShellContent.tsx b/apps/heureka-next/src/components/Shell/ShellContent/ShellContent.tsx
deleted file mode 100644
index adfd67108..000000000
--- a/apps/heureka-next/src/components/Shell/ShellContent/ShellContent.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 { SERVICES, IMAGES, VULNERABILITIES } from "../../../constants"
-import { Services } from "../../Services"
-import { Vulnerabilities } from "../../Vulnerabilities"
-import { Images } from "../../Images"
-
-export const ShellContent = ({ selectedView }: { selectedView: ReactNode }) => {
- switch (selectedView) {
- case SERVICES:
- return
- case VULNERABILITIES:
- return
- case IMAGES:
- return
- default:
- return null
- }
-}
diff --git a/apps/heureka-next/src/components/Shell/ShellContent/index.ts b/apps/heureka-next/src/components/Shell/ShellContent/index.ts
deleted file mode 100644
index 4f4cc6694..000000000
--- a/apps/heureka-next/src/components/Shell/ShellContent/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-export { ShellContent } from "./ShellContent"
diff --git a/apps/heureka-next/src/generated/graphql.tsx b/apps/heureka-next/src/generated/graphql.tsx
new file mode 100644
index 000000000..01a5e5dc5
--- /dev/null
+++ b/apps/heureka-next/src/generated/graphql.tsx
@@ -0,0 +1,1414 @@
+import { gql } from "@apollo/client"
+import * as Apollo from "@apollo/client"
+export type Maybe = T | null
+export type InputMaybe = Maybe
+export type Exact = { [K in keyof T]: T[K] }
+export type MakeOptional = Omit & { [SubKey in K]?: Maybe }
+export type MakeMaybe = Omit & { [SubKey in K]: Maybe }
+export type MakeEmpty = { [_ in K]?: never }
+export type Incremental = T | { [P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never }
+const defaultOptions = {} as const
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+ ID: { input: string; output: string }
+ String: { input: string; output: string }
+ Boolean: { input: boolean; output: boolean }
+ Int: { input: number; output: number }
+ Float: { input: number; output: number }
+ DateTime: { input: any; output: any }
+}
+
+export type Activity = Node & {
+ __typename?: "Activity"
+ evidences?: Maybe
+ id: Scalars["ID"]["output"]
+ issueMatchChanges?: Maybe
+ issues?: Maybe
+ metadata?: Maybe
+ services?: Maybe
+ status?: Maybe
+}
+
+export type ActivityEvidencesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ActivityIssueMatchChangesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ActivityIssuesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ActivityServicesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ActivityConnection = Connection & {
+ __typename?: "ActivityConnection"
+ edges?: Maybe>>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type ActivityEdge = Edge & {
+ __typename?: "ActivityEdge"
+ cursor?: Maybe
+ metadata?: Maybe
+ node: Activity
+}
+
+export type ActivityFilter = {
+ serviceCcrn?: InputMaybe>>
+ status?: InputMaybe>>
+}
+
+export type ActivityInput = {
+ status?: InputMaybe
+}
+
+export enum ActivityStatusValues {
+ Closed = "closed",
+ InProgress = "in_progress",
+ Open = "open",
+}
+
+export type Cvss = {
+ __typename?: "CVSS"
+ base?: Maybe
+ environmental?: Maybe
+ temporal?: Maybe
+ vector?: Maybe
+}
+
+export type CvssBase = {
+ __typename?: "CVSSBase"
+ attackComplexity?: Maybe
+ attackVector?: Maybe
+ availabilityImpact?: Maybe
+ confidentialityImpact?: Maybe
+ integrityImpact?: Maybe
+ privilegesRequired?: Maybe
+ scope?: Maybe
+ score?: Maybe
+ userInteraction?: Maybe
+}
+
+export type CvssEnvironmental = {
+ __typename?: "CVSSEnvironmental"
+ availabilityRequirement?: Maybe
+ confidentialityRequirement?: Maybe
+ integrityRequirement?: Maybe
+ modifiedAttackComplexity?: Maybe
+ modifiedAttackVector?: Maybe
+ modifiedAvailabilityImpact?: Maybe
+ modifiedConfidentialityImpact?: Maybe
+ modifiedIntegrityImpact?: Maybe
+ modifiedPrivilegesRequired?: Maybe
+ modifiedScope?: Maybe
+ modifiedUserInteraction?: Maybe
+ score?: Maybe
+}
+
+export type CvssParameter = {
+ __typename?: "CVSSParameter"
+ name?: Maybe
+ value?: Maybe
+}
+
+export type CvssTemporal = {
+ __typename?: "CVSSTemporal"
+ exploitCodeMaturity?: Maybe
+ remediationLevel?: Maybe
+ reportConfidence?: Maybe
+ score?: Maybe
+}
+
+export type Component = Node & {
+ __typename?: "Component"
+ ccrn?: Maybe
+ componentVersions?: Maybe
+ id: Scalars["ID"]["output"]
+ metadata?: Maybe
+ type?: Maybe
+}
+
+export type ComponentComponentVersionsArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ComponentConnection = Connection & {
+ __typename?: "ComponentConnection"
+ edges?: Maybe>>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type ComponentEdge = Edge & {
+ __typename?: "ComponentEdge"
+ cursor?: Maybe
+ node: Component
+}
+
+export type ComponentFilter = {
+ componentCcrn?: InputMaybe>>
+}
+
+export type ComponentFilterValue = {
+ __typename?: "ComponentFilterValue"
+ componentCcrn?: Maybe
+}
+
+export type ComponentFilterValueComponentCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type ComponentInput = {
+ ccrn?: InputMaybe
+ type?: InputMaybe
+}
+
+export type ComponentInstance = Node & {
+ __typename?: "ComponentInstance"
+ ccrn?: Maybe
+ componentVersion?: Maybe
+ componentVersionId?: Maybe
+ count?: Maybe
+ id: Scalars["ID"]["output"]
+ issueMatches?: Maybe
+ metadata?: Maybe
+ service?: Maybe
+ serviceId?: Maybe
+}
+
+export type ComponentInstanceIssueMatchesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ComponentInstanceConnection = Connection & {
+ __typename?: "ComponentInstanceConnection"
+ edges: Array>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type ComponentInstanceEdge = Edge & {
+ __typename?: "ComponentInstanceEdge"
+ cursor?: Maybe
+ node: ComponentInstance
+}
+
+export type ComponentInstanceFilter = {
+ ccrn?: InputMaybe>>
+ search?: InputMaybe>>
+ serviceCcrn?: InputMaybe>>
+ supportGroup?: InputMaybe>>
+}
+
+export type ComponentInstanceFilterValue = {
+ __typename?: "ComponentInstanceFilterValue"
+ ccrn?: Maybe
+ serviceCcrn?: Maybe
+ supportGroupCcrn?: Maybe
+}
+
+export type ComponentInstanceFilterValueCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type ComponentInstanceFilterValueServiceCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type ComponentInstanceFilterValueSupportGroupCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type ComponentInstanceInput = {
+ ccrn?: InputMaybe
+ componentVersionId?: InputMaybe
+ count?: InputMaybe
+ serviceId?: InputMaybe
+}
+
+export enum ComponentTypeValues {
+ ContainerImage = "containerImage",
+ Repository = "repository",
+ VirtualMachineImage = "virtualMachineImage",
+}
+
+export type ComponentVersion = Node & {
+ __typename?: "ComponentVersion"
+ component?: Maybe
+ componentId?: Maybe
+ componentInstances?: Maybe
+ id: Scalars["ID"]["output"]
+ issues?: Maybe
+ metadata?: Maybe
+ version?: Maybe
+}
+
+export type ComponentVersionComponentInstancesArgs = {
+ after?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ComponentVersionIssuesArgs = {
+ after?: InputMaybe
+ first?: InputMaybe
+}
+
+export type ComponentVersionConnection = Connection & {
+ __typename?: "ComponentVersionConnection"
+ edges: Array>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type ComponentVersionEdge = Edge & {
+ __typename?: "ComponentVersionEdge"
+ cursor?: Maybe
+ node: ComponentVersion
+}
+
+export type ComponentVersionFilter = {
+ componentCcrn?: InputMaybe>>
+ componentId?: InputMaybe>>
+ issueId?: InputMaybe>>
+ version?: InputMaybe>>
+}
+
+export type ComponentVersionInput = {
+ componentId?: InputMaybe
+ version?: InputMaybe
+}
+
+export type Connection = {
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type DateTimeFilter = {
+ after?: InputMaybe
+ before?: InputMaybe
+}
+
+export type Edge = {
+ cursor?: Maybe
+ node: Node
+}
+
+export type Evidence = Node & {
+ __typename?: "Evidence"
+ activity?: Maybe
+ activityId?: Maybe
+ author?: Maybe
+ authorId?: Maybe
+ description?: Maybe
+ id: Scalars["ID"]["output"]
+ issueMatches?: Maybe
+ metadata?: Maybe
+ raaEnd?: Maybe
+ type?: Maybe
+ vector?: Maybe
+}
+
+export type EvidenceIssueMatchesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type EvidenceConnection = Connection & {
+ __typename?: "EvidenceConnection"
+ edges?: Maybe>>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type EvidenceEdge = Edge & {
+ __typename?: "EvidenceEdge"
+ cursor?: Maybe
+ node: Evidence
+}
+
+export type EvidenceFilter = {
+ placeholder?: InputMaybe>>
+}
+
+export type EvidenceInput = {
+ activityId?: InputMaybe
+ authorId?: InputMaybe
+ description?: InputMaybe
+ raaEnd?: InputMaybe
+ severity?: InputMaybe
+ type?: InputMaybe
+}
+
+export type FilterItem = {
+ __typename?: "FilterItem"
+ displayName?: Maybe
+ filterName?: Maybe
+ values?: Maybe>>
+}
+
+export type Issue = Node & {
+ __typename?: "Issue"
+ activities?: Maybe
+ componentVersions?: Maybe
+ description?: Maybe
+ id: Scalars["ID"]["output"]
+ issueMatches?: Maybe
+ issueVariants?: Maybe
+ lastModified?: Maybe
+ metadata?: Maybe
+ objectMetadata?: Maybe
+ primaryName?: Maybe
+ type?: Maybe
+}
+
+export type IssueActivitiesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueComponentVersionsArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueIssueMatchesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueIssueVariantsArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueConnection = Connection & {
+ __typename?: "IssueConnection"
+ edges: Array>
+ pageInfo?: Maybe
+ policyViolationCount: Scalars["Int"]["output"]
+ securityEventCount: Scalars["Int"]["output"]
+ totalCount: Scalars["Int"]["output"]
+ vulnerabilityCount: Scalars["Int"]["output"]
+}
+
+export type IssueEdge = Edge & {
+ __typename?: "IssueEdge"
+ cursor?: Maybe
+ node: Issue
+}
+
+export type IssueFilter = {
+ affectedService?: InputMaybe>>
+ componentVersionId?: InputMaybe>>
+ issueMatchStatus?: InputMaybe>>
+ issueType?: InputMaybe>>
+ primaryName?: InputMaybe>>
+ search?: InputMaybe>>
+}
+
+export type IssueInput = {
+ description?: InputMaybe
+ primaryName?: InputMaybe
+ type?: InputMaybe
+}
+
+export type IssueMatch = Node & {
+ __typename?: "IssueMatch"
+ componentInstance: ComponentInstance
+ componentInstanceId?: Maybe
+ discoveryDate?: Maybe
+ effectiveIssueVariants?: Maybe
+ evidences?: Maybe
+ id: Scalars["ID"]["output"]
+ issue: Issue
+ issueId?: Maybe
+ issueMatchChanges?: Maybe
+ metadata?: Maybe
+ remediationDate?: Maybe
+ severity?: Maybe
+ status?: Maybe
+ targetRemediationDate?: Maybe
+ user?: Maybe
+ userId?: Maybe
+}
+
+export type IssueMatchEffectiveIssueVariantsArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueMatchEvidencesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueMatchIssueMatchChangesArgs = {
+ after?: InputMaybe
+ filter?: InputMaybe
+ first?: InputMaybe
+}
+
+export type IssueMatchChange = Node & {
+ __typename?: "IssueMatchChange"
+ action?: Maybe
+ activity: Activity
+ activityId?: Maybe
+ id: Scalars["ID"]["output"]
+ issueMatch: IssueMatch
+ issueMatchId?: Maybe
+ metadata?: Maybe
+}
+
+export enum IssueMatchChangeActions {
+ Add = "add",
+ Remove = "remove",
+}
+
+export type IssueMatchChangeConnection = Connection & {
+ __typename?: "IssueMatchChangeConnection"
+ edges?: Maybe>>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type IssueMatchChangeEdge = Edge & {
+ __typename?: "IssueMatchChangeEdge"
+ cursor?: Maybe
+ node: IssueMatchChange
+}
+
+export type IssueMatchChangeFilter = {
+ action?: InputMaybe>>
+}
+
+export type IssueMatchChangeInput = {
+ action?: InputMaybe
+ activityId?: InputMaybe
+ issueMatchId?: InputMaybe
+}
+
+export type IssueMatchConnection = Connection & {
+ __typename?: "IssueMatchConnection"
+ edges?: Maybe>>
+ pageInfo?: Maybe
+ totalCount: Scalars["Int"]["output"]
+}
+
+export type IssueMatchEdge = Edge & {
+ __typename?: "IssueMatchEdge"
+ cursor?: Maybe
+ node: IssueMatch
+}
+
+export type IssueMatchFilter = {
+ affectedService?: InputMaybe>>
+ componentCcrn?: InputMaybe>>
+ id?: InputMaybe>>
+ issueType?: InputMaybe>>
+ primaryName?: InputMaybe>>
+ search?: InputMaybe>>
+ severity?: InputMaybe>>
+ status?: InputMaybe>>
+ supportGroupCcrn?: InputMaybe>>
+}
+
+export type IssueMatchFilterValue = {
+ __typename?: "IssueMatchFilterValue"
+ affectedService?: Maybe
+ componentCcrn?: Maybe
+ issueType?: Maybe
+ primaryName?: Maybe
+ severity?: Maybe
+ status?: Maybe
+ supportGroupCcrn?: Maybe
+}
+
+export type IssueMatchFilterValueAffectedServiceArgs = {
+ filter?: InputMaybe
+}
+
+export type IssueMatchFilterValueComponentCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type IssueMatchFilterValuePrimaryNameArgs = {
+ filter?: InputMaybe
+}
+
+export type IssueMatchFilterValueSupportGroupCcrnArgs = {
+ filter?: InputMaybe
+}
+
+export type IssueMatchInput = {
+ componentInstanceId?: InputMaybe
+ discoveryDate?: InputMaybe