Files
discordeno/scripts/openApiSchema.js
Fleny 919474069d chore: Migrate ESLint and prettier to Biome (#3634)
* Migrate eslint and prettier to biomejs

This does NOT include examples/bigbot as it has its own formatter

* Update to biome 1.8.0

* Readd dotenv dev dependency to rest

During a merge it got lost
2024-07-13 13:05:02 -05:00

127 lines
3.9 KiB
JavaScript

/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import fs from 'fs'
// TODO: replace with fetch of live spec
const DISCORD_SPEC = {}
function schemaRefToName(ref) {
if (!ref) return ''
return `Discord${ref?.substring(ref.lastIndexOf('/') + 1)}`
}
function snakeToPascalCase(str) {
if (!str.includes('_')) return str
let result = ''
for (let i = 0, len = str.length; i < len; ++i) {
if (str[i] === '_') {
result += str[++i].toUpperCase()
continue
}
result += str[i]
}
return result
}
function generateFromSpec() {
const finalTypings = []
for (const [key, schema] of Object.entries(DISCORD_SPEC.components.schemas)) {
const interfacey = [`export interface Discord${key} {`]
if (schema.properties) {
for (const [name, property] of Object.entries(schema.properties)) {
const type = Array.isArray(property.type) ? property.type : property.type ? [property.type] : undefined
let ref = property.$ref && schemaRefToName(property.$ref)
let allOf = property.allOf?.find((a) => a.$ref)
if (allOf) {
allOf = schemaRefToName(allOf.$ref)
}
const isArray = property.type === 'array'
if (isArray) {
if (property.items.$ref) ref = schemaRefToName(property.items.$ref)
else if (Array.isArray(property.oneOf)) {
ref = property.oneOf.map((o) => schemaRefToName(o.$ref)).join(' | ')
}
}
if (property.description) {
interfacey.push(` /** ${property.description} */`)
}
let cleanType =
ref ??
allOf ??
type
?.map((type) =>
type === 'integer'
? 'number'
: type === 'array'
? property.items.$ref
? `${schemaRefToName(property.items.$ref)}[]`
: Array.isArray(property.items.oneOf)
? `${property.items.oneOf.map((o) => `${schemaRefToName(o.$ref)}[]`).join(' | ')}`
: `unknown[]`
: type,
)
.join(' | ') ??
property.oneOf
?.map(
(o) =>
(o.type
? o.type === 'integer'
? o.enum
? o.allOf.map((a) => schemaRefToName(a.$ref)).join(' | ')
: 'number'
: o.type
: undefined) ?? schemaRefToName(o.$ref),
)
.join(' | ') ??
'unknown'
if (cleanType.startsWith('null | ')) cleanType = cleanType.substring(cleanType.indexOf('|') + 2) + ' | null'
interfacey.push(` ${name}${schema.required?.includes(name) ? ':' : '?:'} ${cleanType}`)
}
} else {
// No properties so is enum
if (['integer', 'string'].includes(schema.type) && Array.isArray(schema.oneOf)) {
const enumm = [`export enum Discord${key} {`]
for (const possible of schema.oneOf) {
if (possible.description) enumm.push(` /** ${possible.description} */`)
// TODO: camel case the title
enumm.push(
` ${possible.title.includes('-') ? '"' : ''}${snakeToPascalCase(
`${possible.title[0].toUpperCase()}${possible.title.substring(1).toLowerCase()}`,
)}${possible.title.includes('-') ? '"' : ''} = ${schema.type === 'string' ? '"' : ''}${possible.const}${
schema.type === 'string' ? '"' : ''
},`,
)
}
enumm.push('}')
finalTypings.push(enumm.join('\n'))
continue
}
console.log('NO PROPERTIES', key, schema)
continue
}
interfacey.push('}')
finalTypings.push(interfacey.join('\n'))
}
fs.writeFileSync('./packages/types/src/discord.ts', finalTypings.join('\n\n'), function (err, _result) {
if (err) throw err
})
}
generateFromSpec()