diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index cb8ce6ab0..bf64ed31b 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -1018,7 +1018,7 @@ PODS: - React-jsi (= 0.73.33) - React-logger (= 0.73.33) - React-perflogger (= 0.73.33) - - ReactNativeHost (0.4.10): + - ReactNativeHost (0.4.11): - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -1252,7 +1252,7 @@ SPEC CHECKSUMS: React-runtimescheduler: 68e2b8754cceaaa8b443d62018d4c9c0aa4e0741 React-utils: 46cc84b17edde38232668073688b2ed621a3d171 ReactCommon: 0b6b092708b879557708b378a09729fc29900918 - ReactNativeHost: b74433b0e21ca2aae4fd5c1c3a49cbd1a7edf7ca + ReactNativeHost: 02d9df701ce3f7b6560f95315df4bab38b660f58 ReactTestApp-DevSupport: c4abadbb90a8a9903400407e9857c2a2ef0343fb ReactTestApp-Resources: 9d83e280b173ba2ee053b8135730dff60f9ab674 RNWWebStorage: 13da272b965c7233d1c0c167f2306f97722323a1 diff --git a/plugins/index.js b/plugins/index.js index 7de179af0..5d9ff8217 100644 --- a/plugins/index.js +++ b/plugins/index.js @@ -34,5 +34,6 @@ function withSceneDelegate(config, action) { }); } +exports.macos = require("./macos"); exports.withReactNativeHost = withReactNativeHost; exports.withSceneDelegate = withSceneDelegate; diff --git a/plugins/macos.js b/plugins/macos.js new file mode 100644 index 000000000..6fd5f951c --- /dev/null +++ b/plugins/macos.js @@ -0,0 +1,84 @@ +// @ts-check +const { withMod } = require("@expo/config-plugins"); + +/** + * @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig + * @typedef {import("@expo/config-plugins").ExportedConfigWithProps} ExportedConfigWithProps + * @typedef {import("@expo/config-plugins").Mod} Mod + * @typedef {import("@expo/config-plugins").ModConfig} ModConfig + * @typedef {ExportedConfigWithProps & { macos?: { infoPlist?: Record }}} ExportedConfigWithPropsMac + */ + +const macosPlatform = /** @type {keyof ModConfig} */ ("macos"); + +/** + * Provides the `ReactNativeHost` file for modification. + * @param {ExportedConfig} config Exported config + * @param {Mod} action Method to run on the mod when the config is compiled + * @returns {ExportedConfig} Modified config + */ +function withReactNativeHost(config, action) { + return withMod(config, { + platform: macosPlatform, + mod: "reactNativeHost", + action, + }); +} + +/** + * Provides the `AppDelegate` file for modification. + * @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L101} + * @param {ExportedConfig} config Exported config + * @param {Mod} action Method to run on the mod when the config is compiled + * @returns {ExportedConfig} Modified config + */ +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, + }); +} + +exports.withAppDelegate = withAppDelegate; +exports.withInfoPlist = withInfoPlist; +exports.withXcodeProject = withXcodeProject; +exports.withReactNativeHost = withReactNativeHost; diff --git a/plugins/reanimated.js b/plugins/reanimated.js index ba8b1ad49..741342466 100644 --- a/plugins/reanimated.js +++ b/plugins/reanimated.js @@ -6,9 +6,7 @@ const { const { getPackageVersion, toVersionNumber, v } = require("../scripts/helpers"); const { withReactNativeHost } = require("./index"); -/** - * @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig - */ +/** @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig */ const NAME = "react-native-reanimated"; diff --git a/scripts/config-plugins/index.mjs b/scripts/config-plugins/index.mjs index e9267e466..7545d2521 100644 --- a/scripts/config-plugins/index.mjs +++ b/scripts/config-plugins/index.mjs @@ -1,6 +1,7 @@ // @ts-check import { getAndroidModFileProviders } from "./plugins/withAndroidBaseMods.mjs"; import { getIosModFileProviders } from "./plugins/withIosBaseMods.mjs"; +import { getMacOsModFileProviders } from "./plugins/withMacOsBaseMods.mjs"; export { applyConfigPlugins } from "./apply.mjs"; export { @@ -12,4 +13,5 @@ export { withInternal } from "./plugins/withInternal.mjs"; export const BaseMods = { getAndroidModFileProviders, getIosModFileProviders, + getMacOsModFileProviders, }; diff --git a/scripts/config-plugins/plugins/cocoaBaseMods.mjs b/scripts/config-plugins/plugins/cocoaBaseMods.mjs new file mode 100644 index 000000000..a49f66dad --- /dev/null +++ b/scripts/config-plugins/plugins/cocoaBaseMods.mjs @@ -0,0 +1,53 @@ +// @ts-check +import { createRequire } from "node:module"; +import * as path from "node:path"; +import { BaseMods } from "../ExpoConfigPlugins.mjs"; +import { makeFilePathModifier, makeNullProvider } from "../provider.mjs"; + +const require = createRequire(import.meta.url); + +/** + * @param {import("../types.js").CustomModProvider} modifyFilePath + * @returns {import("../types.js").IosModFileProviders} + */ +export function createModFileProviders(modifyFilePath) { + const modifyReactNativeHostFilePath = makeFilePathModifier( + path.dirname(require.resolve("@rnx-kit/react-native-host/package.json")) + ); + + const nullProvider = makeNullProvider(); + + // https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/withIosBaseMods.ts + const expoProviders = BaseMods.getIosModFileProviders(); + + /** @type {import("../types.js").IosModFileProviders} */ + 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(), + }; + + // `@rnx-kit/react-native-host` files + defaultProviders["reactNativeHost"] = modifyReactNativeHostFilePath( + expoProviders.appDelegate, + "cocoa/ReactNativeHost.mm" + ); + + return defaultProviders; +} diff --git a/scripts/config-plugins/plugins/mod-compiler.mjs b/scripts/config-plugins/plugins/mod-compiler.mjs index ce237128e..7b37b3798 100644 --- a/scripts/config-plugins/plugins/mod-compiler.mjs +++ b/scripts/config-plugins/plugins/mod-compiler.mjs @@ -2,6 +2,7 @@ import { BaseMods, evalModsAsync } from "../ExpoConfigPlugins.mjs"; import { getAndroidModFileProviders } from "./withAndroidBaseMods.mjs"; import { getIosModFileProviders } from "./withIosBaseMods.mjs"; +import { getMacOsModFileProviders } from "./withMacOsBaseMods.mjs"; /** @type {import("@expo/config-plugins").withDefaultBaseMods} */ export const withDefaultBaseMods = (config, props) => { @@ -13,6 +14,12 @@ export const withDefaultBaseMods = (config, props) => { ...props, providers: getAndroidModFileProviders(), }); + config = BaseMods.withGeneratedBaseMods(config, { + ...props, + // @ts-expect-error `macos` is not assignable to type `android | ios` + platform: "macos", + providers: getMacOsModFileProviders(), + }); return config; }; diff --git a/scripts/config-plugins/plugins/withAndroidBaseMods.mjs b/scripts/config-plugins/plugins/withAndroidBaseMods.mjs index 7e15df4b1..e13d60c75 100644 --- a/scripts/config-plugins/plugins/withAndroidBaseMods.mjs +++ b/scripts/config-plugins/plugins/withAndroidBaseMods.mjs @@ -6,7 +6,7 @@ const modifyFilePath = makeFilePathModifier( "node_modules/react-native-test-app/android" ); -// https://github.com/expo/expo/blob/93cd0503117d5a25f8b80ed7b30ec5bed3a67c24/packages/@expo/config-plugins/src/plugins/withAndroidBaseMods.ts +// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/withAndroidBaseMods.ts const expoProviders = BaseMods.getAndroidModFileProviders(); /** @type {typeof expoProviders} */ diff --git a/scripts/config-plugins/plugins/withIosBaseMods.mjs b/scripts/config-plugins/plugins/withIosBaseMods.mjs index 471b6751c..ec59f345d 100644 --- a/scripts/config-plugins/plugins/withIosBaseMods.mjs +++ b/scripts/config-plugins/plugins/withIosBaseMods.mjs @@ -1,56 +1,17 @@ // @ts-check -import { createRequire } from "node:module"; -import * as path from "node:path"; +import { createModFileProviders } from "./cocoaBaseMods.mjs"; import { BaseMods } from "../ExpoConfigPlugins.mjs"; -import { makeFilePathModifier, makeNullProvider } from "../provider.mjs"; +import { makeFilePathModifier } from "../provider.mjs"; const modifyFilePath = makeFilePathModifier("node_modules/.generated/ios"); - -const require = createRequire(import.meta.url); -const modifyReactNativeHostFilePath = makeFilePathModifier( - path.dirname(require.resolve("@rnx-kit/react-native-host/package.json")) -); - -const nullProvider = makeNullProvider(); - -// https://github.com/expo/expo/blob/93cd0503117d5a25f8b80ed7b30ec5bed3a67c24/packages/@expo/config-plugins/src/plugins/withIosBaseMods.ts -const expoProviders = BaseMods.getIosModFileProviders(); - -/** @type {typeof expoProviders & Record} */ -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(), -}; +const defaultProviders = createModFileProviders(modifyFilePath); // `react-native-test-app` files defaultProviders["sceneDelegate"] = modifyFilePath( - expoProviders.appDelegate, + BaseMods.getIosModFileProviders().appDelegate, "ReactTestApp/SceneDelegate.swift" ); -// `@rnx-kit/react-native-host` files -defaultProviders["reactNativeHost"] = modifyReactNativeHostFilePath( - expoProviders.appDelegate, - "cocoa/ReactNativeHost.mm" -); - export function getIosModFileProviders() { return defaultProviders; } diff --git a/scripts/config-plugins/plugins/withMacOsBaseMods.mjs b/scripts/config-plugins/plugins/withMacOsBaseMods.mjs new file mode 100644 index 000000000..4c20783b7 --- /dev/null +++ b/scripts/config-plugins/plugins/withMacOsBaseMods.mjs @@ -0,0 +1,10 @@ +// @ts-check +import { createModFileProviders } from "./cocoaBaseMods.mjs"; +import { makeFilePathModifier } from "../provider.mjs"; + +const modifyFilePath = makeFilePathModifier("node_modules/.generated/macos"); +const defaultProviders = createModFileProviders(modifyFilePath); + +export function getMacOsModFileProviders() { + return defaultProviders; +} diff --git a/scripts/config-plugins/types.ts b/scripts/config-plugins/types.ts index be0b578cf..9739563e7 100644 --- a/scripts/config-plugins/types.ts +++ b/scripts/config-plugins/types.ts @@ -1,4 +1,4 @@ -import type { ModPlatform } from "@expo/config-plugins"; +import type { BaseMods, ModPlatform } from "@expo/config-plugins"; import type { BaseModProviderMethods, ForwardedBaseModOptions, @@ -12,6 +12,12 @@ export type CustomModProvider = < file: string ) => BaseModProviderMethods; +export type IosModFileProviders = ReturnType< + typeof BaseMods.getIosModFileProviders +> & + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Record>; + export type ProjectInfo = { projectRoot: string; platforms: ModPlatform[]; diff --git a/test/pack.test.ts b/test/pack.test.ts index dddd5877b..91d009887 100644 --- a/test/pack.test.ts +++ b/test/pack.test.ts @@ -176,6 +176,7 @@ describe("npm pack", () => { "macos/test_app.rb", "package.json", "plugins/index.js", + "plugins/macos.js", "plugins/reanimated.js", "react-native.config.js", "schema.json", @@ -184,10 +185,12 @@ describe("npm pack", () => { "scripts/config-plugins/ExpoConfigPlugins.mjs", "scripts/config-plugins/apply.mjs", "scripts/config-plugins/index.mjs", + "scripts/config-plugins/plugins/cocoaBaseMods.mjs", "scripts/config-plugins/plugins/mod-compiler.mjs", "scripts/config-plugins/plugins/withAndroidBaseMods.mjs", "scripts/config-plugins/plugins/withInternal.mjs", "scripts/config-plugins/plugins/withIosBaseMods.mjs", + "scripts/config-plugins/plugins/withMacOsBaseMods.mjs", "scripts/config-plugins/provider.mjs", "scripts/config-plugins/types.ts", "scripts/configure-projects.js",