@expo/config-plugins
Version:
A library for Expo config plugins
241 lines (232 loc) • 8.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getBundleIdentifier = getBundleIdentifier;
exports.getBundleIdentifierFromPbxproj = getBundleIdentifierFromPbxproj;
exports.resetAllPlistBundleIdentifiers = resetAllPlistBundleIdentifiers;
exports.resetPlistBundleIdentifier = resetPlistBundleIdentifier;
exports.setBundleIdentifier = setBundleIdentifier;
exports.setBundleIdentifierForPbxproj = setBundleIdentifierForPbxproj;
exports.updateBundleIdentifierForPbxproj = updateBundleIdentifierForPbxproj;
exports.withBundleIdentifier = void 0;
function _plist() {
const data = _interopRequireDefault(require("@expo/plist"));
_plist = function () {
return data;
};
return data;
}
function _assert() {
const data = _interopRequireDefault(require("assert"));
_assert = function () {
return data;
};
return data;
}
function _fs() {
const data = _interopRequireDefault(require("fs"));
_fs = function () {
return data;
};
return data;
}
function _xcode() {
const data = _interopRequireDefault(require("xcode"));
_xcode = function () {
return data;
};
return data;
}
function _Paths() {
const data = require("./Paths");
_Paths = function () {
return data;
};
return data;
}
function _Target() {
const data = require("./Target");
_Target = function () {
return data;
};
return data;
}
function _Xcodeproj() {
const data = require("./utils/Xcodeproj");
_Xcodeproj = function () {
return data;
};
return data;
}
function _string() {
const data = require("./utils/string");
_string = function () {
return data;
};
return data;
}
function _iosPlugins() {
const data = require("../plugins/ios-plugins");
_iosPlugins = function () {
return data;
};
return data;
}
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const withBundleIdentifier = (config, {
bundleIdentifier
}) => {
return (0, _iosPlugins().withXcodeProject)(config, async config => {
const bundleId = bundleIdentifier ?? config.ios?.bundleIdentifier;
// Should never happen.
(0, _assert().default)(bundleId, '`bundleIdentifier` must be defined in the app config (`ios.bundleIdentifier`) or passed to the plugin `withBundleIdentifier`.');
config.modResults = updateBundleIdentifierForPbxprojObject(config.modResults, bundleId, false);
return config;
});
};
exports.withBundleIdentifier = withBundleIdentifier;
function getBundleIdentifier(config) {
return config.ios?.bundleIdentifier ?? null;
}
/**
* In Turtle v1 we set the bundleIdentifier directly on Info.plist rather
* than in pbxproj
*/
function setBundleIdentifier(config, infoPlist) {
const bundleIdentifier = getBundleIdentifier(config);
if (!bundleIdentifier) {
return infoPlist;
}
return {
...infoPlist,
CFBundleIdentifier: bundleIdentifier
};
}
/**
* Gets the bundle identifier defined in the Xcode project found in the project directory.
*
* A bundle identifier is stored as a value in XCBuildConfiguration entry.
* Those entries exist for every pair (build target, build configuration).
* Unless target name is passed, the first target defined in the pbxproj is used
* (to keep compatibility with the inaccurate legacy implementation of this function).
* The build configuration is usually 'Release' or 'Debug'. However, it could be any arbitrary string.
* Defaults to 'Release'.
*
* @param {string} projectRoot Path to project root containing the ios directory
* @param {string} targetName Target name
* @param {string} buildConfiguration Build configuration. Defaults to 'Release'.
* @returns {string | null} bundle identifier of the Xcode project or null if the project is not configured
*/
function getBundleIdentifierFromPbxproj(projectRoot, {
targetName,
buildConfiguration = 'Release'
} = {}) {
let pbxprojPath;
try {
pbxprojPath = (0, _Paths().getPBXProjectPath)(projectRoot);
} catch {
return null;
}
const project = _xcode().default.project(pbxprojPath);
project.parseSync();
const xcBuildConfiguration = (0, _Target().getXCBuildConfigurationFromPbxproj)(project, {
targetName,
buildConfiguration
});
if (!xcBuildConfiguration) {
return null;
}
return getProductBundleIdentifierFromBuildConfiguration(xcBuildConfiguration);
}
function getProductBundleIdentifierFromBuildConfiguration(xcBuildConfiguration) {
const bundleIdentifierRaw = xcBuildConfiguration.buildSettings.PRODUCT_BUNDLE_IDENTIFIER;
if (bundleIdentifierRaw) {
const bundleIdentifier = (0, _string().trimQuotes)(bundleIdentifierRaw);
return (0, _Xcodeproj().resolveXcodeBuildSetting)(bundleIdentifier, setting => xcBuildConfiguration.buildSettings[setting]);
} else {
return null;
}
}
/**
* Updates the bundle identifier for a given pbxproj
*
* @param {string} pbxprojPath Path to pbxproj file
* @param {string} bundleIdentifier Bundle identifier to set in the pbxproj
* @param {boolean} [updateProductName=true] Whether to update PRODUCT_NAME
*/
function updateBundleIdentifierForPbxproj(pbxprojPath, bundleIdentifier, updateProductName = true) {
const project = _xcode().default.project(pbxprojPath);
project.parseSync();
_fs().default.writeFileSync(pbxprojPath, updateBundleIdentifierForPbxprojObject(project, bundleIdentifier, updateProductName).writeSync());
}
/**
* Updates the bundle identifier for a given pbxproj
*
* @param {string} project pbxproj file
* @param {string} bundleIdentifier Bundle identifier to set in the pbxproj
* @param {boolean} [updateProductName=true] Whether to update PRODUCT_NAME
*/
function updateBundleIdentifierForPbxprojObject(project, bundleIdentifier, updateProductName = true) {
const [, nativeTarget] = (0, _Target().findFirstNativeTarget)(project);
(0, _Xcodeproj().getBuildConfigurationsForListId)(project, nativeTarget.buildConfigurationList).forEach(([, item]) => {
if (item.buildSettings.PRODUCT_BUNDLE_IDENTIFIER === bundleIdentifier) {
return;
}
item.buildSettings.PRODUCT_BUNDLE_IDENTIFIER = `"${bundleIdentifier}"`;
if (updateProductName) {
const productName = bundleIdentifier.split('.').pop();
if (!productName?.includes('$')) {
item.buildSettings.PRODUCT_NAME = productName;
}
}
});
return project;
}
/**
* Updates the bundle identifier for pbx projects inside the ios directory of the given project root
*
* @param {string} projectRoot Path to project root containing the ios directory
* @param {string} bundleIdentifier Desired bundle identifier
* @param {boolean} [updateProductName=true] Whether to update PRODUCT_NAME
*/
function setBundleIdentifierForPbxproj(projectRoot, bundleIdentifier, updateProductName = true) {
// Get all pbx projects in the ${projectRoot}/ios directory
let pbxprojPaths = [];
try {
pbxprojPaths = (0, _Paths().getAllPBXProjectPaths)(projectRoot);
} catch {}
for (const pbxprojPath of pbxprojPaths) {
updateBundleIdentifierForPbxproj(pbxprojPath, bundleIdentifier, updateProductName);
}
}
/**
* Reset bundle identifier field in Info.plist to use PRODUCT_BUNDLE_IDENTIFIER, as recommended by Apple.
*/
const defaultBundleId = '$(PRODUCT_BUNDLE_IDENTIFIER)';
function resetAllPlistBundleIdentifiers(projectRoot) {
const infoPlistPaths = (0, _Paths().getAllInfoPlistPaths)(projectRoot);
for (const plistPath of infoPlistPaths) {
resetPlistBundleIdentifier(plistPath);
}
}
function resetPlistBundleIdentifier(plistPath) {
const rawPlist = _fs().default.readFileSync(plistPath, 'utf8');
const plistObject = _plist().default.parse(rawPlist);
if (plistObject.CFBundleIdentifier) {
if (plistObject.CFBundleIdentifier === defaultBundleId) return;
// attempt to match default Info.plist format
const format = {
pretty: true,
indent: `\t`
};
const xml = _plist().default.build({
...plistObject,
CFBundleIdentifier: defaultBundleId
}, format);
if (xml !== rawPlist) {
_fs().default.writeFileSync(plistPath, xml);
}
}
}
//# sourceMappingURL=BundleIdentifier.js.map