@@ -7,6 +7,9 @@ const { stat, readFile, writeFile } = require('fs/promises');
7
7
const { join : joinPath } = require ( 'path' ) ;
8
8
const { spawn } = require ( 'child_process' ) ;
9
9
10
+ const { ApiModel } = require ( '@microsoft/api-extractor-model' ) ;
11
+ const { inspect } = require ( 'util' ) ;
12
+
10
13
class APIPrinterError extends Error { }
11
14
12
15
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');
28
31
const DOC_MODEL = joinPath ( DRIVER_REPO_DIR , 'etc/api.json' ) ;
29
32
30
33
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
-
36
34
const repoExists = await stat ( DRIVER_REPO_DIR ) . then ( statRes => statRes . isDirectory ( ) ) ;
37
35
if ( ! repoExists ) {
38
36
throw new APIPrinterError ( 'You must clone the driver repo next to this script' ) ;
@@ -50,33 +48,56 @@ async function getDriverAPI() {
50
48
return await readJSON ( DOC_MODEL ) ;
51
49
}
52
50
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 ) ;
74
76
}
77
+ recursivelyWalkApi ( member ) ;
75
78
}
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
+ ) ;
77
98
}
78
99
79
- main ( )
100
+ main ( process . argv )
80
101
. then ( ( ) => {
81
102
process . exitCode = 0 ;
82
103
} )
0 commit comments