1082815dcSEvan Bacon"use strict";
2082815dcSEvan Bacon
3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", {
4082815dcSEvan Bacon  value: true
5082815dcSEvan Bacon});
6082815dcSEvan Baconexports.getApplicationIdAsync = getApplicationIdAsync;
7082815dcSEvan Baconexports.getPackage = getPackage;
8082815dcSEvan Baconexports.renameJniOnDiskForType = renameJniOnDiskForType;
9082815dcSEvan Baconexports.renamePackageOnDisk = renamePackageOnDisk;
10082815dcSEvan Baconexports.renamePackageOnDiskForType = renamePackageOnDiskForType;
11082815dcSEvan Baconexports.setPackageInBuildGradle = setPackageInBuildGradle;
123216ce43SKudo Chienexports.withPackageRefactor = exports.withPackageGradle = void 0;
13082815dcSEvan Baconfunction _debug() {
14082815dcSEvan Bacon  const data = _interopRequireDefault(require("debug"));
15082815dcSEvan Bacon  _debug = function () {
16082815dcSEvan Bacon    return data;
17082815dcSEvan Bacon  };
18082815dcSEvan Bacon  return data;
19082815dcSEvan Bacon}
20082815dcSEvan Baconfunction _fs() {
21082815dcSEvan Bacon  const data = _interopRequireDefault(require("fs"));
22082815dcSEvan Bacon  _fs = function () {
23082815dcSEvan Bacon    return data;
24082815dcSEvan Bacon  };
25082815dcSEvan Bacon  return data;
26082815dcSEvan Bacon}
27082815dcSEvan Baconfunction _glob() {
28082815dcSEvan Bacon  const data = require("glob");
29082815dcSEvan Bacon  _glob = function () {
30082815dcSEvan Bacon    return data;
31082815dcSEvan Bacon  };
32082815dcSEvan Bacon  return data;
33082815dcSEvan Bacon}
34082815dcSEvan Baconfunction _path() {
35082815dcSEvan Bacon  const data = _interopRequireDefault(require("path"));
36082815dcSEvan Bacon  _path = function () {
37082815dcSEvan Bacon    return data;
38082815dcSEvan Bacon  };
39082815dcSEvan Bacon  return data;
40082815dcSEvan Bacon}
41*8a424bebSJames Idefunction _Paths() {
42*8a424bebSJames Ide  const data = require("./Paths");
43*8a424bebSJames Ide  _Paths = function () {
44*8a424bebSJames Ide    return data;
45*8a424bebSJames Ide  };
46*8a424bebSJames Ide  return data;
47*8a424bebSJames Ide}
48082815dcSEvan Baconfunction _androidPlugins() {
49082815dcSEvan Bacon  const data = require("../plugins/android-plugins");
50082815dcSEvan Bacon  _androidPlugins = function () {
51082815dcSEvan Bacon    return data;
52082815dcSEvan Bacon  };
53082815dcSEvan Bacon  return data;
54082815dcSEvan Bacon}
55082815dcSEvan Baconfunction _withDangerousMod() {
56082815dcSEvan Bacon  const data = require("../plugins/withDangerousMod");
57082815dcSEvan Bacon  _withDangerousMod = function () {
58082815dcSEvan Bacon    return data;
59082815dcSEvan Bacon  };
60082815dcSEvan Bacon  return data;
61082815dcSEvan Bacon}
62082815dcSEvan Baconfunction _modules() {
63082815dcSEvan Bacon  const data = require("../utils/modules");
64082815dcSEvan Bacon  _modules = function () {
65082815dcSEvan Bacon    return data;
66082815dcSEvan Bacon  };
67082815dcSEvan Bacon  return data;
68082815dcSEvan Bacon}
69082815dcSEvan Baconfunction _warnings() {
70082815dcSEvan Bacon  const data = require("../utils/warnings");
71082815dcSEvan Bacon  _warnings = function () {
72082815dcSEvan Bacon    return data;
73082815dcSEvan Bacon  };
74082815dcSEvan Bacon  return data;
75082815dcSEvan Bacon}
76082815dcSEvan Baconfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
77082815dcSEvan Baconconst debug = (0, _debug().default)('expo:config-plugins:android:package');
78082815dcSEvan Baconconst withPackageGradle = config => {
79082815dcSEvan Bacon  return (0, _androidPlugins().withAppBuildGradle)(config, config => {
80082815dcSEvan Bacon    if (config.modResults.language === 'groovy') {
81082815dcSEvan Bacon      config.modResults.contents = setPackageInBuildGradle(config, config.modResults.contents);
82082815dcSEvan Bacon    } else {
83082815dcSEvan Bacon      (0, _warnings().addWarningAndroid)('android.package', `Cannot automatically configure app build.gradle if it's not groovy`);
84082815dcSEvan Bacon    }
85082815dcSEvan Bacon    return config;
86082815dcSEvan Bacon  });
87082815dcSEvan Bacon};
88082815dcSEvan Baconexports.withPackageGradle = withPackageGradle;
89082815dcSEvan Baconconst withPackageRefactor = config => {
90082815dcSEvan Bacon  return (0, _withDangerousMod().withDangerousMod)(config, ['android', async config => {
91082815dcSEvan Bacon    await renamePackageOnDisk(config, config.modRequest.projectRoot);
92082815dcSEvan Bacon    return config;
93082815dcSEvan Bacon  }]);
94082815dcSEvan Bacon};
95082815dcSEvan Baconexports.withPackageRefactor = withPackageRefactor;
96082815dcSEvan Baconfunction getPackage(config) {
97082815dcSEvan Bacon  var _config$android$packa, _config$android;
98082815dcSEvan Bacon  return (_config$android$packa = (_config$android = config.android) === null || _config$android === void 0 ? void 0 : _config$android.package) !== null && _config$android$packa !== void 0 ? _config$android$packa : null;
99082815dcSEvan Bacon}
100082815dcSEvan Baconfunction getPackageRoot(projectRoot, type) {
101082815dcSEvan Bacon  return _path().default.join(projectRoot, 'android', 'app', 'src', type, 'java');
102082815dcSEvan Bacon}
103082815dcSEvan Baconfunction getCurrentPackageName(projectRoot, packageRoot) {
104082815dcSEvan Bacon  const mainApplication = (0, _Paths().getProjectFilePath)(projectRoot, 'MainApplication');
105082815dcSEvan Bacon  const packagePath = _path().default.dirname(mainApplication);
106082815dcSEvan Bacon  const packagePathParts = _path().default.relative(packageRoot, packagePath).split(_path().default.sep).filter(Boolean);
107082815dcSEvan Bacon  return packagePathParts.join('.');
108082815dcSEvan Bacon}
109082815dcSEvan Baconfunction getCurrentPackageForProjectFile(projectRoot, packageRoot, fileName, type) {
110082815dcSEvan Bacon  const filePath = (0, _glob().sync)(_path().default.join(projectRoot, `android/app/src/${type}/java/**/${fileName}.@(java|kt)`))[0];
111082815dcSEvan Bacon  if (!filePath) {
112082815dcSEvan Bacon    return null;
113082815dcSEvan Bacon  }
114082815dcSEvan Bacon  const packagePath = _path().default.dirname(filePath);
115082815dcSEvan Bacon  const packagePathParts = _path().default.relative(packageRoot, packagePath).split(_path().default.sep).filter(Boolean);
116082815dcSEvan Bacon  return packagePathParts.join('.');
117082815dcSEvan Bacon}
118082815dcSEvan Baconfunction getCurrentPackageNameForType(projectRoot, type) {
119082815dcSEvan Bacon  const packageRoot = getPackageRoot(projectRoot, type);
120082815dcSEvan Bacon  if (type === 'main') {
121082815dcSEvan Bacon    return getCurrentPackageName(projectRoot, packageRoot);
122ee216927STomasz Sapeta  }
123ee216927STomasz Sapeta  // debug, etc..
124082815dcSEvan Bacon  return getCurrentPackageForProjectFile(projectRoot, packageRoot, '*', type);
125ee216927STomasz Sapeta}
126ee216927STomasz Sapeta
127ee216927STomasz Sapeta// NOTE(brentvatne): this assumes that our MainApplication.java file is in the root of the package
128082815dcSEvan Bacon// this makes sense for standard react-native projects but may not apply in customized projects, so if
129082815dcSEvan Bacon// we want this to be runnable in any app we need to handle other possibilities
130082815dcSEvan Baconasync function renamePackageOnDisk(config, projectRoot) {
131082815dcSEvan Bacon  const newPackageName = getPackage(config);
132082815dcSEvan Bacon  if (newPackageName === null) {
133082815dcSEvan Bacon    return;
134082815dcSEvan Bacon  }
13584f418d7SKudo Chien  for (const type of ['debug', 'main', 'release']) {
136082815dcSEvan Bacon    await renameJniOnDiskForType({
137082815dcSEvan Bacon      projectRoot,
138082815dcSEvan Bacon      type,
139082815dcSEvan Bacon      packageName: newPackageName
140082815dcSEvan Bacon    });
141082815dcSEvan Bacon    await renamePackageOnDiskForType({
142082815dcSEvan Bacon      projectRoot,
143082815dcSEvan Bacon      type,
144082815dcSEvan Bacon      packageName: newPackageName
145082815dcSEvan Bacon    });
146082815dcSEvan Bacon  }
147082815dcSEvan Bacon}
148082815dcSEvan Baconasync function renameJniOnDiskForType({
149082815dcSEvan Bacon  projectRoot,
150082815dcSEvan Bacon  type,
151082815dcSEvan Bacon  packageName
152082815dcSEvan Bacon}) {
153082815dcSEvan Bacon  if (!packageName) {
154082815dcSEvan Bacon    return;
155082815dcSEvan Bacon  }
156082815dcSEvan Bacon  const currentPackageName = getCurrentPackageNameForType(projectRoot, type);
157082815dcSEvan Bacon  if (!currentPackageName || !packageName || currentPackageName === packageName) {
158082815dcSEvan Bacon    return;
159082815dcSEvan Bacon  }
160082815dcSEvan Bacon  const jniRoot = _path().default.join(projectRoot, 'android', 'app', 'src', type, 'jni');
161082815dcSEvan Bacon  const filesToUpdate = [...(0, _glob().sync)('**/*', {
162082815dcSEvan Bacon    cwd: jniRoot,
163082815dcSEvan Bacon    absolute: true
164ee216927STomasz Sapeta  })];
165ee216927STomasz Sapeta  // Replace all occurrences of the path in the project
166082815dcSEvan Bacon  filesToUpdate.forEach(filepath => {
167082815dcSEvan Bacon    try {
168082815dcSEvan Bacon      if (_fs().default.lstatSync(filepath).isFile() && ['.h', '.cpp'].includes(_path().default.extname(filepath))) {
169082815dcSEvan Bacon        let contents = _fs().default.readFileSync(filepath).toString();
170082815dcSEvan Bacon        contents = contents.replace(new RegExp(transformJavaClassDescriptor(currentPackageName).replace(/\//g, '\\/'), 'g'), transformJavaClassDescriptor(packageName));
171082815dcSEvan Bacon        _fs().default.writeFileSync(filepath, contents);
172082815dcSEvan Bacon      }
173082815dcSEvan Bacon    } catch {
174082815dcSEvan Bacon      debug(`Error updating "${filepath}" for type "${type}"`);
175082815dcSEvan Bacon    }
176082815dcSEvan Bacon  });
177082815dcSEvan Bacon}
178082815dcSEvan Baconasync function renamePackageOnDiskForType({
179082815dcSEvan Bacon  projectRoot,
180082815dcSEvan Bacon  type,
181082815dcSEvan Bacon  packageName
182082815dcSEvan Bacon}) {
183082815dcSEvan Bacon  if (!packageName) {
184082815dcSEvan Bacon    return;
185082815dcSEvan Bacon  }
186082815dcSEvan Bacon  const currentPackageName = getCurrentPackageNameForType(projectRoot, type);
187082815dcSEvan Bacon  debug(`Found package "${currentPackageName}" for type "${type}"`);
188082815dcSEvan Bacon  if (!currentPackageName || currentPackageName === packageName) {
189082815dcSEvan Bacon    return;
190082815dcSEvan Bacon  }
191082815dcSEvan Bacon  debug(`Refactor "${currentPackageName}" to "${packageName}" for type "${type}"`);
192ee216927STomasz Sapeta  const packageRoot = getPackageRoot(projectRoot, type);
193ee216927STomasz Sapeta  // Set up our paths
194082815dcSEvan Bacon  if (!(await (0, _modules().directoryExistsAsync)(packageRoot))) {
195082815dcSEvan Bacon    debug(`- skipping refactor of missing directory: ${packageRoot}`);
196082815dcSEvan Bacon    return;
197082815dcSEvan Bacon  }
198082815dcSEvan Bacon  const currentPackagePath = _path().default.join(packageRoot, ...currentPackageName.split('.'));
199ee216927STomasz Sapeta  const newPackagePath = _path().default.join(packageRoot, ...packageName.split('.'));
200082815dcSEvan Bacon
201ee216927STomasz Sapeta  // Create the new directory
202082815dcSEvan Bacon  _fs().default.mkdirSync(newPackagePath, {
203082815dcSEvan Bacon    recursive: true
204ee216927STomasz Sapeta  });
205082815dcSEvan Bacon
206ee216927STomasz Sapeta  // Move everything from the old directory over
207082815dcSEvan Bacon  (0, _glob().sync)('**/*', {
208082815dcSEvan Bacon    cwd: currentPackagePath
209082815dcSEvan Bacon  }).forEach(relativePath => {
210082815dcSEvan Bacon    const filepath = _path().default.join(currentPackagePath, relativePath);
211082815dcSEvan Bacon    if (_fs().default.lstatSync(filepath).isFile()) {
212082815dcSEvan Bacon      moveFileSync(filepath, _path().default.join(newPackagePath, relativePath));
213082815dcSEvan Bacon    } else {
214082815dcSEvan Bacon      _fs().default.mkdirSync(filepath, {
215082815dcSEvan Bacon        recursive: true
216082815dcSEvan Bacon      });
217082815dcSEvan Bacon    }
218ee216927STomasz Sapeta  });
219ee216927STomasz Sapeta
220ee216927STomasz Sapeta  // Remove the old directory recursively from com/old/package to com/old and com,
221082815dcSEvan Bacon  // as long as the directories are empty
222082815dcSEvan Bacon  const oldPathParts = currentPackageName.split('.');
223082815dcSEvan Bacon  while (oldPathParts.length) {
224082815dcSEvan Bacon    const pathToCheck = _path().default.join(packageRoot, ...oldPathParts);
225082815dcSEvan Bacon    try {
226082815dcSEvan Bacon      const files = _fs().default.readdirSync(pathToCheck);
227082815dcSEvan Bacon      if (files.length === 0) {
228082815dcSEvan Bacon        _fs().default.rmdirSync(pathToCheck);
229082815dcSEvan Bacon      }
230082815dcSEvan Bacon    } finally {
231082815dcSEvan Bacon      oldPathParts.pop();
232082815dcSEvan Bacon    }
233082815dcSEvan Bacon  }
234082815dcSEvan Bacon  const filesToUpdate = [...(0, _glob().sync)('**/*', {
235082815dcSEvan Bacon    cwd: newPackagePath,
236082815dcSEvan Bacon    absolute: true
237ee216927STomasz Sapeta  })];
238ee216927STomasz Sapeta  // Only update the BUCK file to match the main package name
239082815dcSEvan Bacon  if (type === 'main') {
240ed3bd27bSEvan Bacon    // NOTE(EvanBacon): We dropped this file in SDK 48 but other templates may still use it.
241082815dcSEvan Bacon    filesToUpdate.push(_path().default.join(projectRoot, 'android', 'app', 'BUCK'));
242ee216927STomasz Sapeta  }
243ee216927STomasz Sapeta  // Replace all occurrences of the path in the project
244082815dcSEvan Bacon  filesToUpdate.forEach(filepath => {
245082815dcSEvan Bacon    try {
246082815dcSEvan Bacon      if (_fs().default.lstatSync(filepath).isFile()) {
247082815dcSEvan Bacon        let contents = _fs().default.readFileSync(filepath).toString();
248082815dcSEvan Bacon        contents = contents.replace(new RegExp(currentPackageName, 'g'), packageName);
249082815dcSEvan Bacon        if (['.h', '.cpp'].includes(_path().default.extname(filepath))) {
250082815dcSEvan Bacon          contents = contents.replace(new RegExp(transformJavaClassDescriptor(currentPackageName).replace(/\//g, '\\'), 'g'), transformJavaClassDescriptor(packageName));
251082815dcSEvan Bacon        }
252082815dcSEvan Bacon        _fs().default.writeFileSync(filepath, contents);
253082815dcSEvan Bacon      }
254082815dcSEvan Bacon    } catch {
255082815dcSEvan Bacon      debug(`Error updating "${filepath}" for type "${type}"`);
256082815dcSEvan Bacon    }
257082815dcSEvan Bacon  });
258082815dcSEvan Bacon}
259082815dcSEvan Baconfunction moveFileSync(src, dest) {
260082815dcSEvan Bacon  _fs().default.mkdirSync(_path().default.dirname(dest), {
261082815dcSEvan Bacon    recursive: true
262082815dcSEvan Bacon  });
263082815dcSEvan Bacon  _fs().default.renameSync(src, dest);
264082815dcSEvan Bacon}
265082815dcSEvan Baconfunction setPackageInBuildGradle(config, buildGradle) {
266082815dcSEvan Bacon  const packageName = getPackage(config);
267082815dcSEvan Bacon  if (packageName === null) {
268082815dcSEvan Bacon    return buildGradle;
269082815dcSEvan Bacon  }
27084f418d7SKudo Chien  const pattern = new RegExp(`(applicationId|namespace) ['"].*['"]`, 'g');
27184f418d7SKudo Chien  return buildGradle.replace(pattern, `$1 '${packageName}'`);
272082815dcSEvan Bacon}
273082815dcSEvan Baconasync function getApplicationIdAsync(projectRoot) {
274082815dcSEvan Bacon  var _matchResult$;
275082815dcSEvan Bacon  const buildGradlePath = (0, _Paths().getAppBuildGradleFilePath)(projectRoot);
276082815dcSEvan Bacon  if (!_fs().default.existsSync(buildGradlePath)) {
277082815dcSEvan Bacon    return null;
278082815dcSEvan Bacon  }
279082815dcSEvan Bacon  const buildGradle = await _fs().default.promises.readFile(buildGradlePath, 'utf8');
280ee216927STomasz Sapeta  const matchResult = buildGradle.match(/applicationId ['"](.*)['"]/);
281ee216927STomasz Sapeta  // TODO add fallback for legacy cases to read from AndroidManifest.xml
282082815dcSEvan Bacon  return (_matchResult$ = matchResult === null || matchResult === void 0 ? void 0 : matchResult[1]) !== null && _matchResult$ !== void 0 ? _matchResult$ : null;
283082815dcSEvan Bacon}
284ee216927STomasz Sapeta
285082815dcSEvan Bacon/**
286082815dcSEvan Bacon * Transform a java package name to java class descriptor,
287082815dcSEvan Bacon * e.g. `com.helloworld` -> `Lcom/helloworld`.
288082815dcSEvan Bacon */
289082815dcSEvan Baconfunction transformJavaClassDescriptor(packageName) {
290082815dcSEvan Bacon  return `L${packageName.replace(/\./g, '/')}`;
291082815dcSEvan Bacon}
292082815dcSEvan Bacon//# sourceMappingURL=Package.js.map