Skip to content

Commit 17dbe5b

Browse files
authored
chore(NODE-4568): add api-extractor script (#4)
1 parent eb71df5 commit 17dbe5b

File tree

5 files changed

+548
-44
lines changed

5 files changed

+548
-44
lines changed

etc/print_async_api.js

+49-28
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ const { stat, readFile, writeFile } = require('fs/promises');
77
const { join: joinPath } = require('path');
88
const { spawn } = require('child_process');
99

10+
const { ApiModel } = require('@microsoft/api-extractor-model');
11+
const { inspect } = require('util');
12+
1013
class APIPrinterError extends Error {}
1114

1215
const readJSON = async filePath => JSON.parse(await readFile(filePath, { encoding: 'utf8' }));
@@ -28,11 +31,6 @@ const API_CONFIG = joinPath(DRIVER_REPO_DIR, 'api-extractor.json');
2831
const DOC_MODEL = joinPath(DRIVER_REPO_DIR, 'etc/api.json');
2932

3033
async function getDriverAPI() {
31-
const apiExists = await stat(DOC_MODEL).then(statRes => statRes.isFile());
32-
if (apiExists) {
33-
return await readJSON(DOC_MODEL);
34-
}
35-
3634
const repoExists = await stat(DRIVER_REPO_DIR).then(statRes => statRes.isDirectory());
3735
if (!repoExists) {
3836
throw new APIPrinterError('You must clone the driver repo next to this script');
@@ -50,33 +48,56 @@ async function getDriverAPI() {
5048
return await readJSON(DOC_MODEL);
5149
}
5250

53-
async function main() {
54-
const api = await getDriverAPI();
55-
56-
const packageMembers = api.members[0].members;
57-
58-
for (const classDescription of packageMembers.filter(m => m.kind === 'Class')) {
59-
const className = classDescription.name;
60-
const methodsPrinted = new Set();
61-
for (const methodDescription of classDescription.members.filter(m => m.kind === 'Method')) {
62-
/** @type {string} */
63-
const returnType = methodDescription.excerptTokens
64-
.slice(
65-
methodDescription.returnTypeTokenRange.startIndex,
66-
methodDescription.returnTypeTokenRange.endIndex
67-
)
68-
.map(token => token.text.replaceAll('\n', '').replace(/\s\s+/g, ' '))
69-
.join('');
70-
if (returnType.includes('Promise<') && !methodsPrinted.has(methodDescription.name)) {
71-
methodsPrinted.add(methodDescription.name);
72-
const apiString = `${className}.${methodDescription.name}(): ${returnType}`;
73-
console.log(apiString);
51+
/**
52+
* @param {string[]} args
53+
*/
54+
async function main(args) {
55+
if (args.includes('build:api')) {
56+
return await getDriverAPI();
57+
}
58+
const apiModel = new ApiModel();
59+
const apiPackage = apiModel.loadPackage(DOC_MODEL);
60+
61+
const apiList = [];
62+
63+
const recursivelyWalkApi = rootMember => {
64+
if (rootMember == null) {
65+
return;
66+
}
67+
const printedMethods = new Set(); // make overloads only print once
68+
for (const member of rootMember.members) {
69+
if (member.kind === 'Method') {
70+
/** @type {string} */
71+
const returnType = member.returnTypeExcerpt.text;
72+
if (returnType.includes('Promise<') && !printedMethods.has(member.name)) {
73+
apiList.push({ className: member.parent.name, method: member.name, returnType });
74+
}
75+
printedMethods.add(member.name);
7476
}
77+
recursivelyWalkApi(member);
7578
}
76-
}
79+
};
80+
recursivelyWalkApi(apiPackage);
81+
82+
writeFile(
83+
'test/tools/api.new.js', // use new in the name to not override the source of truth
84+
Buffer.from(
85+
`/* eslint-disable prettier/prettier */
86+
'use strict';
87+
88+
module.exports = Object.create(null);
89+
Object.defineProperty(module.exports, '__esModule', { value: true });
90+
91+
module.exports.asyncApi = [
92+
${apiList.map(v => inspect(v, { depth: Infinity, breakLength: Infinity })).join(',\n ')}
93+
];
94+
`,
95+
'utf8'
96+
)
97+
);
7798
}
7899

79-
main()
100+
main(process.argv)
80101
.then(() => {
81102
process.exitCode = 0;
82103
})

0 commit comments

Comments
 (0)