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 16import fs from 'fs'; 17import path from 'path'; 18import { createSourceFile, ScriptTarget } from 'typescript'; 19import { 20 collectAllFileName, 21 getAllClassDeclaration, 22 dtsFileList, 23 getOhosInterfacesDir, 24 specialFiles, 25 generateKitMap, 26 generateDependJsonFile, 27 generateMyComponent 28} from './common/commonUtils'; 29import { getSourceFileAssembly } from './declaration-node/sourceFileElementsAssemply'; 30import { generateEntry } from './generate/generateEntry'; 31import { generateIndex } from './generate/generateIndex'; 32import { generateSourceFileElements } from './generate/generateMockJsFile'; 33import { generateSystemIndex } from './generate/generateSystemIndex'; 34 35/** 36 * get all api .d.ts file path 37 * @param dir 38 * @returns 39 */ 40function getAllDtsFile(dir: string): void { 41 const arr = fs.readdirSync(dir); 42 if (!dir.toString().includes('node_modules') && !dir.toString().includes(path.join('@internal', 'component'))) { 43 arr.forEach(value => { 44 const fullPath = path.join(dir, value); 45 const stats = fs.statSync(fullPath); 46 if (stats.isDirectory()) { 47 getAllDtsFile(fullPath); 48 } else { 49 dtsFileList.push(fullPath); 50 } 51 }); 52 } 53} 54 55/** 56 * get all component .d.ts file path 57 * @param dir 58 * @returns 59 */ 60function getAllComponentsFilePath(dir: string): Array<string> { 61 const componentPath = path.join(dir, '@internal', 'component', 'ets'); 62 if (!fs.existsSync(componentPath)) { 63 return; 64 } 65 const componentPathArr = fs.readdirSync(componentPath); 66 componentPathArr.forEach(value => { 67 const fullPath = path.join(componentPath, value); 68 if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) { 69 const componentName = `@internal/component/ets/${value}`; 70 if (!specialFiles.includes(componentName)) { 71 specialFiles.push(componentName); 72 } 73 } 74 }); 75} 76 77/** 78 * mkdir 79 * @param dirname 80 * @returns 81 */ 82function mkdirsSync(dirname): boolean { 83 if (fs.existsSync(dirname)) { 84 return true; 85 } else { 86 if (mkdirsSync(path.dirname(dirname))) { 87 fs.mkdirSync(dirname); 88 return true; 89 } 90 } 91 return false; 92} 93 94/** 95 * hgandle all ets file mock logic 96 * @param outMockJsFileDir automated mock file output path 97 * @returns 98 */ 99function etsFileToMock(outMockJsFileDir: string): void { 100 let index = 0; 101 while (index < dtsFileList.length) { 102 const value = dtsFileList[index]; 103 index++; 104 105 if (!value.endsWith('.d.ts') && !value.endsWith('.d.ets')) { 106 continue; 107 } 108 109 const code = fs.readFileSync(value); 110 const sourceFile = createSourceFile(value, code.toString(), ScriptTarget.Latest); 111 let fileName: string; 112 if (value.endsWith('.d.ts')) { 113 fileName = path.basename(value, '.d.ts'); 114 } else if (value.endsWith('.d.ets')) { 115 fileName = path.basename(value, '.d.ets'); 116 } else { 117 continue; 118 } 119 let outputFileName = ''; 120 if (fileName.includes('@')) { 121 outputFileName = fileName.split('@')[1].replace(/\./g, '_'); 122 } else { 123 outputFileName = fileName; 124 } 125 126 let tmpOutputMockJsFileDir = outMockJsFileDir; 127 if (!outputFileName.startsWith('system_')) { 128 tmpOutputMockJsFileDir = path.join(outMockJsFileDir, 'napi'); 129 } 130 131 if (value.startsWith(getOhosInterfacesDir()) && !apiInputPath.startsWith(getOhosInterfacesDir())) { 132 tmpOutputMockJsFileDir = path.join(tmpOutputMockJsFileDir, '@ohos'); 133 } 134 135 let dirName = ''; 136 dirName = path.join(tmpOutputMockJsFileDir, path.dirname(value).split(`${path.sep}api`)[1]); 137 if (!fs.existsSync(dirName)) { 138 mkdirsSync(dirName); 139 } 140 const sourceFileEntity = getSourceFileAssembly(sourceFile, fileName); 141 const filePath = path.join(dirName, outputFileName + '.js'); 142 fs.writeFileSync(filePath, ''); 143 fs.appendFileSync( 144 path.join(filePath), 145 generateSourceFileElements('', sourceFileEntity, sourceFile, outputFileName) 146 ); 147 } 148} 149 150/** 151 * Project Entry Function 152 * @param apiInputPath interface_sdk-js\api absolute file path 153 * @returns 154 */ 155function main(apiInputPath): void { 156 const dtsDir = apiInputPath; 157 const outMockJsFileDir = path.join(__dirname, '../../runtime/main/extend/systemplugin'); 158 generateKitMap(apiInputPath); 159 getAllDtsFile(dtsDir); 160 getAllComponentsFilePath(dtsDir); 161 dtsFileList.forEach(value => { 162 collectAllFileName(value); 163 if (value.endsWith('.d.ts') || value.endsWith('.d.ets')) { 164 const code = fs.readFileSync(value); 165 const sourceFile = createSourceFile(value, code.toString(), ScriptTarget.Latest); 166 getAllClassDeclaration(sourceFile); 167 } 168 }); 169 170 etsFileToMock(outMockJsFileDir); 171 172 if (!fs.existsSync(path.join(outMockJsFileDir, 'napi'))) { 173 mkdirsSync(path.join(outMockJsFileDir, 'napi')); 174 } 175 generateDependJsonFile(); 176 generateMyComponent(outMockJsFileDir); 177 fs.writeFileSync(path.join(outMockJsFileDir, 'napi', 'index.js'), generateIndex()); 178 fs.writeFileSync(path.join(outMockJsFileDir, 'index.js'), generateSystemIndex()); 179 fs.writeFileSync(path.join(outMockJsFileDir, 'entry.js'), generateEntry()); 180} 181 182const paramIndex = 2; 183const apiInputPath = process.argv[paramIndex]; 184main(apiInputPath); 185