onesignal-expo-plugin
Advanced tools
Comparing version 1.0.0-beta7 to 1.0.0-beta8
@@ -6,5 +6,13 @@ "use strict"; | ||
*/ | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.withOneSignalIos = void 0; | ||
exports.xcodeProjectAddNse = exports.withOneSignalIos = void 0; | ||
const config_plugins_1 = require("@expo/config-plugins"); | ||
const fs_1 = __importDefault(require("fs")); | ||
const xcode_1 = __importDefault(require("xcode")); | ||
const iosConstants_1 = require("../support/iosConstants"); | ||
const updatePodfile_1 = require("../support/updatePodfile"); | ||
const updateNSEEntitlements_1 = require("../support/updateNSEEntitlements"); | ||
// ---------- ---------- ---------- ---------- | ||
@@ -15,5 +23,11 @@ /** | ||
*/ | ||
const withAppEnvironment = (config, { mode }) => { | ||
const withAppEnvironment = (config, onesignalProps) => { | ||
return (0, config_plugins_1.withEntitlementsPlist)(config, (newConfig) => { | ||
newConfig.modResults["aps-environment"] = mode; | ||
if ((onesignalProps === null || onesignalProps === void 0 ? void 0 : onesignalProps.mode) == null) { | ||
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.`); | ||
} | ||
newConfig.modResults["aps-environment"] = onesignalProps.mode; | ||
return newConfig; | ||
@@ -55,2 +69,9 @@ }); | ||
}; | ||
const withOneSignalNSE = (config, onesignalProps) => { | ||
return (0, config_plugins_1.withXcodeProject)(config, async (props) => { | ||
var _a; | ||
xcodeProjectAddNse(props.modRequest.projectName || "", props.modRequest.platformProjectRoot, ((_a = props.ios) === null || _a === void 0 ? void 0 : _a.bundleIdentifier) || "", onesignalProps === null || onesignalProps === void 0 ? void 0 : onesignalProps.devTeam, "node_modules/onesignal-expo-plugin/build/support/serviceExtensionFiles/"); | ||
return props; | ||
}); | ||
}; | ||
// ---------- ---------- ---------- ---------- | ||
@@ -61,4 +82,82 @@ const withOneSignalIos = (config, props) => { | ||
withAppGroupPermissions(config, props); | ||
withOneSignalNSE(config, props); | ||
return config; | ||
}; | ||
exports.withOneSignalIos = withOneSignalIos; | ||
function xcodeProjectAddNse(appName, iosPath, bundleIdentifier, devTeam, sourceDir) { | ||
(0, updatePodfile_1.updatePodfile)(iosPath); | ||
(0, updateNSEEntitlements_1.updateNSEEntitlements)(`group.${bundleIdentifier}.onesignal`); | ||
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`; | ||
const targetName = "OneSignalNotificationServiceExtension"; | ||
const extFiles = [ | ||
"NotificationService.h", | ||
"NotificationService.m", | ||
`${targetName}.entitlements`, | ||
`${targetName}-Info.plist` | ||
]; | ||
const xcodeProject = xcode_1.default.project(projPath); | ||
xcodeProject.parse(function (err) { | ||
if (err) { | ||
console.log(`Error parsing iOS project: ${JSON.stringify(err)}`); | ||
return; | ||
} | ||
// Copy in the extension files | ||
fs_1.default.mkdirSync(`${iosPath}/${targetName}`, { recursive: true }); | ||
extFiles.forEach(function (extFile) { | ||
let targetFile = `${iosPath}/${targetName}/${extFile}`; | ||
try { | ||
fs_1.default.createReadStream(`${sourceDir}${extFile}`).pipe(fs_1.default.createWriteStream(targetFile)); | ||
} | ||
catch (err) { | ||
console.log(err); | ||
} | ||
}); | ||
const projObjects = xcodeProject.hash.project.objects; | ||
// Create new PBXGroup for the extension | ||
let extGroup = xcodeProject.addPbxGroup(extFiles, targetName, targetName); | ||
// Add the new PBXGroup to the top level group. This makes the | ||
// files / folder appear in the file explorer in Xcode. | ||
let groups = xcodeProject.hash.project.objects["PBXGroup"]; | ||
Object.keys(groups).forEach(function (key) { | ||
if (groups[key].name === undefined) { | ||
xcodeProject.addToPbxGroup(extGroup.uuid, key); | ||
} | ||
}); | ||
// WORK AROUND for codeProject.addTarget BUG | ||
// Xcode projects don't contain these if there is only one target | ||
// 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 | ||
projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {}; | ||
projObjects['PBXContainerItemProxy'] = projObjects['PBXTargetDependency'] || {}; | ||
if (!!xcodeProject.pbxTargetByName(targetName)) { | ||
console.log(targetName, "already exists in project. Skipping..."); | ||
return; | ||
} | ||
// Add the NSE target | ||
// This adds PBXTargetDependency and PBXContainerItemProxy for you | ||
const nseTarget = xcodeProject.addTarget(targetName, "app_extension", targetName, `${bundleIdentifier}.${targetName}`); | ||
// Add build phases to the new target | ||
xcodeProject.addBuildPhase(["NotificationService.m"], "PBXSourcesBuildPhase", "Sources", nseTarget.uuid); | ||
xcodeProject.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", nseTarget.uuid); | ||
xcodeProject.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", nseTarget.uuid); | ||
// Edit the Deployment info of the new Target, only IphoneOS and Targeted Device Family | ||
// However, can be more | ||
let configurations = xcodeProject.pbxXCBuildConfigurationSection(); | ||
for (let key in configurations) { | ||
if (typeof configurations[key].buildSettings !== "undefined" && | ||
configurations[key].buildSettings.PRODUCT_NAME == `"${targetName}"`) { | ||
let buildSettingsObj = configurations[key].buildSettings; | ||
buildSettingsObj.DEVELOPMENT_TEAM = devTeam; | ||
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = iosConstants_1.IPHONEOS_DEPLOYMENT_TARGET; | ||
buildSettingsObj.TARGETED_DEVICE_FAMILY = iosConstants_1.TARGETED_DEVICE_FAMILY; | ||
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${targetName}/${targetName}.entitlements`; | ||
buildSettingsObj.CODE_SIGN_STYLE = "Automatic"; | ||
} | ||
} | ||
// Add development teams to both your target and the original project | ||
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam, nseTarget); | ||
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam); | ||
fs_1.default.writeFileSync(projPath, xcodeProject.writeSync()); | ||
}); | ||
} | ||
exports.xcodeProjectAddNse = xcodeProjectAddNse; |
@@ -16,2 +16,3 @@ /** | ||
iOsBundleIdentifier: string; | ||
devTeam: string; | ||
}; | ||
@@ -18,0 +19,0 @@ |
@@ -10,4 +10,10 @@ /** | ||
withInfoPlist, | ||
withXcodeProject, | ||
} from "@expo/config-plugins"; | ||
import { OneSignalPluginProps } from "./withOneSignal"; | ||
import fs from 'fs'; | ||
import xcode from 'xcode'; | ||
import { IPHONEOS_DEPLOYMENT_TARGET, TARGETED_DEVICE_FAMILY } from "../support/iosConstants"; | ||
import { updatePodfile } from "../support/updatePodfile"; | ||
import { updateNSEEntitlements } from "../support/updateNSEEntitlements"; | ||
@@ -22,6 +28,13 @@ // ---------- ---------- ---------- ---------- | ||
config, | ||
{ mode } | ||
onesignalProps | ||
) => { | ||
return withEntitlementsPlist(config, (newConfig) => { | ||
newConfig.modResults["aps-environment"] = mode; | ||
if (onesignalProps?.mode == null) { | ||
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.` | ||
) | ||
} | ||
newConfig.modResults["aps-environment"] = onesignalProps.mode; | ||
return newConfig; | ||
@@ -73,2 +86,16 @@ }); | ||
const withOneSignalNSE: ConfigPlugin<OneSignalPluginProps> = (config, onesignalProps) => { | ||
return withXcodeProject(config, async props => { | ||
xcodeProjectAddNse( | ||
props.modRequest.projectName || "", | ||
props.modRequest.platformProjectRoot, | ||
props.ios?.bundleIdentifier || "", | ||
onesignalProps?.devTeam, | ||
"node_modules/onesignal-expo-plugin/build/support/serviceExtensionFiles/" | ||
); | ||
return props; | ||
}); | ||
} | ||
// ---------- ---------- ---------- ---------- | ||
@@ -82,4 +109,118 @@ export const withOneSignalIos: ConfigPlugin<OneSignalPluginProps> = ( | ||
withAppGroupPermissions(config, props); | ||
withOneSignalNSE(config, props); | ||
return config; | ||
}; | ||
export function xcodeProjectAddNse( | ||
appName: string, | ||
iosPath: string, | ||
bundleIdentifier: string, | ||
devTeam: string | undefined, | ||
sourceDir: string | ||
): void { | ||
updatePodfile(iosPath); | ||
updateNSEEntitlements(`group.${bundleIdentifier}.onesignal`) | ||
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`; | ||
const targetName = "OneSignalNotificationServiceExtension"; | ||
const extFiles = [ | ||
"NotificationService.h", | ||
"NotificationService.m", | ||
`${targetName}.entitlements`, | ||
`${targetName}-Info.plist` | ||
]; | ||
const xcodeProject = xcode.project(projPath); | ||
xcodeProject.parse(function(err: Error) { | ||
if (err) { | ||
console.log(`Error parsing iOS project: ${JSON.stringify(err)}`); | ||
return; | ||
} | ||
// Copy in the extension files | ||
fs.mkdirSync(`${iosPath}/${targetName}`, { recursive: true }); | ||
extFiles.forEach(function (extFile) { | ||
let targetFile = `${iosPath}/${targetName}/${extFile}`; | ||
try { | ||
fs.createReadStream(`${sourceDir}${extFile}`).pipe( | ||
fs.createWriteStream(targetFile) | ||
); | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
}); | ||
const projObjects = xcodeProject.hash.project.objects; | ||
// Create new PBXGroup for the extension | ||
let extGroup = xcodeProject.addPbxGroup(extFiles, targetName, targetName); | ||
// Add the new PBXGroup to the top level group. This makes the | ||
// files / folder appear in the file explorer in Xcode. | ||
let groups = xcodeProject.hash.project.objects["PBXGroup"]; | ||
Object.keys(groups).forEach(function (key) { | ||
if (groups[key].name === undefined) { | ||
xcodeProject.addToPbxGroup(extGroup.uuid, key); | ||
} | ||
}); | ||
// WORK AROUND for codeProject.addTarget BUG | ||
// Xcode projects don't contain these if there is only one target | ||
// 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 | ||
projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {}; | ||
projObjects['PBXContainerItemProxy'] = projObjects['PBXTargetDependency'] || {}; | ||
if (!!xcodeProject.pbxTargetByName(targetName)) { | ||
console.log(targetName, "already exists in project. Skipping..."); | ||
return; | ||
} | ||
// Add the NSE target | ||
// This adds PBXTargetDependency and PBXContainerItemProxy for you | ||
const nseTarget = xcodeProject.addTarget(targetName, "app_extension", targetName, `${bundleIdentifier}.${targetName}`); | ||
// Add build phases to the new target | ||
xcodeProject.addBuildPhase( | ||
["NotificationService.m"], | ||
"PBXSourcesBuildPhase", | ||
"Sources", | ||
nseTarget.uuid | ||
); | ||
xcodeProject.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", nseTarget.uuid); | ||
xcodeProject.addBuildPhase( | ||
[], | ||
"PBXFrameworksBuildPhase", | ||
"Frameworks", | ||
nseTarget.uuid | ||
); | ||
// Edit the Deployment info of the new Target, only IphoneOS and Targeted Device Family | ||
// However, can be more | ||
let configurations = xcodeProject.pbxXCBuildConfigurationSection(); | ||
for (let key in configurations) { | ||
if ( | ||
typeof configurations[key].buildSettings !== "undefined" && | ||
configurations[key].buildSettings.PRODUCT_NAME == `"${targetName}"` | ||
) { | ||
let buildSettingsObj = configurations[key].buildSettings; | ||
buildSettingsObj.DEVELOPMENT_TEAM = devTeam; | ||
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = IPHONEOS_DEPLOYMENT_TARGET; | ||
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY; | ||
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${targetName}/${targetName}.entitlements`; | ||
buildSettingsObj.CODE_SIGN_STYLE = "Automatic"; | ||
} | ||
} | ||
// Add development teams to both your target and the original project | ||
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam, nseTarget); | ||
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam); | ||
fs.writeFileSync(projPath, xcodeProject.writeSync()); | ||
}) | ||
} |
{ | ||
"name": "onesignal-expo-plugin", | ||
"version": "1.0.0-beta7", | ||
"version": "1.0.0-beta8", | ||
"description": "The OneSignal Expo plugin allows you to use OneSignal without leaving the managed workflow. Developed in collaboration with SweetGreen.", | ||
@@ -8,3 +8,3 @@ "main": "./app.plugin.js", | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"build": "tsc", | ||
"build": "rm -rf build && tsc && cp -a support/serviceExtensionFiles build/support/", | ||
"prepare": "yarn run build" | ||
@@ -39,4 +39,5 @@ }, | ||
"dependencies": { | ||
"react-native-onesignal": "^4.3.1" | ||
"react-native-onesignal": "^4.3.1", | ||
"xcode": "^3.0.1" | ||
} | ||
} |
@@ -10,5 +10,2 @@ <h1 align="center">Welcome to onesignal-expo-plugin 👋</h1> | ||
</a> | ||
<a href="https://github.com/OneSignal/onesignal-expo-plugin/blob/main/LICENSE" target="_blank"> | ||
<img alt="License: MIT" src="https://img.shields.io/github/license/OneSignal/onesignal-expo-plugin" /> | ||
</a> | ||
<a href="https://twitter.com/onesignal" target="_blank"> | ||
@@ -21,7 +18,16 @@ <img alt="Twitter: onesignal" src="https://img.shields.io/twitter/follow/onesignal.svg?style=social" /> | ||
### 🏠 [Homepage](https://github.com/OneSignal/onesignal-expo-plugin#readme) | ||
### 🖤 [npm](https://www.npmjs.com/package/onesignal-expo-plugin) | ||
* 🏠 [Homepage](https://github.com/OneSignal/onesignal-expo-plugin#readme) | ||
* 🖤 [npm](https://www.npmjs.com/package/onesignal-expo-plugin) | ||
## 🚧 In Beta 🚧 | ||
## Overview | ||
This plugin is an [Expo Config Plugin](https://docs.expo.dev/guides/config-plugins/). It extends the Expo config to allow customizing the prebuild phase of managed workflow builds (no need to eject to a bare workflow). For the purposes of OneSignal integration, the plugin facilitates automatically generating/configuring the necessary native code files needed to get the [OneSignal React-Native SDK](https://github.com/OneSignal/react-native-onesignal) to work. You can think of adding a plugin as adding custom native code. | ||
## Supported environments: | ||
* [The Expo run commands](https://docs.expo.dev/workflow/customizing/) (`expo run:[android|ios]`) | ||
* [Custom clients](https://blog.expo.dev/introducing-custom-development-clients-5a2c79a9ddf8) | ||
* [EAS Build](https://docs.expo.dev/build/introduction/) | ||
--- | ||
## Install | ||
@@ -44,3 +50,4 @@ | ||
{ | ||
"mode": "development" | ||
"mode": "development", | ||
"devTeam": "91SW8A37CR" | ||
} | ||
@@ -62,3 +69,4 @@ ] | ||
{ | ||
mode: process.env.NODE_ENV || "development" | ||
mode: process.env.NODE_ENV || "development", | ||
devTeam: "91SW8A37CR" | ||
} | ||
@@ -74,2 +82,3 @@ ] | ||
- `"production"` | ||
* `devTeam`: *optional* - used to configure Apple Team ID. You can find your Apple Team ID by running `expo credentials:manager`. | ||
@@ -96,2 +105,19 @@ ### OneSignal App ID | ||
Alternatively, pass the app ID directly to the function: | ||
```js | ||
OneSignal.setAppId("YOUR-ONESIGNAL-APP-ID"); | ||
``` | ||
## Run | ||
```sh | ||
$ expo prebuild | ||
# Build your native iOS project | ||
$ expo run:ios | ||
# Build your native Android project | ||
$ expo run:android | ||
``` | ||
--- | ||
@@ -98,0 +124,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40265
30
659
138
2
4
1
+ Addedxcode@^3.0.1
+ Added@xmldom/xmldom@0.8.10(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbig-integer@1.6.52(transitive)
+ Addedbplist-creator@0.1.1(transitive)
+ Addedbplist-parser@0.3.2(transitive)
+ Addedplist@3.1.0(transitive)
+ Addedsimple-plist@1.4.0(transitive)
+ Addedstream-buffers@2.2.0(transitive)
+ Addeduuid@7.0.3(transitive)
+ Addedxcode@3.0.1(transitive)
+ Addedxmlbuilder@15.1.1(transitive)