UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

89 lines (74 loc) 2.8 kB
import { Logger } from '@apic/studio-shared'; import { SchemaHandler, YamlContent } from '@apic/studio-shared'; import { Ajv } from 'ajv'; import addFormats from 'ajv-formats'; export class AssetValidator { private ajv: Ajv; private schemaHandler: SchemaHandler; constructor(schemaHandler: SchemaHandler) { this.ajv = new Ajv(); addFormats.default(this.ajv); this.ajv.addFormat('uint64', { type: 'number', validate: (x: number) => Number.isInteger(x) && x >= 0 && x <= Number.MAX_SAFE_INTEGER, }); this.schemaHandler = schemaHandler; } public validateAssets(genObj: YamlContent): { valid: boolean; errors: string[]; } { const errors: string[] = []; try { const kind = genObj.kind; const version = genObj.apiVersion || undefined; const assetRef = `${genObj.metadata.namespace}:${genObj.metadata.name}:${genObj.metadata.version}`; if (!kind) { const msg = 'Kind or version is undefined or null'; Logger.error(msg); return { valid: false, errors: [msg] }; } let allValid = true; const schemaStr = this.schemaHandler.getSchema(kind, version); if (!schemaStr) { const msg = `Schema not found for kind: ${kind}, version: ${version}`; Logger.error(msg); errors.push(msg); allValid = false; return { valid: false, errors }; } const schema = typeof schemaStr === 'string' ? JSON.parse(schemaStr) : schemaStr; const validate = this.ajv.compile(schema); const isValid = validate(genObj); if (!isValid) { const ajvMessages = (validate.errors || []) .map((err: any) => { const path = err.instancePath || '/'; const keyword = err.keyword; const message = err.message || 'Validation error'; const params = JSON.stringify(err.params, null, 2); return { path, keyword, message, params, }; }) .sort((a: any, b: any) => a.path.localeCompare(b.path)) .map((err: any) => { return `At path "${err.path}": ${err.message} (keyword: ${err.keyword}, params: ${err.params})`; }) .join('\n'); const msg = `The asset ${assetRef} has one or more problems. ${ajvMessages}. Review the error and try publishing again.`; Logger.error(msg); errors.push(msg); allValid = false; } return { valid: allValid, errors }; } catch (err) { const msg = `Error validating asset: ${err instanceof Error ? err.message : String(err)}`; Logger.error(msg, err instanceof Error ? err : new Error(String(err))); return { valid: false, errors: [msg] }; } } }