Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use new expo config appleTeamId #242

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,18 +1 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
parserOptions: {
project: "tsconfig.json",
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
"@typescript-eslint/no-floating-promises": "error",
"no-extra-boolean-cast": "off"
}
};
module.exports = require('expo-module-scripts/eslintrc.base.js');
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ You can pass props to the plugin config object to configure:
| Plugin Prop | | |
|--------------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | **required** | Used to configure [APNs environment](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment) entitlement. `"development"` or `"production"` |
| `devTeam` | optional | Used to configure Apple Team ID. You can find your Apple Team ID by running `expo credentials:manager` e.g: `"91SW8A37CR"` |
| `iPhoneDeploymentTarget` | optional | Target `IPHONEOS_DEPLOYMENT_TARGET` value to be used when adding the iOS [NSE](https://documentation.onesignal.com/docs/service-extensions). A deployment target is nothing more than the minimum version of the operating system the application can run on. This value should match the value in your Podfile e.g: `"12.0"`. |
| `smallIcons` | optional | An array of local paths to small notification icons for Android. Image should be white, transparent, and 96x96 in size. Input images will be automatically scaled down and placed in the appropriate resource folders. e.g: `["./assets/ic_stat_onesignal_default.png"]`. See https://documentation.onesignal.com/docs/customize-notification-icons#small-notification-icons. |
| `largeIcons` | optional | An array of local paths to large notification icons for Android. Image should be white, transparent, and 256x256 in size. e.g: `["./assets/ic_onesignal_large_icon_default.png"]`. See https://documentation.onesignal.com/docs/customize-notification-icons#large-notification-icons. |
Expand Down
155 changes: 101 additions & 54 deletions onesignal/withOneSignalIos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ import {
withEntitlementsPlist,
withInfoPlist,
withXcodeProject,
withDangerousMod
withDangerousMod,
} from "@expo/config-plugins";
import * as fs from 'fs';
import * as path from 'path';
import * as fs from "fs";
import * as path from "path";
import {
DEFAULT_BUNDLE_SHORT_VERSION,
DEFAULT_BUNDLE_VERSION,
IPHONEOS_DEPLOYMENT_TARGET,
NSE_TARGET_NAME,
NSE_SOURCE_FILE,
NSE_EXT_FILES,
TARGETED_DEVICE_FAMILY
TARGETED_DEVICE_FAMILY,
} from "../support/iosConstants";
import { updatePodfile } from "../support/updatePodfile";
import NseUpdaterManager from "../support/NseUpdaterManager";
import { OneSignalLog } from "../support/OneSignalLog";
import { FileManager } from "../support/FileManager";
import { OneSignalPluginProps } from "../types/types";
import assert from 'assert';
import assert from "assert";
import getEasManagedCredentialsConfigExtra from "../support/eas/getEasManagedCredentialsConfigExtra";
import { ExpoConfig } from '@expo/config-types';
import { ExpoConfig } from "@expo/config-types";

/**
* Add 'aps-environment' record with current environment to '<project-name>.entitlements' file
Expand All @@ -43,8 +43,7 @@ const withAppEnvironment: ConfigPlugin<OneSignalPluginProps> = (
throw new Error(`
Missing required "mode" key in your app.json or app.config.js file for "onesignal-expo-plugin".
"mode" can be either "development" or "production".
Please see onesignal-expo-plugin's README.md for more details.`
)
Please see onesignal-expo-plugin's README.md for more details.`);
}
newConfig.modResults["aps-environment"] = onesignalProps.mode;
return newConfig;
Expand Down Expand Up @@ -81,12 +80,14 @@ const withAppGroupPermissions: ConfigPlugin<OneSignalPluginProps> = (
config
) => {
const APP_GROUP_KEY = "com.apple.security.application-groups";
return withEntitlementsPlist(config, newConfig => {
return withEntitlementsPlist(config, (newConfig) => {
if (!Array.isArray(newConfig.modResults[APP_GROUP_KEY])) {
newConfig.modResults[APP_GROUP_KEY] = [];
}
const modResultsArray = (newConfig.modResults[APP_GROUP_KEY] as Array<any>);
const entitlement = `group.${newConfig?.ios?.bundleIdentifier || ""}.onesignal`;
const modResultsArray = newConfig.modResults[APP_GROUP_KEY] as Array<any>;
const entitlement = `group.${
newConfig?.ios?.bundleIdentifier || ""
}.onesignal`;
if (modResultsArray.indexOf(entitlement) !== -1) {
return newConfig;
}
Expand All @@ -96,34 +97,47 @@ const withAppGroupPermissions: ConfigPlugin<OneSignalPluginProps> = (
});
};

const withEasManagedCredentials: ConfigPlugin<OneSignalPluginProps> = (config) => {
assert(config.ios?.bundleIdentifier, "Missing 'ios.bundleIdentifier' in app config.")
const withEasManagedCredentials: ConfigPlugin<OneSignalPluginProps> = (
config
) => {
assert(
config?.ios?.bundleIdentifier,
"Missing 'ios.bundleIdentifier' in app config."
);
config.extra = getEasManagedCredentialsConfigExtra(config as ExpoConfig);
return config;
}
};

const withOneSignalPodfile: ConfigPlugin<OneSignalPluginProps> = (config) => {
return withDangerousMod(config, [
'ios',
async config => {
"ios",
async (config) => {
// not awaiting in order to not block main thread
const iosRoot = path.join(config.modRequest.projectRoot, "ios")
updatePodfile(iosRoot).catch(err => { OneSignalLog.error(err) });
const iosRoot = path.join(config.modRequest.projectRoot, "ios");
updatePodfile(iosRoot).catch((err) => {
OneSignalLog.error(err);
});

return config;
},
]);
}
};

const withOneSignalNSE: ConfigPlugin<OneSignalPluginProps> = (config, props) => {
const withOneSignalNSE: ConfigPlugin<OneSignalPluginProps> = (
config,
props
) => {
// support for monorepos where node_modules can be above the project directory.
const pluginDir = require.resolve("onesignal-expo-plugin/package.json")
const sourceDir = path.join(pluginDir, "../build/support/serviceExtensionFiles/")
const pluginDir = require.resolve("onesignal-expo-plugin/package.json");
const sourceDir = path.join(
pluginDir,
"../build/support/serviceExtensionFiles/"
);

return withDangerousMod(config, [
'ios',
async config => {
const iosPath = path.join(config.modRequest.projectRoot, "ios")
"ios",
async (config) => {
const iosPath = path.join(config.modRequest.projectRoot, "ios");

/* COPY OVER EXTENSION FILES */
fs.mkdirSync(`${iosPath}/${NSE_TARGET_NAME}`, { recursive: true });
Expand All @@ -135,38 +149,58 @@ const withOneSignalNSE: ConfigPlugin<OneSignalPluginProps> = (config, props) =>
}

// Copy NSE source file either from configuration-provided location, falling back to the default one.
const sourcePath = props.iosNSEFilePath ?? `${sourceDir}${NSE_SOURCE_FILE}`
const sourcePath =
props.iosNSEFilePath ?? `${sourceDir}${NSE_SOURCE_FILE}`;
const targetFile = `${iosPath}/${NSE_TARGET_NAME}/${NSE_SOURCE_FILE}`;
await FileManager.copyFile(`${sourcePath}`, targetFile);

/* MODIFY COPIED EXTENSION FILES */
const nseUpdater = new NseUpdaterManager(iosPath);
await nseUpdater.updateNSEEntitlements(`group.${config.ios?.bundleIdentifier}.onesignal`)
await nseUpdater.updateNSEBundleVersion(config.ios?.buildNumber ?? DEFAULT_BUNDLE_VERSION);
await nseUpdater.updateNSEBundleShortVersion(config?.version ?? DEFAULT_BUNDLE_SHORT_VERSION);
await nseUpdater.updateNSEEntitlements(
`group.${config?.ios?.bundleIdentifier}.onesignal`
);
await nseUpdater.updateNSEBundleVersion(
config.ios?.buildNumber ?? DEFAULT_BUNDLE_VERSION
);
await nseUpdater.updateNSEBundleShortVersion(
config?.version ?? DEFAULT_BUNDLE_SHORT_VERSION
);

return config;
},
]);
}
};

const withOneSignalXcodeProject: ConfigPlugin<OneSignalPluginProps> = (config, props) => {
return withXcodeProject(config, newConfig => {
const xcodeProject = newConfig.modResults
const withOneSignalXcodeProject: ConfigPlugin<OneSignalPluginProps> = (
config,
props
) => {
return withXcodeProject(config, (newConfig) => {
const xcodeProject = newConfig.modResults;

if (!!xcodeProject.pbxTargetByName(NSE_TARGET_NAME)) {
OneSignalLog.log(`${NSE_TARGET_NAME} already exists in project. Skipping...`);
OneSignalLog.log(
`${NSE_TARGET_NAME} already exists in project. Skipping...`
);
return newConfig;
}

// Create new PBXGroup for the extension
const extGroup = xcodeProject.addPbxGroup([...NSE_EXT_FILES, NSE_SOURCE_FILE], NSE_TARGET_NAME, NSE_TARGET_NAME);
const extGroup = xcodeProject.addPbxGroup(
[...NSE_EXT_FILES, NSE_SOURCE_FILE],
NSE_TARGET_NAME,
NSE_TARGET_NAME
);

// Add the new PBXGroup to the top level group. This makes the
// files / folder appear in the file explorer in Xcode.
const groups = xcodeProject.hash.project.objects["PBXGroup"];
Object.keys(groups).forEach(function(key) {
if (typeof groups[key] === "object" && groups[key].name === undefined && groups[key].path === undefined) {
Object.keys(groups).forEach(function (key) {
if (
typeof groups[key] === "object" &&
groups[key].name === undefined &&
groups[key].path === undefined
) {
xcodeProject.addToPbxGroup(extGroup.uuid, key);
}
});
Expand All @@ -176,12 +210,19 @@ const withOneSignalXcodeProject: ConfigPlugin<OneSignalPluginProps> = (config, p
// An upstream fix should be made to the code referenced in this link:
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
const projObjects = xcodeProject.hash.project.objects;
projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {};
projObjects['PBXContainerItemProxy'] = projObjects['PBXTargetDependency'] || {};
projObjects["PBXTargetDependency"] =
projObjects["PBXTargetDependency"] || {};
projObjects["PBXContainerItemProxy"] =
projObjects["PBXTargetDependency"] || {};

// Add the NSE target
// This adds PBXTargetDependency and PBXContainerItemProxy for you
const nseTarget = xcodeProject.addTarget(NSE_TARGET_NAME, "app_extension", NSE_TARGET_NAME, `${config.ios?.bundleIdentifier}.${NSE_TARGET_NAME}`);
const nseTarget = xcodeProject.addTarget(
NSE_TARGET_NAME,
"app_extension",
NSE_TARGET_NAME,
`${config.ios?.bundleIdentifier}.${NSE_TARGET_NAME}`
);

// Add build phases to the new target
xcodeProject.addBuildPhase(
Expand All @@ -190,7 +231,12 @@ const withOneSignalXcodeProject: ConfigPlugin<OneSignalPluginProps> = (config, p
"Sources",
nseTarget.uuid
);
xcodeProject.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", nseTarget.uuid);
xcodeProject.addBuildPhase(
[],
"PBXResourcesBuildPhase",
"Resources",
nseTarget.uuid
);

xcodeProject.addBuildPhase(
[],
Expand All @@ -208,28 +254,29 @@ const withOneSignalXcodeProject: ConfigPlugin<OneSignalPluginProps> = (config, p
configurations[key].buildSettings.PRODUCT_NAME == `"${NSE_TARGET_NAME}"`
) {
const buildSettingsObj = configurations[key].buildSettings;
buildSettingsObj.DEVELOPMENT_TEAM = props?.devTeam;
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = props?.iPhoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
buildSettingsObj.DEVELOPMENT_TEAM = config?.ios?.appleTeamId;
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
props?.iPhoneDeploymentTarget ?? IPHONEOS_DEPLOYMENT_TARGET;
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${NSE_TARGET_NAME}/${NSE_TARGET_NAME}.entitlements`;
buildSettingsObj.CODE_SIGN_STYLE = "Automatic";
buildSettingsObj.CODE_SIGN_STYLE = "Manual";
}
}

// Add development teams to both your target and the original project
xcodeProject.addTargetAttribute("DevelopmentTeam", props?.devTeam, nseTarget);
xcodeProject.addTargetAttribute("DevelopmentTeam", props?.devTeam);
return newConfig;
})
}
});
};

export const withOneSignalIos: ConfigPlugin<OneSignalPluginProps> = (config, props) => {
export const withOneSignalIos: ConfigPlugin<OneSignalPluginProps> = (
config,
props
) => {
config = withAppEnvironment(config, props);
config = withRemoteNotificationsPermissions(config, props);
config = withAppGroupPermissions(config, props);
config = withOneSignalPodfile(config, props)
config = withOneSignalNSE(config, props)
config = withOneSignalXcodeProject(config, props)
config = withOneSignalPodfile(config, props);
config = withOneSignalNSE(config, props);
config = withOneSignalXcodeProject(config, props);
config = withEasManagedCredentials(config, props);
return config;
};
};
16 changes: 5 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
{
"name": "onesignal-expo-plugin",
"name": "@pierrecapo/onesignal-expo-plugin",
"version": "2.0.3",
"description": "The OneSignal Expo plugin allows you to use OneSignal without leaving the managed workflow. Developed in collaboration with SweetGreen.",
"main": "./app.plugin.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "yarn run lint && rm -rf build && tsc && cp -a support/serviceExtensionFiles build/support/",
"lint": "eslint . --ext .ts",
"prepare": "yarn run build"
"build": "expo-module build && cp -a support/serviceExtensionFiles build/support/"
},
"repository": {
"type": "git",
Expand All @@ -34,14 +32,10 @@
},
"homepage": "https://github.com/OneSignal/onesignal-expo-plugin#readme",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.10.1",
"@typescript-eslint/parser": "^5.10.1",
"eslint": "^8.8.0",
"expo-module-scripts": "^2.0.0",
"readme-md-generator": "^1.0.0",
"typescript": "^4.5.5"
"expo-module-scripts": "^4.0.3"
},
"dependencies": {
"@expo/image-utils": "^0.3.22"
"@expo/image-utils": "^0.3.22",
"@expo/config-plugins": "^9.0.12"
}
}
4 changes: 0 additions & 4 deletions support/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ export function validatePluginProps(props: any): void {
throw new Error("OneSignal Expo Plugin: 'mode' must be a string.");
}

if (props.devTeam && typeof props.devTeam !== "string") {
throw new Error("OneSignal Expo Plugin: 'devTeam' must be a string.");
}

if (props.iPhoneDeploymentTarget && typeof props.iPhoneDeploymentTarget !== "string") {
throw new Error("OneSignal Expo Plugin: 'iPhoneDeploymentTarget' must be a string.");
}
Expand Down
Loading