@mattnucc/apple-targets
Version:
Generate Apple Targets with Expo Prebuild
431 lines (430 loc) • 18.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWatchAppTarget = exports.getAuxiliaryTargets = exports.getMainAppTarget = exports.isNativeTargetOfType = exports.getFrameworksForType = exports.needsEmbeddedSwift = exports.productTypeForType = exports.getTargetInfoPlistForType = exports.SHOULD_USE_APP_GROUPS_BY_DEFAULT = exports.KNOWN_EXTENSION_POINT_IDENTIFIERS = void 0;
exports.KNOWN_EXTENSION_POINT_IDENTIFIERS = {
"com.apple.message-payload-provider": "imessage",
"com.apple.widgetkit-extension": "widget",
"com.apple.usernotifications.content-extension": "notification-content",
"com.apple.share-services": "share",
"com.apple.usernotifications.service": "notification-service",
"com.apple.spotlight.import": "spotlight",
"com.apple.intents-service": "intent",
"com.apple.intents-ui-service": "intent-ui",
"com.apple.Safari.web-extension": "safari",
"com.apple.background-asset-downloader-extension": "bg-download",
"com.apple.matter.support.extension.device-setup": "matter",
"com.apple.quicklook.thumbnail": "quicklook-thumbnail",
"com.apple.location.push.service": "location-push",
"com.apple.authentication-services-credential-provider-ui": "credentials-provider",
"com.apple.authentication-services-account-authentication-modification-ui": "account-auth",
"com.apple.services": "action",
"com.apple.appintents-extension": "app-intent",
"com.apple.deviceactivity.monitor-extension": "device-activity-monitor",
// "com.apple.intents-service": "intents",
"com.apple.networkextension.packet-tunnel": "network-packet-tunnel",
"com.apple.networkextension.app-proxy": "network-app-proxy",
"com.apple.networkextension.dns-proxy": "network-dns-proxy",
"com.apple.networkextension.filter-data": "network-filter-data",
"com.apple.keyboard-service": "keyboard",
// "com.apple.intents-service": "intents",
};
// An exhaustive list of extension types that should sync app groups from the main target by default when
// no app groups are specified.
exports.SHOULD_USE_APP_GROUPS_BY_DEFAULT = {
share: true,
"bg-download": true,
clip: true,
widget: true,
"watch-widget": true,
keyboard: true,
"account-auth": false,
"credentials-provider": false,
"device-activity-monitor": false,
"app-intent": false,
"intent-ui": false,
"location-push": false,
"notification-content": false,
"notification-service": false,
"quicklook-thumbnail": false,
action: false,
imessage: false,
intent: false,
matter: false,
safari: false,
spotlight: false,
watch: false,
"network-packet-tunnel": false,
"network-app-proxy": false,
"network-dns-proxy": false,
"network-filter-data": false,
};
// TODO: Maybe we can replace `NSExtensionPrincipalClass` with the `@main` annotation that newer extensions use?
function getTargetInfoPlistForType(type) {
// TODO: Use exhaustive switch to ensure external contributors don't forget to add this.
const NSExtensionPointIdentifier = Object.keys(exports.KNOWN_EXTENSION_POINT_IDENTIFIERS).find((key) => exports.KNOWN_EXTENSION_POINT_IDENTIFIERS[key] === type);
switch (type) {
case "watch":
return {};
case "action":
return {
NSExtension: {
NSExtensionAttributes: {
NSExtensionActivationRule: {
NSExtensionActivationSupportsFileWithMaxCount: 0,
NSExtensionActivationSupportsImageWithMaxCount: 0,
NSExtensionActivationSupportsMovieWithMaxCount: 0,
NSExtensionActivationSupportsText: false,
NSExtensionActivationSupportsWebURLWithMaxCount: 1,
},
NSExtensionJavaScriptPreprocessingFile: "assets/index",
NSExtensionServiceAllowsFinderPreviewItem: true,
NSExtensionServiceAllowsTouchBarItem: true,
NSExtensionServiceFinderPreviewIconName: "NSActionTemplate",
NSExtensionServiceTouchBarBezelColorName: "TouchBarBezel",
NSExtensionServiceTouchBarIconName: "NSActionTemplate",
},
NSExtensionPointIdentifier: "com.apple.services",
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).ActionRequestHandler",
},
};
case "app-intent":
return {
EXAppExtensionAttributes: {
EXExtensionPointIdentifier: "com.apple.appintents-extension",
},
};
case "clip":
return {
CFBundleName: "$(PRODUCT_NAME)",
CFBundleIdentifier: "$(PRODUCT_BUNDLE_IDENTIFIER)",
CFBundleVersion: "$(CURRENT_PROJECT_VERSION)",
CFBundleExecutable: "$(EXECUTABLE_NAME)",
CFBundlePackageType: "$(PRODUCT_BUNDLE_PACKAGE_TYPE)",
CFBundleShortVersionString: "$(MARKETING_VERSION)",
UIApplicationSupportsIndirectInputEvents: true,
NSAppClip: {
NSAppClipRequestEphemeralUserNotification: false,
NSAppClipRequestLocationConfirmation: false,
},
NSAppTransportSecurity: {
NSAllowsArbitraryLoads: false,
NSAllowsLocalNetworking: true,
},
UILaunchStoryboardName: "SplashScreen",
UIUserInterfaceStyle: "Automatic",
UIViewControllerBasedStatusBarAppearance: false,
};
case "imessage":
return {
NSExtension: {
NSExtensionPointIdentifier,
// This is hardcoded as there is no Swift code in the imessage extension.
NSExtensionPrincipalClass: "StickerBrowserViewController",
},
};
case "account-auth":
return {
NSExtension: {
NSExtensionPointIdentifier,
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).AccountAuthViewController",
NSExtensionAttributes: {
ASAccountAuthenticationModificationSupportsStrongPasswordChange: true,
ASAccountAuthenticationModificationSupportsUpgradeToSignInWithApple: true,
},
},
};
case "credentials-provider":
return {
NSExtension: {
NSExtensionPointIdentifier,
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).CredentialProviderViewController",
},
};
case "keyboard":
return {
NSExtension: {
NSExtensionPointIdentifier,
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).KeyboardViewController",
NSExtensionAttributes: {
RequestsOpenAccess: false,
IsASCIICapable: false,
PrefersRightToLeft: false,
PrimaryLanguage: "en-US",
},
},
};
case "notification-service":
return {
NSExtension: {
NSExtensionAttributes: {
NSExtensionActivationRule: "TRUEPREDICATE",
},
// TODO: Update `NotificationService` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).NotificationService",
// NSExtensionMainStoryboard: 'MainInterface',
NSExtensionPointIdentifier,
},
};
case "quicklook-thumbnail":
return {
NSExtension: {
NSExtensionAttributes: {
QLSupportedContentTypes: [],
QLThumbnailMinimumDimension: 0,
},
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).ThumbnailProvider",
NSExtensionPointIdentifier,
},
};
case "spotlight":
return {
CSExtensionLabel: "myImporter",
NSExtension: {
NSExtensionAttributes: {
CSSupportedContentTypes: ["com.example.plain-text"],
},
// TODO: Update `ImportExtension` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).ImportExtension",
// NSExtensionMainStoryboard: 'MainInterface',
NSExtensionPointIdentifier,
},
};
case "share":
return {
NSExtension: {
NSExtensionAttributes: {
NSExtensionActivationRule: "TRUEPREDICATE",
},
// TODO: Update `ShareViewController` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).ShareViewController",
// NSExtensionMainStoryboard: 'MainInterface',
NSExtensionPointIdentifier,
},
};
case "intent-ui":
return {
NSExtension: {
NSExtensionAttributes: {
IntentsSupported: ["INSendMessageIntent"],
},
// TODO: Update `IntentViewController` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).IntentViewController",
NSExtensionPointIdentifier,
},
};
case "intent":
return {
NSExtension: {
NSExtensionAttributes: {
IntentsRestrictedWhileLocked: [],
IntentsSupported: [
"INSendMessageIntent",
"INSearchForMessagesIntent",
"INSetMessageAttributeIntent",
],
},
// TODO: Update `IntentHandler` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).IntentHandler",
NSExtensionPointIdentifier,
},
};
case "matter":
return {
NSExtension: {
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).RequestHandler",
NSExtensionPointIdentifier,
},
};
case "location-push":
return {
NSExtension: {
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).LocationPushService",
NSExtensionPointIdentifier,
},
};
case "safari":
return {
NSExtension: {
// TODO: Update `SafariWebExtensionHandler` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler",
// NSExtensionMainStoryboard: 'MainInterface',
NSExtensionPointIdentifier,
},
};
case "notification-content":
return {
NSExtension: {
NSExtensionAttributes: {
UNNotificationExtensionCategory: "myNotificationCategory",
UNNotificationExtensionInitialContentSizeRatio: 1,
},
// TODO: Update `NotificationViewController` dynamically
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).NotificationViewController",
// NSExtensionMainStoryboard: 'MainInterface',
NSExtensionPointIdentifier,
},
};
case "network-packet-tunnel":
return {
NSExtension: {
NSExtensionPointIdentifier: "com.apple.networkextension.packet-tunnel",
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).PacketTunnelProvider",
},
};
case "network-app-proxy":
return {
NSExtension: {
NSExtensionPointIdentifier: "com.apple.networkextension.app-proxy",
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).AppProxyProvider",
},
};
case "network-dns-proxy":
return {
NSExtension: {
NSExtensionPointIdentifier: "com.apple.networkextension.dns-proxy",
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).DNSProxyProvider",
},
};
case "network-filter-data":
return {
NSExtension: {
NSExtensionPointIdentifier: "com.apple.networkextension.filter-data",
NSExtensionPrincipalClass: "$(PRODUCT_MODULE_NAME).FilterDataProvider",
},
};
default:
// Default: used for widget and bg-download
return {
NSExtension: {
NSExtensionPointIdentifier,
},
};
}
}
exports.getTargetInfoPlistForType = getTargetInfoPlistForType;
function productTypeForType(type) {
switch (type) {
case "clip":
return "com.apple.product-type.application.on-demand-install-capable";
case "watch":
return "com.apple.product-type.application";
case "app-intent":
return "com.apple.product-type.extensionkit-extension";
default:
return "com.apple.product-type.app-extension";
}
}
exports.productTypeForType = productTypeForType;
function needsEmbeddedSwift(type) {
return [
"watch",
"watch-widget",
"spotlight",
"share",
"intent",
"intent-ui",
"bg-download",
"quicklook-thumbnail",
"matter",
"clip",
"network-packet-tunnel",
"network-app-proxy",
"network-dns-proxy",
"network-filter-data",
"keyboard",
].includes(type);
}
exports.needsEmbeddedSwift = needsEmbeddedSwift;
function getFrameworksForType(type) {
switch (type) {
case "widget":
return [
// CD07060B2A2EBE2E009C1192 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
"WidgetKit",
// CD07060D2A2EBE2E009C1192 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
"SwiftUI",
"ActivityKit",
"AppIntents",
];
case "watch-widget":
return ["AppIntents", "WidgetKit", "SwiftUI"];
case "intent":
return ["Intents"];
case "intent-ui":
return ["IntentsUI"];
case "quicklook-thumbnail":
return ["QuickLookThumbnailing"];
case "notification-content":
return ["UserNotifications", "UserNotificationsUI"];
case "app-intent":
return ["AppIntents"];
case "device-activity-monitor":
return ["DeviceActivity"];
case "action":
return [
// "UniformTypeIdentifiers"
];
case "network-packet-tunnel":
case "network-app-proxy":
case "network-dns-proxy":
case "network-filter-data":
return ["NetworkExtension"];
default:
return [];
}
}
exports.getFrameworksForType = getFrameworksForType;
function isNativeTargetOfType(target, type) {
var _a;
if (type === "watch" &&
target.props.productType === "com.apple.product-type.application") {
return ("WATCHOS_DEPLOYMENT_TARGET" in
target.getDefaultConfiguration().props.buildSettings);
}
if ((type === "watch-widget" || type === "widget") &&
target.props.productType === "com.apple.product-type.app-extension") {
return ("WATCHOS_DEPLOYMENT_TARGET" in
target.getDefaultConfiguration().props.buildSettings) && type === "watch-widget";
}
if (type === "clip" &&
target.props.productType ===
"com.apple.product-type.application.on-demand-install-capable") {
return true;
}
if (target.props.productType !== "com.apple.product-type.app-extension") {
return false;
}
// Could be a Today Extension, Share Extension, etc.
const infoPlist = target.getDefaultConfiguration().getInfoPlist();
if (!((_a = infoPlist.NSExtension) === null || _a === void 0 ? void 0 : _a.NSExtensionPointIdentifier)) {
console.error("No NSExtensionPointIdentifier found in extension Info.plist for target: " +
target.getDisplayName());
return false;
}
const identifier = infoPlist.NSExtension.NSExtensionPointIdentifier;
const mappedType = exports.KNOWN_EXTENSION_POINT_IDENTIFIERS[identifier];
return mappedType === type;
}
exports.isNativeTargetOfType = isNativeTargetOfType;
function getMainAppTarget(project) {
const target = project.rootObject.getMainAppTarget("ios");
if (!target) {
throw new Error("No main app target found");
}
return target;
}
exports.getMainAppTarget = getMainAppTarget;
function getAuxiliaryTargets(project) {
const mainTarget = project.rootObject.getMainAppTarget("ios");
return project.rootObject.props.targets.filter((target) => {
return target.uuid !== (mainTarget === null || mainTarget === void 0 ? void 0 : mainTarget.uuid);
});
}
exports.getAuxiliaryTargets = getAuxiliaryTargets;
function getWatchAppTarget(project) {
return getAuxiliaryTargets(project).find((target) => {
return target.props.productType === "com.apple.product-type.application" &&
"WATCHOS_DEPLOYMENT_TARGET" in target.getDefaultConfiguration().props.buildSettings;
});
}
exports.getWatchAppTarget = getWatchAppTarget;