import fs from 'fs' ; import path from 'path' ; import directoryTree from 'directory-tree' ; import { Project , Writers } from 'ts-morph' ; import { quicktype , InputData , JSONSchemaInput , FetchingJSONSchemaStore , } from 'quicktype-core' ; import { apiMapFile , schemaFolder , typesLabel , typeFile , } from './Utils.js' ; console . log ( schemaFolder ) ; if ( ! fs . existsSync ( schemaFolder ) ) { console . log ( 'Schemas not found, please clone the "PokeAPI/api-data" repository on the root of this project first and change all $refs from "/schema/v2" to "api-data/data/schema/v2")' ) ; process . exit ( 1 ) ; } function clearAndUpper ( text ) { return text . replace ( /-/ , '' ) . toUpperCase ( ) ; } function toPascalCase ( text ) { return text . replace ( /(^\w|-\w)/g , clearAndUpper ) ; } const apiMap = { } ; async function generateFinalFile ( types ) { console . timeLog ( typesLabel , '- Types generated, starting the generation of the definition file...' ) ; const project = new Project ( ) ; const file = project . createSourceFile ( typeFile , `/*
* Type definitions for pokedex-promise-v2 v4.x
* DO NOT MODIFY, THIS IS AUTO GENERATED
* Code by: HRKings <https://github.com/HRKings/>
* And: Christian Garza <https://github.com/C-Garza/>
* Code inspired by: Mudkip <https://github.com/mudkipme/>
* Execute \`npm run generate\` to regenerate
*/` , { overwrite : true } ) ; const rootModule = file . addModule ( { name : '\'pokedex-promise-v2\'' , } ) ; const namespace = rootModule . addModule ( { name : 'PokeAPI' , } ) ; namespace . setBodyText ( types ) ; namespace . getInterface ( 'EvolutionChainElement' ) . remove ( ) ; namespace . getInterface ( 'GenerationElement' ) . remove ( ) ; namespace . getInterface ( 'VersionGroupNamedList' ) . remove ( ) ; namespace . setBodyText ( namespace . getBodyText ( ) . replace ( /EvolutionChainElement/g , 'APIResource' ) . replace ( /GenerationElement/g , 'NamedAPIResource' ) ) ; namespace . formatText ( ) ; rootModule . addInterface ( { name : 'ListEndpointOptions' , properties : [ { name : 'offset' , type : 'number' , hasQuestionToken : true , docs : [ 'The offset to be used in the request' ] , } , { name : 'limit' , type : 'number' , hasQuestionToken : true , docs : [ 'The limit to be used in the request' ] , } , { name : 'cacheLimit' , type : 'number' , hasQuestionToken : true , docs : [ 'The limit of the cache in milliseconds' ] , } ] , } ) ; rootModule . addInterface ( { name : 'PokeAPIOptions' , properties : [ { name : 'protocol' , type : Writers . unionType ( '\'https\'' , '\'http\'' ) , hasQuestionToken : true , docs : [ 'The protocol to be used' , '@default \'https\'' ] , } , { name : 'hostName' , type : 'string' , hasQuestionToken : true , docs : [ 'The hostname of the PokeAPI instance' , '@default \'pokeapi.co\'' ] , } , { name : 'versionPath' , type : 'string' , hasQuestionToken : true , docs : [ 'The version path of the API' , '@default \'/api/v2/\'' ] , } , { name : 'offset' , type : 'number' , hasQuestionToken : true , docs : [ 'The offset to be used in list requests' , '@default 0' ] , } , { name : 'limit' , type : 'number' , hasQuestionToken : true , docs : [ 'The limit to be used in list requests' , '@default 100000' ] , } , { name : 'timeout' , type : 'number' , hasQuestionToken : true , docs : [ 'The timeout of a response in milliseconds' , '@default 10 * 1000 // (10 seconds)' ] , } , { name : 'cacheLimit' , type : 'number' , hasQuestionToken : true , docs : [ 'The limit of the cache in milliseconds' , '@default 1000000 * 1000 // (11 days)' ] , } ] , } ) ; await file . save ( ) ; fs . writeFileSync ( apiMapFile , JSON . stringify ( apiMap , null , 2 ) ) ; console . timeEnd ( typesLabel ) ; console . log ( 'Definition file created!' ) ; } console . time ( typesLabel ) ; console . timeLog ( typesLabel , '- Starting to generate types...' ) ; const schemaInput = new JSONSchemaInput ( new FetchingJSONSchemaStore ( ) ) ; const inputData = new InputData ( ) ; async function quicktypeMain ( jsonSchema , basename ) { await schemaInput . addSource ( { name : basename , schema : jsonSchema } ) ; if ( basename === 'VersionGroupNamedList' ) { inputData . addInput ( schemaInput ) ; const qt = await quicktype ( { inputData , lang : 'TypeScript' , rendererOptions : { 'just-types' : 'true' , } , } ) ; await generateFinalFile ( qt . lines . join ( '\n' ) . replace ( /export /g , '' ) ) ; } } const tree = directoryTree ( schemaFolder , { extensions : /\.json$/ , normalizePath : true } ) ; tree . children . forEach ( ( child ) => { if ( ! child . children ) { let basename = path . basename ( child . path , '.json' ) . replace ( /_/g , '-' ) ; if ( basename === 'index' ) { basename = 'EndpointsList' ; } else { basename = toPascalCase ( basename ) ; } const jsonSchema = fs . readFileSync ( child . path , 'utf8' ) ; quicktypeMain ( jsonSchema , basename ) ; } } ) ; directoryTree ( schemaFolder , { extensions : /\.json$/ , normalizePath : true } , ( item ) => { const paths = item . path . split ( '/' ) . reverse ( ) ; if ( paths [ 1 ] !== 'v2' && ! item . path . includes ( 'move-ailment/-1' ) ) { let basename ; let interfaceName ; if ( item . path . includes ( 'pokemon/$id/encounters' ) ) { basename = 'pokemon-encounter' ; interfaceName = 'PokemonEncounter' ; } else if ( item . path . includes ( '$id' ) ) { basename = paths [ 2 ] ; interfaceName = toPascalCase ( basename ) ; } else { basename = `${ paths [ 1 ] }-list` ; interfaceName = toPascalCase ( basename ) ; } apiMap [ basename ] = interfaceName ; const jsonSchema = fs . readFileSync ( item . path , 'utf8' ) ; if ( interfaceName . includes ( 'List' ) && jsonSchema . includes ( 'named_api_resource_list.json' ) ) { interfaceName = interfaceName . replace ( 'List' , 'NamedList' ) ; apiMap [ basename ] = interfaceName ; } quicktypeMain ( jsonSchema , interfaceName ) ; } } ) ;