1import { getConfig, getProjectConfigDescriptionWithPaths } from '@expo/config';
2
3import { CommandError, UnimplementedError } from '../../utils/errors';
4import { get } from '../../utils/obj';
5
6/** Resolves a native app identifier (bundle identifier, package name) from the project files. */
7export class AppIdResolver {
8  constructor(
9    protected projectRoot: string,
10    /** Platform to use. */
11    protected platform: string,
12    /** Nested key in the Expo config like `android.package` or `ios.bundleIdentifier`. */
13    protected configProperty: string
14  ) {}
15
16  /** Resolve the application ID for the project. */
17  async getAppIdAsync(): Promise<string> {
18    if (await this.hasNativeProjectAsync()) {
19      return this.getAppIdFromNativeAsync();
20    }
21    return this.getAppIdFromConfigAsync();
22  }
23
24  /** Returns `true` if the project has native project code. */
25  async hasNativeProjectAsync(): Promise<boolean> {
26    throw new UnimplementedError();
27  }
28
29  /** Return the app ID from the Expo config or assert. */
30  async getAppIdFromConfigAsync(): Promise<string> {
31    const config = getConfig(this.projectRoot);
32
33    const appId = get(config.exp, this.configProperty);
34    if (!appId) {
35      throw new CommandError(
36        'NO_APP_ID',
37        `Required property '${
38          this.configProperty
39        }' is not found in the project ${getProjectConfigDescriptionWithPaths(
40          this.projectRoot,
41          config
42        )}. This is required to open the app.`
43      );
44    }
45    return appId;
46  }
47
48  /** Return the app ID from the native project files or null if the app ID cannot be found. */
49  async resolveAppIdFromNativeAsync(): Promise<string | null> {
50    throw new UnimplementedError();
51  }
52
53  /** Return the app ID from the native project files or assert. */
54  async getAppIdFromNativeAsync(): Promise<string> {
55    const appId = await this.resolveAppIdFromNativeAsync();
56    if (!appId) {
57      throw new CommandError(
58        'NO_APP_ID',
59        `Failed to locate the ${this.platform} application identifier in the "${this.platform}/" folder. This is required to open the app.`
60      );
61    }
62    return appId;
63  }
64}
65