1{"version":3,"file":"withMod.js","names":["EXPO_DEBUG","boolish","withBaseMod","config","platform","mod","action","skipEmptyMod","isProvider","isIntrospective","saveToInternal","mods","interceptedMod","noopMod","debugTrace","isDebug","_internal","stack","Error","getDebugPluginStackFromStackTrace","modStack","chalk","bold","PluginError","interceptingMod","modRequest","console","log","results","nextMod","saveToInternalObject","modResults","platformName","modName","stacktrace","treeStackLines","line","split","first","second","trim","push","plugins","map","match","filter","Boolean","plugin","includes","commonPlugins","reverse","pluginName","index","toLowerCase","red","blue","dim","join","withMod"],"sources":["../../src/plugins/withMod.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config-types';\nimport { JSONObject } from '@expo/json-file';\nimport chalk from 'chalk';\nimport { boolish } from 'getenv';\n\nimport { ExportedConfig, ExportedConfigWithProps, Mod, ModPlatform } from '../Plugin.types';\nimport { PluginError } from '../utils/errors';\n\nconst EXPO_DEBUG = boolish('EXPO_DEBUG', false);\n\nexport type BaseModOptions = {\n  platform: ModPlatform;\n  mod: string;\n  isProvider?: boolean;\n  skipEmptyMod?: boolean;\n  saveToInternal?: boolean;\n  /**\n   * If the mod supports introspection, and avoids making any filesystem modifications during compilation.\n   * By enabling, this mod, and all of its descendants will be run in introspection mode.\n   * This should only be used for static files like JSON or XML, and not for application files that require regexes,\n   * or complex static files that require other files to be generated like Xcode `.pbxproj`.\n   */\n  isIntrospective?: boolean;\n};\n\n/**\n * Plugin to intercept execution of a given `mod` with the given `action`.\n * If an action was already set on the given `config` config for `mod`, then it\n * will be provided to the `action` as `nextMod` when it's evaluated, otherwise\n * `nextMod` will be an identity function.\n *\n * @param config exported config\n * @param platform platform to target (ios or android)\n * @param mod name of the platform function to intercept\n * @param skipEmptyMod should skip running the action if there is no existing mod to intercept\n * @param saveToInternal should save the results to `_internal.modResults`, only enable this when the results are pure JSON.\n * @param isProvider should provide data up to the other mods.\n * @param action method to run on the mod when the config is compiled\n */\nexport function withBaseMod<T>(\n  config: ExportedConfig,\n  {\n    platform,\n    mod,\n    action,\n    skipEmptyMod,\n    isProvider,\n    isIntrospective,\n    saveToInternal,\n  }: BaseModOptions & { action: Mod<T> }\n): ExportedConfig {\n  if (!config.mods) {\n    config.mods = {};\n  }\n  if (!config.mods[platform]) {\n    config.mods[platform] = {};\n  }\n\n  let interceptedMod: Mod<T> = (config.mods[platform] as Record<string, any>)[mod];\n\n  // No existing mod to intercept\n  if (!interceptedMod) {\n    if (skipEmptyMod) {\n      // Skip running the action\n      return config;\n    }\n    // Use a noop mod and continue\n    const noopMod: Mod<T> = (config) => config;\n    interceptedMod = noopMod;\n  }\n\n  // Create a stack trace for debugging ahead of time\n  let debugTrace: string = '';\n  // Use the possibly user defined value. Otherwise fallback to the env variable.\n  // We support the env variable because user mods won't have _internal defined in time.\n  const isDebug = config._internal?.isDebug ?? EXPO_DEBUG;\n  if (isDebug) {\n    // Get a stack trace via the Error API\n    const stack = new Error().stack;\n    // Format the stack trace to create the debug log\n    debugTrace = getDebugPluginStackFromStackTrace(stack);\n    const modStack = chalk.bold(`${platform}.${mod}`);\n\n    debugTrace = `${modStack}: ${debugTrace}`;\n  }\n\n  // Prevent adding multiple providers to a mod.\n  // Base mods that provide files ignore any incoming modResults and therefore shouldn't have provider mods as parents.\n  if (interceptedMod.isProvider) {\n    if (isProvider) {\n      throw new PluginError(\n        `Cannot set provider mod for \"${platform}.${mod}\" because another is already being used.`,\n        'CONFLICTING_PROVIDER'\n      );\n    } else {\n      throw new PluginError(\n        `Cannot add mod to \"${platform}.${mod}\" because the provider has already been added. Provider must be the last mod added.`,\n        'INVALID_MOD_ORDER'\n      );\n    }\n  }\n\n  async function interceptingMod({ modRequest, ...config }: ExportedConfigWithProps<T>) {\n    if (isDebug) {\n      // In debug mod, log the plugin stack in the order which they were invoked\n      console.log(debugTrace);\n    }\n    const results = await action({\n      ...config,\n      modRequest: { ...modRequest, nextMod: interceptedMod },\n    });\n\n    if (saveToInternal) {\n      saveToInternalObject(results, platform, mod, results.modResults as unknown as JSONObject);\n    }\n    return results;\n  }\n\n  // Ensure this base mod is registered as the provider.\n  interceptingMod.isProvider = isProvider;\n\n  if (isIntrospective) {\n    // Register the mode as idempotent so introspection doesn't remove it.\n    interceptingMod.isIntrospective = isIntrospective;\n  }\n\n  (config.mods[platform] as any)[mod] = interceptingMod;\n\n  return config;\n}\n\nfunction saveToInternalObject(\n  config: Pick<ExpoConfig, '_internal'>,\n  platformName: ModPlatform,\n  modName: string,\n  results: JSONObject\n) {\n  if (!config._internal) config._internal = {};\n  if (!config._internal.modResults) config._internal.modResults = {};\n  if (!config._internal.modResults[platformName]) config._internal.modResults[platformName] = {};\n  config._internal.modResults[platformName][modName] = results;\n}\n\nfunction getDebugPluginStackFromStackTrace(stacktrace?: string): string {\n  if (!stacktrace) {\n    return '';\n  }\n\n  const treeStackLines: string[] = [];\n  for (const line of stacktrace.split('\\n')) {\n    const [first, second] = line.trim().split(' ');\n    if (first === 'at') {\n      treeStackLines.push(second);\n    }\n  }\n\n  const plugins = treeStackLines\n    .map((first) => {\n      // Match the first part of the stack trace against the plugin naming convention\n      // \"with\" followed by a capital letter.\n      return (\n        first?.match(/^(\\bwith[A-Z].*?\\b)/)?.[1]?.trim() ??\n        first?.match(/\\.(\\bwith[A-Z].*?\\b)/)?.[1]?.trim() ??\n        null\n      );\n    })\n    .filter(Boolean)\n    .filter((plugin) => {\n      // redundant as all debug logs are captured in withBaseMod\n      return !['withMod', 'withBaseMod', 'withExtendedMod'].includes(plugin!);\n    });\n\n  const commonPlugins = ['withPlugins', 'withRunOnce', 'withStaticPlugin'];\n\n  return (\n    (plugins as string[])\n      .reverse()\n      .map((pluginName, index) => {\n        // Base mods indicate a logical section.\n        if (pluginName.includes('BaseMod')) {\n          pluginName = chalk.bold(pluginName);\n        }\n        // highlight dangerous mods\n        if (pluginName.toLowerCase().includes('dangerous')) {\n          pluginName = chalk.red(pluginName);\n        }\n\n        if (index === 0) {\n          return chalk.blue(pluginName);\n        } else if (commonPlugins.includes(pluginName)) {\n          // Common mod names often clutter up the logs, dim them out\n          return chalk.dim(pluginName);\n        }\n        return pluginName;\n      })\n      // Join the results:\n      // withAndroidExpoPlugins ➜ withPlugins ➜ withIcons ➜ withDangerousMod ➜ withMod\n      .join(' ➜ ')\n  );\n}\n\n/**\n * Plugin to extend a mod function in the plugins config.\n *\n * @param config exported config\n * @param platform platform to target (ios or android)\n * @param mod name of the platform function to extend\n * @param action method to run on the mod when the config is compiled\n */\nexport function withMod<T>(\n  config: ExportedConfig,\n  {\n    platform,\n    mod,\n    action,\n  }: {\n    platform: ModPlatform;\n    mod: string;\n    action: Mod<T>;\n  }\n): ExportedConfig {\n  return withBaseMod(config, {\n    platform,\n    mod,\n    isProvider: false,\n    async action({ modRequest: { nextMod, ...modRequest }, modResults, ...config }) {\n      const results = await action({ modRequest, modResults: modResults as T, ...config });\n      return nextMod!(results as any);\n    },\n  });\n}\n"],"mappings":"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"}