@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 +21 -19
- package/build/target.d.ts +2 -2
- package/build/target.js +9 -0
- package/build/withXcodeChanges.js +86 -9
- package/package.json +2 -2
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
|
|
246
|
-
|
|
|
247
|
-
| action
|
|
248
|
-
|
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
|
254
|
-
| notification-
|
|
255
|
-
|
|
|
256
|
-
| intent
|
|
257
|
-
|
|
|
258
|
-
|
|
|
259
|
-
|
|
|
260
|
-
|
|
|
261
|
-
|
|
|
262
|
-
|
|
|
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:
|
|
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:
|
|
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 =
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
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.
|
|
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.
|
|
33
|
+
"@bacons/xcode": "^1.0.0-alpha.22",
|
|
34
34
|
"fs-extra": "^11.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|