• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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
16var path = require('path')
17var fs = require('fs')
18var shell = require('shelljs');
19const crypto = require("crypto")
20
21const red = '\u001b[31m';
22const reset = '\u001b[39m';
23const multiResourceBuild = {};
24const systemModules = [];
25
26;(function readSystemModules() {
27  const systemModulesPath = path.resolve(__dirname,'../../api');
28  if (fs.existsSync(systemModulesPath)) {
29    systemModules.push(...fs.readdirSync(systemModulesPath));
30  }
31})();
32
33function deleteFolderRecursive(url) {
34  let files = [];
35  if (fs.existsSync(url)) {
36    files = fs.readdirSync(url);
37    files.forEach(function(file) {
38      const curPath = path.join(url, file);
39      if (fs.statSync(curPath).isDirectory()) {
40        deleteFolderRecursive(curPath);
41      } else {
42        fs.unlinkSync(curPath);
43      }
44    });
45    fs.rmdir(url, function(err) {});
46  }
47}
48
49function readManifest(manifestFilePath) {
50  let manifest = {};
51  try {
52    if (fs.existsSync(manifestFilePath)) {
53      const jsonString = fs.readFileSync(manifestFilePath).toString();
54      manifest = JSON.parse(jsonString);
55    }
56  } catch (e) {
57    throw Error('\u001b[31m' + 'ERROR: the manifest.json file format is invalid.' +
58      '\u001b[39m').message;
59  }
60  return manifest;
61}
62
63function loadEntryObj(projectPath, device_level, abilityType, manifestFilePath) {
64  let entryObj = {};
65  switch (abilityType) {
66    case 'page':
67      const appJSPath = path.resolve(projectPath, 'app.js');
68      if (device_level === 'card') {
69        entryObj = addPageEntryObj(readManifest(manifestFilePath), projectPath);
70      } else {
71        if (!fs.existsSync(appJSPath)) {
72          throw Error(red + 'ERROR: missing app.js' + reset).message;
73        }
74        entryObj['./app'] = path.resolve(projectPath, './app.js?entry');
75      }
76      break;
77    case 'form':
78      entryObj = addPageEntryObj(readManifest(manifestFilePath), projectPath);
79      entryObj[`./${abilityType}`] =  path.resolve(projectPath, `./${abilityType}.js?entry`);
80      break;
81    case 'testrunner':
82      break;
83    default:
84      entryObj[`./${abilityType}`] =  path.resolve(projectPath, `./${abilityType}.js?entry`);
85      break;
86  }
87  return entryObj;
88}
89
90function addPageEntryObj(manifest, projectPath) {
91  let entryObj = {};
92  const pages = manifest.pages;
93  if (pages === undefined) {
94    throw Error('ERROR: missing pages').message;
95  }
96  pages.forEach((element) => {
97    const sourcePath = element;
98    const hmlPath = path.join(projectPath, sourcePath + '.hml');
99    const aceSuperVisualPath = process.env.aceSuperVisualPath || '';
100    const visualPath = path.join(aceSuperVisualPath, sourcePath + '.visual');
101    const isHml = fs.existsSync(hmlPath);
102    const isVisual = fs.existsSync(visualPath);
103    if (isHml && isVisual) {
104      throw Error(red + 'ERROR: ' + sourcePath + ' cannot both have hml && visual').message;
105    } else if (isHml) {
106      entryObj['./' + element] = path.resolve(projectPath, './' + sourcePath + '.hml?entry');
107    } else if (isVisual) {
108      entryObj['./' + element] = path.resolve(aceSuperVisualPath, './' + sourcePath +
109        '.visual?entry');
110    }
111  })
112  return entryObj;
113}
114
115function compileCardModule(env) {
116  if (process.env.aceModuleJsonPath && fs.existsSync(process.env.aceModuleJsonPath)) {
117    const moduleJsonConfig = JSON.parse(fs.readFileSync(process.env.aceModuleJsonPath).toString());
118    if (moduleJsonConfig.module &&
119      (moduleJsonConfig.module.uiSyntax === 'ets' || moduleJsonConfig.module.language === 'ets')) {
120      process.env.DEVICE_LEVEL = 'card';
121    } else if (validateCardModule(moduleJsonConfig) && !process.env.compileCardModule) {
122      process.env.compileCardModule = true;
123      const cmd = `webpack --config webpack.rich.config.js --env compilerType=${env.compilerType} ` +
124        `DEVICE_LEVEL=card aceModuleRoot=${process.env.projectPath} ` +
125        `aceModuleJsonPath=${process.env.aceModuleJsonPath} aceProfilePath=${process.env.aceProfilePath} ` +
126        `watchMode=${process.env.watchMode} cachePath=${process.env.cachePath} ` +
127        `aceModuleBuild=${process.env.buildPath}`;
128      shell.exec(cmd, (err) => {
129        if (err) {
130          throw Error(err).message;
131        }
132      })
133    }
134  }
135}
136
137function validateCardModule(moduleJsonConfig) {
138  if (moduleJsonConfig.module && moduleJsonConfig.module.extensionAbilities) {
139    for (let i = 0; i < moduleJsonConfig.module.extensionAbilities.length; i++) {
140      const extensionAbility = moduleJsonConfig.module.extensionAbilities[i];
141      if (extensionAbility.type && extensionAbility.type === 'form') {
142        return true;
143      }
144    }
145  }
146  return false;
147}
148
149function hashProjectPath(projectPath) {
150  const hash = crypto.createHash('sha256')
151  hash.update(projectPath.toString())
152  process.env.hashProjectPath = "_" + hash.digest('hex');
153}
154
155function checkMultiResourceBuild(aceBuildJson) {
156  if (aceBuildJson && fs.existsSync(aceBuildJson)) {
157    try {
158      const content = JSON.parse(fs.readFileSync(aceBuildJson));
159      if (content["multiResourceBuild"]) {
160        multiResourceBuild.value = content["multiResourceBuild"]
161      }
162      if (content["projectRootPath"]) {
163        process.env.projectRootPath = content["projectRootPath"]
164      }
165    } catch (error) {
166    }
167  }
168}
169
170function readWorkerFile() {
171  const workerEntryObj = {};
172  if (process.env.aceBuildJson && fs.existsSync(process.env.aceBuildJson)) {
173    const workerConfig = JSON.parse(fs.readFileSync(process.env.aceBuildJson).toString());
174    if(workerConfig.workers) {
175      workerConfig.workers.forEach(worker => {
176        if (!/\.(js)$/.test(worker)) {
177          worker += '.js';
178        }
179        const relativePath = path.relative(process.env.projectPath, worker);
180        if (filterWorker(relativePath)) {
181          workerEntryObj[relativePath.replace(/\.(ts|js)$/,'').replace(/\\/g, '/')] = worker;
182        }
183      })
184      return workerEntryObj;
185    }
186  }
187  return null;
188}
189
190function filterWorker(workerPath) {
191  return /\.(ts|js)$/.test(workerPath);
192}
193
194function compareCache(cachePath) {
195  const entryFile = path.join(cachePath, 'entry.json');
196  const cssFile = process.env.watchCSSFiles;
197
198  let files = [];
199  let cssObject = {};
200  if (fs.existsSync(cssFile)) {
201    cssObject = JSON.parse(fs.readFileSync(cssFile));
202    if (cssObject['clear'] === true) {
203      deleteFolderRecursive(cachePath);
204      return;
205    }
206    Object.keys(cssObject).forEach(key => {
207      if (key !== 'entry') {
208        files.push(key);
209      }
210    })
211  }
212
213  if (fs.existsSync(entryFile)) {
214    files = files.concat(JSON.parse(fs.readFileSync(entryFile)));
215  }
216
217  for(let file of files) {
218    if (!fs.existsSync(file)) {
219      deleteFolderRecursive(cachePath);
220      break;
221    } else if (cssObject['atime'] && cssObject['atime'][file]) {
222      if (cssObject['atime'][file] !== fs.statSync(file).atime.toString()) {
223        deleteFolderRecursive(cachePath);
224        break;
225      }
226    }
227  }
228}
229
230function parseAbilityName(abilityType, projectPath) {
231  if (abilityType === 'page') {
232    return path.resolve(__dirname, projectPath, 'app.js');
233  } else {
234    return path.resolve(__dirname, projectPath, abilityType + '.js');
235  }
236}
237
238module.exports = {
239  deleteFolderRecursive: deleteFolderRecursive,
240  readManifest: readManifest,
241  loadEntryObj: loadEntryObj,
242  compileCardModule: compileCardModule,
243  hashProjectPath: hashProjectPath,
244  checkMultiResourceBuild: checkMultiResourceBuild,
245  multiResourceBuild: multiResourceBuild,
246  readWorkerFile: readWorkerFile,
247  compareCache: compareCache,
248  systemModules: systemModules,
249  parseAbilityName: parseAbilityName
250};