1/* 2 * Copyright (c) 2023 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 { ReporterFormat } = require('./configs'); 17const { Logger } = require('./utils'); 18const exceljs = require('exceljs'); 19const fs = require('fs'); 20const path = require('path'); 21 22class ApiJsonWriter { 23 constructor(outputPath) { 24 this.outputPath = outputPath; 25 this.apiInfos = []; 26 this.noSerializeKeys = new Set(['apiSourceFile', 'apiNode']); 27 } 28 29 add(apiInfos) { 30 this.apiInfos.push(...apiInfos); 31 } 32 33 flush() { 34 const output = path.resolve(this.outputPath, 'collectedApi.json'); 35 fs.writeFileSync(output, JSON.stringify(this.apiInfos, (key, value) => { 36 if (this.noSerializeKeys.has(key)) { 37 return undefined; 38 } 39 return value; 40 })); 41 Logger.info('ApiJsonWriter', `report is in ${output}`); 42 } 43} 44 45class ApiExcelWriter { 46 constructor(outputDir, noRepeat) { 47 this.outputDir = outputDir; 48 this.apiInfos = []; 49 this.enable = true; 50 this.noRepeat = noRepeat; 51 } 52 53 close() { 54 this.enable = false; 55 } 56 57 open() { 58 this.enable = true; 59 } 60 61 add(apiInfos) { 62 this.apiInfos.push(...apiInfos.filter((value) => { 63 return !(value.packageName === 'ArkUI' && value.qualifiedTypeName === ''); 64 })); 65 } 66 67 async flush() { 68 if (!this.enable) { 69 return; 70 } 71 this.writeSubscribeApi(); 72 this.writeAppApi(); 73 } 74 75 async writeSubscribeApi() { 76 const apiInfoSet = new Set(); 77 const subscribeWorkbook = new exceljs.Workbook(); 78 const subscribeSheet = subscribeWorkbook.addWorksheet('Js Api', { views: [{ xSplit: 1 }] }); 79 subscribeSheet.getRow(1).values = ['类名', '接口名', '接口类型', '方法声明', '接口全路径']; 80 let lineNumber = 0; 81 const STARTING_LINE_NUMBER = 2; 82 this.apiInfos.forEach((apiInfo, index) => { 83 const typeName = apiInfo.qualifiedTypeName ? apiInfo.qualifiedTypeName : 84 (apiInfo.typeName ? apiInfo.typeName : 'unnamed'); 85 86 if (!apiInfoSet.has(formatInfo(apiInfo, typeName))) { 87 subscribeSheet.getRow(lineNumber + STARTING_LINE_NUMBER).values = [ 88 typeName, 89 apiInfo.propertyName, 90 apiInfo.apiType, 91 apiInfo.apiText.replace(/\;$/g, ''), 92 apiInfo.dtsPath 93 ]; 94 lineNumber++; 95 apiInfoSet.add(formatInfo(apiInfo, typeName)); 96 } 97 }); 98 const subscribeBuffer = await subscribeWorkbook.xlsx.writeBuffer(); 99 const subscribeOutputFile = path.resolve(this.outputDir, 'subscribe_api.xlsx'); 100 fs.writeFileSync(subscribeOutputFile, subscribeBuffer); 101 } 102 103 async writeAppApi() { 104 let lineNumber = 0; 105 const apiInfoSet = new Set(); 106 const workbook = new exceljs.Workbook(); 107 const sheet = workbook.addWorksheet('Js Api', { views: [{ xSplit: 1 }] }); 108 sheet.getRow(1).values = ['模块名', '类名', '方法名', '函数', '文件位置']; 109 this.apiInfos.forEach((apiInfo, index) => { 110 const typeName = apiInfo.componentName ? apiInfo.componentName : 111 (apiInfo.typeName ? apiInfo.typeName : apiInfo.qualifiedTypeName); 112 if (this.noRepeat && !apiInfoSet.has(formatInfo(apiInfo, typeName))) { 113 this.createSheet(sheet, typeName, apiInfo, lineNumber); 114 apiInfoSet.add(formatInfo(apiInfo, typeName)); 115 lineNumber++; 116 } else if (!this.noRepeat) { 117 this.createSheet(sheet, typeName, apiInfo, index); 118 } 119 }); 120 const buffer = await workbook.xlsx.writeBuffer(); 121 const outputFile = path.resolve(this.outputDir, 'app_api.xlsx'); 122 fs.writeFileSync(outputFile, buffer); 123 Logger.info('ApiExcelWriter', `report is in ${outputFile}`); 124 } 125 126 createSheet(sheet, typeName, apiInfo, lineNumber) { 127 const STARTING_LINE_NUMBER = 2; 128 sheet.getRow(lineNumber + STARTING_LINE_NUMBER).values = [ 129 path.basename(apiInfo.packageName, '.d.ts').replace('@', ''), 130 typeName, 131 apiInfo.propertyName, 132 apiInfo.apiRawText, 133 `${apiInfo.sourceFileName}(${apiInfo.pos})` 134 ]; 135 } 136} 137 138class ApiWriter { 139 constructor(outputPath, formatFlag, noRepeat) { 140 this.outputPath = outputPath; 141 this.formatFlag = formatFlag; 142 this.noRepeat = noRepeat; 143 this.apiInfos = []; 144 } 145 146 add(apiInfos) { 147 this.apiInfos.push(...apiInfos); 148 } 149 150 async flush() { 151 if (this.formatFlag === ReporterFormat.FLAG_JSON) { 152 this.writeJson(this.apiInfos); 153 } else if (this.formatFlag === ReporterFormat.FLAG_EXCEL) { 154 await this.writeExcel(this.apiInfos); 155 } else if (this.formatFlag === ReporterFormat.FLAG_DEBUG) { 156 this.writeJson(this.apiInfos); 157 await this.writeExcel(this.apiInfos); 158 } else { 159 this.writeJson(this.apiInfos); 160 } 161 } 162 163 writeJson(apiInfos) { 164 const apiJsonWriter = new ApiJsonWriter(this.outputPath); 165 apiJsonWriter.add(apiInfos); 166 apiJsonWriter.flush(); 167 } 168 169 async writeExcel(apiInfos) { 170 const apiExcelWriter = new ApiExcelWriter(this.outputPath, this.noRepeat); 171 apiExcelWriter.add(apiInfos); 172 await apiExcelWriter.flush(); 173 } 174} 175 176function formatInfo(apiInfo, typeName) { 177 return `${typeName}_${apiInfo.propertyName}_${apiInfo.apiText}_ ${apiInfo.dtsPath}`; 178} 179 180exports.ApiJsonWriter = ApiJsonWriter; 181exports.ApiExcelWriter = ApiExcelWriter; 182exports.ApiWriter = ApiWriter;