16a23e08bSopenharmony_ci/* 26a23e08bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 36a23e08bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 46a23e08bSopenharmony_ci * you may not use this file except in compliance with the License. 56a23e08bSopenharmony_ci * You may obtain a copy of the License at 66a23e08bSopenharmony_ci * 76a23e08bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 86a23e08bSopenharmony_ci * 96a23e08bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 106a23e08bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 116a23e08bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 126a23e08bSopenharmony_ci * See the License for the specific language governing permissions and 136a23e08bSopenharmony_ci * limitations under the License. 146a23e08bSopenharmony_ci */ 156a23e08bSopenharmony_ci 166a23e08bSopenharmony_civar path = require('path') 176a23e08bSopenharmony_civar fs = require('fs') 186a23e08bSopenharmony_civar shell = require('shelljs'); 196a23e08bSopenharmony_ciconst crypto = require("crypto") 206a23e08bSopenharmony_ci 216a23e08bSopenharmony_ciconst red = '\u001b[31m'; 226a23e08bSopenharmony_ciconst reset = '\u001b[39m'; 236a23e08bSopenharmony_ciconst multiResourceBuild = {}; 246a23e08bSopenharmony_ciconst systemModules = []; 256a23e08bSopenharmony_ci 266a23e08bSopenharmony_ci;(function readSystemModules() { 276a23e08bSopenharmony_ci const systemModulesPath = path.resolve(__dirname,'../../api'); 286a23e08bSopenharmony_ci if (fs.existsSync(systemModulesPath)) { 296a23e08bSopenharmony_ci systemModules.push(...fs.readdirSync(systemModulesPath)); 306a23e08bSopenharmony_ci } 316a23e08bSopenharmony_ci})(); 326a23e08bSopenharmony_ci 336a23e08bSopenharmony_cifunction deleteFolderRecursive(url) { 346a23e08bSopenharmony_ci let files = []; 356a23e08bSopenharmony_ci if (fs.existsSync(url)) { 366a23e08bSopenharmony_ci files = fs.readdirSync(url); 376a23e08bSopenharmony_ci files.forEach(function(file) { 386a23e08bSopenharmony_ci const curPath = path.join(url, file); 396a23e08bSopenharmony_ci if (fs.statSync(curPath).isDirectory()) { 406a23e08bSopenharmony_ci deleteFolderRecursive(curPath); 416a23e08bSopenharmony_ci } else { 426a23e08bSopenharmony_ci fs.unlinkSync(curPath); 436a23e08bSopenharmony_ci } 446a23e08bSopenharmony_ci }); 456a23e08bSopenharmony_ci fs.rmdir(url, function(err) {}); 466a23e08bSopenharmony_ci } 476a23e08bSopenharmony_ci} 486a23e08bSopenharmony_ci 496a23e08bSopenharmony_cifunction readManifest(manifestFilePath) { 506a23e08bSopenharmony_ci let manifest = {}; 516a23e08bSopenharmony_ci try { 526a23e08bSopenharmony_ci if (fs.existsSync(manifestFilePath)) { 536a23e08bSopenharmony_ci const jsonString = fs.readFileSync(manifestFilePath).toString(); 546a23e08bSopenharmony_ci manifest = JSON.parse(jsonString); 556a23e08bSopenharmony_ci } 566a23e08bSopenharmony_ci } catch (e) { 576a23e08bSopenharmony_ci throw Error('\u001b[31m' + 'ERROR: the manifest.json file format is invalid.' + 586a23e08bSopenharmony_ci '\u001b[39m').message; 596a23e08bSopenharmony_ci } 606a23e08bSopenharmony_ci return manifest; 616a23e08bSopenharmony_ci} 626a23e08bSopenharmony_ci 636a23e08bSopenharmony_cifunction loadEntryObj(projectPath, device_level, abilityType, manifestFilePath) { 646a23e08bSopenharmony_ci let entryObj = {}; 656a23e08bSopenharmony_ci switch (abilityType) { 666a23e08bSopenharmony_ci case 'page': 676a23e08bSopenharmony_ci const appJSPath = path.resolve(projectPath, 'app.js'); 686a23e08bSopenharmony_ci if (device_level === 'card') { 696a23e08bSopenharmony_ci entryObj = addPageEntryObj(readManifest(manifestFilePath), projectPath); 706a23e08bSopenharmony_ci } else { 716a23e08bSopenharmony_ci if (!fs.existsSync(appJSPath)) { 726a23e08bSopenharmony_ci throw Error(red + 'ERROR: missing app.js' + reset).message; 736a23e08bSopenharmony_ci } 746a23e08bSopenharmony_ci entryObj['./app'] = path.resolve(projectPath, './app.js?entry'); 756a23e08bSopenharmony_ci } 766a23e08bSopenharmony_ci break; 776a23e08bSopenharmony_ci case 'form': 786a23e08bSopenharmony_ci entryObj = addPageEntryObj(readManifest(manifestFilePath), projectPath); 796a23e08bSopenharmony_ci entryObj[`./${abilityType}`] = path.resolve(projectPath, `./${abilityType}.js?entry`); 806a23e08bSopenharmony_ci break; 816a23e08bSopenharmony_ci case 'testrunner': 826a23e08bSopenharmony_ci break; 836a23e08bSopenharmony_ci default: 846a23e08bSopenharmony_ci entryObj[`./${abilityType}`] = path.resolve(projectPath, `./${abilityType}.js?entry`); 856a23e08bSopenharmony_ci break; 866a23e08bSopenharmony_ci } 876a23e08bSopenharmony_ci return entryObj; 886a23e08bSopenharmony_ci} 896a23e08bSopenharmony_ci 906a23e08bSopenharmony_cifunction addPageEntryObj(manifest, projectPath) { 916a23e08bSopenharmony_ci let entryObj = {}; 926a23e08bSopenharmony_ci const pages = manifest.pages; 936a23e08bSopenharmony_ci if (pages === undefined) { 946a23e08bSopenharmony_ci throw Error('ERROR: missing pages').message; 956a23e08bSopenharmony_ci } 966a23e08bSopenharmony_ci pages.forEach((element) => { 976a23e08bSopenharmony_ci const sourcePath = element; 986a23e08bSopenharmony_ci const hmlPath = path.join(projectPath, sourcePath + '.hml'); 996a23e08bSopenharmony_ci const aceSuperVisualPath = process.env.aceSuperVisualPath || ''; 1006a23e08bSopenharmony_ci const visualPath = path.join(aceSuperVisualPath, sourcePath + '.visual'); 1016a23e08bSopenharmony_ci const isHml = fs.existsSync(hmlPath); 1026a23e08bSopenharmony_ci const isVisual = fs.existsSync(visualPath); 1036a23e08bSopenharmony_ci if (isHml && isVisual) { 1046a23e08bSopenharmony_ci throw Error(red + 'ERROR: ' + sourcePath + ' cannot both have hml && visual').message; 1056a23e08bSopenharmony_ci } else if (isHml) { 1066a23e08bSopenharmony_ci entryObj['./' + element] = path.resolve(projectPath, './' + sourcePath + '.hml?entry'); 1076a23e08bSopenharmony_ci } else if (isVisual) { 1086a23e08bSopenharmony_ci entryObj['./' + element] = path.resolve(aceSuperVisualPath, './' + sourcePath + 1096a23e08bSopenharmony_ci '.visual?entry'); 1106a23e08bSopenharmony_ci } 1116a23e08bSopenharmony_ci }) 1126a23e08bSopenharmony_ci return entryObj; 1136a23e08bSopenharmony_ci} 1146a23e08bSopenharmony_ci 1156a23e08bSopenharmony_cifunction compileCardModule(env) { 1166a23e08bSopenharmony_ci if (process.env.aceModuleJsonPath && fs.existsSync(process.env.aceModuleJsonPath)) { 1176a23e08bSopenharmony_ci const moduleJsonConfig = JSON.parse(fs.readFileSync(process.env.aceModuleJsonPath).toString()); 1186a23e08bSopenharmony_ci if (moduleJsonConfig.module && 1196a23e08bSopenharmony_ci (moduleJsonConfig.module.uiSyntax === 'ets' || moduleJsonConfig.module.language === 'ets')) { 1206a23e08bSopenharmony_ci process.env.DEVICE_LEVEL = 'card'; 1216a23e08bSopenharmony_ci } else if (validateCardModule(moduleJsonConfig) && !process.env.compileCardModule) { 1226a23e08bSopenharmony_ci process.env.compileCardModule = true; 1236a23e08bSopenharmony_ci const cmd = `webpack --config webpack.rich.config.js --env compilerType=${env.compilerType} ` + 1246a23e08bSopenharmony_ci `DEVICE_LEVEL=card aceModuleRoot=${process.env.projectPath} ` + 1256a23e08bSopenharmony_ci `aceModuleJsonPath=${process.env.aceModuleJsonPath} aceProfilePath=${process.env.aceProfilePath} ` + 1266a23e08bSopenharmony_ci `watchMode=${process.env.watchMode} cachePath=${process.env.cachePath} ` + 1276a23e08bSopenharmony_ci `aceModuleBuild=${process.env.buildPath}`; 1286a23e08bSopenharmony_ci shell.exec(cmd, (err) => { 1296a23e08bSopenharmony_ci if (err) { 1306a23e08bSopenharmony_ci throw Error(err).message; 1316a23e08bSopenharmony_ci } 1326a23e08bSopenharmony_ci }) 1336a23e08bSopenharmony_ci } 1346a23e08bSopenharmony_ci } 1356a23e08bSopenharmony_ci} 1366a23e08bSopenharmony_ci 1376a23e08bSopenharmony_cifunction validateCardModule(moduleJsonConfig) { 1386a23e08bSopenharmony_ci if (moduleJsonConfig.module && moduleJsonConfig.module.extensionAbilities) { 1396a23e08bSopenharmony_ci for (let i = 0; i < moduleJsonConfig.module.extensionAbilities.length; i++) { 1406a23e08bSopenharmony_ci const extensionAbility = moduleJsonConfig.module.extensionAbilities[i]; 1416a23e08bSopenharmony_ci if (extensionAbility.type && extensionAbility.type === 'form') { 1426a23e08bSopenharmony_ci return true; 1436a23e08bSopenharmony_ci } 1446a23e08bSopenharmony_ci } 1456a23e08bSopenharmony_ci } 1466a23e08bSopenharmony_ci return false; 1476a23e08bSopenharmony_ci} 1486a23e08bSopenharmony_ci 1496a23e08bSopenharmony_cifunction hashProjectPath(projectPath) { 1506a23e08bSopenharmony_ci const hash = crypto.createHash('sha256') 1516a23e08bSopenharmony_ci hash.update(projectPath.toString()) 1526a23e08bSopenharmony_ci process.env.hashProjectPath = "_" + hash.digest('hex'); 1536a23e08bSopenharmony_ci} 1546a23e08bSopenharmony_ci 1556a23e08bSopenharmony_cifunction checkMultiResourceBuild(aceBuildJson) { 1566a23e08bSopenharmony_ci if (aceBuildJson && fs.existsSync(aceBuildJson)) { 1576a23e08bSopenharmony_ci try { 1586a23e08bSopenharmony_ci const content = JSON.parse(fs.readFileSync(aceBuildJson)); 1596a23e08bSopenharmony_ci if (content["multiResourceBuild"]) { 1606a23e08bSopenharmony_ci multiResourceBuild.value = content["multiResourceBuild"] 1616a23e08bSopenharmony_ci } 1626a23e08bSopenharmony_ci if (content["projectRootPath"]) { 1636a23e08bSopenharmony_ci process.env.projectRootPath = content["projectRootPath"] 1646a23e08bSopenharmony_ci } 1656a23e08bSopenharmony_ci } catch (error) { 1666a23e08bSopenharmony_ci } 1676a23e08bSopenharmony_ci } 1686a23e08bSopenharmony_ci} 1696a23e08bSopenharmony_ci 1706a23e08bSopenharmony_cifunction readWorkerFile() { 1716a23e08bSopenharmony_ci const workerEntryObj = {}; 1726a23e08bSopenharmony_ci if (process.env.aceBuildJson && fs.existsSync(process.env.aceBuildJson)) { 1736a23e08bSopenharmony_ci const workerConfig = JSON.parse(fs.readFileSync(process.env.aceBuildJson).toString()); 1746a23e08bSopenharmony_ci if(workerConfig.workers) { 1756a23e08bSopenharmony_ci workerConfig.workers.forEach(worker => { 1766a23e08bSopenharmony_ci if (!/\.(js)$/.test(worker)) { 1776a23e08bSopenharmony_ci worker += '.js'; 1786a23e08bSopenharmony_ci } 1796a23e08bSopenharmony_ci const relativePath = path.relative(process.env.projectPath, worker); 1806a23e08bSopenharmony_ci if (filterWorker(relativePath)) { 1816a23e08bSopenharmony_ci workerEntryObj[relativePath.replace(/\.(ts|js)$/,'').replace(/\\/g, '/')] = worker; 1826a23e08bSopenharmony_ci } 1836a23e08bSopenharmony_ci }) 1846a23e08bSopenharmony_ci return workerEntryObj; 1856a23e08bSopenharmony_ci } 1866a23e08bSopenharmony_ci } 1876a23e08bSopenharmony_ci return null; 1886a23e08bSopenharmony_ci} 1896a23e08bSopenharmony_ci 1906a23e08bSopenharmony_cifunction filterWorker(workerPath) { 1916a23e08bSopenharmony_ci return /\.(ts|js)$/.test(workerPath); 1926a23e08bSopenharmony_ci} 1936a23e08bSopenharmony_ci 1946a23e08bSopenharmony_cifunction compareCache(cachePath) { 1956a23e08bSopenharmony_ci const entryFile = path.join(cachePath, 'entry.json'); 1966a23e08bSopenharmony_ci const cssFile = process.env.watchCSSFiles; 1976a23e08bSopenharmony_ci 1986a23e08bSopenharmony_ci let files = []; 1996a23e08bSopenharmony_ci let cssObject = {}; 2006a23e08bSopenharmony_ci if (fs.existsSync(cssFile)) { 2016a23e08bSopenharmony_ci cssObject = JSON.parse(fs.readFileSync(cssFile)); 2026a23e08bSopenharmony_ci if (cssObject['clear'] === true) { 2036a23e08bSopenharmony_ci deleteFolderRecursive(cachePath); 2046a23e08bSopenharmony_ci return; 2056a23e08bSopenharmony_ci } 2066a23e08bSopenharmony_ci Object.keys(cssObject).forEach(key => { 2076a23e08bSopenharmony_ci if (key !== 'entry') { 2086a23e08bSopenharmony_ci files.push(key); 2096a23e08bSopenharmony_ci } 2106a23e08bSopenharmony_ci }) 2116a23e08bSopenharmony_ci } 2126a23e08bSopenharmony_ci 2136a23e08bSopenharmony_ci if (fs.existsSync(entryFile)) { 2146a23e08bSopenharmony_ci files = files.concat(JSON.parse(fs.readFileSync(entryFile))); 2156a23e08bSopenharmony_ci } 2166a23e08bSopenharmony_ci 2176a23e08bSopenharmony_ci for(let file of files) { 2186a23e08bSopenharmony_ci if (!fs.existsSync(file)) { 2196a23e08bSopenharmony_ci deleteFolderRecursive(cachePath); 2206a23e08bSopenharmony_ci break; 2216a23e08bSopenharmony_ci } else if (cssObject['atime'] && cssObject['atime'][file]) { 2226a23e08bSopenharmony_ci if (cssObject['atime'][file] !== fs.statSync(file).atime.toString()) { 2236a23e08bSopenharmony_ci deleteFolderRecursive(cachePath); 2246a23e08bSopenharmony_ci break; 2256a23e08bSopenharmony_ci } 2266a23e08bSopenharmony_ci } 2276a23e08bSopenharmony_ci } 2286a23e08bSopenharmony_ci} 2296a23e08bSopenharmony_ci 2306a23e08bSopenharmony_cifunction parseAbilityName(abilityType, projectPath) { 2316a23e08bSopenharmony_ci if (abilityType === 'page') { 2326a23e08bSopenharmony_ci return path.resolve(__dirname, projectPath, 'app.js'); 2336a23e08bSopenharmony_ci } else { 2346a23e08bSopenharmony_ci return path.resolve(__dirname, projectPath, abilityType + '.js'); 2356a23e08bSopenharmony_ci } 2366a23e08bSopenharmony_ci} 2376a23e08bSopenharmony_ci 2386a23e08bSopenharmony_cimodule.exports = { 2396a23e08bSopenharmony_ci deleteFolderRecursive: deleteFolderRecursive, 2406a23e08bSopenharmony_ci readManifest: readManifest, 2416a23e08bSopenharmony_ci loadEntryObj: loadEntryObj, 2426a23e08bSopenharmony_ci compileCardModule: compileCardModule, 2436a23e08bSopenharmony_ci hashProjectPath: hashProjectPath, 2446a23e08bSopenharmony_ci checkMultiResourceBuild: checkMultiResourceBuild, 2456a23e08bSopenharmony_ci multiResourceBuild: multiResourceBuild, 2466a23e08bSopenharmony_ci readWorkerFile: readWorkerFile, 2476a23e08bSopenharmony_ci compareCache: compareCache, 2486a23e08bSopenharmony_ci systemModules: systemModules, 2496a23e08bSopenharmony_ci parseAbilityName: parseAbilityName 2506a23e08bSopenharmony_ci};