-
-
Notifications
You must be signed in to change notification settings - Fork 209
/
genereteDocs.ts
140 lines (114 loc) · 3.71 KB
/
genereteDocs.ts
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import { MethodDeclaration, Project, SourceFile } from 'ts-morph'
import { allowedApis } from './api/lib/ZwaveClient'
import { readFile, writeFile } from 'fs/promises'
import * as prettier from 'prettier'
import { join } from 'path'
// Make the linter happy
export async function formatWithPrettier(
filename: string,
sourceText: string,
): Promise<string> {
const prettierOptions = {
...require(join(__dirname, '.prettierrc.js')),
// To infer the correct parser
filepath: filename,
}
return await prettier.format(sourceText, prettierOptions)
}
// Inpired by https://github.com/zwave-js/node-zwave-js/blob/master/packages/maintenance/src/generateTypedDocs.ts#L334
async function main() {
const program = new Project({ tsConfigFilePath: 'tsconfig.json' })
const fileName = './api/lib/ZwaveClient.ts'
const docsFile = './docs/guide/mqtt.md'
const sourceFile = program.getSourceFileOrThrow(fileName)
const text = await formatWithPrettier(docsFile, mqttApis(sourceFile))
const content = await readFile(docsFile, 'utf8')
const startPlaceholder = '<!-- AUTO GENERATED START -->'
const endPlaceholder = '<!-- AUTO GENERATED END -->'
const start = content.indexOf(startPlaceholder) + startPlaceholder.length
const end = content.indexOf(endPlaceholder)
const newContent =
content.substring(0, start) + '\n' + text + content.substring(end)
await writeFile(docsFile, newContent)
}
function printMethodDeclaration(method: MethodDeclaration): string {
method = method.toggleModifier('public', false)
method.getDecorators().forEach((d) => d.remove())
const start = method.getStart()
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const end = method.getBody().getStart()
let ret = method
.getText()
.substring(0, end - start)
.trim()
if (!method.getReturnTypeNode()) {
ret += ': ' + method.getSignature().getReturnType().getText(method)
}
ret += ';'
return fixPrinterErrors(ret)
}
function fixPrinterErrors(text: string): string {
return (
text
// The text includes one too many tabs at the start of each line
.replace(/^\t(\t*)/gm, '$1')
// TS 4.2+ has some weird printing bug for aliases: https://github.com/microsoft/TypeScript/issues/43031
.replace(/(\w+) \| \("unknown" & { __brand: \1; }\)/g, 'Maybe<$1>')
)
}
function printOverload(method: MethodDeclaration): string {
method = method.toggleModifier('public', false)
return fixPrinterErrors(method.getText())
}
function mqttApis(file: SourceFile) {
const ZwaveClientClass = file
.getClasses()
.find((c) => c.getName() === 'ZwaveClient')
if (!ZwaveClientClass) throw new Error('ZwaveClient class not found')
const methods = ZwaveClientClass.getInstanceMethods().filter((c) =>
allowedApis.includes(c.getName() as any),
)
let text = ''
for (const method of methods) {
const signatures = method.getOverloads()
text += `#### \`${method.getName()}\`
\`\`\`ts
${
signatures.length > 0
? signatures.map(printOverload).join('\n\n')
: printMethodDeclaration(method)
}
\`\`\`
`
const doc = method.getStructure().docs?.[0]
if (typeof doc === 'string') {
text += doc + '\n\n'
} else if (doc != undefined) {
if (typeof doc.description === 'string') {
let description = doc.description.trim()
if (!description.endsWith('.')) {
description += '.'
}
text += description + '\n\n'
}
}
const params = method.getParameters()
text += `<details>
<summary>Mqtt usage</summary>
Topic: \`zwave/_CLIENTS/ZWAVE_GATEWAY-<mqtt_name>/api/${method.getName()}/set\`
Payload:
\`\`\`json
{
"args": [${
params.length > 0
? '\n\t\t' + params.map((p) => p.getName()).join(',\n\t\t') + '\n\t'
: ''
}]
}
\`\`\`
</details>\n\n`
}
return text
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
main()