mirror of
https://github.com/harness/drone.git
synced 2025-05-06 07:52:58 +00:00
feat: [AH-620]: support generic artifact details view (#3173)
* feat: [AH-620]: support generic artifact details view
This commit is contained in:
parent
aaebea0c5d
commit
2ced78f102
@ -51,7 +51,7 @@
|
|||||||
"@codemirror/view": "^6.9.6",
|
"@codemirror/view": "^6.9.6",
|
||||||
"@harnessio/design-system": "^2.1.1",
|
"@harnessio/design-system": "^2.1.1",
|
||||||
"@harnessio/icons": "^2.1.9",
|
"@harnessio/icons": "^2.1.9",
|
||||||
"@harnessio/react-har-service-client": "^0.2.0",
|
"@harnessio/react-har-service-client": "^0.3.0",
|
||||||
"@harnessio/react-ssca-manager-client": "^0.65.0",
|
"@harnessio/react-ssca-manager-client": "^0.65.0",
|
||||||
"@harnessio/uicore": "^4.1.2",
|
"@harnessio/uicore": "^4.1.2",
|
||||||
"@tanstack/react-query": "4.20.4",
|
"@tanstack/react-query": "4.20.4",
|
||||||
|
@ -25,6 +25,7 @@ import { String } from '@ar/frameworks/strings'
|
|||||||
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
|
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
|
||||||
import GenericVersionHeader from './GenericVersionHeader'
|
import GenericVersionHeader from './GenericVersionHeader'
|
||||||
import GenericOverviewPage from './pages/overview/OverviewPage'
|
import GenericOverviewPage from './pages/overview/OverviewPage'
|
||||||
|
import GenericArtifactDetailsPage from './pages/artifact-details/GenericArtifactDetailsPage'
|
||||||
|
|
||||||
export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
|
export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
|
||||||
protected packageType = RepositoryPackageType.GENERIC
|
protected packageType = RepositoryPackageType.GENERIC
|
||||||
@ -48,7 +49,7 @@ export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
|
|||||||
case VersionDetailsTab.OVERVIEW:
|
case VersionDetailsTab.OVERVIEW:
|
||||||
return <GenericOverviewPage />
|
return <GenericOverviewPage />
|
||||||
case VersionDetailsTab.ARTIFACT_DETAILS:
|
case VersionDetailsTab.ARTIFACT_DETAILS:
|
||||||
return <></>
|
return <GenericArtifactDetailsPage />
|
||||||
case VersionDetailsTab.DEPLOYMENTS:
|
case VersionDetailsTab.DEPLOYMENTS:
|
||||||
return <></>
|
return <></>
|
||||||
case VersionDetailsTab.OSS:
|
case VersionDetailsTab.OSS:
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Page } from '@harnessio/uicore'
|
||||||
|
import { useGetArtifactFilesQuery } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
|
import { DEFAULT_PAGE_INDEX } from '@ar/constants'
|
||||||
|
import type { VersionDetailsPathParams } from '@ar/routes/types'
|
||||||
|
import { useDecodedParams, useGetSpaceRef, useParentHooks } from '@ar/hooks'
|
||||||
|
import {
|
||||||
|
type ArtifactFileListPageQueryParams,
|
||||||
|
useArtifactFileListQueryParamOptions
|
||||||
|
} from '@ar/pages/version-details/components/ArtifactFileListTable/utils'
|
||||||
|
import ArtifactFileListTable from '@ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable'
|
||||||
|
import versionDetailsPageCss from '../../styles.module.scss'
|
||||||
|
|
||||||
|
export default function GenericArtifactDetailsPage() {
|
||||||
|
const registryRef = useGetSpaceRef()
|
||||||
|
const { useQueryParams, useUpdateQueryParams } = useParentHooks()
|
||||||
|
const { updateQueryParams } = useUpdateQueryParams<Partial<ArtifactFileListPageQueryParams>>()
|
||||||
|
|
||||||
|
const pathParams = useDecodedParams<VersionDetailsPathParams>()
|
||||||
|
const queryParamOptions = useArtifactFileListQueryParamOptions()
|
||||||
|
const queryParams = useQueryParams<ArtifactFileListPageQueryParams>(queryParamOptions)
|
||||||
|
const { searchTerm, page, size, sort } = queryParams
|
||||||
|
|
||||||
|
const [sortField, sortOrder] = sort || []
|
||||||
|
|
||||||
|
const {
|
||||||
|
isFetching: loading,
|
||||||
|
error,
|
||||||
|
data,
|
||||||
|
refetch
|
||||||
|
} = useGetArtifactFilesQuery({
|
||||||
|
registry_ref: registryRef,
|
||||||
|
artifact: pathParams.artifactIdentifier,
|
||||||
|
version: pathParams.versionIdentifier,
|
||||||
|
queryParams: {
|
||||||
|
searchTerm,
|
||||||
|
page,
|
||||||
|
size,
|
||||||
|
sortField,
|
||||||
|
sortOrder
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const response = data?.content
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page.Body
|
||||||
|
className={versionDetailsPageCss.pageBody}
|
||||||
|
loading={loading}
|
||||||
|
error={error?.message || error}
|
||||||
|
retryOnError={() => refetch()}>
|
||||||
|
{response && (
|
||||||
|
<ArtifactFileListTable
|
||||||
|
data={response}
|
||||||
|
gotoPage={pageNumber => updateQueryParams({ page: pageNumber })}
|
||||||
|
setSortBy={sortArr => {
|
||||||
|
updateQueryParams({ sort: sortArr, page: DEFAULT_PAGE_INDEX })
|
||||||
|
}}
|
||||||
|
sortBy={sort}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Page.Body>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.table {
|
||||||
|
--typography-size: 12px;
|
||||||
|
--typography-weight: 400;
|
||||||
|
--line-height: 20px;
|
||||||
|
padding: var(--spacing-large);
|
||||||
|
|
||||||
|
[role='cell'],
|
||||||
|
[role='columnheader'] {
|
||||||
|
width: auto !important;
|
||||||
|
padding-right: var(--spacing-large);
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class*='TableV2--cells'],
|
||||||
|
div[class*='TableV2--header'] {
|
||||||
|
display: grid !important;
|
||||||
|
width: 100%; /* Ensure the container doesn't exceed 100% width */
|
||||||
|
grid-template-columns: minmax(var(--har-table-name-column-min-width), 15rem) 80px 350px minmax(0, 1fr) 100px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
// This is an auto-generated file
|
||||||
|
export declare const table: string
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import type { Column } from 'react-table'
|
||||||
|
import { type PaginationProps, TableV2 } from '@harnessio/uicore'
|
||||||
|
import type { FileDetail, FileDetailResponseResponse } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
|
import { useParentHooks } from '@ar/hooks'
|
||||||
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
|
import {
|
||||||
|
FileChecksumListCell,
|
||||||
|
FileCreatedCell,
|
||||||
|
FileDownloadCommandCell,
|
||||||
|
FileNameCell,
|
||||||
|
FileSizeCell
|
||||||
|
} from './ArtifactListTableCells'
|
||||||
|
|
||||||
|
import css from './ArtifactFileListTable.module.scss'
|
||||||
|
|
||||||
|
export interface FileListSortBy {
|
||||||
|
sort: 'name' | 'size' | 'created'
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArtifactFileListTableProps {
|
||||||
|
data: FileDetailResponseResponse
|
||||||
|
gotoPage: (pageNumber: number) => void
|
||||||
|
onPageSizeChange?: PaginationProps['onPageSizeChange']
|
||||||
|
setSortBy: (sortBy: string[]) => void
|
||||||
|
sortBy: string[]
|
||||||
|
minimal?: boolean
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ArtifactFileListTable(props: ArtifactFileListTableProps): JSX.Element {
|
||||||
|
const { data, gotoPage, onPageSizeChange, sortBy, setSortBy, className } = props
|
||||||
|
const { useDefaultPaginationProps } = useParentHooks()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
|
||||||
|
const { files } = data
|
||||||
|
const paginationProps = useDefaultPaginationProps({
|
||||||
|
itemCount: 0,
|
||||||
|
pageSize: 100,
|
||||||
|
pageCount: 1,
|
||||||
|
pageIndex: 1,
|
||||||
|
gotoPage,
|
||||||
|
onPageSizeChange
|
||||||
|
})
|
||||||
|
|
||||||
|
const [currentSort, currentOrder] = sortBy
|
||||||
|
|
||||||
|
const columns: Column<FileDetail>[] = React.useMemo(() => {
|
||||||
|
const getServerSortProps = (id: string) => {
|
||||||
|
return {
|
||||||
|
enableServerSort: true,
|
||||||
|
isServerSorted: currentSort === id,
|
||||||
|
isServerSortedDesc: currentOrder === 'DESC',
|
||||||
|
getSortedColumn: ({ sort }: FileListSortBy) => {
|
||||||
|
setSortBy([sort, currentOrder === 'DESC' ? 'ASC' : 'DESC'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
Header: getString('versionDetails.artifactFiles.table.columns.name'),
|
||||||
|
accessor: 'name',
|
||||||
|
Cell: FileNameCell,
|
||||||
|
serverSortProps: getServerSortProps('name'),
|
||||||
|
width: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: getString('versionDetails.artifactFiles.table.columns.size'),
|
||||||
|
accessor: 'size',
|
||||||
|
Cell: FileSizeCell,
|
||||||
|
serverSortProps: getServerSortProps('size')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: getString('versionDetails.artifactFiles.table.columns.checksum'),
|
||||||
|
accessor: 'checksums',
|
||||||
|
Cell: FileChecksumListCell,
|
||||||
|
disableSortBy: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: getString('versionDetails.artifactFiles.table.columns.downloadCommand'),
|
||||||
|
accessor: 'downloadCommand',
|
||||||
|
Cell: FileDownloadCommandCell,
|
||||||
|
disableSortBy: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: getString('versionDetails.artifactFiles.table.columns.created'),
|
||||||
|
accessor: 'createdAt',
|
||||||
|
Cell: FileCreatedCell,
|
||||||
|
serverSortProps: getServerSortProps('createdAt')
|
||||||
|
}
|
||||||
|
].filter(Boolean) as unknown as Column<FileDetail>[]
|
||||||
|
}, [currentOrder, currentSort, getString])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableV2
|
||||||
|
className={classNames(css.table, className)}
|
||||||
|
columns={columns}
|
||||||
|
data={files as FileDetail[]}
|
||||||
|
pagination={paginationProps}
|
||||||
|
sortable
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Layout } from '@harnessio/uicore'
|
||||||
|
import type { FileDetail } from '@harnessio/react-har-service-client'
|
||||||
|
import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } from 'react-table'
|
||||||
|
|
||||||
|
import { killEvent } from '@ar/common/utils'
|
||||||
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
|
import TableCells from '@ar/components/TableCells/TableCells'
|
||||||
|
import CommandBlock from '@ar/components/CommandBlock/CommandBlock'
|
||||||
|
|
||||||
|
type CellTypeWithActions<D extends Record<string, any>, V = any> = TableInstance<D> & {
|
||||||
|
column: ColumnInstance<D>
|
||||||
|
row: Row<D>
|
||||||
|
cell: Cell<D, V>
|
||||||
|
value: CellValue<V>
|
||||||
|
}
|
||||||
|
|
||||||
|
type CellType = Renderer<CellTypeWithActions<FileDetail>>
|
||||||
|
|
||||||
|
export const FileNameCell: CellType = ({ value }) => {
|
||||||
|
return <TableCells.TextCell value={value} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileSizeCell: CellType = ({ value }) => {
|
||||||
|
return <TableCells.SizeCell value={value} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileChecksumListCell: CellType = ({ value }) => {
|
||||||
|
const { getString } = useStrings()
|
||||||
|
if (Array.isArray(value) && value.length) {
|
||||||
|
return (
|
||||||
|
<Layout.Vertical spacing="xsmall">
|
||||||
|
{value.map(each => (
|
||||||
|
<TableCells.TextCell key={each} value={each} />
|
||||||
|
))}
|
||||||
|
</Layout.Vertical>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <TableCells.TextCell value={getString('na')} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileCreatedCell: CellType = ({ value }) => {
|
||||||
|
return <TableCells.LastModifiedCell value={value} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileDownloadCommandCell: CellType = ({ value }) => {
|
||||||
|
const { getString } = useStrings()
|
||||||
|
if (!value) return <TableCells.TextCell value={getString('na')} />
|
||||||
|
return <CommandBlock noWrap commandSnippet={value} allowCopy onCopy={killEvent} />
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
|
import { useParentHooks } from '@ar/hooks'
|
||||||
|
import { DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE, DEFAULT_PIPELINE_LIST_TABLE_SORT } from '@ar/constants'
|
||||||
|
import type { UseQueryParamsOptions } from '@ar/__mocks__/hooks'
|
||||||
|
|
||||||
|
export type ArtifactFileListPageQueryParams = {
|
||||||
|
page: number
|
||||||
|
size: number
|
||||||
|
sort: string[]
|
||||||
|
searchTerm?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useArtifactFileListQueryParamOptions = (): UseQueryParamsOptions<ArtifactFileListPageQueryParams> => {
|
||||||
|
const { useQueryParamsOptions } = useParentHooks()
|
||||||
|
const _options = useQueryParamsOptions(
|
||||||
|
{
|
||||||
|
page: DEFAULT_PAGE_INDEX,
|
||||||
|
size: DEFAULT_PAGE_SIZE,
|
||||||
|
sort: DEFAULT_PIPELINE_LIST_TABLE_SORT
|
||||||
|
},
|
||||||
|
{ ignoreEmptyString: false }
|
||||||
|
)
|
||||||
|
const options = useMemo(() => ({ ..._options, strictNullHandling: true }), [_options])
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
@ -73,3 +73,11 @@ deploymentsTable:
|
|||||||
triggeredBy: Triggered At
|
triggeredBy: Triggered At
|
||||||
infra: Infrastructure
|
infra: Infrastructure
|
||||||
instanceCount: Instance Count
|
instanceCount: Instance Count
|
||||||
|
artifactFiles:
|
||||||
|
table:
|
||||||
|
columns:
|
||||||
|
name: Name
|
||||||
|
size: Size
|
||||||
|
checksum: Checksum
|
||||||
|
downloadCommand: Download Command
|
||||||
|
created: Created
|
||||||
|
@ -152,6 +152,11 @@ export interface StringsMap {
|
|||||||
'versionDetails.artifactDetails.layers.size': string
|
'versionDetails.artifactDetails.layers.size': string
|
||||||
'versionDetails.artifactDetails.tabs.layers': string
|
'versionDetails.artifactDetails.tabs.layers': string
|
||||||
'versionDetails.artifactDetails.tabs.manifest': string
|
'versionDetails.artifactDetails.tabs.manifest': string
|
||||||
|
'versionDetails.artifactFiles.table.columns.checksum': string
|
||||||
|
'versionDetails.artifactFiles.table.columns.created': string
|
||||||
|
'versionDetails.artifactFiles.table.columns.downloadCommand': string
|
||||||
|
'versionDetails.artifactFiles.table.columns.name': string
|
||||||
|
'versionDetails.artifactFiles.table.columns.size': string
|
||||||
'versionDetails.cards.container.title': string
|
'versionDetails.cards.container.title': string
|
||||||
'versionDetails.cards.container.versionDigest': string
|
'versionDetails.cards.container.versionDigest': string
|
||||||
'versionDetails.cards.deploymentsCard.buildTitle': string
|
'versionDetails.cards.deploymentsCard.buildTitle': string
|
||||||
|
@ -1945,10 +1945,10 @@
|
|||||||
yargs "^17.6.2"
|
yargs "^17.6.2"
|
||||||
zod "^3.19.1"
|
zod "^3.19.1"
|
||||||
|
|
||||||
"@harnessio/react-har-service-client@^0.2.0":
|
"@harnessio/react-har-service-client@^0.3.0":
|
||||||
version "0.2.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.2.0.tgz#83f1f793c18e0e796ba7b1652801bfd676854963"
|
resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.3.0.tgz#b434034093c6619effe42720c7c078d18a9ecc50"
|
||||||
integrity sha512-W4GSiBTiI6DOCo9eqJPmxEf9I7PJA01AxAf9TrQ21fxFDuZbSk0c3YvZFz7INiHGUnNrB5QTLVgCVZRvelOkgw==
|
integrity sha512-+pFkxlUUM9CEkB60kx3SjppCdHdycfJhRN6t4p1R0M/n93dQLrdI0uHkoDZEeWb0o1Q0oQ21pkwTYktQr24E3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@harnessio/oats-cli" "^3.0.0"
|
"@harnessio/oats-cli" "^3.0.0"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user