@bacons/apple-targets 0.0.10 → 0.1.1

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 CHANGED
@@ -9,11 +9,13 @@ An experimental Expo Config Plugin that generates native Apple Targets like Widg
9
9
 
10
10
  ## 🚀 How to use
11
11
 
12
+ > This plugin requires at least CocoaPods 1.16.2 and Xcode 16.
13
+
12
14
  - Add targets to `targets/` directory with an `expo-target.config.json` file.
13
15
  - Currently, if you don't have an `Info.plist`, it'll be generated on `npx expo prebuild`. This may be changed in the future so if you have an `Info.plist` it'll be used, otherwise, it'll be generated.
14
16
  - Any files in a top-level `target/*/assets` directory will be linked as resources of the target. This was added to support Safari Extensions.
15
17
  - A single top-level `*.entitlements` file will be linked as the entitlements of the target. This is not currently used in EAS Capability signing, but may be in the future.
16
- - All top-level swift files will be linked as build sources of the target. There is currently no support for storyboard or `.xib` files because I can't be bothered.
18
+ - All Swift files will be linked as build sources of the target. There is currently no support for storyboard or `.xib` files because I can't be bothered.
17
19
  - All top-level `*.xcassets` will be linked as resources, and accessible in the targets. If you add files outside of Xcode, you'll need to re-run `npx expo prebuild` to link them.
18
20
  - In Expo SDK +52, set the `ios.appleTeamId`, for SDK 51 and below, set the `appleTeamId` prop in the Config Plugin in `app.config.js`:
19
21
 
@@ -34,7 +36,7 @@ You can change the root directory from `./targets` to something else with `root:
34
36
 
35
37
  ## Using React Native in Targets
36
38
 
37
- I'm not sure, that's not the purpose of this plugin. I built this so I could easily build iOS widgets and other minor targets with SwiftUI. I imagine it would be straightforward to use React Native in share, notification, iMessage, Safari, and photo editing extensions, you can build that on top of this plugin if you want.
39
+ I'm not sure, that's not the purpose of this plugin. I built this so I could easily build iOS widgets and other minor targets with SwiftUI. I imagine it would be straightforward to use React Native in share, notification, iMessage, Safari, and photo editing extensions, you can build that on top of this plugin if you want. Look at the App Clip example for a starting point.
38
40
 
39
41
  ## `expo-target.config.json`
40
42
 
@@ -240,24 +242,26 @@ module.exports = {
240
242
 
241
243
  Ideally, this would be generated automatically based on a fully qualified Xcode project, but for now it's a manual process. The currently supported types are based on static analysis of the most commonly used targets in the iOS App Store. I haven't tested all of these and they may not work.
242
244
 
243
- | Type | Description |
244
- | -------------------- | ---------------------------------- |
245
- | action | Share Action |
246
- | widget | Widget / Live Activity |
247
- | watch | Watch App (with companion iOS App) |
248
- | clip | App Clip |
249
- | safari | Safari Extension |
250
- | share | Share Extension |
251
- | notification-content | Notification Content Extension |
252
- | notification-service | Notification Service Extension |
253
- | intent | Siri Intent Extension |
254
- | intent-ui | Siri Intent UI Extension |
255
- | spotlight | Spotlight Index Extension |
256
- | bg-download | Background Download Extension |
257
- | quicklook-thumbnail | Quick Look Thumbnail Extension |
258
- | location-push | Location Push Service Extension |
259
- | credentials-provider | Credentials Provider Extension |
260
- | account-auth | Account Authentication Extension |
245
+ | Type | Description |
246
+ | ----------------------- | ---------------------------------- |
247
+ | action | Share Action |
248
+ | app-intent | App Intent Extension |
249
+ | widget | Widget / Live Activity |
250
+ | watch | Watch App (with companion iOS App) |
251
+ | clip | App Clip |
252
+ | safari | Safari Extension |
253
+ | share | Share Extension |
254
+ | notification-content | Notification Content Extension |
255
+ | notification-service | Notification Service Extension |
256
+ | intent | Siri Intent Extension |
257
+ | intent-ui | Siri Intent UI Extension |
258
+ | spotlight | Spotlight Index Extension |
259
+ | bg-download | Background Download Extension |
260
+ | quicklook-thumbnail | Quick Look Thumbnail Extension |
261
+ | location-push | Location Push Service Extension |
262
+ | credentials-provider | Credentials Provider Extension |
263
+ | account-auth | Account Authentication Extension |
264
+ | device-activity-monitor | Device Activity Monitor Extension |
261
265
 
262
266
  <!-- | imessage | iMessage Extension | -->
263
267
 
package/build/index.js CHANGED
@@ -26,6 +26,7 @@ const withTargetsDir = (config, _props) => {
26
26
  appleTeamId,
27
27
  ...require(configPath),
28
28
  directory: path_1.default.relative(projectRoot, path_1.default.dirname(configPath)),
29
+ configPath,
29
30
  });
30
31
  });
31
32
  (0, withPodTargetExtension_1.withPodTargetExtension)(config);
package/build/target.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { PBXNativeTarget, XcodeProject } from "@bacons/xcode";
2
- export type ExtensionType = "widget" | "notification-content" | "notification-service" | "share" | "intent" | "bg-download" | "intent-ui" | "spotlight" | "matter" | "quicklook-thumbnail" | "imessage" | "clip" | "watch" | "location-push" | "credentials-provider" | "account-auth" | "action" | "safari";
2
+ export type ExtensionType = "widget" | "notification-content" | "notification-service" | "share" | "intent" | "bg-download" | "intent-ui" | "spotlight" | "matter" | "quicklook-thumbnail" | "imessage" | "clip" | "watch" | "location-push" | "credentials-provider" | "account-auth" | "action" | "safari" | "app-intent" | "device-activity-monitor";
3
3
  export declare const KNOWN_EXTENSION_POINT_IDENTIFIERS: Record<string, ExtensionType>;
4
4
  export declare function getTargetInfoPlistForType(type: ExtensionType): string;
5
- export declare function productTypeForType(type: ExtensionType): "com.apple.product-type.application.on-demand-install-capable" | "com.apple.product-type.application" | "com.apple.product-type.app-extension";
5
+ export declare function productTypeForType(type: ExtensionType): "com.apple.product-type.application.on-demand-install-capable" | "com.apple.product-type.application" | "com.apple.product-type.extensionkit-extension" | "com.apple.product-type.app-extension";
6
6
  export declare function needsEmbeddedSwift(type: ExtensionType): boolean;
7
7
  export declare function getFrameworksForType(type: ExtensionType): string[];
8
8
  export declare function isNativeTargetOfType(target: PBXNativeTarget, type: ExtensionType): boolean;
package/build/target.js CHANGED
@@ -22,6 +22,7 @@ exports.KNOWN_EXTENSION_POINT_IDENTIFIERS = {
22
22
  "com.apple.authentication-services-credential-provider-ui": "credentials-provider",
23
23
  "com.apple.authentication-services-account-authentication-modification-ui": "account-auth",
24
24
  "com.apple.services": "action",
25
+ "com.apple.appintents-extension": "app-intent",
25
26
  // "com.apple.intents-service": "intents",
26
27
  };
27
28
  // TODO: Maybe we can replace `NSExtensionPrincipalClass` with the `@main` annotation that newer extensions use?
@@ -232,6 +233,8 @@ function productTypeForType(type) {
232
233
  return "com.apple.product-type.application.on-demand-install-capable";
233
234
  case "watch":
234
235
  return "com.apple.product-type.application";
236
+ case "app-intent":
237
+ return "com.apple.product-type.extensionkit-extension";
235
238
  default:
236
239
  return "com.apple.product-type.app-extension";
237
240
  }
@@ -272,6 +275,12 @@ function getFrameworksForType(type) {
272
275
  else if (type === "notification-content") {
273
276
  return ["UserNotifications", "UserNotificationsUI"];
274
277
  }
278
+ else if (type === "app-intent") {
279
+ return ["AppIntents"];
280
+ }
281
+ else if (type === "device-activity-monitor") {
282
+ return ["DeviceActivity"];
283
+ }
275
284
  else if (type === "action") {
276
285
  return [
277
286
  // "UniformTypeIdentifiers"
@@ -2,6 +2,7 @@ import { ConfigPlugin } from "@expo/config-plugins";
2
2
  import { Config } from "./config";
3
3
  type Props = Config & {
4
4
  directory: string;
5
+ configPath: string;
5
6
  };
6
7
  declare const withWidget: ConfigPlugin<Props>;
7
8
  export default withWidget;
@@ -113,6 +113,7 @@ const withWidget = (config, props) => {
113
113
  const targetName = (_c = props.name) !== null && _c !== void 0 ? _c : widget;
114
114
  const bundleId = config.ios.bundleIdentifier + "." + widget;
115
115
  (0, withXcodeChanges_1.withXcodeChanges)(config, {
116
+ configPath: props.configPath,
116
117
  name: targetName,
117
118
  cwd: "../" +
118
119
  path_1.default.relative(config._internal.projectRoot, path_1.default.resolve(props.directory)),
@@ -14,5 +14,7 @@ export type XcodeSettings = {
14
14
  teamId?: string;
15
15
  icon?: string;
16
16
  exportJs?: boolean;
17
+ /** File path to the extension config file. */
18
+ configPath: string;
17
19
  };
18
20
  export declare const withXcodeChanges: ConfigPlugin<XcodeSettings>;
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.withXcodeChanges = void 0;
7
7
  const xcode_1 = require("@bacons/xcode");
8
- const json_1 = require("@bacons/xcode/json");
9
8
  const fs_1 = __importDefault(require("fs"));
10
9
  const glob_1 = require("glob");
11
10
  const path_1 = __importDefault(require("path"));
@@ -40,14 +39,19 @@ function createNotificationContentConfigurationList(project, { name, cwd, bundle
40
39
  INFOPLIST_KEY_CFBundleDisplayName: name,
41
40
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
42
41
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
43
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
42
+ LD_RUNPATH_SEARCH_PATHS: [
43
+ "$(inherited)",
44
+ "@executable_path/Frameworks",
45
+ "@executable_path/../../Frameworks",
46
+ ],
44
47
  MARKETING_VERSION: "1.0",
45
48
  MTL_FAST_MATH: "YES",
46
49
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
47
50
  PRODUCT_NAME: "$(TARGET_NAME)",
48
51
  SKIP_INSTALL: "YES",
49
52
  SWIFT_EMIT_LOC_STRINGS: "YES",
50
- SWIFT_OPTIMIZATION_LEVEL: "-Owholemodule",
53
+ SWIFT_COMPILATION_MODE: "wholemodule",
54
+ SWIFT_OPTIMIZATION_LEVEL: "-O",
51
55
  SWIFT_VERSION: "5.0",
52
56
  TARGETED_DEVICE_FAMILY: "1,2",
53
57
  };
@@ -117,6 +121,68 @@ extensionType, { name, cwd, bundleId, deploymentTarget, currentProjectVersion, i
117
121
  });
118
122
  return configurationList;
119
123
  }
124
+ function createAppIntentConfigurationList(project, { name, cwd, bundleId }) {
125
+ const commonBuildSettings = {
126
+ // @ts-expect-error
127
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS: "YES",
128
+ CLANG_ANALYZER_NONNULL: "YES",
129
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: "YES_AGGRESSIVE",
130
+ CLANG_CXX_LANGUAGE_STANDARD: "gnu++20",
131
+ CLANG_ENABLE_OBJC_WEAK: "YES",
132
+ CLANG_WARN_DOCUMENTATION_COMMENTS: "YES",
133
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER: "YES",
134
+ CLANG_WARN_UNGUARDED_AVAILABILITY: "YES_AGGRESSIVE",
135
+ CODE_SIGN_STYLE: "Automatic",
136
+ CURRENT_PROJECT_VERSION: "1",
137
+ DEBUG_INFORMATION_FORMAT: "dwarf",
138
+ ENABLE_USER_SCRIPT_SANDBOXING: "YES",
139
+ GCC_C_LANGUAGE_STANDARD: "gnu17",
140
+ GENERATE_INFOPLIST_FILE: "YES",
141
+ INFOPLIST_FILE: cwd + "/Info.plist",
142
+ INFOPLIST_KEY_CFBundleDisplayName: name,
143
+ INFOPLIST_KEY_NSHumanReadableCopyright: "",
144
+ IPHONEOS_DEPLOYMENT_TARGET: "17.0",
145
+ LD_RUNPATH_SEARCH_PATHS: [
146
+ "$(inherited)",
147
+ "@executable_path/Frameworks",
148
+ "@executable_path/../../Frameworks",
149
+ ],
150
+ LOCALIZATION_PREFERS_STRING_CATALOGS: "YES",
151
+ MARKETING_VERSION: "1.0",
152
+ MTL_FAST_MATH: "YES",
153
+ PRODUCT_BUNDLE_IDENTIFIER: bundleId,
154
+ PRODUCT_NAME: "$(TARGET_NAME)",
155
+ SKIP_INSTALL: "YES",
156
+ SWIFT_EMIT_LOC_STRINGS: "YES",
157
+ SWIFT_VERSION: "5.0",
158
+ TARGETED_DEVICE_FAMILY: "1,2",
159
+ };
160
+ const debugBuildConfig = xcode_1.XCBuildConfiguration.create(project, {
161
+ name: "Debug",
162
+ buildSettings: {
163
+ ...commonBuildSettings,
164
+ GCC_PREPROCESSOR_DEFINITIONS: ["DEBUG=1", "$(inherited)"],
165
+ MTL_ENABLE_DEBUG_INFO: "INCLUDE_SOURCE",
166
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: "DEBUG $(inherited)",
167
+ SWIFT_OPTIMIZATION_LEVEL: "-Onone",
168
+ },
169
+ });
170
+ const releaseBuildConfig = xcode_1.XCBuildConfiguration.create(project, {
171
+ name: "Release",
172
+ buildSettings: {
173
+ ...commonBuildSettings,
174
+ COPY_PHASE_STRIP: "NO",
175
+ DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
176
+ ...{ SWIFT_COMPILATION_MODE: "wholemodule" },
177
+ },
178
+ });
179
+ const configurationList = xcode_1.XCConfigurationList.create(project, {
180
+ buildConfigurations: [debugBuildConfig, releaseBuildConfig],
181
+ defaultConfigurationIsVisible: 0,
182
+ defaultConfigurationName: "Release",
183
+ });
184
+ return configurationList;
185
+ }
120
186
  function createShareConfigurationList(project, { name, cwd, bundleId, deploymentTarget, currentProjectVersion, }) {
121
187
  const common = {
122
188
  CLANG_ANALYZER_NONNULL: "YES",
@@ -135,7 +201,11 @@ function createShareConfigurationList(project, { name, cwd, bundleId, deployment
135
201
  INFOPLIST_KEY_CFBundleDisplayName: name,
136
202
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
137
203
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
138
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
204
+ LD_RUNPATH_SEARCH_PATHS: [
205
+ "$(inherited)",
206
+ "@executable_path/Frameworks",
207
+ "@executable_path/../../Frameworks",
208
+ ],
139
209
  MARKETING_VERSION: "1.0",
140
210
  MTL_FAST_MATH: "YES",
141
211
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
@@ -202,7 +272,11 @@ function createIMessageConfigurationList(project, { name, cwd, bundleId, deploym
202
272
  INFOPLIST_KEY_CFBundleDisplayName: name,
203
273
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
204
274
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
205
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
275
+ LD_RUNPATH_SEARCH_PATHS: [
276
+ "$(inherited)",
277
+ "@executable_path/Frameworks",
278
+ "@executable_path/../../Frameworks",
279
+ ],
206
280
  MARKETING_VERSION: "1.0",
207
281
  MTL_FAST_MATH: "YES",
208
282
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
@@ -260,7 +334,7 @@ function createWatchAppConfigurationList(project, { name, cwd, bundleId, deploym
260
334
  INFOPLIST_KEY_WKCompanionAppBundleIdentifier: mainAppTarget.props.buildSettings.PRODUCT_BUNDLE_IDENTIFIER,
261
335
  // INFOPLIST_KEY_WKCompanionAppBundleIdentifier: "$(BUNDLE_IDENTIFIER)",
262
336
  // INFOPLIST_KEY_WKCompanionAppBundleIdentifier: rootBundleId,
263
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks",
337
+ LD_RUNPATH_SEARCH_PATHS: ["$(inherited)", "@executable_path/Frameworks"],
264
338
  MARKETING_VERSION: "1.0",
265
339
  MTL_FAST_MATH: "YES",
266
340
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
@@ -292,7 +366,8 @@ function createWatchAppConfigurationList(project, { name, cwd, bundleId, deploym
292
366
  buildSettings: {
293
367
  ...common,
294
368
  // Diff
295
- SWIFT_OPTIMIZATION_LEVEL: "-Owholemodule",
369
+ SWIFT_COMPILATION_MODE: "wholemodule",
370
+ SWIFT_OPTIMIZATION_LEVEL: "-O",
296
371
  COPY_PHASE_STRIP: "NO",
297
372
  DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
298
373
  },
@@ -321,7 +396,11 @@ function createSafariConfigurationList(project, { name, cwd, bundleId, deploymen
321
396
  INFOPLIST_KEY_CFBundleDisplayName: name,
322
397
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
323
398
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
324
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
399
+ LD_RUNPATH_SEARCH_PATHS: [
400
+ "$(inherited)",
401
+ "@executable_path/Frameworks",
402
+ "@executable_path/../../Frameworks",
403
+ ],
325
404
  MARKETING_VERSION: "1.0",
326
405
  MTL_FAST_MATH: "YES",
327
406
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
@@ -348,7 +427,8 @@ function createSafariConfigurationList(project, { name, cwd, bundleId, deploymen
348
427
  buildSettings: {
349
428
  ...common,
350
429
  // Diff
351
- SWIFT_OPTIMIZATION_LEVEL: "-Owholemodule",
430
+ SWIFT_COMPILATION_MODE: "wholemodule",
431
+ SWIFT_OPTIMIZATION_LEVEL: "-O",
352
432
  COPY_PHASE_STRIP: "NO",
353
433
  DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
354
434
  },
@@ -404,7 +484,7 @@ function createAppClipConfigurationList(project, { name, cwd, bundleId, deployme
404
484
  ...infoPlist,
405
485
  ...superCommon,
406
486
  ASSETCATALOG_COMPILER_APPICON_NAME: "AppIcon",
407
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks",
487
+ LD_RUNPATH_SEARCH_PATHS: ["$(inherited)", "@executable_path/Frameworks"],
408
488
  MTL_FAST_MATH: "YES",
409
489
  ENABLE_PREVIEWS: "YES",
410
490
  };
@@ -424,7 +504,8 @@ function createAppClipConfigurationList(project, { name, cwd, bundleId, deployme
424
504
  buildSettings: {
425
505
  ...common,
426
506
  // Diff
427
- SWIFT_OPTIMIZATION_LEVEL: "-Owholemodule",
507
+ SWIFT_COMPILATION_MODE: "wholemodule",
508
+ SWIFT_OPTIMIZATION_LEVEL: "-O",
428
509
  COPY_PHASE_STRIP: "NO",
429
510
  DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
430
511
  },
@@ -458,7 +539,11 @@ function createConfigurationList(project, { name, cwd, bundleId, deploymentTarge
458
539
  INFOPLIST_KEY_CFBundleDisplayName: name,
459
540
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
460
541
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
461
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
542
+ LD_RUNPATH_SEARCH_PATHS: [
543
+ "$(inherited)",
544
+ "@executable_path/Frameworks",
545
+ "@executable_path/../../Frameworks",
546
+ ],
462
547
  MARKETING_VERSION: "1.0",
463
548
  MTL_ENABLE_DEBUG_INFO: "INCLUDE_SOURCE",
464
549
  MTL_FAST_MATH: "YES",
@@ -494,14 +579,19 @@ function createConfigurationList(project, { name, cwd, bundleId, deploymentTarge
494
579
  INFOPLIST_KEY_CFBundleDisplayName: name,
495
580
  INFOPLIST_KEY_NSHumanReadableCopyright: "",
496
581
  IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
497
- LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks",
582
+ LD_RUNPATH_SEARCH_PATHS: [
583
+ "$(inherited)",
584
+ "@executable_path/Frameworks",
585
+ "@executable_path/../../Frameworks",
586
+ ],
498
587
  MARKETING_VERSION: "1.0",
499
588
  MTL_FAST_MATH: "YES",
500
589
  PRODUCT_BUNDLE_IDENTIFIER: bundleId,
501
590
  PRODUCT_NAME: "$(TARGET_NAME)",
502
591
  SKIP_INSTALL: "YES",
503
592
  SWIFT_EMIT_LOC_STRINGS: "YES",
504
- SWIFT_OPTIMIZATION_LEVEL: "-Owholemodule",
593
+ SWIFT_COMPILATION_MODE: "wholemodule",
594
+ SWIFT_OPTIMIZATION_LEVEL: "-O",
505
595
  SWIFT_VERSION: "5",
506
596
  TARGETED_DEVICE_FAMILY: "1,2",
507
597
  },
@@ -535,42 +625,14 @@ function createConfigurationListForType(project, props) {
535
625
  else if (props.type === "watch") {
536
626
  return createWatchAppConfigurationList(project, props);
537
627
  }
628
+ else if (props.type === "app-intent") {
629
+ return createAppIntentConfigurationList(project, props);
630
+ }
538
631
  else {
539
632
  // TODO: More
540
633
  return createNotificationContentConfigurationList(project, props);
541
634
  }
542
635
  }
543
- /** It's common for all frameworks to exist in the top-level "Frameworks" folder that shows in Xcode. */
544
- function addFrameworksToDisplayFolder(project, frameworks) {
545
- var _a;
546
- const mainFrameworksGroup = (_a = project.rootObject.props.mainGroup
547
- .getChildGroups()
548
- .find((group) => group.getDisplayName() === "Frameworks")) !== null && _a !== void 0 ? _a :
549
- // If this happens, there's a big problem. But just in case...
550
- project.rootObject.props.mainGroup.createGroup({
551
- name: "Frameworks",
552
- sourceTree: "<group>",
553
- });
554
- frameworks.forEach((file) => {
555
- if (!mainFrameworksGroup.props.children.find((child) => child.uuid === file.uuid)) {
556
- mainFrameworksGroup.props.children.push(file);
557
- }
558
- });
559
- }
560
- function getFramework(project, name) {
561
- const frameworkName = name + ".framework";
562
- for (const [, entry] of project.entries()) {
563
- if (xcode_1.PBXFileReference.is(entry) &&
564
- entry.props.lastKnownFileType === "wrapper.framework" &&
565
- entry.props.sourceTree === "SDKROOT" &&
566
- entry.props.name === frameworkName) {
567
- return entry;
568
- }
569
- }
570
- return xcode_1.PBXFileReference.create(project, {
571
- path: "System/Library/Frameworks/" + frameworkName,
572
- });
573
- }
574
636
  async function applyXcodeChanges(config, project, props) {
575
637
  var _a, _b;
576
638
  const mainAppTarget = (0, target_1.getMainAppTarget)(project);
@@ -592,18 +654,6 @@ async function applyXcodeChanges(config, project, props) {
592
654
  console.log(`Target "${targetToUpdate.props.productName}" already exists, updating instead of creating a new one`);
593
655
  }
594
656
  const magicCwd = path_1.default.join(config._internal.projectRoot, "ios", props.cwd);
595
- function getOrCreateBuildFile(file) {
596
- for (const entry of file.getReferrers()) {
597
- if (xcode_1.PBXBuildFile.is(entry) && entry.props.fileRef.uuid === file.uuid) {
598
- return entry;
599
- }
600
- }
601
- return xcode_1.PBXBuildFile.create(project, {
602
- fileRef: file,
603
- });
604
- }
605
- // Add the widget target to the display folder (cosmetic)
606
- addFrameworksToDisplayFolder(project, props.frameworks.map((framework) => getFramework(project, framework)));
607
657
  const developmentTeamId = (_b = props.teamId) !== null && _b !== void 0 ? _b : mainAppTarget.getDefaultBuildSetting("DEVELOPMENT_TEAM");
608
658
  if (!developmentTeamId) {
609
659
  throw new Error("Couldn't find DEVELOPMENT_TEAM in Xcode project and none were provided in the Expo config.");
@@ -646,19 +696,11 @@ async function applyXcodeChanges(config, project, props) {
646
696
  }
647
697
  function configureTargetWithEntitlements(target) {
648
698
  const entitlements = (0, glob_1.sync)("*.entitlements", {
649
- absolute: true,
699
+ absolute: false,
650
700
  cwd: magicCwd,
651
- }).map((file) => {
652
- return xcode_1.PBXBuildFile.create(project, {
653
- fileRef: xcode_1.PBXFileReference.create(project, {
654
- path: path_1.default.basename(file),
655
- explicitFileType: "text.plist.entitlements",
656
- sourceTree: "<group>",
657
- }),
658
- });
659
701
  });
660
702
  if (entitlements.length > 0) {
661
- target.setBuildSetting("CODE_SIGN_ENTITLEMENTS", props.cwd + "/" + entitlements[0].props.fileRef.props.path);
703
+ target.setBuildSetting("CODE_SIGN_ENTITLEMENTS", props.cwd + "/" + entitlements[0]);
662
704
  }
663
705
  else {
664
706
  target.removeBuildSetting("CODE_SIGN_ENTITLEMENTS");
@@ -674,50 +716,6 @@ async function applyXcodeChanges(config, project, props) {
674
716
  }
675
717
  });
676
718
  }
677
- function buildFileGroupHierarchy(files) {
678
- const root = [];
679
- function getOrCreateGroup(name, segment, group) {
680
- const fullPath = path_1.default.join(magicCwd, name);
681
- let newGroup = group.find((child) => child.props.isa === json_1.ISA.PBXGroup && child.props.path === fullPath);
682
- if (!newGroup) {
683
- newGroup = xcode_1.PBXGroup.create(project, {
684
- name: segment,
685
- path: fullPath,
686
- children: [],
687
- });
688
- group.push(newGroup);
689
- }
690
- return newGroup;
691
- }
692
- files.forEach((filePath) => {
693
- const pathSegments = filePath.split(path_1.default.sep);
694
- let currentLevel = root;
695
- pathSegments.forEach((part, index) => {
696
- const isRoot = part === ".";
697
- const currentPath = pathSegments.slice(0, index + 1).join(path_1.default.sep);
698
- currentLevel = isRoot ? currentLevel : getOrCreateGroup(currentPath, part, currentLevel).props.children;
699
- const isFinalPart = index === pathSegments.length - 1;
700
- if (swiftBuildFiles[filePath] && isFinalPart) {
701
- const filex = swiftBuildFiles[filePath];
702
- currentLevel.push(...filex);
703
- }
704
- });
705
- });
706
- return root;
707
- }
708
- function generateProjectGroups(project, structure, magicCwd) {
709
- return structure.map((item) => {
710
- if (item.props.isa === json_1.ISA.PBXGroup) {
711
- // @ts-ignore
712
- const childGroups = generateProjectGroups(project, item.props.children, path_1.default.join(magicCwd, item.props.name));
713
- item.props.children = childGroups;
714
- return item;
715
- }
716
- else if (item.props.isa === json_1.ISA.PBXBuildFile) {
717
- return item.props.fileRef;
718
- }
719
- });
720
- }
721
719
  function configureTargetWithPreview(target) {
722
720
  const assets = (0, glob_1.sync)("preview/*.xcassets", {
723
721
  absolute: true,
@@ -736,7 +734,9 @@ async function applyXcodeChanges(config, project, props) {
736
734
  const shellScript = mainAppTarget.props.buildPhases.find((phase) => xcode_1.PBXShellScriptBuildPhase.is(phase) &&
737
735
  phase.props.name === "Bundle React Native code and images");
738
736
  if (!shellScript) {
739
- throw new Error('Failed to find the "Bundle React Native code and images" build phase in the main app target.');
737
+ console.warn('Failed to find the "Bundle React Native code and images" build phase in the main app target. Will not be able to configure: ' +
738
+ props.type);
739
+ return;
740
740
  }
741
741
  const currentShellScript = target.props.buildPhases.find((phase) => xcode_1.PBXShellScriptBuildPhase.is(phase) &&
742
742
  phase.props.name === "Bundle React Native code and images");
@@ -777,7 +777,8 @@ async function applyXcodeChanges(config, project, props) {
777
777
  });
778
778
  targetToUpdate.props.buildConfigurationList.removeFromProject();
779
779
  // Create new build phases
780
- targetToUpdate.props.buildConfigurationList = createConfigurationListForType(project, props);
780
+ targetToUpdate.props.buildConfigurationList =
781
+ createConfigurationListForType(project, props);
781
782
  configureTargetWithEntitlements(targetToUpdate);
782
783
  configureTargetWithPreview(targetToUpdate);
783
784
  configureTargetWithKnownSettings(targetToUpdate);
@@ -786,130 +787,16 @@ async function applyXcodeChanges(config, project, props) {
786
787
  syncMarketingVersions();
787
788
  return project;
788
789
  }
789
- // Build Files
790
- const swiftBuildFiles = {};
791
- (0, glob_1.sync)("**/*.swift", {
792
- absolute: true,
793
- cwd: magicCwd,
794
- }).forEach((file) => {
795
- const fileDir = path_1.default.dirname(path_1.default.relative(magicCwd, file));
796
- const pbxFile = xcode_1.PBXBuildFile.create(project, {
797
- fileRef: xcode_1.PBXFileReference.create(project, {
798
- path: file,
799
- sourceTree: "<group>",
800
- }),
801
- });
802
- if (!swiftBuildFiles[fileDir]) {
803
- swiftBuildFiles[fileDir] = [];
804
- }
805
- swiftBuildFiles[fileDir].push(pbxFile);
806
- return undefined;
807
- });
808
- const swiftStructure = buildFileGroupHierarchy(Object.keys(swiftBuildFiles));
809
- const swiftGroups = generateProjectGroups(project, swiftStructure, magicCwd);
810
- // NOTE: Single-level only
811
- const intentFiles = (0, glob_1.sync)("*.intentdefinition", {
812
- absolute: true,
813
- cwd: magicCwd,
814
- }).map((file) => {
815
- return xcode_1.PBXFileReference.create(project, {
816
- lastKnownFileType: "file.intentdefinition",
817
- path: path_1.default.basename(file),
818
- sourceTree: "<group>",
819
- });
820
- });
821
- const intentBuildFiles = [0, 1].map((_) => intentFiles.map((file) => {
822
- return xcode_1.PBXBuildFile.create(project, {
823
- fileRef: file,
824
- });
825
- }));
826
- let assetFiles = [
827
- // All assets`
828
- // "assets/*",
829
- // NOTE: Single-level only
830
- "*.xcassets",
831
- ]
832
- .map((glob) => (0, glob_1.sync)(glob, {
833
- absolute: true,
834
- cwd: magicCwd,
835
- }).map((file) => {
836
- return xcode_1.PBXBuildFile.create(project, {
837
- fileRef: xcode_1.PBXFileReference.create(project, {
838
- path: path_1.default.basename(file),
839
- sourceTree: "<group>",
840
- }),
841
- });
842
- }))
843
- .flat();
844
- const resAssets = [];
845
- // Support for LaunchScreen files
846
- const baseProj = path_1.default.join(magicCwd, "Base.lproj");
847
- if (fs_1.default.existsSync(baseProj)) {
848
- // Link LaunchScreen.storyboard
849
- fs_1.default.readdirSync(baseProj).forEach((file) => {
850
- if (file === ".DS_Store")
851
- return;
852
- const stat = fs_1.default.statSync(path_1.default.join(baseProj, file));
853
- if (stat.isFile()) {
854
- if (file.endsWith(".storyboard")) {
855
- assetFiles.push(xcode_1.PBXBuildFile.create(project, {
856
- fileRef: xcode_1.PBXVariantGroup.create(project, {
857
- name: file,
858
- sourceTree: "<group>",
859
- children: [
860
- xcode_1.PBXFileReference.create(project, {
861
- lastKnownFileType: "file.storyboard",
862
- name: "Base",
863
- path: path_1.default.join("Base.lproj", file),
864
- sourceTree: "<group>",
865
- }),
866
- ],
867
- }),
868
- }));
869
- }
870
- }
871
- });
872
- }
873
- // TODO: Maybe just limit this to Safari?
874
- if (fs_1.default.existsSync(path_1.default.join(magicCwd, "assets"))) {
875
- // get top-level directories in `assets/` and append them to assetFiles as folder types
876
- fs_1.default.readdirSync(path_1.default.join(magicCwd, "assets")).forEach((file) => {
877
- if (file === ".DS_Store")
878
- return;
879
- const stat = fs_1.default.statSync(path_1.default.join(magicCwd, "assets", file));
880
- if (stat.isDirectory()) {
881
- resAssets.push(xcode_1.PBXBuildFile.create(project, {
882
- fileRef: xcode_1.PBXFileReference.create(project, {
883
- path: file,
884
- sourceTree: "<group>",
885
- lastKnownFileType: "folder",
886
- }),
887
- }));
888
- }
889
- else if (stat.isFile()) {
890
- resAssets.push(xcode_1.PBXBuildFile.create(project, {
891
- fileRef: xcode_1.PBXFileReference.create(project, {
892
- path: file,
893
- explicitFileType: file.endsWith(".js")
894
- ? "sourcecode.javascript"
895
- : file.endsWith(".json")
896
- ? "text.json"
897
- : file.endsWith(".html")
898
- ? "text.html"
899
- : file.endsWith(".css")
900
- ? "text.css"
901
- : "text",
902
- sourceTree: "<group>",
903
- }),
904
- }));
905
- }
906
- });
907
- }
908
- const alphaExtensionAppexBf = xcode_1.PBXBuildFile.create(project, {
790
+ const productType = (0, target_1.productTypeForType)(props.type);
791
+ const isExtension = productType === "com.apple.product-type.app-extension";
792
+ const isExtensionKit = productType === "com.apple.product-type.extensionkit-extension";
793
+ const appExtensionBuildFile = xcode_1.PBXBuildFile.create(project, {
909
794
  fileRef: xcode_1.PBXFileReference.create(project, {
910
- explicitFileType: "wrapper.app-extension",
795
+ explicitFileType: isExtensionKit
796
+ ? "wrapper.extensionkit-extension"
797
+ : "wrapper.app-extension",
911
798
  includeInIndex: 0,
912
- path: productName + ".appex",
799
+ path: productName + (isExtension ? ".appex" : ".app"),
913
800
  sourceTree: "BUILT_PRODUCTS_DIR",
914
801
  }),
915
802
  settings: {
@@ -918,53 +805,46 @@ async function applyXcodeChanges(config, project, props) {
918
805
  });
919
806
  project.rootObject.ensureProductGroup().props.children.push(
920
807
  // @ts-expect-error
921
- alphaExtensionAppexBf.props.fileRef);
922
- const widgetTarget = project.rootObject.createNativeTarget({
808
+ appExtensionBuildFile.props.fileRef);
809
+ const extensionTarget = project.rootObject.createNativeTarget({
923
810
  buildConfigurationList: createConfigurationListForType(project, props),
924
811
  name: productName,
925
812
  productName,
926
813
  // @ts-expect-error
927
- productReference: alphaExtensionAppexBf.props.fileRef /* alphaExtension.appex */,
928
- productType: (0, target_1.productTypeForType)(props.type),
929
- });
930
- configureTargetWithKnownSettings(widgetTarget);
931
- const entitlementFiles = configureTargetWithEntitlements(widgetTarget);
932
- configureTargetWithPreview(widgetTarget);
933
- widgetTarget.createBuildPhase(xcode_1.PBXSourcesBuildPhase, {
934
- files: [
935
- ...Object.values(swiftBuildFiles).flat(),
936
- ...intentBuildFiles[0],
937
- // ...entitlementFiles
938
- ],
939
- // CD0706152A2EBE2E009C1192 /* index.swift in Sources */,
940
- // CD07061A2A2EBE2F009C1192 /* alpha.intentdefinition in Sources */,
941
- // CD0706112A2EBE2E009C1192 /* alphaBundle.swift in Sources */,
942
- // CD0706132A2EBE2E009C1192 /* alphaLiveActivity.swift in Sources */,
943
- });
944
- widgetTarget.createBuildPhase(xcode_1.PBXFrameworksBuildPhase, {
945
- files: props.frameworks.map((framework) => getOrCreateBuildFile(getFramework(project, framework))),
946
- });
947
- widgetTarget.createBuildPhase(xcode_1.PBXResourcesBuildPhase, {
948
- files: [...assetFiles, ...resAssets],
949
- });
950
- configureJsExport(widgetTarget);
814
+ productReference: appExtensionBuildFile.props.fileRef /* alphaExtension.appex */,
815
+ productType: productType,
816
+ });
817
+ configureTargetWithKnownSettings(extensionTarget);
818
+ configureTargetWithEntitlements(extensionTarget);
819
+ configureTargetWithPreview(extensionTarget);
820
+ extensionTarget.ensureFrameworks(props.frameworks);
821
+ extensionTarget.getSourcesBuildPhase();
822
+ extensionTarget.getResourcesBuildPhase();
823
+ configureJsExport(extensionTarget);
951
824
  const containerItemProxy = xcode_1.PBXContainerItemProxy.create(project, {
952
825
  containerPortal: project.rootObject,
953
826
  proxyType: 1,
954
- remoteGlobalIDString: widgetTarget.uuid,
827
+ remoteGlobalIDString: extensionTarget.uuid,
955
828
  remoteInfo: productName,
956
829
  });
957
830
  const targetDependency = xcode_1.PBXTargetDependency.create(project, {
958
- target: widgetTarget,
831
+ target: extensionTarget,
959
832
  targetProxy: containerItemProxy,
960
833
  });
961
834
  // Add the target dependency to the main app, should be only one.
962
835
  mainAppTarget.props.dependencies.push(targetDependency);
963
- const WELL_KNOWN_COPY_EXTENSIONS_NAME = props.type === "clip"
964
- ? "Embed App Clips"
965
- : props.type === "watch"
966
- ? "Embed Watch Content"
967
- : "Embed Foundation Extensions";
836
+ const WELL_KNOWN_COPY_EXTENSIONS_NAME = (() => {
837
+ switch (props.type) {
838
+ case "clip":
839
+ return "Embed App Clips";
840
+ case "watch":
841
+ return "Embed Watch Content";
842
+ case "app-intent":
843
+ return "Embed ExtensionKit Extensions";
844
+ default:
845
+ return "Embed Foundation Extensions";
846
+ }
847
+ })();
968
848
  // Could exist from a Share Extension
969
849
  const copyFilesBuildPhase = mainAppTarget.props.buildPhases.find((phase) => {
970
850
  if (xcode_1.PBXCopyFilesBuildPhase.is(phase)) {
@@ -974,105 +854,63 @@ async function applyXcodeChanges(config, project, props) {
974
854
  });
975
855
  if (copyFilesBuildPhase) {
976
856
  // Assume that this is the first run if there is no matching target that we identified from a previous run.
977
- copyFilesBuildPhase.props.files.push(alphaExtensionAppexBf);
857
+ copyFilesBuildPhase.props.files.push(appExtensionBuildFile);
978
858
  }
979
859
  else {
980
- const dstPath = { clip: "AppClips", watch: "Watch" }[props.type];
981
- if (dstPath) {
982
- mainAppTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
983
- dstPath: "$(CONTENTS_FOLDER_PATH)/" + dstPath,
984
- dstSubfolderSpec: 16,
985
- buildActionMask: 2147483647,
986
- files: [alphaExtensionAppexBf],
987
- name: WELL_KNOWN_COPY_EXTENSIONS_NAME,
988
- runOnlyForDeploymentPostprocessing: 0,
989
- });
990
- }
991
- else {
992
- mainAppTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
993
- dstSubfolderSpec: 13,
994
- buildActionMask: 2147483647,
995
- files: [alphaExtensionAppexBf],
996
- name: WELL_KNOWN_COPY_EXTENSIONS_NAME,
997
- runOnlyForDeploymentPostprocessing: 0,
998
- });
999
- }
860
+ mainAppTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
861
+ files: [appExtensionBuildFile],
862
+ });
1000
863
  }
1001
- const mainSourcesBuildPhase = mainAppTarget.getBuildPhase(xcode_1.PBXSourcesBuildPhase);
1002
- // TODO: Idempotent
1003
- mainSourcesBuildPhase === null || mainSourcesBuildPhase === void 0 ? void 0 : mainSourcesBuildPhase.props.files.push(...intentBuildFiles[1]);
1004
- const protectedGroup = ensureProtectedGroup(project).createGroup({
1005
- // This is where it gets fancy
1006
- // TODO: The user should be able to know that this is safe to modify and won't be overwritten.
1007
- name: path_1.default.basename(props.cwd),
1008
- // Like `../alpha`
1009
- path: props.cwd,
1010
- sourceTree: "<group>",
1011
- children: [
1012
- ...swiftGroups,
1013
- ...intentFiles.sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
1014
- ...assetFiles
1015
- .map((buildFile) => buildFile.props.fileRef)
1016
- .sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
1017
- ...entitlementFiles
1018
- .map((buildFile) => buildFile.props.fileRef)
1019
- .sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
1020
- // CD0706192A2EBE2F009C1192 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1021
- xcode_1.PBXFileReference.create(project, {
1022
- path: "Info.plist",
1023
- sourceTree: "<group>",
1024
- }),
864
+ const syncException = xcode_1.PBXFileSystemSynchronizedBuildFileExceptionSet.create(project, {
865
+ target: extensionTarget,
866
+ membershipExceptions: [
867
+ // TODO: What other files belong here, why is this here?
868
+ "Info.plist",
869
+ // Exclude the config path
870
+ path_1.default.relative(magicCwd, props.configPath),
871
+ ].sort(),
872
+ });
873
+ const assetsDir = path_1.default.join(magicCwd, "assets");
874
+ // TODO: Maybe just limit this to Safari extensions?
875
+ const explicitFolders = !fs_1.default.existsSync(assetsDir)
876
+ ? []
877
+ : fs_1.default
878
+ .readdirSync(assetsDir)
879
+ .filter((file) => file !== ".DS_Store" &&
880
+ fs_1.default.statSync(path_1.default.join(assetsDir, file)).isDirectory())
881
+ .map((file) => path_1.default.join("assets", file));
882
+ const syncRootGroup = xcode_1.PBXFileSystemSynchronizedRootGroup.create(project, {
883
+ path: path_1.default.basename(props.cwd),
884
+ exceptions: [syncException],
885
+ explicitFileTypes: {},
886
+ explicitFolders: [
887
+ // Replaces the previous `lastKnownFileType: "folder",` system that's used in things like Safari extensions to include folders of assets.
888
+ // ex: `"Resources/_locales", "Resources/images"`
889
+ ...explicitFolders,
1025
890
  ],
1026
- // children = (
1027
- // CD0706102A2EBE2E009C1192 /* alphaBundle.swift */,
1028
- // CD0706122A2EBE2E009C1192 /* alphaLiveActivity.swift */,
1029
- // CD0706142A2EBE2E009C1192 /* index.swift */,
1030
- // CD0706162A2EBE2E009C1192 /* alpha.intentdefinition */,
1031
- // CD0706172A2EBE2F009C1192 /* Assets.xcassets */,
1032
- // CD0706192A2EBE2F009C1192 /* Info.plist */,
1033
- // );
1034
- // name = "expo:alpha";
1035
- // path = "../alpha";
1036
- // sourceTree = "<group>";
891
+ sourceTree: "<group>",
1037
892
  });
1038
- if (resAssets.length > 0) {
1039
- protectedGroup.createGroup({
1040
- name: "assets",
1041
- path: "assets",
1042
- sourceTree: "<group>",
1043
- // @ts-expect-error
1044
- children: resAssets
1045
- .map((buildFile) => buildFile.props.fileRef)
1046
- .sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
1047
- });
893
+ if (!extensionTarget.props.fileSystemSynchronizedGroups) {
894
+ extensionTarget.props.fileSystemSynchronizedGroups = [];
1048
895
  }
896
+ extensionTarget.props.fileSystemSynchronizedGroups.push(syncRootGroup);
897
+ ensureProtectedGroup(project, path_1.default.dirname(props.cwd)).props.children.push(syncRootGroup);
1049
898
  applyDevelopmentTeamIdToTargets();
1050
899
  syncMarketingVersions();
1051
900
  return project;
1052
901
  }
1053
902
  const PROTECTED_GROUP_NAME = "expo:targets";
1054
- function ensureProtectedGroup(project) {
903
+ function ensureProtectedGroup(project, relativePath = "../targets") {
1055
904
  const hasProtectedGroup = project.rootObject.props.mainGroup
1056
905
  .getChildGroups()
1057
906
  .find((group) => group.getDisplayName() === PROTECTED_GROUP_NAME);
1058
907
  const protectedGroup = hasProtectedGroup !== null && hasProtectedGroup !== void 0 ? hasProtectedGroup : xcode_1.PBXGroup.create(project, {
1059
908
  name: PROTECTED_GROUP_NAME,
909
+ path: relativePath,
1060
910
  sourceTree: "<group>",
1061
911
  });
1062
912
  if (!hasProtectedGroup) {
1063
913
  project.rootObject.props.mainGroup.props.children.unshift(protectedGroup);
1064
- // let libIndex = project.rootObject.props.mainGroup
1065
- // .getChildGroups()
1066
- // .findIndex((group) => group.getDisplayName() === "Libraries");
1067
- // if (libIndex === -1) {
1068
- // libIndex = 0;
1069
- // }
1070
- // add above the group named "Libraries"
1071
- // project.rootObject.props.mainGroup.props.children.splice(
1072
- // libIndex,
1073
- // 0,
1074
- // protectedGroup
1075
- // );
1076
914
  }
1077
915
  return protectedGroup;
1078
916
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bacons/apple-targets",
3
- "version": "0.0.10",
3
+ "version": "0.1.1",
4
4
  "description": "Generate Apple Targets with Expo Prebuild",
5
5
  "main": "build/index.js",
6
6
  "files": [
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@react-native/normalize-colors": "^0.76.1",
32
32
  "glob": "^10.2.6",
33
- "@bacons/xcode": "^1.0.0-alpha.13",
33
+ "@bacons/xcode": "^1.0.0-alpha.22",
34
34
  "fs-extra": "^11.2.0"
35
35
  },
36
36
  "devDependencies": {