@bacons/apple-targets 4.0.1 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -4
- package/build/target.js +7 -0
- package/build/with-widget.js +1 -2
- package/build/with-xcode-changes.js +52 -7
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# Apple Targets
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> This is an experimental Config Plugin not part of any official Expo workflow. Automated testing of targets is seemingly impossible meaning unexpected regressions can occur between versions.
|
|
5
|
-
|
|
6
|
-
An experimental Expo Config Plugin that generates native Apple Targets like Widgets or App Clips, and links them outside the `/ios` directory. You can open Xcode and develop the targets inside the virtual `expo:targets` folder and the changes will be saved outside of the `ios` directory. This pattern enables building things that fall outside of the scope of React Native while still obtaining all the benefits of [Continuous Native Generation](https://docs.expo.dev/workflow/continuous-native-generation/).
|
|
3
|
+
An Expo Config Plugin that generates native Apple Targets like Widgets or App Clips, and links them outside the `/ios` directory. You can open Xcode and develop the targets inside the virtual `expo:targets` folder and the changes will be saved outside of the `ios` directory. This pattern enables building things that fall outside of the scope of React Native while still obtaining all the benefits of [Continuous Native Generation](https://docs.expo.dev/workflow/continuous-native-generation/).
|
|
7
4
|
|
|
8
5
|
<img width="1728" height="963" alt="targets" src="https://github.com/user-attachments/assets/aedaafa0-1ef0-403c-a797-9f4c82cdb9f1" />
|
|
9
6
|
|
package/build/target.js
CHANGED
|
@@ -621,6 +621,13 @@ function getTargetInfoPlistForType(type) {
|
|
|
621
621
|
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).ShieldConfigurationExtension",
|
|
622
622
|
},
|
|
623
623
|
};
|
|
624
|
+
case "device-activity-monitor":
|
|
625
|
+
return {
|
|
626
|
+
NSExtension: {
|
|
627
|
+
NSExtensionPointIdentifier,
|
|
628
|
+
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).DeviceActivityMonitorExtension",
|
|
629
|
+
},
|
|
630
|
+
};
|
|
624
631
|
case "print-service":
|
|
625
632
|
return {
|
|
626
633
|
NSExtension: {
|
package/build/with-widget.js
CHANGED
|
@@ -19,9 +19,8 @@ const util_1 = require("./util");
|
|
|
19
19
|
const DEFAULT_DEPLOYMENT_TARGET = "18.0";
|
|
20
20
|
const DEFAULT_WATCHOS_DEPLOYMENT_TARGET = "11.0";
|
|
21
21
|
const withWidget = (config, props) => {
|
|
22
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
23
|
-
util_1.LOG_QUEUE.add(() => (0, util_1.warnOnce)((0, chalk_1.default) `\nUsing experimental Config Plugin {bold @bacons/apple-targets} that is subject to breaking changes.`));
|
|
24
22
|
// TODO: Magically based on the top-level folders in the `ios-widgets/` folder
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
25
24
|
if (props.icon && !/https?:\/\//.test(props.icon)) {
|
|
26
25
|
props.icon = path_1.default.join(props.directory, props.icon);
|
|
27
26
|
}
|
|
@@ -13,6 +13,16 @@ const with_bacons_xcode_1 = require("./with-bacons-xcode");
|
|
|
13
13
|
const assert_1 = __importDefault(require("assert"));
|
|
14
14
|
const configuration_list_1 = require("./configuration-list");
|
|
15
15
|
const util_1 = require("./util");
|
|
16
|
+
/**
|
|
17
|
+
* Checks if a target is a watchOS extension by inspecting its build settings.
|
|
18
|
+
* This is more agnostic than checking props.type directly, as it derives
|
|
19
|
+
* the behavior from Xcode project attributes.
|
|
20
|
+
*/
|
|
21
|
+
function isWatchOSExtensionTarget(target) {
|
|
22
|
+
const buildSettings = target.getDefaultConfiguration().props.buildSettings;
|
|
23
|
+
return (buildSettings.SDKROOT === "watchos" ||
|
|
24
|
+
"WATCHOS_DEPLOYMENT_TARGET" in buildSettings);
|
|
25
|
+
}
|
|
16
26
|
const withXcodeChanges = (config, props) => {
|
|
17
27
|
return (0, with_bacons_xcode_1.withXcodeProjectBeta)(config, async (config) => {
|
|
18
28
|
await applyXcodeChanges(config, config.modResults, props);
|
|
@@ -33,8 +43,8 @@ exports.withXcodeChanges = withXcodeChanges;
|
|
|
33
43
|
// return version;
|
|
34
44
|
// }
|
|
35
45
|
async function applyXcodeChanges(config, project, props) {
|
|
36
|
-
var _a, _b;
|
|
37
|
-
var
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
var _d;
|
|
38
48
|
const mainAppTarget = (0, target_1.getMainAppTarget)(project);
|
|
39
49
|
// Special setting for share extensions.
|
|
40
50
|
if ((0, target_1.needsEmbeddedSwift)(props.type)) {
|
|
@@ -218,9 +228,39 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
218
228
|
productReference: appExtensionBuildFile.props.fileRef /* alphaExtension.appex */,
|
|
219
229
|
productType: productType,
|
|
220
230
|
});
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
231
|
+
// For watchOS extensions, embed in the watchOS app target instead of
|
|
232
|
+
// the main iOS app target. getCopyBuildPhaseForTarget() throws when
|
|
233
|
+
// called on non-main targets, so we manually create the
|
|
234
|
+
// "Embed Foundation Extensions" copy phase on the watch target.
|
|
235
|
+
if (isWatchOSExtensionTarget(targetToUpdate)) {
|
|
236
|
+
const watchTarget = project.rootObject.props.targets.find((t) => xcode_1.PBXNativeTarget.is(t) && t.isWatchOSTarget());
|
|
237
|
+
if (watchTarget) {
|
|
238
|
+
const { PBXCopyFilesBuildPhase, } = require("@bacons/xcode/build/api/PBXSourcesBuildPhase");
|
|
239
|
+
const existingPhase = watchTarget.props.buildPhases.find((phase) => PBXCopyFilesBuildPhase.is(phase) &&
|
|
240
|
+
phase.props.name === "Embed Foundation Extensions");
|
|
241
|
+
const embedPhase = existingPhase !== null && existingPhase !== void 0 ? existingPhase : watchTarget.createBuildPhase(PBXCopyFilesBuildPhase, {
|
|
242
|
+
name: "Embed Foundation Extensions",
|
|
243
|
+
dstSubfolderSpec: 13,
|
|
244
|
+
dstPath: "",
|
|
245
|
+
files: [],
|
|
246
|
+
});
|
|
247
|
+
if (!embedPhase.getBuildFile(appExtensionBuildFile.props.fileRef)) {
|
|
248
|
+
embedPhase.props.files.push(appExtensionBuildFile);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.warn("[apple-targets] watchOS extension: could not find watchOS app target, falling back to main app");
|
|
253
|
+
const copyPhase = mainAppTarget.getCopyBuildPhaseForTarget(targetToUpdate);
|
|
254
|
+
if (!copyPhase.getBuildFile(appExtensionBuildFile.props.fileRef)) {
|
|
255
|
+
copyPhase.props.files.push(appExtensionBuildFile);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
const copyPhase = mainAppTarget.getCopyBuildPhaseForTarget(targetToUpdate);
|
|
261
|
+
if (!copyPhase.getBuildFile(appExtensionBuildFile.props.fileRef)) {
|
|
262
|
+
copyPhase.props.files.push(appExtensionBuildFile);
|
|
263
|
+
}
|
|
224
264
|
}
|
|
225
265
|
}
|
|
226
266
|
configureTargetWithKnownSettings(targetToUpdate);
|
|
@@ -230,7 +270,12 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
230
270
|
targetToUpdate.getSourcesBuildPhase();
|
|
231
271
|
targetToUpdate.getResourcesBuildPhase();
|
|
232
272
|
configureJsExport(targetToUpdate);
|
|
233
|
-
|
|
273
|
+
// For watchOS extensions, the dependency belongs on the watchOS
|
|
274
|
+
// app target so Xcode builds the extension before the watch app.
|
|
275
|
+
const dependencyParent = isWatchOSExtensionTarget(targetToUpdate)
|
|
276
|
+
? (_b = project.rootObject.props.targets.find((t) => xcode_1.PBXNativeTarget.is(t) && t.isWatchOSTarget())) !== null && _b !== void 0 ? _b : mainAppTarget
|
|
277
|
+
: mainAppTarget;
|
|
278
|
+
dependencyParent.addDependency(targetToUpdate);
|
|
234
279
|
const assetsDir = path_1.default.join(magicCwd, "assets");
|
|
235
280
|
// TODO: Maybe just limit this to Safari extensions?
|
|
236
281
|
const explicitFolders = !fs_1.default.existsSync(assetsDir)
|
|
@@ -282,7 +327,7 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
282
327
|
}
|
|
283
328
|
// If there's a `_shared` folder, create a PBXFileSystemSynchronizedBuildFileExceptionSet and set the `target` to the main app target. Then add exceptions to the new target's PBXFileSystemSynchronizedRootGroup's exceptions. Finally, ensure the relative paths for each file in the _shared folder are added to the `membershipExceptions` array.
|
|
284
329
|
(0, assert_1.default)(syncRootGroup instanceof xcode_1.PBXFileSystemSynchronizedRootGroup);
|
|
285
|
-
(
|
|
330
|
+
(_c = (_d = syncRootGroup.props).exceptions) !== null && _c !== void 0 ? _c : (_d.exceptions = []);
|
|
286
331
|
const existingExceptionSet = syncRootGroup.props.exceptions.find((exception) => exception instanceof xcode_1.PBXFileSystemSynchronizedBuildFileExceptionSet &&
|
|
287
332
|
exception.props.target === mainAppTarget);
|
|
288
333
|
if (sharedAssets.length) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bacons/apple-targets",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "Generate Apple Targets with Expo Prebuild",
|
|
5
5
|
"main": "build/ExtensionStorage.js",
|
|
6
6
|
"types": "build/ExtensionStorage.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"test": "jest --watch",
|
|
21
21
|
"test:e2e": "jest --no-watch --config e2e/jest.config.js",
|
|
22
22
|
"prepare": "expo-module prepare",
|
|
23
|
-
"prepublishOnly": "
|
|
23
|
+
"prepublishOnly": "proofread",
|
|
24
24
|
"expo-module": "expo-module"
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
|
@@ -45,17 +45,18 @@
|
|
|
45
45
|
"debug": "^4.3.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"expo-module-scripts": "^4.1.7",
|
|
49
|
-
"@types/debug": "^4.1.7",
|
|
50
|
-
"@types/glob": "^8.1.0",
|
|
51
48
|
"@expo/babel-preset-cli": "^0.3.1",
|
|
52
49
|
"@expo/config": "^12.0.13",
|
|
53
50
|
"@expo/config-plugins": "^54.0.4",
|
|
54
51
|
"@expo/image-utils": "^0.8.8",
|
|
52
|
+
"@expo/npm-proofread": "^1.0.1",
|
|
55
53
|
"@expo/plist": "^0.4.8",
|
|
56
54
|
"@expo/prebuild-config": "^54.0.8",
|
|
55
|
+
"@types/debug": "^4.1.7",
|
|
56
|
+
"@types/glob": "^8.1.0",
|
|
57
57
|
"chalk": "^4.0.0",
|
|
58
58
|
"expo": "^54.0.32",
|
|
59
|
+
"expo-module-scripts": "^4.1.7",
|
|
59
60
|
"jest-environment-node": "^26"
|
|
60
61
|
},
|
|
61
62
|
"peerDependencies": {
|