Added documentation generator

This commit is contained in:
delvedor
2019-02-14 07:57:16 +01:00
parent 8cd8dd3410
commit 5a18409a61
3 changed files with 180 additions and 8 deletions

View File

@ -7,7 +7,13 @@ const semver = require('semver')
const ora = require('ora')
const rimraf = require('rimraf')
const standard = require('standard')
const { generate, cloneAndCheckout, genFactory, generateRequestTypes } = require('./utils')
const {
generate,
cloneAndCheckout,
genFactory,
generateRequestTypes,
generateDocs
} = require('./utils')
start(minimist(process.argv.slice(2), {
string: ['tag']
@ -23,6 +29,7 @@ function start (opts) {
const apiOutputFolder = join(packageFolder, 'api')
const mainOutputFile = join(packageFolder, 'index.js')
const typesOutputFile = join(packageFolder, 'generated.d.ts')
const docOutputFile = join(__dirname, '..', 'docs', 'reference.asciidoc')
const requestParamsOutputFile = join(packageFolder, 'requestParams.d.ts')
const allSpec = []
@ -35,8 +42,11 @@ function start (opts) {
return
}
readdirSync(apiFolder).forEach(generateApiFile(apiFolder, log))
readdirSync(xPackFolder).forEach(generateApiFile(xPackFolder, log))
const apiFolderContents = readdirSync(apiFolder)
const xPackFolderContents = readdirSync(xPackFolder)
apiFolderContents.forEach(generateApiFile(apiFolder, log))
xPackFolderContents.forEach(generateApiFile(xPackFolder, log))
writeFileSync(
requestParamsOutputFile,
@ -55,7 +65,21 @@ function start (opts) {
types,
{ encoding: 'utf8' }
)
lintFiles(log)
lintFiles(log, () => {
log.text = 'Generating documentation'
const allSpec = apiFolderContents.filter(f => f !== '_common.json')
.map(f => require(join(apiFolder, f)))
.concat(xPackFolderContents.map(f => require(join(xPackFolder, f))))
writeFileSync(
docOutputFile,
generateDocs(require(join(apiFolder, '_common.json')), allSpec),
{ encoding: 'utf8' }
)
log.succeed('Done!')
console.log('Remember to copy the generated types into the index.d.ts file')
})
})
function generateApiFile (apiFolder, log) {
@ -77,15 +101,14 @@ function start (opts) {
}
}
function lintFiles (log) {
function lintFiles (log, cb) {
log.text = 'Linting...'
const files = [join(packageFolder, '*.js'), join(apiOutputFolder, '*.js')]
standard.lintFiles(files, { fix: true }, err => {
if (err) {
return log.fail(err.message)
}
log.succeed('Done!')
console.log('Remember to copy the generated types into the index.d.ts file')
cb()
})
}
}

View File

@ -0,0 +1,142 @@
'use strict'
const dedent = require('dedent')
function generateDocs (common, spec) {
var doc = '= API Reference\n\n'
doc += commonParameters(common)
spec.forEach(s => {
doc += '\n' + generateApiDoc(s)
})
return doc
}
function commonParameters (spec) {
var doc = dedent`
=== Common parameters
Parameters that are accepted by all API endpoints.
https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html
[cols=2*]
|===\n`
Object.keys(spec.params).forEach(key => {
const name = isSnakeCased(key) && key !== camelify(key)
? '`' + key + '` or `' + camelify(key) + '`'
: '`' + key + '`'
doc += dedent`
|${name}
|${'`' + spec.params[key].type + '`'} - ${spec.params[key].description}`
if (spec.params[key].default) {
doc += ` +
_Default:_ ${'`' + spec.params[key].default + '`'}`
}
doc += '\n\n'
})
doc += dedent`
|===
`
return doc
}
function generateApiDoc (spec) {
const name = Object.keys(spec)[0]
const documentationUrl = spec[name].documentation
const params = []
// url params
const urlParts = spec[name].url.parts
if (urlParts) {
Object.keys(urlParts).forEach(param => {
params.push({
name: param,
type: getType(urlParts[param].type, urlParts[param].options),
description: urlParts[param].description,
default: urlParts[param].default
})
})
}
// query params
const urlParams = spec[name].url.params
if (urlParams) {
Object.keys(urlParams).forEach(param => {
params.push({
name: param,
type: getType(urlParams[param].type, urlParams[param].options),
description: urlParams[param].description,
default: urlParams[param].default
})
})
}
// body params
const body = spec[name].body
if (body) {
params.push({
name: 'body',
type: 'object',
description: body.description,
default: body.default
})
}
var doc = dedent`
=== ${camelify(name)}
[source,js]
----
client.${camelify(name)}([params] [, options] [, callback])
----
${documentationUrl || ''}
[cols=2*]
|===`
doc += '\n' + params.reduce((acc, val) => {
const name = isSnakeCased(val.name) && val.name !== camelify(val.name)
? '`' + val.name + '` or `' + camelify(val.name) + '`'
: '`' + val.name + '`'
acc += dedent`
|${name}
|${'`' + val.type + '`'} - ${val.description}`
if (val.default) {
acc += ` +
_Default:_ ${'`' + val.default + '`'}`
}
return acc + '\n\n'
}, '')
doc += dedent`
|===
`
return doc
}
function getType (type, options) {
switch (type) {
case 'list':
return 'string, string[]'
case 'date':
case 'time':
case 'timeout':
return 'string'
case 'enum':
return options.map(k => `'${k}'`).join(', ')
case 'int':
case 'double':
case 'long':
return 'number'
default:
return type
}
}
function camelify (str) {
return str[0] === '_'
? '_' + str.slice(1).replace(/_([a-z])/g, k => k[1].toUpperCase())
: str.replace(/_([a-z])/g, k => k[1].toUpperCase())
}
function isSnakeCased (str) {
return !!~str.indexOf('_')
}
module.exports = generateDocs

View File

@ -4,5 +4,12 @@ const generate = require('./generate')
const generateRequestTypes = require('./generateRequestTypes')
const cloneAndCheckout = require('./clone-es')
const genFactory = require('./genMain')
const generateDocs = require('./generateDocs')
module.exports = { generate, cloneAndCheckout, genFactory, generateRequestTypes }
module.exports = {
generate,
cloneAndCheckout,
genFactory,
generateRequestTypes,
generateDocs
}