-
Notifications
You must be signed in to change notification settings - Fork 11
/
getAppSource.ts
77 lines (62 loc) · 2.85 KB
/
getAppSource.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { promises as fs } from 'fs';
import { resolve, relative } from 'path';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { IAppSource, ICompilerFile, IMapCompilerFile } from '../definition';
async function walkDirectory(directory: string): Promise<ICompilerFile[]> {
const dirents = await fs.readdir(directory, { withFileTypes: true });
const files = await Promise.all(
dirents
.map(async (dirent) => {
const res = resolve(directory, dirent.name);
const dirsToIgnore = ['node_modules', '.git'];
if (dirsToIgnore.some((dir) => res.includes(dir))) {
return null;
}
if (dirent.isDirectory() || dirent.isSymbolicLink()) {
return walkDirectory(res);
}
const content = await fs.readFile(res, 'utf8');
return {
content,
name: res,
version: 0,
};
})
.filter((entry) => entry),
);
return Array.prototype.concat(...files);
}
function filterProjectFiles(projectDirectory: string, directoryWalkData: ICompilerFile[]): ICompilerFile[] {
return directoryWalkData
// Leave out falsy values
.filter((file: ICompilerFile) => file && !file.name.startsWith('.'))
// Get the file names like it was inside the project's directory
.map((file: ICompilerFile) => ({ ...file, name: relative(projectDirectory, file.name) }));
}
function makeICompilerFileMap(compilerFiles: ICompilerFile[]): IMapCompilerFile {
return compilerFiles
.map((file: ICompilerFile) => ({ [file.name]: file }))
.reduce((acc: IMapCompilerFile, curr: IMapCompilerFile) => ({ ...acc, ...curr }), {});
}
function getAppInfo(projectFiles: ICompilerFile[]): IAppInfo {
const appJson = projectFiles.find((file: ICompilerFile) => file.name === 'app.json');
if (!appJson) {
throw new Error('There is no app.json file in the project');
}
try {
return JSON.parse(appJson.content) as IAppInfo;
} catch (error) {
throw new Error('app.json parsing fail');
}
}
function getTypescriptFilesFromProject(projectFiles: ICompilerFile[]): ICompilerFile[] {
return projectFiles.filter((file: ICompilerFile) => file.name.endsWith('.ts'));
}
export async function getAppSource(path: string): Promise<IAppSource> {
const directoryWalkData: ICompilerFile[] = await walkDirectory(path);
const projectFiles: ICompilerFile[] = filterProjectFiles(path, directoryWalkData);
const tsFiles: ICompilerFile[] = getTypescriptFilesFromProject(projectFiles);
const appInfo: IAppInfo = getAppInfo(projectFiles);
const files: IMapCompilerFile = makeICompilerFileMap(tsFiles);
return { appInfo, sourceFiles: files };
}