@@ -5,6 +5,7 @@ import fs from 'node:fs/promises';
55import { relative } from 'node:path' ;
66import { fileURLToPath } from 'node:url' ;
77
8+ import betterAjvErrors from 'better-ajv-errors' ;
89import esMain from 'es-main' ;
910import stringify from 'fast-json-stable-stringify' ;
1011import { compareVersions } from 'compare-versions' ;
@@ -13,6 +14,9 @@ import { marked } from 'marked';
1314import { InternalSupportStatement } from '../../types/index.js' ;
1415import { BrowserName , CompatData , VersionValue } from '../../types/types.js' ;
1516import compileTS from '../generate-types.js' ;
17+ import compatDataSchema from '../../schemas/compat-data.schema.json' with { type : 'json' } ;
18+ import browserDataSchema from '../../schemas/browsers.schema.json' with { type : 'json' } ;
19+ import { createAjv } from '../lib/ajv.js' ;
1620import { walk } from '../../utils/index.js' ;
1721import { WalkOutput } from '../../utils/walk.js' ;
1822import bcd from '../../index.js' ;
@@ -219,6 +223,35 @@ export const createDataBundle = async (): Promise<CompatData> => {
219223 } ;
220224} ;
221225
226+ /**
227+ * Validates the given data against the schema.
228+ * @param data - The data to validate.
229+ */
230+ const validate = ( data : CompatData ) => {
231+ const ajv = createAjv ( ) ;
232+
233+ for ( const [ key , value ] of Object . entries ( data ) ) {
234+ if ( key === '__meta' ) {
235+ // Not covered by the schema.
236+ continue ;
237+ }
238+
239+ const schema = key === 'browsers' ? browserDataSchema : compatDataSchema ;
240+ const data = { [ key ] : value } ;
241+ if ( ! ajv . validate ( schema , data ) ) {
242+ const errors = ajv . errors || [ ] ;
243+ if ( ! errors . length ) {
244+ console . error ( `${ key } data failed validation with unknown errors!` ) ;
245+ }
246+ // Output messages by one since better-ajv-errors wrongly joins messages
247+ // (see https://github.com/atlassian/better-ajv-errors/pull/21)
248+ errors . forEach ( ( e ) => {
249+ console . error ( betterAjvErrors ( schema , data , [ e ] , { indent : 2 } ) ) ;
250+ } ) ;
251+ }
252+ }
253+ } ;
254+
222255/* c8 ignore start */
223256
224257/**
@@ -227,6 +260,7 @@ export const createDataBundle = async (): Promise<CompatData> => {
227260const writeData = async ( ) => {
228261 const dest = new URL ( 'data.json' , targetdir ) ;
229262 const data = await createDataBundle ( ) ;
263+ validate ( data ) ;
230264 await fs . writeFile ( dest , stringify ( data ) ) ;
231265 logWrite ( dest , 'data' ) ;
232266} ;
0 commit comments