Files
supabase/apps/docs/generator/api.ts

115 lines
3.1 KiB
TypeScript

import template from './templates/ApiTemplate'
import { slugify, toArrayWithKey, toTitle, writeToDisk } from './helpers'
import type { OpenAPIV3, OpenAPIV2 } from 'openapi-types'
import * as fs from 'fs'
import * as ejs from 'ejs'
export default async function gen(inputFileName: string, outputDir: string, apiUrl: string) {
const specRaw = fs.readFileSync(inputFileName, 'utf8')
const spec = JSON.parse(specRaw) as any
switch (spec.openapi || spec.swagger) {
case '3.0.0':
case '3.0.3':
await gen_v3(spec, outputDir, { apiUrl })
break
case '2.0':
await gen_v2(spec, outputDir, { apiUrl })
break
default:
console.log('Unrecognized specification version:', spec.openapi)
break
}
}
/**
* Versioned Generator
*/
// OPENAPI-SPEC-VERSION: 3.0.0
type v3OperationWithPath = OpenAPIV3.OperationObject & {
path: string
}
export type enrichedOperation = OpenAPIV3.OperationObject & {
path: string
fullPath: string
operationId: string
}
async function gen_v3(spec: OpenAPIV3.Document, dest: string, { apiUrl }: { apiUrl: string }) {
const specLayout = spec.tags || []
const operations: enrichedOperation[] = []
Object.entries(spec.paths).forEach(([key, val]) => {
const fullPath = `${apiUrl}${key}`
toArrayWithKey(val!, 'operation').forEach((o) => {
const operation = o as v3OperationWithPath
const enriched = {
...operation,
path: key,
fullPath,
operationId: slugify(operation.summary!),
responseList: toArrayWithKey(operation.responses!, 'responseCode') || [],
}
operations.push(enriched)
})
})
const sections = specLayout.map((section) => {
return {
...section,
title: toTitle(section.name),
id: slugify(section.name),
operations: operations.filter((operation) => operation.tags?.includes(section.name)),
}
})
const content = ejs.render(template, {
info: spec.info,
sections,
operations,
})
// Write to disk
await writeToDisk(dest, content)
console.log('Saved: ', dest)
}
// OPENAPI-SPEC-VERSION: 2.0
async function gen_v2(spec: OpenAPIV2.Document, dest: string, { apiUrl }: { apiUrl: string }) {
const specLayout = spec.tags || []
const operations: enrichedOperation[] = []
Object.entries(spec.paths).forEach(([key, val]) => {
const fullPath = `${apiUrl}${key}`
toArrayWithKey(val!, 'operation').forEach((o) => {
const operation = o as v3OperationWithPath
const enriched = {
...operation,
path: key,
fullPath,
operationId: slugify(operation.summary!),
responseList: toArrayWithKey(operation.responses!, 'responseCode') || [],
}
operations.push(enriched)
})
})
const sections = specLayout.map((section) => {
return {
...section,
title: toTitle(section.name),
id: slugify(section.name),
operations: operations.filter((operation) => operation.tags?.includes(section.name)),
}
})
const content = ejs.render(template, {
info: spec.info,
sections,
operations,
})
// Write to disk
await writeToDisk(dest, content)
console.log('Saved: ', dest)
}