@bacons/apple-targets 0.1.0 → 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
@@ -36,7 +36,7 @@ You can change the root directory from `./targets` to something else with `root:
36
36
 
37
37
  ## Using React Native in Targets
38
38
 
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.
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.
40
40
 
41
41
  ## `expo-target.config.json`
42
42
 
@@ -242,24 +242,26 @@ module.exports = {
242
242
 
243
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.
244
244
 
245
- | Type | Description |
246
- | -------------------- | ---------------------------------- |
247
- | action | Share Action |
248
- | widget | Widget / Live Activity |
249
- | watch | Watch App (with companion iOS App) |
250
- | clip | App Clip |
251
- | safari | Safari Extension |
252
- | share | Share Extension |
253
- | notification-content | Notification Content Extension |
254
- | notification-service | Notification Service Extension |
255
- | intent | Siri Intent Extension |
256
- | intent-ui | Siri Intent UI Extension |
257
- | spotlight | Spotlight Index Extension |
258
- | bg-download | Background Download Extension |
259
- | quicklook-thumbnail | Quick Look Thumbnail Extension |
260
- | location-push | Location Push Service Extension |
261
- | credentials-provider | Credentials Provider Extension |
262
- | 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 |
263
265
 
264
266
  <!-- | imessage | iMessage Extension | -->
265
267
 
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"
@@ -121,6 +121,68 @@ extensionType, { name, cwd, bundleId, deploymentTarget, currentProjectVersion, i
121
121
  });
122
122
  return configurationList;
123
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
+ }
124
186
  function createShareConfigurationList(project, { name, cwd, bundleId, deploymentTarget, currentProjectVersion, }) {
125
187
  const common = {
126
188
  CLANG_ANALYZER_NONNULL: "YES",
@@ -563,6 +625,9 @@ function createConfigurationListForType(project, props) {
563
625
  else if (props.type === "watch") {
564
626
  return createWatchAppConfigurationList(project, props);
565
627
  }
628
+ else if (props.type === "app-intent") {
629
+ return createAppIntentConfigurationList(project, props);
630
+ }
566
631
  else {
567
632
  // TODO: More
568
633
  return createNotificationContentConfigurationList(project, props);
@@ -722,11 +787,16 @@ async function applyXcodeChanges(config, project, props) {
722
787
  syncMarketingVersions();
723
788
  return project;
724
789
  }
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";
725
793
  const appExtensionBuildFile = xcode_1.PBXBuildFile.create(project, {
726
794
  fileRef: xcode_1.PBXFileReference.create(project, {
727
- explicitFileType: "wrapper.app-extension",
795
+ explicitFileType: isExtensionKit
796
+ ? "wrapper.extensionkit-extension"
797
+ : "wrapper.app-extension",
728
798
  includeInIndex: 0,
729
- path: productName + ".appex",
799
+ path: productName + (isExtension ? ".appex" : ".app"),
730
800
  sourceTree: "BUILT_PRODUCTS_DIR",
731
801
  }),
732
802
  settings: {
@@ -742,7 +812,7 @@ async function applyXcodeChanges(config, project, props) {
742
812
  productName,
743
813
  // @ts-expect-error
744
814
  productReference: appExtensionBuildFile.props.fileRef /* alphaExtension.appex */,
745
- productType: (0, target_1.productTypeForType)(props.type),
815
+ productType: productType,
746
816
  });
747
817
  configureTargetWithKnownSettings(extensionTarget);
748
818
  configureTargetWithEntitlements(extensionTarget);
@@ -763,11 +833,18 @@ async function applyXcodeChanges(config, project, props) {
763
833
  });
764
834
  // Add the target dependency to the main app, should be only one.
765
835
  mainAppTarget.props.dependencies.push(targetDependency);
766
- const WELL_KNOWN_COPY_EXTENSIONS_NAME = props.type === "clip"
767
- ? "Embed App Clips"
768
- : props.type === "watch"
769
- ? "Embed Watch Content"
770
- : "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
+ })();
771
848
  // Could exist from a Share Extension
772
849
  const copyFilesBuildPhase = mainAppTarget.props.buildPhases.find((phase) => {
773
850
  if (xcode_1.PBXCopyFilesBuildPhase.is(phase)) {
@@ -791,7 +868,7 @@ async function applyXcodeChanges(config, project, props) {
791
868
  "Info.plist",
792
869
  // Exclude the config path
793
870
  path_1.default.relative(magicCwd, props.configPath),
794
- ],
871
+ ].sort(),
795
872
  });
796
873
  const assetsDir = path_1.default.join(magicCwd, "assets");
797
874
  // TODO: Maybe just limit this to Safari extensions?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bacons/apple-targets",
3
- "version": "0.1.0",
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.21",
33
+ "@bacons/xcode": "^1.0.0-alpha.22",
34
34
  "fs-extra": "^11.2.0"
35
35
  },
36
36
  "devDependencies": {