diff --git a/packages/kbn-content-management-utils/index.ts b/packages/kbn-content-management-utils/index.ts index 12594660136d8..8e4751ba223ea 100644 --- a/packages/kbn-content-management-utils/index.ts +++ b/packages/kbn-content-management-utils/index.ts @@ -6,4 +6,5 @@ * Side Public License, v 1. */ -export * from './types'; +export * from './src/types'; +export * from './src/schema'; diff --git a/packages/kbn-content-management-utils/src/schema.ts b/packages/kbn-content-management-utils/src/schema.ts new file mode 100644 index 0000000000000..2e95624c36a22 --- /dev/null +++ b/packages/kbn-content-management-utils/src/schema.ts @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { schema, ObjectType } from '@kbn/config-schema'; + +export const apiError = schema.object({ + error: schema.string(), + message: schema.string(), + statusCode: schema.number(), + metadata: schema.object({}, { unknowns: 'allow' }), +}); + +export const referenceSchema = schema.object( + { + name: schema.maybe(schema.string()), + type: schema.string(), + id: schema.string(), + }, + { unknowns: 'forbid' } +); + +export const referencesSchema = schema.arrayOf(referenceSchema); + +export const savedObjectSchema = (attributesSchema: ObjectType) => + schema.object( + { + id: schema.string(), + type: schema.string(), + version: schema.maybe(schema.string()), + createdAt: schema.maybe(schema.string()), + updatedAt: schema.maybe(schema.string()), + error: schema.maybe(apiError), + attributes: attributesSchema, + references: referencesSchema, + namespaces: schema.maybe(schema.arrayOf(schema.string())), + originId: schema.maybe(schema.string()), + }, + { unknowns: 'allow' } + ); + +export const objectTypeToGetResultSchema = (soSchema: ObjectType) => + schema.object( + { + item: soSchema, + meta: schema.object( + { + outcome: schema.oneOf([ + schema.literal('exactMatch'), + schema.literal('aliasMatch'), + schema.literal('conflict'), + ]), + aliasTargetId: schema.maybe(schema.string()), + aliasPurpose: schema.maybe( + schema.oneOf([ + schema.literal('savedObjectConversion'), + schema.literal('savedObjectImport'), + ]) + ), + }, + { unknowns: 'forbid' } + ), + }, + { unknowns: 'forbid' } + ); + +// its recommended to create a subset of this schema for stricter validation +export const createOptionsSchemas = { + id: schema.maybe(schema.string()), + references: schema.maybe(referencesSchema), + overwrite: schema.maybe(schema.boolean()), + version: schema.maybe(schema.string()), + refresh: schema.maybe(schema.boolean()), + initialNamespaces: schema.maybe(schema.arrayOf(schema.string())), +}; + +export const schemaAndOr = schema.oneOf([schema.literal('AND'), schema.literal('OR')]); + +// its recommended to create a subset of this schema for stricter validation +export const searchOptionsSchemas = { + page: schema.maybe(schema.number()), + perPage: schema.maybe(schema.number()), + sortField: schema.maybe(schema.string()), + sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), + fields: schema.maybe(schema.arrayOf(schema.string())), + search: schema.maybe(schema.string()), + searchFields: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + rootSearchFields: schema.maybe(schema.arrayOf(schema.string())), + + hasReference: schema.maybe(schema.oneOf([referenceSchema, schema.arrayOf(referenceSchema)])), + hasReferenceOperator: schema.maybe(schemaAndOr), + hasNoReference: schema.maybe(schema.oneOf([referenceSchema, schema.arrayOf(referenceSchema)])), + hasNoReferenceOperator: schema.maybe(schemaAndOr), + defaultSearchOperator: schema.maybe(schemaAndOr), + namespaces: schema.maybe(schema.arrayOf(schema.string())), + type: schema.maybe(schema.string()), + + filter: schema.maybe(schema.string()), + pit: schema.maybe( + schema.object({ id: schema.string(), keepAlive: schema.maybe(schema.string()) }) + ), +}; + +// its recommended to create a subset of this schema for stricter validation +export const updateOptionsSchema = { + references: schema.maybe(referencesSchema), + version: schema.maybe(schema.string()), + refresh: schema.maybe(schema.oneOf([schema.boolean(), schema.literal('wait_for')])), + upsert: (attributesSchema: ObjectType) => schema.maybe(savedObjectSchema(attributesSchema)), + retryOnConflict: schema.maybe(schema.number()), +}; + +export const createResultSchema = (soSchema: ObjectType) => + schema.object( + { + item: soSchema, + }, + { unknowns: 'forbid' } + ); diff --git a/packages/kbn-content-management-utils/types.ts b/packages/kbn-content-management-utils/src/types.ts similarity index 100% rename from packages/kbn-content-management-utils/types.ts rename to packages/kbn-content-management-utils/src/types.ts diff --git a/packages/kbn-content-management-utils/tsconfig.json b/packages/kbn-content-management-utils/tsconfig.json index 7de04c3c13451..89a1d2520f322 100644 --- a/packages/kbn-content-management-utils/tsconfig.json +++ b/packages/kbn-content-management-utils/tsconfig.json @@ -17,6 +17,7 @@ ], "kbn_references": [ "@kbn/content-management-plugin", + "@kbn/config-schema", "@kbn/core-saved-objects-api-server", ] } diff --git a/x-pack/plugins/maps/common/content_management/v1/cm_services.ts b/x-pack/plugins/maps/common/content_management/v1/cm_services.ts index 5ea8008f53225..65d2e3082da7d 100644 --- a/x-pack/plugins/maps/common/content_management/v1/cm_services.ts +++ b/x-pack/plugins/maps/common/content_management/v1/cm_services.ts @@ -6,24 +6,12 @@ */ import { schema } from '@kbn/config-schema'; import type { ContentManagementServicesDefinition as ServicesDefinition } from '@kbn/object-versioning'; - -const apiError = schema.object({ - error: schema.string(), - message: schema.string(), - statusCode: schema.number(), - metadata: schema.object({}, { unknowns: 'allow' }), -}); - -const referenceSchema = schema.object( - { - name: schema.maybe(schema.string()), - type: schema.string(), - id: schema.string(), - }, - { unknowns: 'forbid' } -); - -const referencesSchema = schema.arrayOf(referenceSchema); +import { + savedObjectSchema, + objectTypeToGetResultSchema, + createOptionsSchemas, + createResultSchema, +} from '@kbn/content-management-utils'; const mapAttributesSchema = schema.object( { @@ -36,48 +24,19 @@ const mapAttributesSchema = schema.object( { unknowns: 'forbid' } ); -const mapSavedObjectSchema = schema.object( - { - id: schema.string(), - type: schema.string(), - version: schema.maybe(schema.string()), - createdAt: schema.maybe(schema.string()), - updatedAt: schema.maybe(schema.string()), - error: schema.maybe(apiError), - attributes: mapAttributesSchema, - references: referencesSchema, - namespaces: schema.maybe(schema.arrayOf(schema.string())), - originId: schema.maybe(schema.string()), - }, - { unknowns: 'allow' } -); +const mapSavedObjectSchema = savedObjectSchema(mapAttributesSchema); -const getResultSchema = schema.object( - { - item: mapSavedObjectSchema, - meta: schema.object( - { - outcome: schema.oneOf([ - schema.literal('exactMatch'), - schema.literal('aliasMatch'), - schema.literal('conflict'), - ]), - aliasTargetId: schema.maybe(schema.string()), - aliasPurpose: schema.maybe( - schema.oneOf([ - schema.literal('savedObjectConversion'), - schema.literal('savedObjectImport'), - ]) - ), - }, - { unknowns: 'forbid' } - ), - }, - { unknowns: 'forbid' } +const searchOptionsSchema = schema.maybe( + schema.object( + { + onlyTitle: schema.maybe(schema.boolean()), + }, + { unknowns: 'forbid' } + ) ); const createOptionsSchema = schema.object({ - references: schema.maybe(referencesSchema), + references: schema.maybe(createOptionsSchemas.references), }); // Content management service definition. @@ -86,7 +45,7 @@ export const serviceDefinition: ServicesDefinition = { get: { out: { result: { - schema: getResultSchema, + schema: objectTypeToGetResultSchema(mapSavedObjectSchema), }, }, }, @@ -101,12 +60,7 @@ export const serviceDefinition: ServicesDefinition = { }, out: { result: { - schema: schema.object( - { - item: mapSavedObjectSchema, - }, - { unknowns: 'forbid' } - ), + schema: createResultSchema(mapSavedObjectSchema), }, }, }, @@ -123,14 +77,7 @@ export const serviceDefinition: ServicesDefinition = { search: { in: { options: { - schema: schema.maybe( - schema.object( - { - onlyTitle: schema.maybe(schema.boolean()), - }, - { unknowns: 'forbid' } - ) - ), + schema: searchOptionsSchema, }, }, },