1"use strict"; 2 3Object.defineProperty(exports, "__esModule", { 4 value: true 5}); 6exports.compileModsAsync = compileModsAsync; 7exports.evalModsAsync = evalModsAsync; 8exports.withDefaultBaseMods = withDefaultBaseMods; 9exports.withIntrospectionBaseMods = withIntrospectionBaseMods; 10 11function _debug() { 12 const data = _interopRequireDefault(require("debug")); 13 14 _debug = function () { 15 return data; 16 }; 17 18 return data; 19} 20 21function _path() { 22 const data = _interopRequireDefault(require("path")); 23 24 _path = function () { 25 return data; 26 }; 27 28 return data; 29} 30 31function _Xcodeproj() { 32 const data = require("../ios/utils/Xcodeproj"); 33 34 _Xcodeproj = function () { 35 return data; 36 }; 37 38 return data; 39} 40 41function _errors() { 42 const data = require("../utils/errors"); 43 44 _errors = function () { 45 return data; 46 }; 47 48 return data; 49} 50 51function Warnings() { 52 const data = _interopRequireWildcard(require("../utils/warnings")); 53 54 Warnings = function () { 55 return data; 56 }; 57 58 return data; 59} 60 61function _createBaseMod() { 62 const data = require("./createBaseMod"); 63 64 _createBaseMod = function () { 65 return data; 66 }; 67 68 return data; 69} 70 71function _withAndroidBaseMods() { 72 const data = require("./withAndroidBaseMods"); 73 74 _withAndroidBaseMods = function () { 75 return data; 76 }; 77 78 return data; 79} 80 81function _withIosBaseMods() { 82 const data = require("./withIosBaseMods"); 83 84 _withIosBaseMods = function () { 85 return data; 86 }; 87 88 return data; 89} 90 91function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } 92 93function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 94 95function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 96 97const debug = (0, _debug().default)('expo:config-plugins:mod-compiler'); 98 99function withDefaultBaseMods(config, props = {}) { 100 config = (0, _withIosBaseMods().withIosBaseMods)(config, props); 101 config = (0, _withAndroidBaseMods().withAndroidBaseMods)(config, props); 102 return config; 103} 104/** 105 * Get a prebuild config that safely evaluates mods without persisting any changes to the file system. 106 * Currently this only supports infoPlist, entitlements, androidManifest, strings, gradleProperties, and expoPlist mods. 107 * This plugin should be evaluated directly: 108 */ 109 110 111function withIntrospectionBaseMods(config, props = {}) { 112 config = (0, _withIosBaseMods().withIosBaseMods)(config, { 113 saveToInternal: true, 114 // This writing optimization can be skipped since we never write in introspection mode. 115 // Including empty mods will ensure that all mods get introspected. 116 skipEmptyMod: false, 117 ...props 118 }); 119 config = (0, _withAndroidBaseMods().withAndroidBaseMods)(config, { 120 saveToInternal: true, 121 skipEmptyMod: false, 122 ...props 123 }); 124 125 if (config.mods) { 126 // Remove all mods that don't have an introspection base mod, for instance `dangerous` mods. 127 for (const platform of Object.keys(config.mods)) { 128 // const platformPreserve = preserve[platform]; 129 for (const key of Object.keys(config.mods[platform] || {})) { 130 var _config$mods$platform, _config$mods$platform2; 131 132 // @ts-ignore 133 if (!((_config$mods$platform = config.mods[platform]) !== null && _config$mods$platform !== void 0 && (_config$mods$platform2 = _config$mods$platform[key]) !== null && _config$mods$platform2 !== void 0 && _config$mods$platform2.isIntrospective)) { 134 var _config$mods$platform3; 135 136 debug(`removing non-idempotent mod: ${platform}.${key}`); // @ts-ignore 137 138 (_config$mods$platform3 = config.mods[platform]) === null || _config$mods$platform3 === void 0 ? true : delete _config$mods$platform3[key]; 139 } 140 } 141 } 142 } 143 144 return config; 145} 146/** 147 * 148 * @param projectRoot 149 * @param config 150 */ 151 152 153async function compileModsAsync(config, props) { 154 if (props.introspect === true) { 155 config = withIntrospectionBaseMods(config); 156 } else { 157 config = withDefaultBaseMods(config); 158 } 159 160 return await evalModsAsync(config, props); 161} 162 163function sortMods(commands, order) { 164 const allKeys = commands.map(([key]) => key); 165 const completeOrder = [...new Set([...order, ...allKeys])]; 166 const sorted = []; 167 168 while (completeOrder.length) { 169 const group = completeOrder.shift(); 170 const commandSet = commands.find(([key]) => key === group); 171 172 if (commandSet) { 173 sorted.push(commandSet); 174 } 175 } 176 177 return sorted; 178} 179 180function getRawClone({ 181 mods, 182 ...config 183}) { 184 // Configs should be fully serializable, so we can clone them without worrying about 185 // the mods. 186 return Object.freeze(JSON.parse(JSON.stringify(config))); 187} 188 189const orders = { 190 ios: [// dangerous runs first 191 'dangerous', // run the XcodeProject mod second because many plugins attempt to read from it. 192 'xcodeproj'], 193 android: ['dangerous'] 194}; 195/** 196 * A generic plugin compiler. 197 * 198 * @param config 199 */ 200 201async function evalModsAsync(config, { 202 projectRoot, 203 introspect, 204 platforms, 205 206 /** 207 * Throw errors when mods are missing providers. 208 * @default true 209 */ 210 assertMissingModProviders 211}) { 212 const modRawConfig = getRawClone(config); 213 214 for (const [platformName, platform] of Object.entries((_config$mods = config.mods) !== null && _config$mods !== void 0 ? _config$mods : {})) { 215 var _config$mods; 216 217 if (platforms && !platforms.includes(platformName)) { 218 debug(`skip platform: ${platformName}`); 219 continue; 220 } 221 222 let entries = Object.entries(platform); 223 224 if (entries.length) { 225 // Move dangerous item to the first position if it exists, this ensures that all dangerous code runs first. 226 entries = sortMods(entries, orders[platformName]); 227 debug(`run in order: ${entries.map(([name]) => name).join(', ')}`); 228 229 const platformProjectRoot = _path().default.join(projectRoot, platformName); 230 231 const projectName = platformName === 'ios' ? (0, _Xcodeproj().getHackyProjectName)(projectRoot, config) : undefined; 232 233 for (const [modName, mod] of entries) { 234 const modRequest = { 235 projectRoot, 236 projectName, 237 platformProjectRoot, 238 platform: platformName, 239 modName, 240 introspect: !!introspect 241 }; 242 243 if (!mod.isProvider) { 244 // In strict mode, throw an error. 245 const errorMessage = `Initial base modifier for "${platformName}.${modName}" is not a provider and therefore will not provide modResults to child mods`; 246 247 if (assertMissingModProviders !== false) { 248 throw new (_errors().PluginError)(errorMessage, 'MISSING_PROVIDER'); 249 } else { 250 Warnings().addWarningForPlatform(platformName, `${platformName}.${modName}`, `Skipping: Initial base modifier for "${platformName}.${modName}" is not a provider and therefore will not provide modResults to child mods. This may be due to an outdated version of Expo CLI.`); // In loose mode, just skip the mod entirely. 251 252 continue; 253 } 254 } 255 256 const results = await mod({ ...config, 257 modResults: null, 258 modRequest, 259 modRawConfig 260 }); // Sanity check to help locate non compliant mods. 261 262 config = (0, _createBaseMod().assertModResults)(results, platformName, modName); // @ts-ignore: `modResults` is added for modifications 263 264 delete config.modResults; // @ts-ignore: `modRequest` is added for modifications 265 266 delete config.modRequest; // @ts-ignore: `modRawConfig` is added for modifications 267 268 delete config.modRawConfig; 269 } 270 } 271 } 272 273 return config; 274} 275//# sourceMappingURL=mod-compiler.js.map