/
android.js
126 lines (106 loc) · 3.39 KB
/
android.js
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const path = require('path');
const xml = require('xmldoc');
const fs = require('fs');
const glob = require('glob');
/**
* Default android source directory to look for files
*/
const BASE_DIR = './android';
const GLOB_PATTERN = '**/*.java';
/**
* Gets source directory for current folder
*
* Given folder, it checks if /android exists, if no - returns null
* Tries to find /app folder in /android and if it exists - returns it
* Otherwise returns /android
*/
const getSourceDirectory = (folder) => {
if (!fs.existsSync(path.join(folder, BASE_DIR))) {
return null;
}
if (fs.existsSync(path.join(folder, BASE_DIR, 'app'))) {
return path.join(BASE_DIR, 'app');
}
return BASE_DIR;
};
/**
* Gets package name by opening AndroidManifest.xml and reading
* package attribute
*/
const getPackageName = (src) => {
const manifest = new xml.XmlDocument(
fs.readFileSync(path.join(src, 'src/main/AndroidManifest.xml'), 'utf8')
);
return manifest.attr.package;
};
/**
* Given package name, replaces . to separators to follow Java convention
* and locate .java files
*/
const getPackageFolder = (packageName) => packageName.replace('.', path.sep);
/**
* Gets package name (class that implements ReactPackage) by searching for its
* declaration in all Java files present in the src
*/
const getPackageInstance = (src) => {
const files = glob.sync(GLOB_PATTERN, {
cwd: src,
});
const packages = files
.map(filePath => fs.readFileSync(path.join(src, filePath), 'utf8'))
.map(file => file.match(/class (.*) implements ReactPackage/))
.filter(match => match);
/**
* No packages exported, ignore
*/
if (packages.length === 0) {
return null;
}
return packages[0][1];
};
/**
* Gets android project config by analyzing given folder and taking some
* defaults specified by user into consideration
*/
exports.projectConfig = function projectConfigAndroid(folder, userConfig) {
const src = userConfig.sourceDir || getSourceDirectory(folder);
if (!src) {
return null;
}
const sourceDir = path.join(folder, src);
const packageName = userConfig.packageName || getPackageName(sourceDir);
const packageFolder = userConfig.packageFolder || getPackageFolder(packageName);
return {
sourceDir,
folder,
buildGradlePath: path.join(sourceDir, userConfig.buildGradlePath || 'build.gradle'),
settingsGradlePath: path.join(folder, BASE_DIR, userConfig.settingsGradlePath || 'settings.gradle'),
assetsPath: path.join(sourceDir, userConfig.assetsPath || 'src/main/assets'),
mainActivityPath: path.join(sourceDir, userConfig.mainActivityPath || `src/main/java/${packageFolder}/MainActivity.java`),
};
};
/**
* Same as projectConfigAndroid except it returns
* different config that applies to packages only
*/
exports.dependencyConfig = function dependencyConfigAndroid(folder, userConfig) {
const src = userConfig.sourceDir || getSourceDirectory(folder);
if (!src) {
return null;
}
const sourceDir = path.join(folder, src);
const packageName = userConfig.packageName || getPackageName(sourceDir);
const packageInstance = userConfig.packageInstance || getPackageInstance(sourceDir);
/**
* This module has no package to export
*/
if (!packageInstance) {
return null;
}
return {
sourceDir,
folder,
packageImportPath: `import ${packageName}.${packageInstance}`,
packageInstance: `new ${packageInstance}()`,
};
};