@@ -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,7 +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' ;
16- import { walk } from '../../utils/index.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 , walk } from '../../utils/index.js' ;
1720import { WalkOutput } from '../../utils/walk.js' ;
1821import bcd from '../../index.js' ;
1922
@@ -219,6 +222,35 @@ export const createDataBundle = async (): Promise<CompatData> => {
219222 } ;
220223} ;
221224
225+ /**
226+ * Validates the given data against the schema.
227+ * @param data - The data to validate.
228+ */
229+ const validate = ( data : CompatData ) => {
230+ const ajv = createAjv ( ) ;
231+
232+ for ( const [ key , value ] of Object . entries ( data ) ) {
233+ if ( key === '__meta' ) {
234+ // Not covered by the schema.
235+ continue ;
236+ }
237+
238+ const schema = key === 'browsers' ? browserDataSchema : compatDataSchema ;
239+ const data = { [ key ] : value } ;
240+ if ( ! ajv . validate ( schema , data ) ) {
241+ const errors = ajv . errors || [ ] ;
242+ if ( ! errors . length ) {
243+ console . error ( `${ key } data failed validation with unknown errors!` ) ;
244+ }
245+ // Output messages by one since better-ajv-errors wrongly joins messages
246+ // (see https://github.com/atlassian/better-ajv-errors/pull/21)
247+ errors . forEach ( ( e ) => {
248+ console . error ( betterAjvErrors ( schema , data , [ e ] , { indent : 2 } ) ) ;
249+ } ) ;
250+ }
251+ }
252+ } ;
253+
222254/* c8 ignore start */
223255
224256/**
@@ -227,6 +259,7 @@ export const createDataBundle = async (): Promise<CompatData> => {
227259const writeData = async ( ) => {
228260 const dest = new URL ( 'data.json' , targetdir ) ;
229261 const data = await createDataBundle ( ) ;
262+ validate ( data ) ;
230263 await fs . writeFile ( dest , stringify ( data ) ) ;
231264 logWrite ( dest , 'data' ) ;
232265} ;
@@ -383,5 +416,3 @@ const main = async () => {
383416if ( esMain ( import . meta) ) {
384417 await main ( ) ;
385418}
386-
387- /* c8 ignore stop */
0 commit comments