From 5b857426d3e3bd1b7cfc0827e6bcb9557fcd464f Mon Sep 17 00:00:00 2001 From: EnzoVezzaro Date: Wed, 21 Sep 2022 07:06:30 -0400 Subject: [PATCH] added schema tipying and integration to marketprovider --- src/@context/MarketMetadata/_shaclType.ts | 316 ++++++++++++++++++++++ src/@context/MarketMetadata/_types.ts | 5 + src/@context/MarketMetadata/index.tsx | 12 +- src/@utils/aquarius.ts | 10 +- src/components/Publish/_validation.ts | 63 +++-- src/components/Publish/index.tsx | 11 +- 6 files changed, 380 insertions(+), 37 deletions(-) create mode 100644 src/@context/MarketMetadata/_shaclType.ts diff --git a/src/@context/MarketMetadata/_shaclType.ts b/src/@context/MarketMetadata/_shaclType.ts new file mode 100644 index 000000000..fc12346ef --- /dev/null +++ b/src/@context/MarketMetadata/_shaclType.ts @@ -0,0 +1,316 @@ +export interface ShaclSchema { + chainId: { + maxCount: number + minCount: number + } + credentials: { + allow: { + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + values: { + maxLength: number + minCount: number + pattern: string + } + } + deny: { + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + values: { + maxLength: number + minCount: number + pattern: string + } + } + } + id: { + maxCount: number + maxLength: number + minCount: number + minLength: number + pattern: string + } + metadata: { + additionalInformation: any + algorithm: { + consumerParameters: { + default: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + description: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + label: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + name: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + options: { + maxLength: number + pattern: string + } + required: { + maxCount: number + minCount: number + } + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + container: { + checksum: { + maxCount: number + maxLength: number + minCount: number + minLength: number + pattern: string + } + entrypoint: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + image: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + tag: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + language: { + maxCount: number + maxLength: number + pattern: string + } + version: { + maxCount: number + maxLength: number + pattern: string + } + } + author: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + categories: { + maxCount: number + maxLength: number + pattern: string + } + contentLanguage: { + maxCount: number + maxLength: number + pattern: string + } + copyrightHolder: { + maxCount: number + maxLength: number + pattern: string + } + description: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + license: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + links: { + maxCount: number + maxLength: number + pattern: string + } + name: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + tags: { + maxCount: number + maxLength: number + pattern: string + } + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + nftAddress: { + maxCount: number + maxLength: number + minCount: number + minLength: number + } + services: { + additionalInformation: any + compute: { + allowNetworkAccess: { + maxCount: number + minCount: number + } + allowRawAlgorithm: { + maxCount: number + minCount: number + } + publisherTrustedAlgorithmPublishers: { + maxLength: number + pattern: string + } + publisherTrustedAlgorithms: { + containerSectionChecksum: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + did: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + filesChecksum: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + } + consumerParameters: { + default: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + description: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + label: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + name: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + options: { + maxLength: number + pattern: string + } + required: { + maxCount: number + minCount: number + } + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + datatokenAddress: { + maxCount: number + maxLength: number + minCount: number + minLength: number + pattern: string + } + description: { + maxCount: number + maxLength: number + minLength: number + pattern: string + } + files: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + id: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + name: { + maxCount: number + maxLength: number + minLength: number + pattern: string + } + serviceEndpoint: { + maxCount: number + maxLength: number + minCount: number + minLength: number + pattern: string + } + timeout: { + maxCount: number + minCount: number + pattern: string + } + type: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } + } + version: { + maxCount: number + maxLength: number + minCount: number + pattern: string + } +} diff --git a/src/@context/MarketMetadata/_types.ts b/src/@context/MarketMetadata/_types.ts index 62b61b5bc..8056e03b7 100644 --- a/src/@context/MarketMetadata/_types.ts +++ b/src/@context/MarketMetadata/_types.ts @@ -1,3 +1,7 @@ +import { Asset } from '@oceanprotocol/lib' +import { CancelToken } from 'axios' +import { ShaclSchema } from './_shaclType' + export interface OpcFee { chainId: number swapNotApprovedFee: string @@ -50,4 +54,5 @@ export interface MarketMetadataProviderValue { siteContent: SiteContent appConfig: AppConfig getOpcFeeForToken: (tokenAddress: string, chainId: number) => string + getShaclSchema: (token?: CancelToken) => Promise } diff --git a/src/@context/MarketMetadata/index.tsx b/src/@context/MarketMetadata/index.tsx index 0d612e127..2e624945a 100644 --- a/src/@context/MarketMetadata/index.tsx +++ b/src/@context/MarketMetadata/index.tsx @@ -15,6 +15,9 @@ import siteContent from '../../../content/site.json' import appConfig from '../../../app.config' import { fetchData, getQueryContext } from '@utils/subgraph' import { LoggerInstance } from '@oceanprotocol/lib' +import { retrieveShaclSchema } from '@utils/aquarius' +import { CancelToken } from 'axios' +import { ShaclSchema } from './_shaclType' const MarketMetadataContext = createContext({} as MarketMetadataProviderValue) @@ -64,6 +67,12 @@ function MarketMetadataProvider({ }, [opcFees] ) + + const getShaclSchema = useCallback(async (token?: CancelToken) => { + const schema = await retrieveShaclSchema() + return schema + }, []) + return ( diff --git a/src/@utils/aquarius.ts b/src/@utils/aquarius.ts index a48df0baa..e79ddfcc0 100644 --- a/src/@utils/aquarius.ts +++ b/src/@utils/aquarius.ts @@ -8,6 +8,7 @@ import { SortTermOptions } from '../@types/aquarius/SearchQuery' import { transformAssetToAssetSelection } from './assetConvertor' +import { ShaclSchema } from '@context/MarketMetadata/_shaclType' export const MAXIMUM_NUMBER_OF_PAGES_WITH_RESULTS = 476 @@ -140,13 +141,10 @@ export async function retrieveAsset( } } -export async function retrieveShaclSchema( - cancelToken: CancelToken -): Promise { +export async function retrieveShaclSchema(): Promise { try { - const response: AxiosResponse = await axios.get( - `${metadataCacheUri}/api/aquarius/validation/schema`, - { cancelToken } + const response: AxiosResponse = await axios.get( + `${metadataCacheUri}/api/aquarius/validation/schema` ) if (!response || response.status !== 200 || !response.data) return diff --git a/src/components/Publish/_validation.ts b/src/components/Publish/_validation.ts index 39ac4245a..0f7c1ee95 100644 --- a/src/components/Publish/_validation.ts +++ b/src/components/Publish/_validation.ts @@ -1,30 +1,53 @@ import { MAX_DECIMALS } from '@utils/constants' import * as Yup from 'yup' import { getMaxDecimalsValidation } from '@utils/numbers' +import { retrieveShaclSchema } from '@utils/aquarius' // TODO: conditional validation // e.g. when algo is selected, Docker image is required // hint, hint: https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema -const validationMetadata = { - type: Yup.string() - .matches(/dataset|algorithm/g, { excludeEmptyString: true }) - .required('Required'), - name: Yup.string() - .min(4, (param) => `Title must be at least ${param.min} characters`) - .required('Required'), - description: Yup.string() - .min(10, (param) => `Description must be at least ${param.min} characters`) - .max( - 5000, - (param) => `Description must have maximum ${param.max} characters` - ) - .required('Required'), - author: Yup.string().required('Required'), - tags: Yup.string().nullable(), - termsAndConditions: Yup.boolean() - .required('Required') - .isTrue('Please agree to the Terms and Conditions.') +const getValidationMetadata = async () => { + const { metadata } = await retrieveShaclSchema() + console.log(metadata) + + return { + type: Yup.string() + .matches(/dataset|algorithm/g, { excludeEmptyString: true }) + .required('Required'), + name: Yup.string() + .min(4, (param) => `Title must be at least ${param.min} characters`) + .max( + metadata.name.maxLength, + (param) => `Description must have maximum ${param.max} characters` + ) + .required('Required'), + description: Yup.string() + .min( + 10, + (param) => `Description must be at least ${param.min} characters` + ) + .max( + metadata.description.maxLength, + (param) => `Description must have maximum ${param.max} characters` + ) + .required('Required'), + author: Yup.string() + .max( + metadata.author.maxLength, + (param) => `Author must have maximum ${param.max} characters` + ) + .required('Required'), + tags: Yup.string() + .max( + metadata.tags.maxLength, + (param) => `Tags must have maximum ${param.max} characters` + ) + .nullable(), + termsAndConditions: Yup.boolean() + .required('Required') + .isTrue('Please agree to the Terms and Conditions.') + } } const validationService = { @@ -91,7 +114,7 @@ export const validationSchema: Yup.SchemaOf = Yup.object().shape({ chainId: Yup.number().required('Required'), accountId: Yup.string().required('Required') }), - metadata: Yup.object().shape(validationMetadata), + metadata: Yup.object().shape(getValidationMetadata()), services: Yup.array().of(Yup.object().shape(validationService)), pricing: Yup.object().shape(validationPricing) }) diff --git a/src/components/Publish/index.tsx b/src/components/Publish/index.tsx index dad8b048f..8fb060cbe 100644 --- a/src/components/Publish/index.tsx +++ b/src/components/Publish/index.tsx @@ -25,8 +25,7 @@ import { getOceanConfig } from '@utils/ocean' import { validationSchema } from './_validation' import { useAbortController } from '@hooks/useAbortController' import { setNFTMetadataAndTokenURI } from '@utils/nft' -import { retrieveShaclSchema } from '@utils/aquarius' -import { CancelToken } from 'axios' +import { useMarketMetadata } from '@context/MarketMetadata' // TODO: restore FormikPersist, add back clear form action // const formName = 'ocean-publish-form' @@ -54,14 +53,6 @@ export default function PublishPage({ const [ddoEncrypted, setDdoEncrypted] = useState() const [did, setDid] = useState() - const getShaclSchema = useCallback(async (token?: CancelToken) => { - const schema = await retrieveShaclSchema(token) - console.log(schema) - }, []) - useEffect(() => { - getShaclSchema() - }, []) - // -------------------------------------------------- // 1. Create NFT & datatokens & create pricing schema // --------------------------------------------------