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