From f4f28f367db6d18588602d734623863ccfea1a01 Mon Sep 17 00:00:00 2001 From: Nikita Gorin <36075690+NikitaCG@users.noreply.github.com> Date: Mon, 15 May 2023 13:51:22 +0300 Subject: [PATCH] feat: create schemas (#41) * feat: create shemas * feat: refactor schemas usage after review * feat: update import paths --- package-lock.json | 6 ++--- package.json | 2 +- src/blocks/Author/schema.ts | 23 +++++++++++++++++++ src/blocks/Banner/schema.ts | 32 ++++++++++++++++++++++++++ src/blocks/CTA/schema.ts | 32 ++++++++++++++++++++++++++ src/blocks/ColoredText/schema.ts | 39 ++++++++++++++++++++++++++++++++ src/blocks/Feed/schema.ts | 29 ++++++++++++++++++++++++ src/blocks/Header/schema.ts | 21 +++++++++++++++++ src/blocks/Layout/schema.ts | 25 ++++++++++++++++++++ src/blocks/Media/schema.ts | 24 ++++++++++++++++++++ src/blocks/Meta/schema.ts | 19 ++++++++++++++++ src/blocks/Suggest/schema.ts | 19 ++++++++++++++++ src/blocks/YFM/schema.ts | 24 ++++++++++++++++++++ src/index.ts | 2 ++ src/schema/README.md | 5 ++++ src/schema/blocks.ts | 10 ++++++++ src/schema/common.ts | 34 ++++++++++++++++++++++++++++ src/schema/headers.ts | 1 + src/schema/index.ts | 29 ++++++++++++++++++++++++ src/schema/utils.ts | 19 ++++++++++++++++ 20 files changed, 391 insertions(+), 4 deletions(-) create mode 100644 src/blocks/Author/schema.ts create mode 100644 src/blocks/Banner/schema.ts create mode 100644 src/blocks/CTA/schema.ts create mode 100644 src/blocks/ColoredText/schema.ts create mode 100644 src/blocks/Feed/schema.ts create mode 100644 src/blocks/Header/schema.ts create mode 100644 src/blocks/Layout/schema.ts create mode 100644 src/blocks/Media/schema.ts create mode 100644 src/blocks/Meta/schema.ts create mode 100644 src/blocks/Suggest/schema.ts create mode 100644 src/blocks/YFM/schema.ts create mode 100644 src/schema/README.md create mode 100644 src/schema/blocks.ts create mode 100644 src/schema/common.ts create mode 100644 src/schema/headers.ts create mode 100644 src/schema/index.ts create mode 100644 src/schema/utils.ts diff --git a/package-lock.json b/package-lock.json index 7a7df42c..4a998fa9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1709,9 +1709,9 @@ "integrity": "sha512-KNYNhQjA9XqLo0RVEwNRqdA7/Lx5LLrNDtqWCvOGzXTwKU0GFNlWJaoSvk7u97apag23nTxgmpk551FlRCfehA==" }, "@gravity-ui/page-constructor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@gravity-ui/page-constructor/-/page-constructor-2.6.0.tgz", - "integrity": "sha512-Te0iO4vIve9dznkIPaWXCX87MXC9ReipuDOWU1wOoyEnoUVcOc2SOt/rc4Z/U+9ii4PdH4uniW1iLgaAV7aXsQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@gravity-ui/page-constructor/-/page-constructor-2.13.0.tgz", + "integrity": "sha512-GF7s3LiYq8ir+8vdfyMyfVBV2VI4KZQTHBVgXVcQgVa7VxEid+My/uqeGWn/ugBfXp4Nl8h0/mjiM42/NsgtPQ==", "dev": true, "requires": { "@gravity-ui/i18n": "^1.0.0", diff --git a/package.json b/package.json index e2e299c7..34d71c99 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "@commitlint/config-conventional": "^17.4.3", "@doc-tools/transform": "^2.9.0", "@gravity-ui/eslint-config": "^2.0.0", - "@gravity-ui/page-constructor": "^2.6.0", + "@gravity-ui/page-constructor": "^2.13.0", "@gravity-ui/prettier-config": "^1.0.1", "@gravity-ui/stylelint-config": "^1.0.0", "@gravity-ui/tsconfig": "^1.0.0", diff --git a/src/blocks/Author/schema.ts b/src/blocks/Author/schema.ts new file mode 100644 index 00000000..8e7cc984 --- /dev/null +++ b/src/blocks/Author/schema.ts @@ -0,0 +1,23 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {BlockBaseProps}, +} = validators; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +export const Author = { + [BlockType.Author]: { + type: 'object', + additionalProperties: false, + required: ['authorId'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + authorId: { + type: 'number', + }, + }, + }, +}; diff --git a/src/blocks/Banner/schema.ts b/src/blocks/Banner/schema.ts new file mode 100644 index 00000000..47b8f4c8 --- /dev/null +++ b/src/blocks/Banner/schema.ts @@ -0,0 +1,32 @@ +import {validators} from '@gravity-ui/page-constructor'; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +const { + subBlocks: {ContentBase}, + common: {BlockBaseProps}, +} = validators; + +export const Banner = { + [BlockType.Banner]: { + type: 'object', + additionalProperties: false, + required: ['title', 'text', 'image'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + ...ContentBase, + color: { + type: 'string', + }, + image: { + type: 'string', + }, + imageSize: { + type: 'string', + enum: ['s', 'm'], + }, + }, + }, +}; diff --git a/src/blocks/CTA/schema.ts b/src/blocks/CTA/schema.ts new file mode 100644 index 00000000..b399ffa0 --- /dev/null +++ b/src/blocks/CTA/schema.ts @@ -0,0 +1,32 @@ +import {validators} from '@gravity-ui/page-constructor'; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +const { + subBlocks: {ContentBase}, + common: {BlockBaseProps}, +} = validators; + +export const CTA = { + [BlockType.CTA]: { + type: 'object', + additionalProperties: false, + required: ['items'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + items: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['title', 'links'], + properties: { + ...ContentBase, + }, + }, + }, + }, + }, +}; diff --git a/src/blocks/ColoredText/schema.ts b/src/blocks/ColoredText/schema.ts new file mode 100644 index 00000000..0afc3950 --- /dev/null +++ b/src/blocks/ColoredText/schema.ts @@ -0,0 +1,39 @@ +import {validators} from '@gravity-ui/page-constructor'; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +const { + subBlocks: {ContentBase}, + components: {ImageProps}, + common: {BlockBaseProps}, +} = validators; + +const BackgroundProps = { + type: 'object', + additionalProperties: false, + properties: { + image: ImageProps, + color: { + type: 'string', + }, + altText: { + type: 'string', + contentType: 'text', + }, + }, +}; + +export const ColoredText = { + [BlockType.ColoredText]: { + type: 'object', + additionalProperties: false, + required: ['text'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + ...ContentBase, + background: BackgroundProps, + }, + }, +}; diff --git a/src/blocks/Feed/schema.ts b/src/blocks/Feed/schema.ts new file mode 100644 index 00000000..1ff3da34 --- /dev/null +++ b/src/blocks/Feed/schema.ts @@ -0,0 +1,29 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {TitleProps, BlockBaseProps}, +} = validators; + +import {BlockType} from '../../models/common'; + +export const Feed = { + [BlockType.Feed]: { + additionalProperties: false, + required: [], + properties: { + ...BlockBaseProps, + title: TitleProps, + image: { + type: 'string', + }, + description: { + type: 'string', + contentType: 'text', + }, + size: { + type: 'string', + enum: ['s', 'm'], + }, + }, + }, +}; diff --git a/src/blocks/Header/schema.ts b/src/blocks/Header/schema.ts new file mode 100644 index 00000000..e75354e7 --- /dev/null +++ b/src/blocks/Header/schema.ts @@ -0,0 +1,21 @@ +import {validators} from '@gravity-ui/page-constructor'; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +const { + blocks: {HeaderProperties}, + common: {BlockBaseProps}, +} = validators; + +export const Header = { + [BlockType.Header]: { + type: 'object', + additionalProperties: false, + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + ...HeaderProperties, + }, + }, +}; diff --git a/src/blocks/Layout/schema.ts b/src/blocks/Layout/schema.ts new file mode 100644 index 00000000..6bcb7437 --- /dev/null +++ b/src/blocks/Layout/schema.ts @@ -0,0 +1,25 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {BlockBaseProps, ChildrenProps}, +} = validators; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +export const Layout = { + [BlockType.Layout]: { + type: 'object', + additionalProperties: false, + required: ['children'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + children: ChildrenProps, + mobileOrder: { + type: 'string', + enum: ['reverse', 'straight'], + }, + }, + }, +}; diff --git a/src/blocks/Media/schema.ts b/src/blocks/Media/schema.ts new file mode 100644 index 00000000..1f1b2f91 --- /dev/null +++ b/src/blocks/Media/schema.ts @@ -0,0 +1,24 @@ +import {validators} from '@gravity-ui/page-constructor'; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +const { + common: {BlockBaseProps, MediaProps}, +} = validators; + +export const Media = { + [BlockType.Media]: { + type: 'object', + additionalProperties: false, + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + ...MediaProps, + text: { + type: 'string', + contentType: 'text', + }, + }, + }, +}; diff --git a/src/blocks/Meta/schema.ts b/src/blocks/Meta/schema.ts new file mode 100644 index 00000000..860ad999 --- /dev/null +++ b/src/blocks/Meta/schema.ts @@ -0,0 +1,19 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {BlockBaseProps}, +} = validators; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +export const Meta = { + [BlockType.Meta]: { + type: 'object', + additionalProperties: false, + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + }, + }, +}; diff --git a/src/blocks/Suggest/schema.ts b/src/blocks/Suggest/schema.ts new file mode 100644 index 00000000..305b8a29 --- /dev/null +++ b/src/blocks/Suggest/schema.ts @@ -0,0 +1,19 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {BlockBaseProps}, +} = validators; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +export const Suggest = { + [BlockType.Suggest]: { + type: 'object', + additionalProperties: false, + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + }, + }, +}; diff --git a/src/blocks/YFM/schema.ts b/src/blocks/YFM/schema.ts new file mode 100644 index 00000000..8ba52dbc --- /dev/null +++ b/src/blocks/YFM/schema.ts @@ -0,0 +1,24 @@ +import {validators} from '@gravity-ui/page-constructor'; + +const { + common: {BlockBaseProps}, +} = validators; + +import {BlockType} from '../../models/common'; +import {BlogBlockBase} from '../../schema/common'; + +export const YFM = { + [BlockType.YFM]: { + type: 'object', + additionalProperties: false, + required: ['text'], + properties: { + ...BlockBaseProps, + ...BlogBlockBase, + text: { + type: 'string', + contentType: 'yfm', + }, + }, + }, +}; diff --git a/src/index.ts b/src/index.ts index 4d8fd6e3..4a0f64d1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,4 +8,6 @@ export {BlogPage} from './containers/BlogPage/BlogPage'; export * from './models/common'; export * from './models/locale'; +export * from './schema'; + export {BREAKPOINTS} from './constants'; diff --git a/src/schema/README.md b/src/schema/README.md new file mode 100644 index 00000000..21e81755 --- /dev/null +++ b/src/schema/README.md @@ -0,0 +1,5 @@ +## Shemas and validators + +#### We use [`Ajv JSON schema validator`](https://ajv.js.org/) for validation configs with blocks descriptions. + +#### You can use blocks schemas in your backoffice or everything else places where you check configs. diff --git a/src/schema/blocks.ts b/src/schema/blocks.ts new file mode 100644 index 00000000..e83e13ef --- /dev/null +++ b/src/schema/blocks.ts @@ -0,0 +1,10 @@ +export * from '../blocks/Author/schema'; +export * from '../blocks/Banner/schema'; +export * from '../blocks/ColoredText/schema'; +export * from '../blocks/CTA/schema'; +export * from '../blocks/Feed/schema'; +export * from '../blocks/Layout/schema'; +export * from '../blocks/Media/schema'; +export * from '../blocks/Meta/schema'; +export * from '../blocks/Suggest/schema'; +export * from '../blocks/YFM/schema'; diff --git a/src/schema/common.ts b/src/schema/common.ts new file mode 100644 index 00000000..8c6fdd57 --- /dev/null +++ b/src/schema/common.ts @@ -0,0 +1,34 @@ +export interface ObjectSchema extends Record { + properties: object; +} + +const sizeTypes = ['xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl']; + +export const filteredItem = (itemsSchema: ObjectSchema) => ({ + ...itemsSchema, + type: 'object', + properties: { + when: { + type: 'string', + }, + ...itemsSchema.properties, + }, +}); + +export const BlogBlockBase = { + paddingTop: { + type: 'string', + enum: sizeTypes, + }, + paddingBottom: { + type: 'string', + enum: sizeTypes, + }, + fullWidth: { + type: 'boolean', + }, + column: { + type: 'string', + enum: ['left', 'right'], + }, +}; diff --git a/src/schema/headers.ts b/src/schema/headers.ts new file mode 100644 index 00000000..87997ce3 --- /dev/null +++ b/src/schema/headers.ts @@ -0,0 +1 @@ +export * from '../blocks/Header/schema'; diff --git a/src/schema/index.ts b/src/schema/index.ts new file mode 100644 index 00000000..f1d141dd --- /dev/null +++ b/src/schema/index.ts @@ -0,0 +1,29 @@ +import {BlockType} from '../models/common'; +import * as blocks from './blocks'; +import * as headers from './headers'; + +const {Author, Banner, ColoredText, CTA, Feed, Layout, Media, Meta, Suggest, YFM} = blocks; +const {Header} = headers; + +export const validators = { + blocks, + headers, +}; + +export const schemasForCustom = { + headers: { + [BlockType.Header]: Header, + }, + blocks: { + [BlockType.Author]: Author, + [BlockType.Banner]: Banner, + [BlockType.ColoredText]: ColoredText, + [BlockType.CTA]: CTA, + [BlockType.Feed]: Feed, + [BlockType.Layout]: Layout, + [BlockType.Media]: Media, + [BlockType.Meta]: Meta, + [BlockType.Suggest]: Suggest, + [BlockType.YFM]: YFM, + }, +}; diff --git a/src/schema/utils.ts b/src/schema/utils.ts new file mode 100644 index 00000000..1afd78ec --- /dev/null +++ b/src/schema/utils.ts @@ -0,0 +1,19 @@ +import {BlockType} from '../models/common'; + +type BlockConfig = { + [x in BlockType]: Object; +}; + +type GenerateConfig = (config: BlockConfig) => {[x in BlockType]: BlockConfig}; + +export const generateConfig: GenerateConfig = (config) => { + return Object.keys(config).reduce( + (acc, blockKey) => ({ + ...acc, + blockKey: { + blockKey: config[blockKey as BlockType], + }, + }), + {} as {[x in BlockType]: BlockConfig}, + ); +};