Skip to content

Commit 4b9227d

Browse files
authored
feat(macos): add macOS support for config plugins (#2160)
1 parent 04090d7 commit 4b9227d

File tree

12 files changed

+175
-50
lines changed

12 files changed

+175
-50
lines changed

example/macos/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ PODS:
10181018
- React-jsi (= 0.73.33)
10191019
- React-logger (= 0.73.33)
10201020
- React-perflogger (= 0.73.33)
1021-
- ReactNativeHost (0.4.10):
1021+
- ReactNativeHost (0.4.11):
10221022
- glog
10231023
- RCT-Folly (= 2022.05.16.00)
10241024
- React-Core
@@ -1252,7 +1252,7 @@ SPEC CHECKSUMS:
12521252
React-runtimescheduler: 68e2b8754cceaaa8b443d62018d4c9c0aa4e0741
12531253
React-utils: 46cc84b17edde38232668073688b2ed621a3d171
12541254
ReactCommon: 0b6b092708b879557708b378a09729fc29900918
1255-
ReactNativeHost: b74433b0e21ca2aae4fd5c1c3a49cbd1a7edf7ca
1255+
ReactNativeHost: 02d9df701ce3f7b6560f95315df4bab38b660f58
12561256
ReactTestApp-DevSupport: c4abadbb90a8a9903400407e9857c2a2ef0343fb
12571257
ReactTestApp-Resources: 9d83e280b173ba2ee053b8135730dff60f9ab674
12581258
RNWWebStorage: 13da272b965c7233d1c0c167f2306f97722323a1

plugins/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ function withSceneDelegate(config, action) {
3434
});
3535
}
3636

37+
exports.macos = require("./macos");
3738
exports.withReactNativeHost = withReactNativeHost;
3839
exports.withSceneDelegate = withSceneDelegate;

plugins/macos.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// @ts-check
2+
const { withMod } = require("@expo/config-plugins");
3+
4+
/**
5+
* @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig
6+
* @typedef {import("@expo/config-plugins").ExportedConfigWithProps} ExportedConfigWithProps
7+
* @typedef {import("@expo/config-plugins").Mod} Mod
8+
* @typedef {import("@expo/config-plugins").ModConfig} ModConfig
9+
* @typedef {ExportedConfigWithProps & { macos?: { infoPlist?: Record<string, unknown> }}} ExportedConfigWithPropsMac
10+
*/
11+
12+
const macosPlatform = /** @type {keyof ModConfig} */ ("macos");
13+
14+
/**
15+
* Provides the `ReactNativeHost` file for modification.
16+
* @param {ExportedConfig} config Exported config
17+
* @param {Mod} action Method to run on the mod when the config is compiled
18+
* @returns {ExportedConfig} Modified config
19+
*/
20+
function withReactNativeHost(config, action) {
21+
return withMod(config, {
22+
platform: macosPlatform,
23+
mod: "reactNativeHost",
24+
action,
25+
});
26+
}
27+
28+
/**
29+
* Provides the `AppDelegate` file for modification.
30+
* @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L101}
31+
* @param {ExportedConfig} config Exported config
32+
* @param {Mod} action Method to run on the mod when the config is compiled
33+
* @returns {ExportedConfig} Modified config
34+
*/
35+
function withAppDelegate(config, action) {
36+
return withMod(config, {
37+
platform: macosPlatform,
38+
mod: "appDelegate",
39+
action,
40+
});
41+
}
42+
43+
/**
44+
* Provides the `Info.plist` file for modification.
45+
* @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L116}
46+
* @param {ExportedConfig} config Exported config
47+
* @param {Mod} action Method to run on the mod when the config is compiled
48+
* @returns {ExportedConfig} Modified config
49+
*/
50+
function withInfoPlist(config, action) {
51+
return withMod(config, {
52+
platform: macosPlatform,
53+
mod: "infoPlist",
54+
async action(cfg) {
55+
/** @type {ExportedConfigWithPropsMac} */
56+
const config = await action(cfg);
57+
if (!config.macos) {
58+
config.macos = {};
59+
}
60+
config.macos.infoPlist = config.modResults;
61+
return config;
62+
},
63+
});
64+
}
65+
66+
/**
67+
* Provides the main `.xcodeproj` for modification.
68+
* @see {@link https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L173}
69+
* @param {ExportedConfig} config Exported config
70+
* @param {Mod} action Method to run on the mod when the config is compiled
71+
* @returns {ExportedConfig} Modified config
72+
*/
73+
function withXcodeProject(config, action) {
74+
return withMod(config, {
75+
platform: macosPlatform,
76+
mod: "xcodeproj",
77+
action,
78+
});
79+
}
80+
81+
exports.withAppDelegate = withAppDelegate;
82+
exports.withInfoPlist = withInfoPlist;
83+
exports.withXcodeProject = withXcodeProject;
84+
exports.withReactNativeHost = withReactNativeHost;

plugins/reanimated.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ const {
66
const { getPackageVersion, toVersionNumber, v } = require("../scripts/helpers");
77
const { withReactNativeHost } = require("./index");
88

9-
/**
10-
* @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig
11-
*/
9+
/** @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig */
1210

1311
const NAME = "react-native-reanimated";
1412

scripts/config-plugins/index.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @ts-check
22
import { getAndroidModFileProviders } from "./plugins/withAndroidBaseMods.mjs";
33
import { getIosModFileProviders } from "./plugins/withIosBaseMods.mjs";
4+
import { getMacOsModFileProviders } from "./plugins/withMacOsBaseMods.mjs";
45

56
export { applyConfigPlugins } from "./apply.mjs";
67
export {
@@ -12,4 +13,5 @@ export { withInternal } from "./plugins/withInternal.mjs";
1213
export const BaseMods = {
1314
getAndroidModFileProviders,
1415
getIosModFileProviders,
16+
getMacOsModFileProviders,
1517
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// @ts-check
2+
import { createRequire } from "node:module";
3+
import * as path from "node:path";
4+
import { BaseMods } from "../ExpoConfigPlugins.mjs";
5+
import { makeFilePathModifier, makeNullProvider } from "../provider.mjs";
6+
7+
const require = createRequire(import.meta.url);
8+
9+
/**
10+
* @param {import("../types.js").CustomModProvider} modifyFilePath
11+
* @returns {import("../types.js").IosModFileProviders}
12+
*/
13+
export function createModFileProviders(modifyFilePath) {
14+
const modifyReactNativeHostFilePath = makeFilePathModifier(
15+
path.dirname(require.resolve("@rnx-kit/react-native-host/package.json"))
16+
);
17+
18+
const nullProvider = makeNullProvider();
19+
20+
// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/withIosBaseMods.ts
21+
const expoProviders = BaseMods.getIosModFileProviders();
22+
23+
/** @type {import("../types.js").IosModFileProviders} */
24+
const defaultProviders = {
25+
dangerous: expoProviders.dangerous,
26+
finalized: expoProviders.finalized,
27+
appDelegate: modifyFilePath(
28+
expoProviders.appDelegate,
29+
"ReactTestApp/AppDelegate.swift"
30+
),
31+
expoPlist: nullProvider,
32+
xcodeproj: modifyFilePath(
33+
expoProviders.xcodeproj,
34+
"ReactTestApp.xcodeproj/project.pbxproj"
35+
),
36+
infoPlist: modifyFilePath(expoProviders.infoPlist, "Info.plist"),
37+
entitlements: nullProvider,
38+
podfile: makeNullProvider({
39+
path: "",
40+
language: /** @type {const} */ ("rb"),
41+
contents: "",
42+
}),
43+
podfileProperties: makeNullProvider(),
44+
};
45+
46+
// `@rnx-kit/react-native-host` files
47+
defaultProviders["reactNativeHost"] = modifyReactNativeHostFilePath(
48+
expoProviders.appDelegate,
49+
"cocoa/ReactNativeHost.mm"
50+
);
51+
52+
return defaultProviders;
53+
}

scripts/config-plugins/plugins/mod-compiler.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { BaseMods, evalModsAsync } from "../ExpoConfigPlugins.mjs";
33
import { getAndroidModFileProviders } from "./withAndroidBaseMods.mjs";
44
import { getIosModFileProviders } from "./withIosBaseMods.mjs";
5+
import { getMacOsModFileProviders } from "./withMacOsBaseMods.mjs";
56

67
/** @type {import("@expo/config-plugins").withDefaultBaseMods} */
78
export const withDefaultBaseMods = (config, props) => {
@@ -13,6 +14,12 @@ export const withDefaultBaseMods = (config, props) => {
1314
...props,
1415
providers: getAndroidModFileProviders(),
1516
});
17+
config = BaseMods.withGeneratedBaseMods(config, {
18+
...props,
19+
// @ts-expect-error `macos` is not assignable to type `android | ios`
20+
platform: "macos",
21+
providers: getMacOsModFileProviders(),
22+
});
1623
return config;
1724
};
1825

scripts/config-plugins/plugins/withAndroidBaseMods.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const modifyFilePath = makeFilePathModifier(
66
"node_modules/react-native-test-app/android"
77
);
88

9-
// https://github.com/expo/expo/blob/93cd0503117d5a25f8b80ed7b30ec5bed3a67c24/packages/@expo/config-plugins/src/plugins/withAndroidBaseMods.ts
9+
// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/withAndroidBaseMods.ts
1010
const expoProviders = BaseMods.getAndroidModFileProviders();
1111

1212
/** @type {typeof expoProviders} */
Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,17 @@
11
// @ts-check
2-
import { createRequire } from "node:module";
3-
import * as path from "node:path";
2+
import { createModFileProviders } from "./cocoaBaseMods.mjs";
43
import { BaseMods } from "../ExpoConfigPlugins.mjs";
5-
import { makeFilePathModifier, makeNullProvider } from "../provider.mjs";
4+
import { makeFilePathModifier } from "../provider.mjs";
65

76
const modifyFilePath = makeFilePathModifier("node_modules/.generated/ios");
8-
9-
const require = createRequire(import.meta.url);
10-
const modifyReactNativeHostFilePath = makeFilePathModifier(
11-
path.dirname(require.resolve("@rnx-kit/react-native-host/package.json"))
12-
);
13-
14-
const nullProvider = makeNullProvider();
15-
16-
// https://github.com/expo/expo/blob/93cd0503117d5a25f8b80ed7b30ec5bed3a67c24/packages/@expo/config-plugins/src/plugins/withIosBaseMods.ts
17-
const expoProviders = BaseMods.getIosModFileProviders();
18-
19-
/** @type {typeof expoProviders & Record<string, unknown>} */
20-
const defaultProviders = {
21-
dangerous: expoProviders.dangerous,
22-
finalized: expoProviders.finalized,
23-
appDelegate: modifyFilePath(
24-
expoProviders.appDelegate,
25-
"ReactTestApp/AppDelegate.swift"
26-
),
27-
expoPlist: nullProvider,
28-
xcodeproj: modifyFilePath(
29-
expoProviders.xcodeproj,
30-
"ReactTestApp.xcodeproj/project.pbxproj"
31-
),
32-
infoPlist: modifyFilePath(expoProviders.infoPlist, "Info.plist"),
33-
entitlements: nullProvider,
34-
podfile: makeNullProvider({
35-
path: "",
36-
language: /** @type {const} */ ("rb"),
37-
contents: "",
38-
}),
39-
podfileProperties: makeNullProvider(),
40-
};
7+
const defaultProviders = createModFileProviders(modifyFilePath);
418

429
// `react-native-test-app` files
4310
defaultProviders["sceneDelegate"] = modifyFilePath(
44-
expoProviders.appDelegate,
11+
BaseMods.getIosModFileProviders().appDelegate,
4512
"ReactTestApp/SceneDelegate.swift"
4613
);
4714

48-
// `@rnx-kit/react-native-host` files
49-
defaultProviders["reactNativeHost"] = modifyReactNativeHostFilePath(
50-
expoProviders.appDelegate,
51-
"cocoa/ReactNativeHost.mm"
52-
);
53-
5415
export function getIosModFileProviders() {
5516
return defaultProviders;
5617
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @ts-check
2+
import { createModFileProviders } from "./cocoaBaseMods.mjs";
3+
import { makeFilePathModifier } from "../provider.mjs";
4+
5+
const modifyFilePath = makeFilePathModifier("node_modules/.generated/macos");
6+
const defaultProviders = createModFileProviders(modifyFilePath);
7+
8+
export function getMacOsModFileProviders() {
9+
return defaultProviders;
10+
}

0 commit comments

Comments
 (0)