1import fs from 'fs';
2
3import { findFirstNativeTarget, findNativeTargetByName } from './Target';
4import {
5  ConfigurationSectionEntry,
6  getBuildConfigurationsForListId,
7  getPbxproj,
8  getProjectSection,
9  isNotComment,
10  ProjectSectionEntry,
11} from './utils/Xcodeproj';
12import { trimQuotes } from './utils/string';
13
14type ProvisioningProfileSettings = {
15  targetName?: string;
16  appleTeamId: string;
17  profileName: string;
18  buildConfiguration?: string;
19};
20
21export function setProvisioningProfileForPbxproj(
22  projectRoot: string,
23  {
24    targetName,
25    profileName,
26    appleTeamId,
27    buildConfiguration = 'Release',
28  }: ProvisioningProfileSettings
29): void {
30  const project = getPbxproj(projectRoot);
31
32  const nativeTargetEntry = targetName
33    ? findNativeTargetByName(project, targetName)
34    : findFirstNativeTarget(project);
35  const [nativeTargetId, nativeTarget] = nativeTargetEntry;
36
37  const quotedAppleTeamId = ensureQuotes(appleTeamId);
38
39  getBuildConfigurationsForListId(project, nativeTarget.buildConfigurationList)
40    .filter(([, item]: ConfigurationSectionEntry) => trimQuotes(item.name) === buildConfiguration)
41    .forEach(([, item]: ConfigurationSectionEntry) => {
42      item.buildSettings.PROVISIONING_PROFILE_SPECIFIER = `"${profileName}"`;
43      item.buildSettings.DEVELOPMENT_TEAM = quotedAppleTeamId;
44      item.buildSettings.CODE_SIGN_IDENTITY = '"iPhone Distribution"';
45      item.buildSettings.CODE_SIGN_STYLE = 'Manual';
46    });
47
48  Object.entries(getProjectSection(project))
49    .filter(isNotComment)
50    .forEach(([, item]: ProjectSectionEntry) => {
51      if (!item.attributes.TargetAttributes[nativeTargetId]) {
52        item.attributes.TargetAttributes[nativeTargetId] = {};
53      }
54      item.attributes.TargetAttributes[nativeTargetId].DevelopmentTeam = quotedAppleTeamId;
55      item.attributes.TargetAttributes[nativeTargetId].ProvisioningStyle = 'Manual';
56    });
57
58  fs.writeFileSync(project.filepath, project.writeSync());
59}
60
61const ensureQuotes = (value: string) => {
62  if (!value.match(/^['"]/)) {
63    return `"${value}"`;
64  }
65  return value;
66};
67