UNPKG

@bacons/apple-targets

Version:
124 lines (123 loc) 6.23 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveEntitlementsForCodeSign = exports.getEntitlementsConflictMessage = exports.classifySourceEntitlementsFile = exports.writeGeneratedEntitlements = exports.getGeneratedEntitlementsCodeSignPath = exports.getGeneratedEntitlementsPath = exports.getGeneratedEntitlementsDir = exports.GENERATED_ENTITLEMENTS_FILE_NAME = void 0; const plist_1 = __importDefault(require("@expo/plist")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const target_1 = require("./target"); /** * File name used for entitlements generated from the `entitlements` object in * `expo-target.config`. The `generated` prefix signals the file is derived and * should not be hand-edited. */ exports.GENERATED_ENTITLEMENTS_FILE_NAME = "generated.entitlements"; /** * Absolute path to the directory that holds a target's generated entitlements, * e.g. `<projectRoot>/ios/.targets/<productName>/`. */ function getGeneratedEntitlementsDir(projectRoot, productName) { return path_1.default.join(projectRoot, "ios", target_1.TARGET_GENERATED_DIR, productName); } exports.getGeneratedEntitlementsDir = getGeneratedEntitlementsDir; /** * Absolute path to a target's generated entitlements file, e.g. * `<projectRoot>/ios/.targets/<productName>/generated.entitlements`. */ function getGeneratedEntitlementsPath(projectRoot, productName) { return path_1.default.join(getGeneratedEntitlementsDir(projectRoot, productName), exports.GENERATED_ENTITLEMENTS_FILE_NAME); } exports.getGeneratedEntitlementsPath = getGeneratedEntitlementsPath; /** * Value for the `CODE_SIGN_ENTITLEMENTS` build setting pointing at a generated * entitlements file. The path is resolved by Xcode relative to the `ios/` * project root, e.g. `.targets/<productName>/generated.entitlements`. */ function getGeneratedEntitlementsCodeSignPath(productName) { return `${target_1.TARGET_GENERATED_DIR}/${productName}/${exports.GENERATED_ENTITLEMENTS_FILE_NAME}`; } exports.getGeneratedEntitlementsCodeSignPath = getGeneratedEntitlementsCodeSignPath; /** * Write a target's entitlements to its generated location, creating parent * directories as needed. Returns the absolute path of the written file. * * This is the single place a generated entitlements file is created — it always * writes under `ios/<TARGET_GENERATED_DIR>/` and never into the target's source * directory, keeping derived artifacts out of version control. */ function writeGeneratedEntitlements(projectRoot, productName, entitlements) { const dir = getGeneratedEntitlementsDir(projectRoot, productName); const file = getGeneratedEntitlementsPath(projectRoot, productName); fs_1.default.mkdirSync(dir, { recursive: true }); fs_1.default.writeFileSync(file, plist_1.default.build(entitlements)); return file; } exports.writeGeneratedEntitlements = writeGeneratedEntitlements; function classifySourceEntitlementsFile(filePath) { return path_1.default.basename(filePath) === exports.GENERATED_ENTITLEMENTS_FILE_NAME ? "stale-generated" : "handwritten"; } exports.classifySourceEntitlementsFile = classifySourceEntitlementsFile; /** * Warning shown when a target has BOTH a `generated.entitlements` file in its * source folder (written by an older version of this plugin) AND an * `entitlements` object in `expo-target.config`. The two are an ambiguous, * conflicting source of truth. This is non-fatal — the config object wins and * the file is generated under `ios/` — but the user should remove one of the * two to resolve the ambiguity. * * @param entitlementsFileRelativePath project-root-relative path to the source * `generated.entitlements` file, e.g. `targets/clip/generated.entitlements`. * @param configRelativePath project-root-relative path to the target config, * e.g. `targets/clip/expo-target.config.js`. */ function getEntitlementsConflictMessage(entitlementsFileRelativePath, configRelativePath) { return `Ignoring ${entitlementsFileRelativePath} in favor of entitlements object in ${configRelativePath}. Either delete the generated file or remove the entitlements object to continue.`; } exports.getEntitlementsConflictMessage = getEntitlementsConflictMessage; /** * Resolve which entitlements file should drive `CODE_SIGN_ENTITLEMENTS` for a * target, with a deterministic precedence: * * 1. A generated entitlements file under `ios/<TARGET_GENERATED_DIR>/` (written * when the config defines an `entitlements` object) always wins. * 2. Otherwise, a hand-written `*.entitlements` file in the target's source * folder is used. * 3. If neither exists, returns `null` and the caller removes the setting. */ function resolveEntitlementsForCodeSign({ projectRoot, productName, cwd, }) { const generatedAbsolutePath = getGeneratedEntitlementsPath(projectRoot, productName); if (fs_1.default.existsSync(generatedAbsolutePath)) { return { absolutePath: generatedAbsolutePath, codeSignEntitlements: getGeneratedEntitlementsCodeSignPath(productName), }; } const sourceCwd = path_1.default.join(projectRoot, "ios", cwd); const sourceEntitlements = findSourceEntitlementsFiles(sourceCwd); if (sourceEntitlements.length > 0) { return { absolutePath: path_1.default.join(sourceCwd, sourceEntitlements[0]), codeSignEntitlements: `${cwd}/${sourceEntitlements[0]}`, }; } return null; } exports.resolveEntitlementsForCodeSign = resolveEntitlementsForCodeSign; /** * List the `*.entitlements` files directly inside a target's source folder, * sorted for deterministic ordering. Non-recursive, mirroring the `*.glob` used * elsewhere — there should normally be at most one. */ function findSourceEntitlementsFiles(sourceCwd) { if (!fs_1.default.existsSync(sourceCwd)) { return []; } return fs_1.default .readdirSync(sourceCwd) .filter((name) => name.endsWith(".entitlements")) .sort(); }