• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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): Array<string> {
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  return dtsFileList;
54}
55
56/**
57 * get all component .d.ts file path
58 * @param dir
59 * @returns
60 */
61function getAllComponentsFilePath(dir: string): Array<string> {
62  const componentPath = path.join(dir, '@internal', 'component', 'ets');
63  if (!fs.existsSync(componentPath)) {
64    return;
65  }
66  const componentPathArr = fs.readdirSync(componentPath);
67  componentPathArr.forEach(value => {
68    const fullPath = path.join(componentPath, value);
69    if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) {
70      const componentName = `@internal/component/ets/${value}`;
71      if (!specialFiles.includes(componentName)) {
72        specialFiles.push(componentName);
73      }
74    }
75  });
76}
77/**
78 * delete the old mock file befor generate new mock file
79 * @param outDir
80 */
81function deleteOldMockJsFile(outDir: string): void {
82  const arr = fs.readdirSync(outDir);
83  arr.forEach(value => {
84    const currPath = path.join(outDir, value);
85    const stas = fs.statSync(currPath);
86    if (stas.isDirectory()) {
87      deleteOldMockJsFile(currPath);
88    } else {
89      fs.unlink(currPath, function (err) {
90        if (err) {
91          console.log(err);
92        }
93      });
94    }
95  });
96}
97
98/**
99 * mkdir
100 * @param dirname
101 * @returns
102 */
103function mkdirsSync(dirname): boolean {
104  if (fs.existsSync(dirname)) {
105    return true;
106  } else {
107    if (mkdirsSync(path.dirname(dirname))) {
108      fs.mkdirSync(dirname);
109      return true;
110    }
111  }
112  return false;
113}
114
115/**
116 * hgandle all ets file mock logic
117 * @param outMockJsFileDir automated mock file output path
118 * @returns
119 */
120function etsFileToMock(outMockJsFileDir: string): void {
121  let index = 0;
122  while (index < dtsFileList.length) {
123    const value = dtsFileList[index];
124    index++;
125
126    if (!value.endsWith('.d.ts') && !value.endsWith('.d.ets')) {
127      continue;
128    }
129
130    const code = fs.readFileSync(value);
131    const sourceFile = createSourceFile(value, code.toString(), ScriptTarget.Latest);
132    let fileName: string;
133    if (value.endsWith('.d.ts')) {
134      fileName = path.basename(value, '.d.ts');
135    } else if (value.endsWith('.d.ets')) {
136      fileName = path.basename(value, '.d.ets');
137    } else {
138      continue;
139    }
140    let outputFileName = '';
141    if (fileName.includes('@')) {
142      outputFileName = fileName.split('@')[1].replace(/\./g, '_');
143    } else {
144      outputFileName = fileName;
145    }
146
147    let tmpOutputMockJsFileDir = outMockJsFileDir;
148    if (!outputFileName.startsWith('system_')) {
149      tmpOutputMockJsFileDir = path.join(outMockJsFileDir, 'napi');
150    }
151
152    if (value.startsWith(getOhosInterfacesDir()) && !apiInputPath.startsWith(getOhosInterfacesDir())) {
153      tmpOutputMockJsFileDir = path.join(tmpOutputMockJsFileDir, '@ohos');
154    }
155
156    let dirName = '';
157    dirName = path.join(tmpOutputMockJsFileDir, path.dirname(value).split(`${path.sep}api`)[1]);
158    if (!fs.existsSync(dirName)) {
159      mkdirsSync(dirName);
160    }
161    const sourceFileEntity = getSourceFileAssembly(sourceFile, fileName);
162    const filePath = path.join(dirName, outputFileName + '.js');
163    fs.writeFileSync(filePath, '');
164    fs.appendFileSync(path.join(filePath), generateSourceFileElements('', sourceFileEntity, sourceFile, outputFileName));
165  }
166}
167
168/**
169 * Project Entry Function
170 * @param apiInputPath interface_sdk-js\api absolute file path
171 * @returns
172 */
173function main(apiInputPath): void {
174  const dtsDir = apiInputPath;
175  const outMockJsFileDir = path.join(__dirname, '../../runtime/main/extend/systemplugin');
176  generateKitMap(apiInputPath);
177  getAllDtsFile(dtsDir);
178  getAllComponentsFilePath(dtsDir);
179  dtsFileList.forEach(value => {
180    collectAllFileName(value);
181    if (value.endsWith('.d.ts') || value.endsWith('.d.ets')) {
182      const code = fs.readFileSync(value);
183      const sourceFile = createSourceFile(value, code.toString(), ScriptTarget.Latest);
184      getAllClassDeclaration(sourceFile);
185    }
186  });
187
188  etsFileToMock(outMockJsFileDir);
189
190  if (!fs.existsSync(path.join(outMockJsFileDir, 'napi'))) {
191    mkdirsSync(path.join(outMockJsFileDir, 'napi'));
192  }
193  generateDependJsonFile();
194  generateMyComponent(outMockJsFileDir);
195  fs.writeFileSync(path.join(outMockJsFileDir, 'napi', 'index.js'), generateIndex());
196  fs.writeFileSync(path.join(outMockJsFileDir, 'index.js'), generateSystemIndex());
197  fs.writeFileSync(path.join(outMockJsFileDir, 'entry.js'), generateEntry());
198}
199
200const paramIndex = 2;
201const apiInputPath = process.argv[paramIndex];
202main(apiInputPath);
203