1082815dcSEvan Baconimport { ExpoConfig } from '@expo/config-types';
2082815dcSEvan Baconimport plist from '@expo/plist';
3082815dcSEvan Baconimport assert from 'assert';
4082815dcSEvan Baconimport fs from 'fs';
5082815dcSEvan Baconimport path from 'path';
6082815dcSEvan Baconimport { XcodeProject } from 'xcode';
7082815dcSEvan Bacon
8082815dcSEvan Baconimport { InfoPlist } from './IosConfig.types';
9082815dcSEvan Baconimport { getSourceRoot } from './Paths';
10082815dcSEvan Baconimport { appendScheme } from './Scheme';
11082815dcSEvan Baconimport { addResourceFileToGroup, getProjectName } from './utils/Xcodeproj';
12*8a424bebSJames Ideimport { ConfigPlugin, ModProps } from '../Plugin.types';
13*8a424bebSJames Ideimport { withInfoPlist, withXcodeProject } from '../plugins/ios-plugins';
14082815dcSEvan Bacon
15082815dcSEvan Baconexport const withGoogle: ConfigPlugin = (config) => {
16082815dcSEvan Bacon  return withInfoPlist(config, (config) => {
17082815dcSEvan Bacon    config.modResults = setGoogleConfig(config, config.modResults, config.modRequest);
18082815dcSEvan Bacon    return config;
19082815dcSEvan Bacon  });
20082815dcSEvan Bacon};
21082815dcSEvan Bacon
22082815dcSEvan Baconexport const withGoogleServicesFile: ConfigPlugin = (config) => {
23082815dcSEvan Bacon  return withXcodeProject(config, (config) => {
24082815dcSEvan Bacon    config.modResults = setGoogleServicesFile(config, {
25082815dcSEvan Bacon      projectRoot: config.modRequest.projectRoot,
26082815dcSEvan Bacon      project: config.modResults,
27082815dcSEvan Bacon    });
28082815dcSEvan Bacon    return config;
29082815dcSEvan Bacon  });
30082815dcSEvan Bacon};
31082815dcSEvan Bacon
32082815dcSEvan Baconfunction readGoogleServicesInfoPlist(
33082815dcSEvan Bacon  relativePath: string,
34082815dcSEvan Bacon  { projectRoot }: { projectRoot: string }
35082815dcSEvan Bacon) {
36082815dcSEvan Bacon  const googleServiceFilePath = path.resolve(projectRoot, relativePath);
37082815dcSEvan Bacon  const contents = fs.readFileSync(googleServiceFilePath, 'utf8');
38082815dcSEvan Bacon  assert(contents, 'GoogleService-Info.plist is empty');
39082815dcSEvan Bacon  return plist.parse(contents);
40082815dcSEvan Bacon}
41082815dcSEvan Bacon
425f51f606SEvan Baconexport function getGoogleSignInReversedClientId(
43082815dcSEvan Bacon  config: Pick<ExpoConfig, 'ios'>,
44082815dcSEvan Bacon  modRequest: Pick<ModProps<InfoPlist>, 'projectRoot'>
45082815dcSEvan Bacon): string | null {
46082815dcSEvan Bacon  const googleServicesFileRelativePath = getGoogleServicesFile(config);
47082815dcSEvan Bacon  if (googleServicesFileRelativePath === null) {
48082815dcSEvan Bacon    return null;
49082815dcSEvan Bacon  }
50082815dcSEvan Bacon
51082815dcSEvan Bacon  const infoPlist = readGoogleServicesInfoPlist(googleServicesFileRelativePath, modRequest);
52082815dcSEvan Bacon
53082815dcSEvan Bacon  return infoPlist.REVERSED_CLIENT_ID ?? null;
54082815dcSEvan Bacon}
55082815dcSEvan Bacon
56082815dcSEvan Baconexport function getGoogleServicesFile(config: Pick<ExpoConfig, 'ios'>) {
57082815dcSEvan Bacon  return config.ios?.googleServicesFile ?? null;
58082815dcSEvan Bacon}
59082815dcSEvan Bacon
605f51f606SEvan Baconexport function setGoogleSignInReversedClientId(
61082815dcSEvan Bacon  config: Pick<ExpoConfig, 'ios'>,
62082815dcSEvan Bacon  infoPlist: InfoPlist,
63082815dcSEvan Bacon  modRequest: Pick<ModProps<InfoPlist>, 'projectRoot'>
64082815dcSEvan Bacon): InfoPlist {
655f51f606SEvan Bacon  const reversedClientId = getGoogleSignInReversedClientId(config, modRequest);
66082815dcSEvan Bacon
675f51f606SEvan Bacon  if (reversedClientId === null) {
68082815dcSEvan Bacon    return infoPlist;
69082815dcSEvan Bacon  }
70082815dcSEvan Bacon
715f51f606SEvan Bacon  return appendScheme(reversedClientId, infoPlist);
72082815dcSEvan Bacon}
73082815dcSEvan Bacon
74082815dcSEvan Baconexport function setGoogleConfig(
75082815dcSEvan Bacon  config: Pick<ExpoConfig, 'ios'>,
76082815dcSEvan Bacon  infoPlist: InfoPlist,
77082815dcSEvan Bacon  modRequest: ModProps<InfoPlist>
78082815dcSEvan Bacon): InfoPlist {
795f51f606SEvan Bacon  infoPlist = setGoogleSignInReversedClientId(config, infoPlist, modRequest);
80082815dcSEvan Bacon  return infoPlist;
81082815dcSEvan Bacon}
82082815dcSEvan Bacon
83082815dcSEvan Baconexport function setGoogleServicesFile(
84082815dcSEvan Bacon  config: Pick<ExpoConfig, 'ios'>,
85082815dcSEvan Bacon  { projectRoot, project }: { project: XcodeProject; projectRoot: string }
86082815dcSEvan Bacon): XcodeProject {
87082815dcSEvan Bacon  const googleServicesFileRelativePath = getGoogleServicesFile(config);
88082815dcSEvan Bacon  if (googleServicesFileRelativePath === null) {
89082815dcSEvan Bacon    return project;
90082815dcSEvan Bacon  }
91082815dcSEvan Bacon
92082815dcSEvan Bacon  const googleServiceFilePath = path.resolve(projectRoot, googleServicesFileRelativePath);
93082815dcSEvan Bacon  fs.copyFileSync(
94082815dcSEvan Bacon    googleServiceFilePath,
95082815dcSEvan Bacon    path.join(getSourceRoot(projectRoot), 'GoogleService-Info.plist')
96082815dcSEvan Bacon  );
97082815dcSEvan Bacon
98082815dcSEvan Bacon  const projectName = getProjectName(projectRoot);
99082815dcSEvan Bacon  const plistFilePath = `${projectName}/GoogleService-Info.plist`;
100082815dcSEvan Bacon  if (!project.hasFile(plistFilePath)) {
101082815dcSEvan Bacon    project = addResourceFileToGroup({
102082815dcSEvan Bacon      filepath: plistFilePath,
103082815dcSEvan Bacon      groupName: projectName,
104082815dcSEvan Bacon      project,
105082815dcSEvan Bacon      isBuildFile: true,
106082815dcSEvan Bacon      verbose: true,
107082815dcSEvan Bacon    });
108082815dcSEvan Bacon  }
109082815dcSEvan Bacon  return project;
110082815dcSEvan Bacon}
111