@bacons/apple-targets 4.0.3 → 4.0.5

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.
@@ -12,10 +12,16 @@ const with_widget_1 = __importDefault(require("./with-widget"));
12
12
  const with_bacons_xcode_1 = require("./with-bacons-xcode");
13
13
  const util_1 = require("./util");
14
14
  const withTargetsDir = (config, _props) => {
15
- var _a;
15
+ var _a, _b;
16
16
  let { appleTeamId = (_a = config === null || config === void 0 ? void 0 : config.ios) === null || _a === void 0 ? void 0 : _a.appleTeamId } = _props || {};
17
17
  const { root = "./targets", match = "*" } = _props || {};
18
18
  const projectRoot = config._internal.projectRoot;
19
+ if (!((_b = config.ios) === null || _b === void 0 ? void 0 : _b.bundleIdentifier)) {
20
+ const fallbackBundleId = `com.example.${config.slug}`;
21
+ (0, util_1.warnOnce)((0, chalk_1.default) `{yellow [bacons/apple-targets]} Expo config is missing {cyan ios.bundleIdentifier} property. Using fallback: {cyan ${fallbackBundleId}}. Add it to your app.json or app.config.js for production builds.`);
22
+ config.ios = config.ios || {};
23
+ config.ios.bundleIdentifier = fallbackBundleId;
24
+ }
19
25
  if (!appleTeamId) {
20
26
  (0, util_1.warnOnce)((0, chalk_1.default) `{yellow [bacons/apple-targets]} Expo config is missing required {cyan ios.appleTeamId} property. Find this in Xcode and add to the Expo Config to correct. iOS builds may fail until this is corrected.`);
21
27
  }
@@ -81,7 +81,6 @@ function createActionConfigurationList({ name, displayName, cwd, bundleId, deplo
81
81
  SWIFT_EMIT_LOC_STRINGS: "YES",
82
82
  SWIFT_VERSION: "5.0",
83
83
  TARGETED_DEVICE_FAMILY: "1,2",
84
- // @ts-expect-error
85
84
  LOCALIZATION_PREFERS_STRING_CATALOGS: "YES",
86
85
  ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS: "YES",
87
86
  };
@@ -116,7 +115,6 @@ function createActionConfigurationList({ name, displayName, cwd, bundleId, deplo
116
115
  }
117
116
  function createAppIntentConfigurationList({ name, displayName, cwd, bundleId, }) {
118
117
  const commonBuildSettings = {
119
- // @ts-expect-error
120
118
  ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS: "YES",
121
119
  CLANG_ANALYZER_NONNULL: "YES",
122
120
  CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: "YES_AGGRESSIVE",
@@ -262,11 +260,13 @@ function createIMessageConfigurationList({ name, displayName, cwd, bundleId, dep
262
260
  },
263
261
  };
264
262
  }
265
- function createWatchAppConfigurationList(project, { name, displayName, cwd, bundleId, deploymentTarget, currentProjectVersion, hasAccentColor, }) {
263
+ function createWatchAppConfigurationList(project, { name, displayName, cwd, bundleId, deploymentTarget, currentProjectVersion, hasAccentColor, icon, }) {
266
264
  const mainAppTarget = (0, target_1.getMainAppTarget)(project).getDefaultConfiguration();
267
265
  // NOTE: No base Info.plist needed.
268
266
  const common = {
269
- ASSETCATALOG_COMPILER_APPICON_NAME: "AppIcon",
267
+ // Only set AppIcon when an icon is provided, otherwise Xcode will fail
268
+ // to build because the asset catalog doesn't exist
269
+ ...(icon && { ASSETCATALOG_COMPILER_APPICON_NAME: "AppIcon" }),
270
270
  CLANG_ANALYZER_NONNULL: "YES",
271
271
  CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION: "YES_AGGRESSIVE",
272
272
  CLANG_CXX_LANGUAGE_STANDARD: "gnu++20",
@@ -14,14 +14,16 @@ const assert_1 = __importDefault(require("assert"));
14
14
  const configuration_list_1 = require("./configuration-list");
15
15
  const util_1 = require("./util");
16
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.
17
+ * Checks if a target is a watchOS extension (NOT a watch app) by inspecting
18
+ * its build settings and product type. This includes modern WidgetKit-based
19
+ * watch widgets which use app-extension product type with WATCHOS_DEPLOYMENT_TARGET.
20
20
  */
21
21
  function isWatchOSExtensionTarget(target) {
22
22
  const buildSettings = target.getDefaultConfiguration().props.buildSettings;
23
- return (buildSettings.SDKROOT === "watchos" ||
24
- "WATCHOS_DEPLOYMENT_TARGET" in buildSettings);
23
+ const isWatchOS = buildSettings.SDKROOT === "watchos" ||
24
+ "WATCHOS_DEPLOYMENT_TARGET" in buildSettings;
25
+ // Watch apps are detected by isWatchOSTarget() - extensions are watchOS but NOT watch apps
26
+ return isWatchOS && !target.isWatchOSTarget();
25
27
  }
26
28
  const withXcodeChanges = (config, props) => {
27
29
  return (0, with_bacons_xcode_1.withXcodeProjectBeta)(config, async (config) => {
@@ -204,11 +206,18 @@ async function applyXcodeChanges(config, project, props) {
204
206
  const productType = (0, target_1.productTypeForType)(props.type);
205
207
  const isExtension = productType === "com.apple.product-type.app-extension";
206
208
  const isExtensionKit = productType === "com.apple.product-type.extensionkit-extension";
209
+ const isApplication = productType === "com.apple.product-type.application";
210
+ // Determine the correct file type for the product reference
211
+ const explicitFileType = isExtensionKit
212
+ ? "wrapper.extensionkit-extension"
213
+ : isExtension
214
+ ? "wrapper.app-extension"
215
+ : isApplication
216
+ ? "wrapper.application"
217
+ : "wrapper.app-extension";
207
218
  const appExtensionBuildFile = xcode_1.PBXBuildFile.create(project, {
208
219
  fileRef: xcode_1.PBXFileReference.create(project, {
209
- explicitFileType: isExtensionKit
210
- ? "wrapper.extensionkit-extension"
211
- : "wrapper.app-extension",
220
+ explicitFileType: explicitFileType,
212
221
  includeInIndex: 0,
213
222
  path: props.name + (isExtension ? ".appex" : ".app"),
214
223
  sourceTree: "BUILT_PRODUCTS_DIR",
@@ -228,17 +237,14 @@ async function applyXcodeChanges(config, project, props) {
228
237
  productReference: appExtensionBuildFile.props.fileRef /* alphaExtension.appex */,
229
238
  productType: productType,
230
239
  });
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.
240
+ // For watchOS extensions (like watch-widget), embed in the watchOS app target
241
+ // instead of the main iOS app target.
235
242
  if (isWatchOSExtensionTarget(targetToUpdate)) {
236
243
  const watchTarget = project.rootObject.props.targets.find((t) => xcode_1.PBXNativeTarget.is(t) && t.isWatchOSTarget());
237
244
  if (watchTarget) {
238
- const { PBXCopyFilesBuildPhase, } = require("@bacons/xcode/build/api/PBXSourcesBuildPhase");
239
- const existingPhase = watchTarget.props.buildPhases.find((phase) => PBXCopyFilesBuildPhase.is(phase) &&
245
+ const existingPhase = watchTarget.props.buildPhases.find((phase) => xcode_1.PBXCopyFilesBuildPhase.is(phase) &&
240
246
  phase.props.name === "Embed Foundation Extensions");
241
- const embedPhase = existingPhase !== null && existingPhase !== void 0 ? existingPhase : watchTarget.createBuildPhase(PBXCopyFilesBuildPhase, {
247
+ const embedPhase = existingPhase !== null && existingPhase !== void 0 ? existingPhase : watchTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
242
248
  name: "Embed Foundation Extensions",
243
249
  dstSubfolderSpec: 13,
244
250
  dstPath: "",
@@ -257,6 +263,8 @@ async function applyXcodeChanges(config, project, props) {
257
263
  }
258
264
  }
259
265
  else {
266
+ // For watch apps, getCopyBuildPhaseForTarget returns "Embed Watch Content".
267
+ // For regular extensions, it returns "Embed Foundation Extensions".
260
268
  const copyPhase = mainAppTarget.getCopyBuildPhaseForTarget(targetToUpdate);
261
269
  if (!copyPhase.getBuildFile(appExtensionBuildFile.props.fileRef)) {
262
270
  copyPhase.props.files.push(appExtensionBuildFile);
@@ -272,6 +280,7 @@ async function applyXcodeChanges(config, project, props) {
272
280
  configureJsExport(targetToUpdate);
273
281
  // For watchOS extensions, the dependency belongs on the watchOS
274
282
  // app target so Xcode builds the extension before the watch app.
283
+ // For watch apps, the dependency belongs on the main iOS app.
275
284
  const dependencyParent = isWatchOSExtensionTarget(targetToUpdate)
276
285
  ? (_b = project.rootObject.props.targets.find((t) => xcode_1.PBXNativeTarget.is(t) && t.isWatchOSTarget())) !== null && _b !== void 0 ? _b : mainAppTarget
277
286
  : mainAppTarget;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bacons/apple-targets",
3
- "version": "4.0.3",
3
+ "version": "4.0.5",
4
4
  "description": "Generate Apple Targets with Expo Prebuild",
5
5
  "main": "build/ExtensionStorage.js",
6
6
  "types": "build/ExtensionStorage.d.ts",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "license": "MIT",
41
41
  "dependencies": {
42
- "@bacons/xcode": "1.0.0-alpha.27",
42
+ "@bacons/xcode": "1.0.0-alpha.31",
43
43
  "@react-native/normalize-colors": "^0.79.2",
44
44
  "glob": "^10.4.2",
45
45
  "debug": "^4.3.4"