Skip to content

Commit

Permalink
feat: update doc api to use generated doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Orange Mi committed Jan 5, 2022
1 parent 58f8a3c commit d5b0449
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 6 deletions.
86 changes: 86 additions & 0 deletions classes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
[
{
"name": "MongodbCollectionRecordStorageBllImpl",
"documentation": "",
"type": "typeof MongodbCollectionRecordStorageBllImpl",
"constructors": [
{
"parameters": [
{
"name": "options",
"documentation": "",
"type": "{ dbClient?: MongoClient; }"
}
],
"returnType": "MongodbCollectionRecordStorageBllImpl",
"documentation": ""
}
]
},
{
"name": "MongodbCollectionRecordQueryBllImpl",
"documentation": "",
"type": "typeof MongodbCollectionRecordQueryBllImpl",
"constructors": [
{
"parameters": [
{
"name": "options",
"documentation": "",
"type": "{ dbClient?: MongoClient; }"
}
],
"returnType": "MongodbCollectionRecordQueryBllImpl",
"documentation": ""
}
]
},
{
"name": "RecordBllImpl",
"documentation": "",
"type": "typeof RecordBllImpl",
"constructors": [
{
"parameters": [
{
"name": "options",
"documentation": "",
"type": "{ recordStorageBll?: RecordStorageBll; recordQueryBll?: RecordQueryBll<any, any>; }"
}
],
"returnType": "RecordBllImpl",
"documentation": ""
}
]
},
{
"name": "RecordAuthBll",
"documentation": "",
"type": "typeof RecordAuthBll",
"constructors": [
{
"parameters": [],
"returnType": "RecordAuthBll",
"documentation": ""
}
]
},
{
"name": "RecordAPI",
"documentation": "Function2 2023423i",
"type": "typeof RecordAPI",
"constructors": [
{
"parameters": [
{
"name": "options",
"documentation": "",
"type": "{ recordBll?: RecordStorageBll & RecordQueryBll<any, any>; }"
}
],
"returnType": "RecordAPI",
"documentation": ""
}
]
}
]
5 changes: 5 additions & 0 deletions docs/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ paths:
summary: Query Record in JSON Array Mode
tags:
- Record API
params:
- name: xxx
in: path
- name: yyy
in: header
requestBody:
content:
application/json:
Expand Down
10 changes: 6 additions & 4 deletions src/api/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from 'path'
import * as yaml from 'js-yaml'
import * as config from 'config'
import { before, controller, get } from '../http-server/decorator'
import { generateOpenApiDoc } from '../http-server/openapi'
import * as createHttpError from 'http-errors'

let openapi: any
Expand All @@ -19,9 +20,10 @@ let openapi: any
export class VersionAPI {
@get('/')
async doc() {
if (!openapi) {
openapi = yaml.load(fs.readFileSync(path.resolve(__dirname, '../../docs/api.yml'), {encoding: 'utf-8'}))
}
return openapi
// if (!openapi) {
// openapi = yaml.load(fs.readFileSync(path.resolve(__dirname, '../../docs/api.yml'), {encoding: 'utf-8'}))
// }
// return openapi
return generateOpenApiDoc()
}
}
18 changes: 17 additions & 1 deletion src/api/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export function resultMW(): MiddlewareFn {
}
}

/** Function2 2023423i
* @summary ggg
* @description ggghhh
*/
@controller('/api/record')
@before(async (ctx) => {
let token = ctx.get('authorization') as string || ''
Expand Down Expand Up @@ -159,12 +163,21 @@ export class RecordAPI {
return records
}

/**
* @summary abc create record api
* @description bcd balala
* @response
* schema:
* type: object
* properties:
* result:
*/
@post('/create')
@validator({
type: 'object',
required: ['spaceId', 'entityId'],
properties: {
id: { type: 'string' },
id: { type: 'string', summary: 'xxx', description: 'yyy' },
spaceId: { type: 'string' },
entityId: { type: 'string' },
cf: { type: 'object' },
Expand All @@ -183,6 +196,9 @@ export class RecordAPI {
return record
}

/**
* @description bcc l999
*/
@post('/update')
@validator({
type: 'object',
Expand Down
11 changes: 11 additions & 0 deletions src/api/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ try {
})
export class VersionAPI {
@get('/')
@skipLogger()
async version() {
return version
}
@get('/')
@skipLogger()
async version() {
return version
}
@get('/')
@skipLogger()
async version() {
return version
}
Expand Down
2 changes: 1 addition & 1 deletion src/http-server/decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface RouteMeta {
propertyName: string
}

const controllerMap = new Map<ControllerConstructor, ControllerMeta>()
export const controllerMap = new Map<ControllerConstructor, ControllerMeta>()
// const controllers: ControllerMeta[] = []

export function controller(prefix = '/') {
Expand Down
107 changes: 107 additions & 0 deletions src/http-server/jsdoc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as ts from "typescript"
import * as fs from "fs"

interface DocEntry {
name?: string
fileName?: string
documentation?: string
type?: string
constructors?: DocEntry[]
parameters?: DocEntry[]
returnType?: string
}

/** Generate documentation for all classes in a set of .ts files */
function generateDocumentation(
fileNames: string[],
options: ts.CompilerOptions
): void {
// Build a program using the set of root file names in fileNames
const program = ts.createProgram(fileNames, options)

// Get the checker, we will use it to find more about classes
const checker = program.getTypeChecker()
const output: DocEntry[] = []

// Visit every sourceFile in the program
for (const sourceFile of program.getSourceFiles()) {
if (!sourceFile.isDeclarationFile) {
// Walk the tree to search for classes
ts.forEachChild(sourceFile, visit)
}
}

// // print out the doc
fs.writeFileSync("classes.json", JSON.stringify(output, undefined, 4))

return

/** visit nodes finding exported classes */
function visit(node: ts.Node) {
// Only consider exported nodes
if (!isNodeExported(node)) {
return
}

if (ts.isClassDeclaration(node) && node.name) {
// This is a top level class, get its symbol
const symbol = checker.getSymbolAtLocation(node.name)
if (symbol) {
output.push(serializeClass(symbol))
}
// No need to walk any further, class expressions/inner declarations
// cannot be exported
} else if (ts.isModuleDeclaration(node)) {
// This is a namespace, visit its children
ts.forEachChild(node, visit)
}
}

/** Serialize a symbol into a json object */
function serializeSymbol(symbol: ts.Symbol): DocEntry {
return {
name: symbol.getName(),
documentation: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
type: checker.typeToString(
checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration!)
)
}
}

/** Serialize a class symbol information */
function serializeClass(symbol: ts.Symbol) {
const details = serializeSymbol(symbol)

// Get the construct signatures
const constructorType = checker.getTypeOfSymbolAtLocation(
symbol,
symbol.valueDeclaration!
)
details.constructors = constructorType
.getConstructSignatures()
.map(serializeSignature)
return details
}

/** Serialize a signature (call or construct) */
function serializeSignature(signature: ts.Signature) {
return {
parameters: signature.parameters.map(serializeSymbol),
returnType: checker.typeToString(signature.getReturnType()),
documentation: ts.displayPartsToString(signature.getDocumentationComment(checker))
}
}

/** True if this is visible outside this file, false otherwise */
function isNodeExported(node: ts.Node): boolean {
return (
(ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export) !== 0 ||
(!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
)
}
}

generateDocumentation(process.argv.slice(2), {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS
})
Loading

0 comments on commit d5b0449

Please sign in to comment.