@@ -3,10 +3,13 @@ import fs from 'fs';
33import { globSync } from 'glob' ;
44import jsonschema from 'jsonschema' ;
55import path from 'path' ;
6+ import { fileURLToPath } from 'url' ;
67import shell from 'shelljs' ;
78import YAML from 'js-yaml' ;
89import marky from 'marky' ;
910import { createRequire } from 'module' ;
11+ import { compileFromFile } from 'json-schema-to-typescript' ;
12+ import { toSafeString } from 'json-schema-to-typescript/dist/src/utils.js' ;
1013
1114import fetchTranslations from './translations.js' ;
1215
@@ -187,7 +190,8 @@ function processData(options, type) {
187190 minifyJSON ( distDir + '/preset_defaults.json' , distDir + '/preset_defaults.min.json' ) ,
188191 minifyJSON ( distDir + '/deprecated.json' , distDir + '/deprecated.min.json' ) ,
189192 minifyJSON ( distDir + '/discarded.json' , distDir + '/discarded.min.json' ) ,
190- minifyJSON ( distDir + '/translations/' + sourceLocale + '.json' , distDir + '/translations/' + sourceLocale + '.min.json' )
193+ minifyJSON ( distDir + '/translations/' + sourceLocale + '.json' , distDir + '/translations/' + sourceLocale + '.min.json' ) ,
194+ generateTypeDefs ( distDir ) ,
191195 ] ;
192196
193197 if ( doFetchTranslations ) {
@@ -693,6 +697,68 @@ function generateIconsList(presets, fields, categories) {
693697 return Object . keys ( icons ) . sort ( ) ;
694698}
695699
700+ /** @param {string } distDir */
701+ async function generateTypeDefs ( distDir ) {
702+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
703+ const inputFolder = path . join ( __dirname , '../schemas' ) ;
704+
705+ /**
706+ * Some generated files use plural names because they
707+ * export an object, e.g. `Fields = Record<string, Field>`
708+ */
709+ const KEY_MAP = {
710+ field : 'fields' ,
711+ preset : 'presets' ,
712+ preset_category : 'preset_categories' ,
713+ } ;
714+ const fileNames = await fs . promises . readdir ( inputFolder ) ;
715+
716+ for ( const fileName of fileNames ) {
717+ const key = fileName . replace ( '.json' , '' ) ;
718+ const pluralKey = KEY_MAP [ key ] ;
719+
720+ let base = `
721+ declare const json: ${ toSafeString ( pluralKey || key ) } ;
722+ export default json;
723+ ` ;
724+
725+ if ( pluralKey ) {
726+ base += `
727+ export type ${ toSafeString ( pluralKey ) } = {
728+ [id: string]: ${ toSafeString ( key ) }
729+ };
730+ ` ;
731+ }
732+
733+ const tsFile = await compileFromFile ( path . join ( inputFolder , fileName ) , {
734+ additionalProperties : false ,
735+ bannerComment : base ,
736+
737+ // ensure that the default export uses a consistent name
738+ customName : ( schema ) =>
739+ schema . $schema && schema . $id ? path . parse ( schema . $id ) . name : undefined ,
740+ } ) ;
741+
742+ await fs . promises . writeFile (
743+ path . join ( distDir , `${ pluralKey || key } .d.json.ts` ) ,
744+ tsFile ,
745+ ) ;
746+ }
747+
748+ // finally, create the index file which re-exports everything
749+ // as named types.
750+ const indexFile = fileNames
751+ . map ( ( fileName ) => {
752+ const key = fileName . replace ( '.json' , '' ) ;
753+ return `export type * from './${ KEY_MAP [ key ] || key } .d.json.ts';` ;
754+ } )
755+ . join ( '\n' ) ;
756+
757+ await fs . promises . writeFile (
758+ path . join ( distDir , 'index.d.ts' ) ,
759+ indexFile + '\n' ,
760+ ) ;
761+ }
696762
697763function validateCategoryPresets ( categories , presets ) {
698764 Object . keys ( categories ) . forEach ( id => {
0 commit comments