Skip to content

Commit 90ae790

Browse files
committed
feat(macos): add macOS support for config plugins
1 parent 0091244 commit 90ae790

File tree

10 files changed

+137
-49
lines changed

10 files changed

+137
-49
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: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,57 @@ const { withMod } = require("@expo/config-plugins");
33

44
/**
55
* @typedef {import("@expo/config-plugins").ExportedConfig} ExportedConfig
6+
* @typedef {import("@expo/config-plugins").ExportedConfigWithProps} ExportedConfigWithProps
67
* @typedef {import("@expo/config-plugins").Mod} Mod
8+
* @typedef {import("@expo/config-plugins").ModConfig} ModConfig
9+
* @typedef {ExportedConfigWithProps & { macos?: { infoPlist?: Record<string, unknown> }}} ExportedConfigWithPropsMac
710
*/
811

12+
const macosPlatform = /** @type {keyof ModConfig} */ ("macos");
13+
14+
/** @type {Record<string, (config: ExportedConfig, mod: Mod) => ExportedConfig>} */
15+
const macos = {
16+
withReactNativeHost: (config, action) => {
17+
return withMod(config, {
18+
platform: macosPlatform,
19+
mod: "reactNativeHost",
20+
action,
21+
});
22+
},
23+
// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L101
24+
withAppDelegate: (config, action) => {
25+
return withMod(config, {
26+
platform: macosPlatform,
27+
mod: "appDelegate",
28+
action,
29+
});
30+
},
31+
// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L116
32+
withInfoPlist: (config, action) => {
33+
return withMod(config, {
34+
platform: macosPlatform,
35+
mod: "infoPlist",
36+
async action(cfg) {
37+
/** @type {ExportedConfigWithPropsMac} */
38+
const config = await action(cfg);
39+
if (!config.macos) {
40+
config.macos = {};
41+
}
42+
config.macos.infoPlist = config.modResults;
43+
return config;
44+
},
45+
});
46+
},
47+
// https://github.com/expo/expo/blob/sdk-51/packages/%40expo/config-plugins/src/plugins/ios-plugins.ts#L173
48+
withXcodeProject: (config, action) => {
49+
return withMod(config, {
50+
platform: macosPlatform,
51+
mod: "xcodeproj",
52+
action,
53+
});
54+
},
55+
};
56+
957
/**
1058
* Provides the `ReactNativeHost` file for modification.
1159
* @param {ExportedConfig} config Exported config
@@ -34,5 +82,6 @@ function withSceneDelegate(config, action) {
3482
});
3583
}
3684

85+
exports.macos = macos;
3786
exports.withReactNativeHost = withReactNativeHost;
3887
exports.withSceneDelegate = withSceneDelegate;

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/93cd0503117d5a25f8b80ed7b30ec5bed3a67c24/packages/@expo/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

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+
}

scripts/config-plugins/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ModPlatform } from "@expo/config-plugins";
1+
import type { BaseMods, ModPlatform } from "@expo/config-plugins";
22
import type {
33
BaseModProviderMethods,
44
ForwardedBaseModOptions,
@@ -12,6 +12,12 @@ export type CustomModProvider = <
1212
file: string
1313
) => BaseModProviderMethods<ModType, Props>;
1414

15+
export type IosModFileProviders = ReturnType<
16+
typeof BaseMods.getIosModFileProviders
17+
> &
18+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
19+
Record<string, BaseModProviderMethods<any, any>>;
20+
1521
export type ProjectInfo = {
1622
projectRoot: string;
1723
platforms: ModPlatform[];

test/pack.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,12 @@ describe("npm pack", () => {
184184
"scripts/config-plugins/ExpoConfigPlugins.mjs",
185185
"scripts/config-plugins/apply.mjs",
186186
"scripts/config-plugins/index.mjs",
187+
"scripts/config-plugins/plugins/cocoaBaseMods.mjs",
187188
"scripts/config-plugins/plugins/mod-compiler.mjs",
188189
"scripts/config-plugins/plugins/withAndroidBaseMods.mjs",
189190
"scripts/config-plugins/plugins/withInternal.mjs",
190191
"scripts/config-plugins/plugins/withIosBaseMods.mjs",
192+
"scripts/config-plugins/plugins/withMacOsBaseMods.mjs",
191193
"scripts/config-plugins/provider.mjs",
192194
"scripts/config-plugins/types.ts",
193195
"scripts/configure-projects.js",

0 commit comments

Comments
 (0)