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