forked from octokit/octokit.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate-api-docs.js
117 lines (96 loc) · 3.57 KB
/
generate-api-docs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env node
const { writeFileSync } = require('fs')
const { join: pathJoin } = require('path')
const camelCase = require('lodash.camelcase')
const upperFirst = require('lodash.upperfirst')
const ROUTES = require('./lib/get-routes')()
const API_DOC_PATH = pathJoin(__dirname, '..', 'doc', 'apidoc.js')
const apiDocs = Object.keys(ROUTES)
.filter(namespaceName => namespaceName !== 'scim')
.map(namespaceName => prepareNamespace(namespaceName))
.join('\n\n\n')
function prepareNamespace (namespaceName) {
return [toSectionComment(namespaceName)]
.concat(
ROUTES[namespaceName]
.filter(endpoint => !/legacy$/.test(endpoint.idName))
.map(endpoint => toApiComment(namespaceName, endpoint.idName, endpoint))
).join('\n\n\n')
}
function toSectionComment (namespaceName) {
return `
/**,
* ${upperFirst(namespaceName)}
* @namespace ${upperFirst(namespaceName)}
*/`
}
function toApiComment (namespaceName, apiName, endpoint) {
if (!endpoint.method) {
throw new Error(
`No HTTP method specified for ${namespaceName}.${apiName} in @octokit/routes`
)
}
const method = endpoint.method.toUpperCase()
const params = endpoint.params
const descriptionWithLinkToV3Docs = [
endpoint.description,
`<a href="${endpoint.documentationUrl}">REST API doc</a>`
].filter(Boolean).join('\n\n')
const commentLines = [
'/**',
` * @api {${method}} ${endpoint.path} ${apiName}`,
` * @apiName ${apiName}`,
` * @apiDescription ${descriptionWithLinkToV3Docs}`,
` * @apiGroup ${upperFirst(namespaceName)}`,
' *'
].concat(
params.map(toApiParamComment)
)
const paramsString = params.map(param => param.name).join(', ')
if (endpoint.deprecated) {
const message = `octokit.${namespaceName}.${camelCase(endpoint.deprecated.before.idName)}() has been renamed to octokit.${namespaceName}.${camelCase(endpoint.deprecated.after.idName)}() (${endpoint.deprecated.date})`
commentLines.push(` * @apiDeprecated ${message}`)
}
return commentLines.concat([
' * @apiExample {js} async/await',
` * const result = await octokit.${namespaceName}.${apiName}({${paramsString}})`,
' * @apiExample {js} Promise',
` * octokit.${namespaceName}.${apiName}({${paramsString}}).then(result => {})`
]).join('\n') + '\n */'
}
function toApiParamComment (paramInfo) {
const paramRequired = paramInfo['required']
const paramDescription = paramInfo['description'] || ''
const paramDefaultVal = paramInfo['default']
const paramType = paramInfo['type']
.toLowerCase()
// https://github.com/octokit/rest.js/issues/721
.replace('string | object', 'object')
let paramLabel = paramInfo.name
// add default value if there is one
if (typeof paramDefaultVal !== 'undefined') {
paramLabel += `="${String(paramDefaultVal).replace(/[<>]/g, '')}"`
}
// show param as either required or optional
if (!paramRequired) {
paramLabel = `[${paramLabel}]`
}
let allowedValues = ''
if (paramInfo['enum']) {
allowedValues = `=${paramInfo['enum'].join(',')}`
}
return ` * @apiParam {${paramType}${allowedValues}} ${paramLabel.replace(/\./g, ':').replace(/\[\]/g, '')} ${paramDescription}`
}
// function sortByRequired (api, paramA, paramB) {
// const paramInfoA = api[paramA]
// const paramInfoB = api[paramB]
//
// const aIsRequired = paramInfoA['required']
// const bIsRequired = paramInfoB['required']
//
// if (aIsRequired && !bIsRequired) return -1
// if (!aIsRequired && bIsRequired) return 1
// return 0
// }
writeFileSync(API_DOC_PATH, apiDocs.trim() + '\n')
console.log(`${API_DOC_PATH} written.`)