1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const lazyImports_1 = require("./lazyImports");
4function babelPresetExpo(api, options = {}) {
5    const { web = {}, native = {}, reanimated } = options;
6    const bundler = api.caller(getBundler);
7    const isWebpack = bundler === 'webpack';
8    let platform = api.caller((caller) => caller?.platform);
9    // If the `platform` prop is not defined then this must be a custom config that isn't
10    // defining a platform in the babel-loader. Currently this may happen with Next.js + Expo web.
11    if (!platform && isWebpack) {
12        platform = 'web';
13    }
14    const platformOptions = platform === 'web'
15        ? {
16            // Only disable import/export transform when Webpack is used because
17            // Metro does not support tree-shaking.
18            disableImportExportTransform: isWebpack,
19            ...web,
20        }
21        : { disableImportExportTransform: false, ...native };
22    // Note that if `options.lazyImports` is not set (i.e., `null` or `undefined`),
23    // `metro-react-native-babel-preset` will handle it.
24    const lazyImportsOption = options?.lazyImports;
25    const extraPlugins = [
26        // `metro-react-native-babel-preset` configures this plugin with `{ loose: true }`, which breaks all
27        // getters and setters in spread objects. We need to add this plugin ourself without that option.
28        // @see https://github.com/expo/expo/pull/11960#issuecomment-887796455
29        [require.resolve('@babel/plugin-proposal-object-rest-spread'), { loose: false }],
30    ];
31    // Set true to disable `@babel/plugin-transform-react-jsx`
32    // we override this logic outside of the metro preset so we can add support for
33    // React 17 automatic JSX transformations.
34    // If the logic for `useTransformReactJSXExperimental` ever changes in `metro-react-native-babel-preset`
35    // then this block should be updated to reflect those changes.
36    if (!platformOptions.useTransformReactJSXExperimental) {
37        extraPlugins.push([
38            require('@babel/plugin-transform-react-jsx'),
39            {
40                // Defaults to `automatic`, pass in `classic` to disable auto JSX transformations.
41                runtime: (options && options.jsxRuntime) || 'automatic',
42                ...(options &&
43                    options.jsxRuntime !== 'classic' && {
44                    importSource: (options && options.jsxImportSource) || 'react',
45                }),
46            },
47        ]);
48        // Purposefully not adding the deprecated packages:
49        // `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`
50        // back to the preset.
51    }
52    const aliasPlugin = getAliasPlugin();
53    if (aliasPlugin) {
54        extraPlugins.push(aliasPlugin);
55    }
56    if (platform === 'web') {
57        extraPlugins.push(require.resolve('babel-plugin-react-native-web'));
58    }
59    return {
60        presets: [
61            [
62                // We use `require` here instead of directly using the package name because we want to
63                // specifically use the `metro-react-native-babel-preset` installed by this package (ex:
64                // `babel-preset-expo/node_modules/`). This way the preset will not change unintentionally.
65                // Reference: https://github.com/expo/expo/pull/4685#discussion_r307143920
66                require('metro-react-native-babel-preset'),
67                {
68                    // Defaults to undefined, set to something truthy to disable `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`.
69                    withDevTools: platformOptions.withDevTools,
70                    // Defaults to undefined, set to `true` to disable `@babel/plugin-transform-flow-strip-types`
71                    disableFlowStripTypesTransform: platformOptions.disableFlowStripTypesTransform,
72                    // Defaults to undefined, set to `false` to disable `@babel/plugin-transform-runtime`
73                    enableBabelRuntime: platformOptions.enableBabelRuntime,
74                    // Defaults to `'default'`, can also use `'hermes-canary'`
75                    unstable_transformProfile: platformOptions.unstable_transformProfile,
76                    // Set true to disable `@babel/plugin-transform-react-jsx` and
77                    // the deprecated packages `@babel/plugin-transform-react-jsx-self`, and `@babel/plugin-transform-react-jsx-source`.
78                    //
79                    // Otherwise, you'll sometime get errors like the following (starting in Expo SDK 43, React Native 64, React 17):
80                    //
81                    // TransformError App.js: /path/to/App.js: Duplicate __self prop found. You are most likely using the deprecated transform-react-jsx-self Babel plugin.
82                    // Both __source and __self are automatically set when using the automatic jsxRuntime. Please remove transform-react-jsx-source and transform-react-jsx-self from your Babel config.
83                    useTransformReactJSXExperimental: true,
84                    disableImportExportTransform: platformOptions.disableImportExportTransform,
85                    lazyImportExportTransform: lazyImportsOption === true
86                        ? (importModuleSpecifier) => {
87                            // Do not lazy-initialize packages that are local imports (similar to `lazy: true`
88                            // behavior) or are in the blacklist.
89                            return !(importModuleSpecifier.includes('./') || lazyImports_1.lazyImports.has(importModuleSpecifier));
90                        }
91                        : // Pass the option directly to `metro-react-native-babel-preset`, which in turn
92                            // passes it to `babel-plugin-transform-modules-commonjs`
93                            lazyImportsOption,
94                },
95            ],
96        ],
97        plugins: [
98            ...extraPlugins,
99            // TODO: Remove
100            [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
101            require.resolve('@babel/plugin-proposal-export-namespace-from'),
102            // Automatically add `react-native-reanimated/plugin` when the package is installed.
103            // TODO: Move to be a customTransformOption.
104            hasModule('react-native-reanimated') &&
105                reanimated !== false && [require.resolve('react-native-reanimated/plugin')],
106        ].filter(Boolean),
107    };
108}
109function getAliasPlugin() {
110    if (!hasModule('@expo/vector-icons')) {
111        return null;
112    }
113    return [
114        require.resolve('babel-plugin-module-resolver'),
115        {
116            alias: {
117                'react-native-vector-icons': '@expo/vector-icons',
118            },
119        },
120    ];
121}
122function hasModule(name) {
123    try {
124        return !!require.resolve(name);
125    }
126    catch (error) {
127        if (error.code === 'MODULE_NOT_FOUND' && error.message.includes(name)) {
128            return false;
129        }
130        throw error;
131    }
132}
133/** Determine which bundler is being used. */
134function getBundler(caller) {
135    if (!caller)
136        return null;
137    if (caller.bundler)
138        return caller.bundler;
139    if (
140    // Known tools that use `webpack`-mode via `babel-loader`: `@expo/webpack-config`, Next.js <10
141    caller.name === 'babel-loader' ||
142        // NextJS 11 uses this custom caller name.
143        caller.name === 'next-babel-turbo-loader') {
144        return 'webpack';
145    }
146    // Assume anything else is Metro.
147    return 'metro';
148}
149exports.default = babelPresetExpo;
150module.exports = babelPresetExpo;
151