1import fs from 'fs-extra';
2import path from 'path';
3
4import { TransformPipeline } from '.';
5
6export function podspecTransforms(versionName: string): TransformPipeline {
7  return {
8    transforms: [
9      // Common transforms
10      {
11        // Transforms some podspec fields by adding versionName at the beginning
12        replace: /\.(name|header_dir|module_name)(\s*=\s*["'])([^"']+)(["'])/g,
13        with: `.$1$2${versionName}$3$4`,
14      },
15      {
16        // Prefixes dependencies listed in the podspecs
17        replace: /(\.dependency\s+["'])(Yoga|React\-|ReactCommon|RCT|FB)(?!-Folly)([^"']*["'])/g,
18        with: `$1${versionName}$2$3`,
19      },
20      {
21        // Removes source conditional
22        replace: /source\s*\=\s*\{[.\S\s]+?end/g,
23        with: '',
24      },
25      {
26        // Points spec source at correct directory
27        replace: /(\.source\s*\=\s*)\S+\n/g,
28        with: '$1{ :path => "." }\n',
29      },
30
31      // React-Core & ReactCommon
32      {
33        // Fixes header_subspecs for RCTBlobHeaders
34        paths: 'React-Core.podspec',
35        replace: /\{(RCTBlobManager),(RCTFileReaderModule)\}/g,
36        with: `{${versionName}$1,${versionName}$2}`,
37      },
38      {
39        // Prefixes conflicting AccessibilityResources
40        paths: 'React-Core.podspec',
41        replace: /"AccessibilityResources"/g,
42        with: `"${versionName}AccessibilityResources"`,
43      },
44      {
45        // Add custom modulemap for React-Core to generate correct submodules for swift integration
46        // Learn more: `packages/expo-modules-autolinking/scripts/ios/cocoapods/sandbox.rb`
47        paths: 'React-Core.podspec',
48        replace: /(s.default_subspec\s+=.*$)/mg,
49        with: `$1\n  s.module_map             = "${versionName}React-Core.modulemap"`,
50      },
51      {
52        // Hide Hermes headers from public headers because clang modoules does not support c++
53        // Learn more: `packages/expo-modules-autolinking/scripts/ios/cocoapods/sandbox.rb`
54        paths: 'React-Core.podspec',
55        replace: /(s.subspec\s+"Hermes".*$)/mg,
56        with: '$1\n    ss.private_header_files = "ReactCommon/hermes/executor/*.h", "ReactCommon/hermes/inspector/*.h", "ReactCommon/hermes/inspector/chrome/*.h", "ReactCommon/hermes/inspector/detail/*.h"',
57      },
58      {
59        // DEFINES_MODULE for swift integration
60        // Learn more: `packages/expo-modules-autolinking/scripts/ios/cocoapods/sandbox.rb`
61        paths: 'ReactCommon.podspec',
62        replace: /("USE_HEADERMAP" => "YES",)/g,
63        with: '$1 "DEFINES_MODULE" => "YES",',
64      },
65      {
66        // Fixes HEADER_SEARCH_PATHS
67        paths: ['React-Core.podspec', 'ReactCommon.podspec'],
68        replace: /(Headers\/Private\/)(React-Core)/g,
69        with: `$1${versionName}$2`,
70      },
71
72      // React-cxxreact
73      {
74        // Fixes excluding SampleCxxModule.* files
75        paths: 'React-cxxreact.podspec',
76        replace: /\.exclude_files(\s*=\s*["'])(SampleCxxModule\.\*)(["'])/g,
77        with: `.exclude_files$1${versionName}$2$3`,
78      },
79
80      // Yoga
81      {
82        // Unprefixes inner directory for source_files
83        paths: 'Yoga.podspec',
84        replace: /\{(Yoga),(YGEnums),(YGMacros),(YGNode),(YGStyle),(YGValue)\}/g,
85        with: `{${versionName}$1,${versionName}$2,${versionName}$3,${versionName}$4,${versionName}$5,${versionName}$6}`,
86      },
87
88      // FBReactNativeSpec
89      {
90        // Fixes HEADER_SEARCH_PATHS
91        paths: 'FBReactNativeSpec.podspec',
92        replace: /(\/Libraries\/)(FBReactNativeSpec)/g,
93        with: `$1${versionName}$2`,
94      },
95      {
96        // Disable codegen from build phase script
97        paths: 'FBReactNativeSpec.podspec',
98        replace: /(use_react_native_codegen!)/g,
99        with: '# $1',
100      },
101    ],
102  };
103}
104
105export async function generateModulemapAsync(podspecFile: string, versionName: string) {
106    const basename = path.basename(podspecFile, '.podspec');
107    if (basename === 'React-Core') {
108      const modulemap = `\
109module ${versionName}React {
110  umbrella "../../Public/${versionName}React-Core/${versionName}React"
111
112  export *
113  module * { export * }
114}`;
115      const modulemapPath = path.join(path.dirname(podspecFile), `${versionName}React-Core.modulemap`);
116      await fs.writeFile(modulemapPath, modulemap);
117    }
118}
119