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 { ApiCollector, MultiProjectApiCollector } = require('./api_collector'); 17const { Logger } = require('./utils'); 18const path = require('path'); 19const fs = require('fs'); 20 21class AppApiCollectorPlugin { 22 constructor() { 23 this.logTag = 'AppApiCollectorPlugin'; 24 } 25 getPluginOptions() { 26 return { 27 name: 'api-collector', 28 version: '0.1.0', 29 description: 'collect api from app\'s source code.', 30 commands: [ 31 { 32 isRequiredOption: false, 33 options: ['--app <string>', 'app root directory'], 34 }, 35 { 36 isRequiredOption: false, 37 options: ['--appDir <string>', 'a path that contains multiple applications'], 38 }, 39 { 40 isRequiredOption: false, 41 options: ['--sdk <string>', 'sdk path, need to specify the ets directory, e.g sdk-root/version/ets'], 42 }, 43 { 44 isRequiredOption: false, 45 options: ['--sdkRoot <string>', 'sdk root path'], 46 }, 47 { 48 isRequiredOption: false, 49 options: ['--output <string>', 'the path to output the report'], 50 }, 51 { 52 isRequiredOption: false, 53 options: ['--format <json,excel>', 'format of the output report'], 54 }, 55 { 56 isRequiredOption: false, 57 options: ['--scanTest', 'scan ohosTest'], 58 }, 59 { 60 isRequiredOption: false, 61 options: ['--debug', 'output debug logs'], 62 }, 63 { 64 isRequiredOption: false, 65 options: ['--noRepeat', 'apiInfos is not repeat'] 66 } 67 ], 68 }; 69 } 70 71 async start(argv) { 72 if (!this.checkArguments(argv)) { 73 return; 74 } 75 const startTime = Date.now(); 76 if (argv.app) { 77 await this.scanSingleProject(argv); 78 } else if (argv.appDir) { 79 await this.scanMultiProject(argv); 80 } else if (argv.dir) { 81 await this.scanNonProject(argv); 82 } else { 83 Logger.info(this.logTag, 'see --help'); 84 } 85 Logger.info(this.logTag, `elapsed time ${Date.now() - startTime}`); 86 if (argv.debug) { 87 Logger.flush(this.getLogPath(argv)); 88 } 89 } 90 91 async scanSingleProject(argv) { 92 const collector = new ApiCollector(argv); 93 await collector.setLibPath(this.findLibPath()).setIncludeTest(argv.scanTest).start(); 94 } 95 96 async scanMultiProject(argv) { 97 if (!argv.sdk) { 98 const collector = new MultiProjectApiCollector(argv); 99 await collector.setLibPath(this.findLibPath()).setIncludeTest(argv.scanTest).start(); 100 } else { 101 Logger.error(this.logTag, '--appDir and --sdkRoot are used together, replace --sdk with --sdkRoot'); 102 } 103 } 104 105 async scanNonProject(argv) { 106 if (!argv.sdk) { 107 Logger.error(this.logTag, 'the --sdk is required when scanning non-project'); 108 return; 109 } 110 const apiCollector = new ApiCollector(argv); 111 await apiCollector.setLibPath(this.findLibPath()).start(); 112 } 113 114 getLogPath(argv) { 115 if (argv.output) { 116 return argv.output; 117 } 118 if (argv.appDir) { 119 return argv.appDir; 120 } 121 if (argv.app) { 122 return argv.app; 123 } 124 return __dirname; 125 } 126 127 findLibPath() { 128 if (process.env.bundleMode) { 129 return path.resolve(__dirname, 'libs'); 130 } 131 return path.resolve(__dirname, '..', 'libs'); 132 } 133 134 stop() { 135 136 } 137 138 checkArguments(argv) { 139 if (argv.sdk) { 140 const apiPath = path.resolve(argv.sdk, 'api'); 141 const componentPath = path.resolve(argv.sdk, 'component'); 142 if (!fs.existsSync(apiPath) || !fs.existsSync(componentPath)) { 143 Logger.error(this.logTag, '--sdk option need to specify the ets directory'); 144 return false; 145 } 146 } 147 return this.checkPathIsValid(argv.app) && 148 this.checkPathIsValid(argv.output) && 149 this.checkPathIsValid(argv.sdkRoot) && 150 this.checkPathIsValid(argv.appDir); 151 } 152 153 checkPathIsValid(path) { 154 if (path && !fs.existsSync(path)) { 155 Logger.error(this.logTag, `${path} not exists`); 156 return false; 157 } 158 return true; 159 } 160} 161 162module.exports = AppApiCollectorPlugin;