1import {
2  ConfigPlugin,
3  createRunOncePlugin,
4  PluginParameters,
5  withPlugins,
6  withStaticPlugin,
7} from '@expo/config-plugins';
8import { ExpoConfig } from '@expo/config-types';
9
10const toCamelCase = (s: string) => s.replace(/-./g, (x) => x.toUpperCase()[1]);
11
12function isModuleExcluded(config: Pick<ExpoConfig, '_internal'>, packageName: string): boolean {
13  // Skip using the versioned plugin when autolinking is enabled
14  // and doesn't link the native module.
15  return (
16    config._internal?.autolinkedModules && !config._internal.autolinkedModules.includes(packageName)
17  );
18}
19
20export function createLegacyPlugin({
21  packageName,
22  fallback,
23}: {
24  packageName: string;
25  fallback: ConfigPlugin | PluginParameters<typeof withPlugins>;
26}): ConfigPlugin {
27  let withFallback: ConfigPlugin;
28
29  if (Array.isArray(fallback)) {
30    withFallback = (config) => withPlugins(config, fallback);
31  } else {
32    withFallback = fallback;
33  }
34
35  const withUnknown: ConfigPlugin = (config) => {
36    // Skip using the versioned plugin when autolinking is enabled
37    // and doesn't link the native module.
38    if (isModuleExcluded(config, packageName)) {
39      return createRunOncePlugin(withFallback, packageName)(config);
40    }
41
42    return withStaticPlugin(config, {
43      _isLegacyPlugin: true,
44      plugin: packageName,
45      // If the static plugin isn't found, use the unversioned one.
46      fallback: createRunOncePlugin(withFallback, packageName),
47    });
48  };
49
50  const methodName = toCamelCase(`with-${packageName}`);
51  Object.defineProperty(withUnknown, 'name', {
52    value: methodName,
53  });
54
55  return withUnknown;
56}
57