• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const path = require('path');
17const fs = require('fs');
18const ts = require('typescript');
19const ExcelJS = require('exceljs');
20const applicationModules = [];
21
22const typeCollection = false;
23const isNotMerge = false;
24
25function parse(files) {
26    const fileContentList = [];
27    files.forEach(file => {
28        let fileContent = fs.readFileSync(file, 'utf-8');
29        fileContentList.push({
30            fileName: path.basename(file).replace(/.d.ts$/g, '.ts'),
31            fileContent: fileContent,
32            fileRoot: file.replace(dir, "")
33        })
34    });
35    const api = [];
36    const exportApi = [];
37    const returnDeclarationArr = new Set([]);
38    const hash = new Set([]);
39    fileContentList.forEach(item => {
40        const fileName = item.fileName.replace(/\.d.ts$/g, '.ts');
41        let packageName = item.fileRoot.indexOf("component\\ets\\") >= 0 ||
42            item.fileRoot.indexOf("component/ets/") >= 0 ? "ArkUI" : fileName.replace(/\@|.ts$/g, "").replace(/D:\\/g, "");
43        ts.transpileModule(item.fileContent, {
44            compilerOptions: {
45                "target": ts.ScriptTarget.ES2017
46            },
47            fileName: fileName,
48            transformers: { before: [getReturnDeclarationArr(packageName, exportApi, returnDeclarationArr, fileName)] }
49        })
50    });
51    fileContentList.forEach(item => {
52        const fileName = item.fileName.replace(/\.d.ts$/g, '.ts');
53        let packageName = item.fileRoot.indexOf("component\\ets\\") >= 0 ||
54            item.fileRoot.indexOf("component/ets/") >= 0 ? "ArkUI" : fileName.replace(/\@|.ts$/g, "").replace(/D:\\/g, "");
55        ts.transpileModule(item.fileContent, {
56            compilerOptions: {
57                "target": ts.ScriptTarget.ES2017
58            },
59            fileName: fileName,
60            transformers: { before: [processDeclarationSourceFile(packageName, api, exportApi, returnDeclarationArr, hash)] }
61        })
62    });
63    return api;
64}
65exports.parse = parse;
66
67
68function visitAllNode(node, returnDeclarationArr, packageName) {
69    if ((ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) && node && node.type &&
70        ts.isTypeReferenceNode(node.type)) {
71        returnDeclarationArr.add(node.type.typeName.getText())
72    }
73    if (ts.isModuleDeclaration(node) && ts.isModuleBlock(node.body) && node.body && node.body.statements) {
74        node.body.statements.forEach(statement => {
75            if (statement.name) {
76                applicationModules.push({
77                    packageName: packageName,
78                    className: node.name.escapedText,
79                    methodName: statement.name.escapedText
80                })
81            }
82        })
83    }
84    node.getChildren().forEach(item => visitAllNode(item, returnDeclarationArr, packageName));
85}
86function getExportApi(node, packageName, exportApi) {
87    node.statements.forEach(stat => {
88        if (ts.isModuleDeclaration(stat)) {
89            if (stat.getText().indexOf('namespace') > 0) {
90                let apiInfo = {
91                    isSystemApi: '公开API',
92                    version: '',
93                    deprecated: '',
94                    permission: 'N/A',
95                    sysCap: 'N/A',
96                    model: ''
97                }
98                exportApi.push({
99                    packageName: packageName,
100                    className: stat.name.escapedText.toString(),
101                    methodName: '',
102                    apiInfo: getApiInfo(stat, apiInfo)
103                })
104            }
105        }
106    });
107}
108const applicationModule = [];
109const getReturnDeclarationArr = (packageName, exportApi, returnDeclarationArr, fileName) => {
110    return (context) => {
111        return (node) => {
112            visitAllNode(node, returnDeclarationArr, packageName);
113            getExportApi(node, packageName, exportApi);
114            return node;
115        }
116    }
117}
118exports.applicationModules = applicationModules;
119
120function processDeclarationSourceFile(packageName, api, exportApi, returnDeclarationArr, hash) {
121    return (context) => {
122        return (node) => {
123            const statements = node.statements;
124            const currentClassFunSet = new Set([]);
125            const currentTypeList = new Array();
126            statements.forEach(stat => {
127                if (ts.isTypeAliasDeclaration(stat)) {
128                    if (stat.type.types) {
129                        let typeObj = {
130                            name: stat.name.escapedText,
131                            value: []
132                        }
133                        stat.type.types.forEach(type => {
134                            if (type.literal && type.literal.text) {
135                                typeObj.value.push(type.literal.text);
136                            }
137                        });
138                        if (typeObj.value.length > 0) {
139                            currentTypeList.push(typeObj);
140                        }
141                    }
142                }
143            })
144            statements.forEach(stat => {
145                let apiInfo = {
146                    isSystemApi: '公开API',
147                    version: '',
148                    deprecated: '',
149                    permission: 'N/A',
150                    sysCap: 'N/A',
151                    model: ''
152                }
153                if (ts.isInterfaceDeclaration(stat)) {
154                    collectInterfaceDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList);
155                } else if (ts.isModuleDeclaration(stat)) {
156                    collectModuleDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList);
157                } else if (ts.isClassDeclaration(stat)) {
158                    collectClassDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList);
159                } else if (ts.isEnumDeclaration(stat)) {
160                    collectEnumDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList);
161                } else if (ts.isTypeAliasDeclaration(stat)) {
162
163                } else {
164                    if (ts.isMethodDeclaration(stat) || ts.isMethodSignature(stat) || ts.isFunctionDeclaration(stat)) {
165                        var methodName = stat.name.escapedText ? stat.name.escapedText.toString() : stat.name.text.toString();
166                        let className = '';
167                        exportApi.forEach(item => {
168                            if (item.methodName == methodName && item.packageName == packageName) {
169                                className = item.className
170                                if (item.apiInfo) {
171                                    apiInfo = item.apiInfo;
172                                }
173                            }
174                        })
175                        addFunctionOnOffApi(packageName, className, methodName, getApiInfo(stat, apiInfo), 'Method', api,
176                            hash, currentClassFunSet, stat);
177                    }
178                }
179            })
180            return node;
181        }
182    }
183}
184
185function collectInterfaceDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList) {
186    const className = stat.name.escapedText.toString();
187    const interfaceChildren = stat.members;
188    collectEachChildNode(interfaceChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash,
189        getApiInfo(stat, apiInfo), currentTypeList)
190}
191
192function collectClassDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList) {
193    const className = stat.name.escapedText.toString();
194    const classChildren = stat.members;
195    collectEachChildNode(classChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash,
196        getApiInfo(stat, apiInfo), currentTypeList)
197}
198
199function collectEnumDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList) {
200    const className = stat.name.escapedText.toString();
201    const enumChildren = stat.members;
202    collectEachChildNode(enumChildren, packageName, className, 'Enum', api, exportApi, returnDeclarationArr, hash,
203        getApiInfo(stat, apiInfo), currentTypeList)
204}
205
206function collectModuleDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList) {
207    const className = stat.name.escapedText ? stat.name.escapedText.toString() : stat.name.text.toString();
208    const moduleChildren = stat.body.statements;
209    collectEachChildNode(moduleChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash,
210        getApiInfo(stat, apiInfo), currentTypeList)
211}
212
213function collectEachChildNode(children, packageName, className, faterApiType, api, exportApi, returnDeclarationArr,
214    hash, apiInfo, currentTypeList) {
215    const currentClassFunSet = new Set([]);
216    children.forEach(child => {
217        if (ts.isTypeAliasDeclaration(child)) {
218            if (child.type) {
219                let typeObj = {
220                    name: child.name.escapedText,
221                    value: []
222                }
223                if (child.type.types) {
224                    child.type.types?.forEach(type => {
225                        if (type.literal && type.literal.text) {
226                            typeObj.value.push(type.literal.text);
227                            if (typeCollection) {
228                                let faterApiInfo = JSON.parse(JSON.stringify(apiInfo));
229                                addApi(packageName, child.name.escapedText, type.literal.text, child.getText(),
230                                    getApiInfo(child, faterApiInfo), 'Type', api, hash);
231                            }
232                        } else {
233                            if (type.getText() != '') {
234                                typeObj.value.push(type.getText());
235                                if (typeCollection) {
236                                    let faterApiInfo = JSON.parse(JSON.stringify(apiInfo));
237                                    addApi(packageName, child.name.escapedText, type.getText(), child.getText(),
238                                        getApiInfo(child, faterApiInfo), 'Type', api, hash);
239                                }
240                            }
241                        }
242                    });
243                } else if (child.type.members) {
244                    child.type.members?.forEach(member => {
245                        member.type.types?.forEach(type => {
246                            if (type.literal && type.literal.text) {
247                                typeObj.value.push(type.literal.text);
248                                if (typeCollection) {
249                                    let faterApiInfo = JSON.parse(JSON.stringify(apiInfo));
250                                    addApi(packageName, child.name.escapedText, type.literal.text, child.getText(),
251                                        getApiInfo(child, faterApiInfo), 'Type', api, hash);
252                                }
253                            } else {
254                                if (type.getText() != '') {
255                                    typeObj.value.push(type.getText());
256                                    if (typeCollection) {
257                                        let faterApiInfo = JSON.parse(JSON.stringify(apiInfo));
258                                        addApi(packageName, className, child.name.escapedText, child.getText(),
259                                            getApiInfo(child, faterApiInfo), 'Type', api, hash);
260                                    }
261                                }
262                            }
263                        });
264                    })
265                }
266                if (typeObj.value.length > 0) {
267                    currentTypeList.push(typeObj)
268                }
269            }
270        }
271    });
272    children.forEach(child => {
273        let faterApiInfo = JSON.parse(JSON.stringify(apiInfo));
274        let apiType = new String(faterApiType);
275        if (/export.*\{.*\}/g.test(child.getText())) {
276            exportApi.push({
277                packageName: packageName,
278                className: className,
279                methodName: child.getText().replace("export", '').replace('{', '').replace('}', '').replace(';', '').trim(),
280                apiInfo: faterApiInfo
281            })
282            return
283        }
284        if (ts.isInterfaceDeclaration(child)) {
285            collectInterfaceDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo);
286        } else if (ts.isModuleDeclaration(child)) {
287            collectModuleDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo);
288        } else if (ts.isClassDeclaration(child)) {
289            collectClassDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo);
290        } else if (ts.isEnumDeclaration(child)) {
291            collectEnumDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo);
292        } else if (ts.isTypeAliasDeclaration(child)) {
293
294        } else {
295            if ((ts.isMethodDeclaration(child) || ts.isMethodSignature(child) || ts.isFunctionDeclaration(child)) &&
296                (child.name.escapedText === 'on' || child.name.escapedText === 'off') && child.parameters && child.parameters.length > 0) {
297                apiType = 'Method'
298                for (let i = 0; i < child.parameters.length; i++) {
299                    const param = child.parameters[i];
300                    if (param.name.escapedText === 'type' || param.name.escapedText === 'event' ||
301                        param.name.escapedText === 'eventType') {
302                        if (param.type && param.type.literal && param.type.literal.text) {
303                            const typeTextArr = param.getText().replace(/\s*/g, "").split(':');
304                            if (typeTextArr[0] === "type" || typeTextArr[0] === "event") {
305                                let methodName = child.name.escapedText + '_' + param.type.literal.text;
306                                addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
307                                    hash, currentClassFunSet, child);
308                            }
309                        } else if (param.type && param.type.types && param.type.types.length > 0) {
310                            param.type.types.forEach(type => {
311                                if (type.literal && type.literal.text) {
312                                    let methodName = child.name.escapedText + "_" + type.literal.text;
313                                    addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
314                                        hash, currentClassFunSet, child);
315                                }
316                            });
317                        } else if (param.type && param.type.typeName && param.type.typeName.escapedText) {
318                            if (currentTypeList && currentTypeList.length > 0) {
319                                currentTypeList.forEach(type => {
320                                    if (type.name == param.type.typeName.escapedText) {
321                                        type.value.forEach(typeString => {
322                                            let methodName = child.name.escapedText + "_" + typeString;
323                                            addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
324                                                hash, currentClassFunSet, child);
325                                        });
326                                    }
327                                });
328                            } else {
329                                let methodName = child.name.escapedText;
330                                addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
331                                    hash, currentClassFunSet, child);
332                            }
333                        } else {
334                            let methodName = child.name.escapedText;
335                            addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
336                                hash, currentClassFunSet, child);
337                        }
338                        break;
339                    } else {
340                        let methodName = child.name.escapedText;
341                        addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
342                            hash, currentClassFunSet, child);
343                    }
344
345                }
346            } else {
347                let methodName = "";
348                let methodText = "";
349                if (ts.isMethodDeclaration(child) || ts.isMethodSignature(child) || ts.isFunctionDeclaration(child) ||
350                    ts.isCallSignatureDeclaration(child) || ts.isConstructSignatureDeclaration(child) ||
351                    ts.isIndexSignatureDeclaration(child)) {
352                    if (child.name) {
353                        methodName = child.name.getText();
354                    } else {
355                        methodName = className;
356                    }
357                    apiType = 'Method'
358                } else if (ts.isPropertyDeclaration(child) || ts.isPropertySignature(child)) {
359                    if (child.type && child.type.parameters) {
360                        methodName = child.name.escapedText;
361                        apiType = 'Method'
362                    } else {
363                        methodName = child.name.escapedText;
364                        apiType = 'Field';
365                    }
366                } else {
367                    if (child.name) {
368                        methodName = child.name.getText();
369                    }
370                }
371                if (methodName !== "") {
372                    addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api,
373                        hash, currentClassFunSet, child);
374                } else {
375                    if (child.getText().indexOf("construnctor") == 0) {
376                        methodName = 'constructor';
377                        apiType = 'Method';
378                    } else if (child.getText().indexOf("const") == 0) {
379                        if (child.getText().replace("const", "").indexOf(":") > 0) {
380                            if (returnDeclarationArr.has(child.getText().replace("const", "").split(":")[1].trim())) {
381                                apiType = 'Field';
382                            } else {
383                                apiType = 'Constant';
384                            }
385                            methodName = child.getText().replace('const', "").split(":")[0].trim();
386                        } else if (child.getText().replace("const", "").indexOf("=") > 0) {
387                            if (returnDeclarationArr.has(child.getText().replace("const", "").split("=")[1].trim())) {
388                                apiType = 'Field';
389                            } else {
390                                apiType = 'Constant';
391                            }
392                            methodName = child.getText().replace('const', "").split("=")[0].trim();
393                        }
394                    } else if (/\w+:\s*\w+/g.test(child.getText())) {
395                        apiType = 'Field';
396                        methodName = child.getText().split(":")[0].trim()
397                    }
398                    if (methodName != '') {
399                        addApi(packageName, className, methodName, child.getText(),
400                            getApiInfo(child, faterApiInfo), apiType, api, hash);
401                    }
402                }
403            }
404        }
405    });
406}
407
408function addFunctionOnOffApi(packageName, className, methodName, apiInfo, apiType, api,
409    hash, currentClassFunSet, childNode) {
410    if (currentClassFunSet.has(methodName) && !isNotMerge) {
411        for (let i = 0; i < api.length; i++) {
412            const curApi = api[i];
413            if (curApi.packageName === packageName && curApi.className === className &&
414                curApi.methodName === methodName) {
415                if (curApi.methodText.indexOf(`${childNode.getText().replace('declare', '').trim()}`) < 0) {
416                    curApi.methodText += `<br>${childNode.getText().replace('declare', '').trim()}`;
417                    break;
418                }
419            }
420        }
421    } else {
422        if (!currentClassFunSet.has(methodName)) {
423            currentClassFunSet.add(methodName);
424            addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(),
425                getApiInfo(childNode, apiInfo), apiType, api, hash);
426        } else {
427            if (childNode.getFullText().indexOf('\/**') >= 0) {
428                addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(),
429                    getApiInfo(childNode, apiInfo), apiType, api, hash);
430            } else {
431                let firstApiInfo = {};
432                for (let i = 0; i < api.length; i++) {
433                    const curApi = api[i];
434                    if (curApi.packageName === packageName && curApi.className === className &&
435                        curApi.methodName === methodName) {
436                        firstApiInfo.isSystemApi = curApi.isSystemApi;
437                        firstApiInfo.version = curApi.version;
438                        firstApiInfo.sysCap = curApi.sysCap;
439                        firstApiInfo.permission = curApi.permission;
440                        firstApiInfo.model = curApi.model;
441                    }
442
443                }
444                addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(),
445                    firstApiInfo, apiType, api, hash);
446            }
447        }
448    }
449}
450function getApiInfo(node, apiInfo) {
451    const notesStr = node.getFullText().replace(node.getText(), "");
452    if (notesStr !== "") {
453        if (/\@[S|s][Y|y][S|s][T|t][E|e][M|m][A|a][P|p][I|i]/g.test(notesStr)) {
454            apiInfo.isSystemApi = '系统API'
455        }
456        if (/\@[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g.test(notesStr)) {
457            notesStr.replace(/\@[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g, (versionInfo) => {
458                apiInfo.version = versionInfo.replace(/\@[S|s][I|i][N|n][C|c][E|e]/g, '').trim();
459            })
460        }
461        if (/\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g.test(notesStr)) {
462            notesStr.replace(/\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g,
463                versionInfo => {
464                    apiInfo.deprecated = versionInfo.replace(
465                        /\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*/g, '').trim();
466                })
467        }
468        if (/\@[F|f][A|a][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g.test(notesStr)) {
469            notesStr.replace(/\@[F|f][A|a][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g, modelInfo => {
470                apiInfo.model = modelInfo;
471            })
472        } else if (/\@[S|s][T|t][A|a][G|g][E|e][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g.test(notesStr)) {
473            notesStr.replace(/\@[S|s][T|t][A|a][G|g][E|e][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g, modelInfo => {
474                apiInfo.model = modelInfo;
475            })
476        }
477        if (/\@[S|s][Y|y][S|s][C|c][A|a][P|p]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) {
478            notesStr.replace(/\@[S|s][Y|y][S|s][C|c][A|a][P|p]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g, sysCapInfo => {
479                apiInfo.sysCap = sysCapInfo.replace(/\@[S|s][Y|y][S|s][C|c][A|a][P|p]/g, '').trim();
480            })
481        }
482        if (/\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) {
483            notesStr.replace(/\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g,
484                permissionInfo => {
485                    apiInfo.permission = permissionInfo.replace(/\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]/g, '').trim();
486                })
487        }
488    }
489    return apiInfo;
490}
491
492function addApi(packageName, className, methodName, methodText, apiInfo, apiType, api, hash) {
493    let recard = isNotMerge ? `${packageName}.${className}/${methodName}/${methodText}` :
494        `${packageName}.${className}/${methodName}`
495    if (!hash.has(recard)) {
496        hash.add(recard);
497        api.push({
498            namespace: '',
499            packageName: packageName,
500            className: className,
501            methodName: methodName,
502            count: 0,
503            methodText: methodText.replace(/export\s/g, ""),
504            isSystemApi: apiInfo.isSystemApi,
505            version: apiInfo.version,
506            deprecated: apiInfo.deprecated,
507            apiType: apiType,
508            sysCap: apiInfo.sysCap,
509            permission: apiInfo.permission,
510            model: apiInfo.model,
511            applicationFile: ''
512        })
513    }
514}
515
516async function buildExportData(fileContentList) {
517    const api = parse(fileContentList);
518    return await getExcelBuffer(api)
519}
520async function getExcelBuffer(api) {
521    const workbook = new ExcelJS.Workbook();
522    const sheet = workbook.addWorksheet('Js Api', { views: [{ xSplit: 1 }] });
523    sheet.getRow(1).values = ['模块名', 'namespace', '类名', '方法名', '调用次数', '函数', '类型', 'SysCap',
524        '权限', '支持起始版本', '访问级别']
525    for (let i = 1; i <= api.length; i++) {
526        const apiData = api[i - 1];
527        sheet.getRow(i + 1).values = [apiData.packageName, apiData.namespace, apiData.className, apiData.methodName,
528        apiData.count, apiData.methodText, apiData.apiType, apiData.sysCap, apiData.permission,
529        apiData.version, apiData.isSystemApi]
530    }
531    const buffer = await workbook.xlsx.writeBuffer();
532    return buffer;
533}
534exports.getExcelBuffer = getExcelBuffer;
535
536function readFile(dir, utFiles) {
537    try {
538        const files = fs.readdirSync(dir);
539        files.forEach((element) => {
540            const filePath = path.join(dir, element);
541            const status = fs.statSync(filePath);
542            if (status.isDirectory()) {
543                readFile(filePath, utFiles);
544            } else {
545                if (/\.d\.ts/.test(filePath)) {
546                    utFiles.push(filePath)
547                }
548            }
549        })
550    } catch (e) {
551        console.error('ETS ERROR: ' + e);
552    }
553}
554exports.readFile = readFile;
555
556async function excel(api) {
557    let buffer = await getExcelBuffer(api)
558    fs.writeFile('Js_Api.xlsx', buffer, function (err) {
559        if (err) {
560            console.error(err);
561            return;
562        }
563    });
564}
565exports.excel = excel;
566const dir = 'D:\\web\\API 管\\api\\@internal\\1';