-
Notifications
You must be signed in to change notification settings - Fork 95
feat(macos): add macOS support for config plugins #2160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
4887941
to
90ae790
Compare
macos
support for config plugins// @ts-expect-error `macos` is not assignable to type `android | ios` | ||
platform: "macos", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, Expo config plugins hard-code the string "ios" all over the place, consequentially searching in the ios
folder and reading values from config.ios
, so I'm not sure which plugins will work and which ones won't with this approach.
I opened a big PR last weekend to add macOS support to Expo config plugins, but I am not optimistic about it being reviewed anytime soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this correctly, this part just registers what's available for the macos
platform. We need to explicitly implement the mods separately, using withMod
, as in plugins/macos.js
.
const defaultProviders = { | ||
dangerous: expoProviders.dangerous, | ||
finalized: expoProviders.finalized, | ||
appDelegate: modifyFilePath( | ||
expoProviders.appDelegate, | ||
"ReactTestApp/AppDelegate.swift" | ||
), | ||
expoPlist: nullProvider, | ||
xcodeproj: modifyFilePath( | ||
expoProviders.xcodeproj, | ||
"ReactTestApp.xcodeproj/project.pbxproj" | ||
), | ||
infoPlist: modifyFilePath(expoProviders.infoPlist, "Info.plist"), | ||
entitlements: nullProvider, | ||
podfile: makeNullProvider({ | ||
path: "", | ||
language: /** @type {const} */ ("rb"), | ||
contents: "", | ||
}), | ||
podfileProperties: makeNullProvider(), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really clever. 👏
Given RNTA has a predictable structure, a lot of the complexity in the plugins (e.g. searching for all possible locations for an Info.plist or Xcodeproj) can be totally sidestepped, as you've done here. And that side-steps a lot of the coupling to ios
.
I am not sure to what extent this sidesteps all of their hard-coding of the ios
platform, though. But given how your test passes, maybe it's quite a lot. Surely at least one of these will end up referring to config.ios
or the ios
folder at some point, though? Do you have an impression of the extent to which Expo config plugins will work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I've understood, the providers are just functions for making modifications. They don't have props that are platform specific, but may be pointing to some iOS specific paths as you're suggesting. We should be overwriting all the props here (TypeScript would complain otherwise). Save for the null providers, I think we can say we are complete.
That said, these providers aren't supposed to be platform specific. The with*
functions (e.g. withAppDelegate
) are platform specific, and we need a separate set for macOS. That's what I've done here:
react-native-test-app/plugins/macos.js
Lines 35 to 79 in 622a257
function withAppDelegate(config, action) { | |
return withMod(config, { | |
platform: macosPlatform, | |
mod: "appDelegate", | |
action, | |
}); | |
} | |
/** | |
* Provides the `Info.plist` file for modification. | |
* @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L116} | |
* @param {ExportedConfig} config Exported config | |
* @param {Mod} action Method to run on the mod when the config is compiled | |
* @returns {ExportedConfig} Modified config | |
*/ | |
function withInfoPlist(config, action) { | |
return withMod(config, { | |
platform: macosPlatform, | |
mod: "infoPlist", | |
async action(cfg) { | |
/** @type {ExportedConfigWithPropsMac} */ | |
const config = await action(cfg); | |
if (!config.macos) { | |
config.macos = {}; | |
} | |
config.macos.infoPlist = config.modResults; | |
return config; | |
}, | |
}); | |
} | |
/** | |
* Provides the main `.xcodeproj` for modification. | |
* @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L173} | |
* @param {ExportedConfig} config Exported config | |
* @param {Mod} action Method to run on the mod when the config is compiled | |
* @returns {ExportedConfig} Modified config | |
*/ | |
function withXcodeProject(config, action) { | |
return withMod(config, { | |
platform: macosPlatform, | |
mod: "xcodeproj", | |
action, | |
}); | |
} |
Which means that for now, we only support these four functions. And you will need to import them from react-native-test-app/plugins/macos.js
.
Description
I had this branch lying around for about a year or so. Rebased, and brushed up a bit.
Platforms affected
Test plan
example/test-plugin.js
:example
folder, runpod install --project-directory=macos
AppDelegate.swift
was written to: