1"use strict"; 2 3Object.defineProperty(exports, "__esModule", { 4 value: true 5}); 6exports.withBaseMod = withBaseMod; 7exports.withMod = withMod; 8 9function _chalk() { 10 const data = _interopRequireDefault(require("chalk")); 11 12 _chalk = function () { 13 return data; 14 }; 15 16 return data; 17} 18 19function _getenv() { 20 const data = require("getenv"); 21 22 _getenv = function () { 23 return data; 24 }; 25 26 return data; 27} 28 29function _errors() { 30 const data = require("../utils/errors"); 31 32 _errors = function () { 33 return data; 34 }; 35 36 return data; 37} 38 39function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 40 41const EXPO_DEBUG = (0, _getenv().boolish)('EXPO_DEBUG', false); 42 43/** 44 * Plugin to intercept execution of a given `mod` with the given `action`. 45 * If an action was already set on the given `config` config for `mod`, then it 46 * will be provided to the `action` as `nextMod` when it's evaluated, otherwise 47 * `nextMod` will be an identity function. 48 * 49 * @param config exported config 50 * @param platform platform to target (ios or android) 51 * @param mod name of the platform function to intercept 52 * @param skipEmptyMod should skip running the action if there is no existing mod to intercept 53 * @param saveToInternal should save the results to `_internal.modResults`, only enable this when the results are pure JSON. 54 * @param isProvider should provide data up to the other mods. 55 * @param action method to run on the mod when the config is compiled 56 */ 57function withBaseMod(config, { 58 platform, 59 mod, 60 action, 61 skipEmptyMod, 62 isProvider, 63 isIntrospective, 64 saveToInternal 65}) { 66 var _config$_internal$isD, _config$_internal; 67 68 if (!config.mods) { 69 config.mods = {}; 70 } 71 72 if (!config.mods[platform]) { 73 config.mods[platform] = {}; 74 } 75 76 let interceptedMod = config.mods[platform][mod]; // No existing mod to intercept 77 78 if (!interceptedMod) { 79 if (skipEmptyMod) { 80 // Skip running the action 81 return config; 82 } // Use a noop mod and continue 83 84 85 const noopMod = config => config; 86 87 interceptedMod = noopMod; 88 } // Create a stack trace for debugging ahead of time 89 90 91 let debugTrace = ''; // Use the possibly user defined value. Otherwise fallback to the env variable. 92 // We support the env variable because user mods won't have _internal defined in time. 93 94 const isDebug = (_config$_internal$isD = (_config$_internal = config._internal) === null || _config$_internal === void 0 ? void 0 : _config$_internal.isDebug) !== null && _config$_internal$isD !== void 0 ? _config$_internal$isD : EXPO_DEBUG; 95 96 if (isDebug) { 97 // Get a stack trace via the Error API 98 const stack = new Error().stack; // Format the stack trace to create the debug log 99 100 debugTrace = getDebugPluginStackFromStackTrace(stack); 101 102 const modStack = _chalk().default.bold(`${platform}.${mod}`); 103 104 debugTrace = `${modStack}: ${debugTrace}`; 105 } // Prevent adding multiple providers to a mod. 106 // Base mods that provide files ignore any incoming modResults and therefore shouldn't have provider mods as parents. 107 108 109 if (interceptedMod.isProvider) { 110 if (isProvider) { 111 throw new (_errors().PluginError)(`Cannot set provider mod for "${platform}.${mod}" because another is already being used.`, 'CONFLICTING_PROVIDER'); 112 } else { 113 throw new (_errors().PluginError)(`Cannot add mod to "${platform}.${mod}" because the provider has already been added. Provider must be the last mod added.`, 'INVALID_MOD_ORDER'); 114 } 115 } 116 117 async function interceptingMod({ 118 modRequest, 119 ...config 120 }) { 121 if (isDebug) { 122 // In debug mod, log the plugin stack in the order which they were invoked 123 console.log(debugTrace); 124 } 125 126 const results = await action({ ...config, 127 modRequest: { ...modRequest, 128 nextMod: interceptedMod 129 } 130 }); 131 132 if (saveToInternal) { 133 saveToInternalObject(results, platform, mod, results.modResults); 134 } 135 136 return results; 137 } // Ensure this base mod is registered as the provider. 138 139 140 interceptingMod.isProvider = isProvider; 141 142 if (isIntrospective) { 143 // Register the mode as idempotent so introspection doesn't remove it. 144 interceptingMod.isIntrospective = isIntrospective; 145 } 146 147 config.mods[platform][mod] = interceptingMod; 148 return config; 149} 150 151function saveToInternalObject(config, platformName, modName, results) { 152 if (!config._internal) config._internal = {}; 153 if (!config._internal.modResults) config._internal.modResults = {}; 154 if (!config._internal.modResults[platformName]) config._internal.modResults[platformName] = {}; 155 config._internal.modResults[platformName][modName] = results; 156} 157 158function getDebugPluginStackFromStackTrace(stacktrace) { 159 if (!stacktrace) { 160 return ''; 161 } 162 163 const treeStackLines = []; 164 165 for (const line of stacktrace.split('\n')) { 166 const [first, second] = line.trim().split(' '); 167 168 if (first === 'at') { 169 treeStackLines.push(second); 170 } 171 } 172 173 const plugins = treeStackLines.map(first => { 174 var _ref, _first$match$1$trim, _first$match, _first$match$, _first$match2, _first$match2$; 175 176 // Match the first part of the stack trace against the plugin naming convention 177 // "with" followed by a capital letter. 178 return (_ref = (_first$match$1$trim = first === null || first === void 0 ? void 0 : (_first$match = first.match(/^(\bwith[A-Z].*?\b)/)) === null || _first$match === void 0 ? void 0 : (_first$match$ = _first$match[1]) === null || _first$match$ === void 0 ? void 0 : _first$match$.trim()) !== null && _first$match$1$trim !== void 0 ? _first$match$1$trim : first === null || first === void 0 ? void 0 : (_first$match2 = first.match(/\.(\bwith[A-Z].*?\b)/)) === null || _first$match2 === void 0 ? void 0 : (_first$match2$ = _first$match2[1]) === null || _first$match2$ === void 0 ? void 0 : _first$match2$.trim()) !== null && _ref !== void 0 ? _ref : null; 179 }).filter(Boolean).filter(plugin => { 180 // redundant as all debug logs are captured in withBaseMod 181 return !['withMod', 'withBaseMod', 'withExtendedMod'].includes(plugin); 182 }); 183 const commonPlugins = ['withPlugins', 'withRunOnce', 'withStaticPlugin']; 184 return plugins.reverse().map((pluginName, index) => { 185 // Base mods indicate a logical section. 186 if (pluginName.includes('BaseMod')) { 187 pluginName = _chalk().default.bold(pluginName); 188 } // highlight dangerous mods 189 190 191 if (pluginName.toLowerCase().includes('dangerous')) { 192 pluginName = _chalk().default.red(pluginName); 193 } 194 195 if (index === 0) { 196 return _chalk().default.blue(pluginName); 197 } else if (commonPlugins.includes(pluginName)) { 198 // Common mod names often clutter up the logs, dim them out 199 return _chalk().default.dim(pluginName); 200 } 201 202 return pluginName; 203 }) // Join the results: 204 // withAndroidExpoPlugins ➜ withPlugins ➜ withIcons ➜ withDangerousMod ➜ withMod 205 .join(' ➜ '); 206} 207/** 208 * Plugin to extend a mod function in the plugins config. 209 * 210 * @param config exported config 211 * @param platform platform to target (ios or android) 212 * @param mod name of the platform function to extend 213 * @param action method to run on the mod when the config is compiled 214 */ 215 216 217function withMod(config, { 218 platform, 219 mod, 220 action 221}) { 222 return withBaseMod(config, { 223 platform, 224 mod, 225 isProvider: false, 226 227 async action({ 228 modRequest: { 229 nextMod, 230 ...modRequest 231 }, 232 modResults, 233 ...config 234 }) { 235 const results = await action({ 236 modRequest, 237 modResults: modResults, 238 ...config 239 }); 240 return nextMod(results); 241 } 242 243 }); 244} 245//# sourceMappingURL=withMod.js.map