onesignal-expo-plugin 2.2.0 → 2.3.0

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Expo config plugin for One Signal
3
+ * @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
4
+ */
5
+ import { ConfigPlugin } from '@expo/config-plugins';
6
+ import { OneSignalPluginProps } from '../types/types';
7
+ declare const withOneSignal: ConfigPlugin<OneSignalPluginProps>;
8
+ export default withOneSignal;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Expo config plugin for OneSignal (Android)
3
+ * @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
4
+ */
5
+ import { ConfigPlugin } from '@expo/config-plugins';
6
+ import { OneSignalPluginProps } from '../types/types';
7
+ export declare const withOneSignalAndroid: ConfigPlugin<OneSignalPluginProps>;
@@ -23,34 +23,34 @@ const SMALL_ICON_DIRS_TO_SIZE = {
23
23
  const LARGE_ICON_DIRS_TO_SIZE = {
24
24
  'drawable-xxxhdpi': 256,
25
25
  };
26
+ const SMALL_ICON_DEFAULT_NAME = 'ic_stat_onesignal_default';
26
27
  const withSmallIcons = (config, onesignalProps) => {
27
28
  if (!onesignalProps.smallIcons && !config.notification?.icon) {
28
29
  return config;
29
30
  }
30
- // we are modifying the android build (adding files) without a base mod
31
31
  return (0, config_plugins_1.withDangerousMod)(config, [
32
32
  'android',
33
33
  async (config) => {
34
34
  if (config.notification?.icon) {
35
- await saveIconAsync(config.notification.icon, config.modRequest.projectRoot, SMALL_ICON_DIRS_TO_SIZE);
35
+ await saveIconAsync(config.notification.icon, config.modRequest.projectRoot, SMALL_ICON_DIRS_TO_SIZE, SMALL_ICON_DEFAULT_NAME);
36
36
  }
37
37
  if (onesignalProps.smallIcons) {
38
- await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.smallIcons, SMALL_ICON_DIRS_TO_SIZE);
38
+ await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.smallIcons, SMALL_ICON_DIRS_TO_SIZE, SMALL_ICON_DEFAULT_NAME);
39
39
  }
40
40
  return config;
41
41
  },
42
42
  ]);
43
43
  };
44
+ const LARGE_ICON_DEFAULT_NAME = 'ic_onesignal_large_icon_default';
44
45
  const withLargeIcons = (config, onesignalProps) => {
45
46
  if (!onesignalProps.largeIcons) {
46
47
  return config;
47
48
  }
48
- // we are modifying the android build (adding files) without a base mod
49
49
  return (0, config_plugins_1.withDangerousMod)(config, [
50
50
  'android',
51
51
  async (config) => {
52
52
  if (onesignalProps.largeIcons) {
53
- await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.largeIcons, LARGE_ICON_DIRS_TO_SIZE);
53
+ await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.largeIcons, LARGE_ICON_DIRS_TO_SIZE, LARGE_ICON_DEFAULT_NAME);
54
54
  }
55
55
  return config;
56
56
  },
@@ -76,13 +76,15 @@ const withSmallIconAccentColor = (config, onesignalProps) => {
76
76
  return config;
77
77
  });
78
78
  };
79
- async function saveIconsArrayAsync(projectRoot, icons, dirsToSize) {
80
- for (const icon of icons) {
81
- await saveIconAsync(icon, projectRoot, dirsToSize);
79
+ async function saveIconsArrayAsync(projectRoot, icons, dirsToSize, defaultName) {
80
+ for (let i = 0; i < icons.length; i++) {
81
+ // the first icon should use OneSignal’s required default drawable name; others keep their file-derived names.
82
+ const outputName = i === 0 ? defaultName : undefined;
83
+ await saveIconAsync(icons[i], projectRoot, dirsToSize, outputName);
82
84
  }
83
85
  }
84
- async function saveIconAsync(icon, projectRoot, dirsToSize) {
85
- const name = (0, path_1.parse)(icon).name;
86
+ async function saveIconAsync(icon, projectRoot, dirsToSize, outputName) {
87
+ const name = outputName ?? (0, path_1.parse)(icon).name;
86
88
  OneSignalLog_1.OneSignalLog.log('Saving icon ' + icon + ' as drawable resource ' + name);
87
89
  for (const iconResourceDir in dirsToSize) {
88
90
  const path = (0, path_1.resolve)(projectRoot, RESOURCE_ROOT_PATH, iconResourceDir);
@@ -99,10 +101,26 @@ async function saveIconAsync(icon, projectRoot, dirsToSize) {
99
101
  (0, fs_1.writeFileSync)((0, path_1.resolve)(path, name + '.png'), resizedIcon);
100
102
  }
101
103
  }
104
+ const OKHTTP_FORCE_FIX = `
105
+ subprojects {
106
+ project.configurations.all {
107
+ resolutionStrategy.force 'com.squareup.okhttp3:okhttp:4.12.0'
108
+ }
109
+ }`;
110
+ const withOkHttpFix = (config) => {
111
+ return (0, config_plugins_1.withProjectBuildGradle)(config, (config) => {
112
+ if (config.modResults.contents.includes("force 'com.squareup.okhttp3:okhttp:4.12.0'")) {
113
+ return config;
114
+ }
115
+ config.modResults.contents += OKHTTP_FORCE_FIX;
116
+ return config;
117
+ });
118
+ };
102
119
  const withOneSignalAndroid = (config, props) => {
103
120
  config = withSmallIcons(config, props);
104
121
  config = withLargeIcons(config, props);
105
122
  config = withSmallIconAccentColor(config, props);
123
+ config = withOkHttpFix(config);
106
124
  return config;
107
125
  };
108
126
  exports.withOneSignalAndroid = withOneSignalAndroid;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Expo config plugin for One Signal (iOS)
3
+ * @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
4
+ */
5
+ import { ConfigPlugin } from '@expo/config-plugins';
6
+ import { OneSignalPluginProps } from '../types/types';
7
+ export declare const withOneSignalIos: ConfigPlugin<OneSignalPluginProps>;
@@ -50,7 +50,6 @@ const updatePodfile_1 = require("../support/updatePodfile");
50
50
  const NseUpdaterManager_1 = __importDefault(require("../support/NseUpdaterManager"));
51
51
  const OneSignalLog_1 = require("../support/OneSignalLog");
52
52
  const FileManager_1 = require("../support/FileManager");
53
- const assert_1 = __importDefault(require("assert"));
54
53
  const getEasManagedCredentialsConfigExtra_1 = __importDefault(require("../support/eas/getEasManagedCredentialsConfigExtra"));
55
54
  /**
56
55
  * Add 'aps-environment' record with current environment to '<project-name>.entitlements' file
@@ -118,7 +117,9 @@ const withCustomAppGroupsKey = (config, props) => {
118
117
  });
119
118
  };
120
119
  const withEasManagedCredentials = (config, props) => {
121
- (0, assert_1.default)(config.ios?.bundleIdentifier, "Missing 'ios.bundleIdentifier' in app config.");
120
+ if (!config.ios?.bundleIdentifier) {
121
+ return config;
122
+ }
122
123
  config.extra = (0, getEasManagedCredentialsConfigExtra_1.default)(config, props?.appGroupName, props?.nseBundleIdentifier);
123
124
  return config;
124
125
  };
@@ -133,12 +134,12 @@ const withOneSignalPodfile = (config) => {
133
134
  ]);
134
135
  };
135
136
  const withOneSignalNSE = (config, props) => {
136
- // support for monorepos where node_modules can be above the project directory.
137
- const pluginDir = require.resolve('onesignal-expo-plugin/package.json');
138
- const sourceDir = path.join(pluginDir, '../build/support/serviceExtensionFiles/');
139
137
  return (0, config_plugins_1.withDangerousMod)(config, [
140
138
  'ios',
141
139
  async (config) => {
140
+ // support for monorepos where node_modules can be above the project directory.
141
+ const pluginDir = require.resolve('onesignal-expo-plugin/package.json');
142
+ const sourceDir = path.join(pluginDir, '../build/support/serviceExtensionFiles/');
142
143
  const iosPath = path.join(config.modRequest.projectRoot, 'ios');
143
144
  /* COPY OVER EXTENSION FILES */
144
145
  fs.mkdirSync(`${iosPath}/${iosConstants_1.NSE_TARGET_NAME}`, {
@@ -224,12 +225,14 @@ const withOneSignalXcodeProject = (config, props) => {
224
225
  const withOneSignalIos = (config, props) => {
225
226
  config = withAppEnvironment(config, props);
226
227
  config = withRemoteNotificationsPermissions(config, props);
227
- config = withCustomAppGroupsKey(config, props);
228
- config = withAppGroupPermissions(config, props);
229
- config = withOneSignalPodfile(config, props);
230
- config = withOneSignalNSE(config, props);
231
- config = withOneSignalXcodeProject(config, props);
232
- config = withEasManagedCredentials(config, props);
228
+ if (!props.disableNSE) {
229
+ config = withCustomAppGroupsKey(config, props);
230
+ config = withAppGroupPermissions(config, props);
231
+ config = withOneSignalPodfile(config, props);
232
+ config = withOneSignalNSE(config, props);
233
+ config = withOneSignalXcodeProject(config, props);
234
+ config = withEasManagedCredentials(config, props);
235
+ }
233
236
  return config;
234
237
  };
235
238
  exports.withOneSignalIos = withOneSignalIos;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * FileManager contains static *awaitable* file-system functions
3
+ */
4
+ export declare class FileManager {
5
+ static readFile(path: string): Promise<string>;
6
+ static writeFile(path: string, contents: string): Promise<void>;
7
+ static copyFile(path1: string, path2: string): Promise<void>;
8
+ static dirExists(path: string): boolean;
9
+ }
@@ -0,0 +1,8 @@
1
+ export default class NseUpdaterManager {
2
+ private nsePath;
3
+ constructor(iosPath: string);
4
+ updateNSEEntitlements(groupIdentifier: string): Promise<void>;
5
+ updateNSEBundleVersion(version: string): Promise<void>;
6
+ updateNSEBundleShortVersion(version: string): Promise<void>;
7
+ updateNSEInfoPlistAppGroupKey(appGroupName: string): Promise<void>;
8
+ }
@@ -0,0 +1,4 @@
1
+ export declare class OneSignalLog {
2
+ static log(str: string): void;
3
+ static error(str: string): void;
4
+ }
@@ -0,0 +1,4 @@
1
+ import { ExpoConfig } from '@expo/config-types';
2
+ export default function getEasManagedCredentialsConfigExtra(config: ExpoConfig, appGroupName?: string, nseBundleIdentifier?: string): {
3
+ [k: string]: any;
4
+ };
@@ -0,0 +1,2 @@
1
+ export declare function validatePluginProps(props: any): void;
2
+ export declare function getAppGroupIdentifier(bundleIdentifier: string, customAppGroupName?: string): string;
@@ -35,6 +35,9 @@ function validatePluginProps(props) {
35
35
  typeof props.nseBundleIdentifier !== 'string') {
36
36
  throw new Error("OneSignal Expo Plugin: 'nseBundleIdentifier' must be a string.");
37
37
  }
38
+ if (props.disableNSE !== undefined && typeof props.disableNSE !== 'boolean') {
39
+ throw new Error("OneSignal Expo Plugin: 'disableNSE' must be a boolean.");
40
+ }
38
41
  // check for extra properties
39
42
  const inputProps = Object.keys(props);
40
43
  for (const prop of inputProps) {
@@ -0,0 +1,12 @@
1
+ export declare const IPHONEOS_DEPLOYMENT_TARGET = "11.0";
2
+ export declare const TARGETED_DEVICE_FAMILY = "\"1,2\"";
3
+ export declare const GROUP_IDENTIFIER_TEMPLATE_REGEX: RegExp;
4
+ export declare const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX: RegExp;
5
+ export declare const BUNDLE_VERSION_TEMPLATE_REGEX: RegExp;
6
+ export declare const DEFAULT_BUNDLE_VERSION = "1";
7
+ export declare const DEFAULT_BUNDLE_SHORT_VERSION = "1.0";
8
+ export declare const NSE_TARGET_NAME = "OneSignalNotificationServiceExtension";
9
+ export declare const NSE_SOURCE_FILE = "NotificationService.m";
10
+ export declare const NSE_PODFILE_SNIPPET = "\ntarget 'OneSignalNotificationServiceExtension' do\n pod 'OneSignalXCFramework', '>= 5.0', '< 6.0'\n use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']\nend";
11
+ export declare const NSE_PODFILE_REGEX: RegExp;
12
+ export declare const NSE_EXT_FILES: string[];
@@ -4,26 +4,31 @@
4
4
 
5
5
  @interface NotificationService ()
6
6
 
7
- @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
8
- @property (nonatomic, strong) UNNotificationRequest *receivedRequest;
9
- @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
7
+ @property(nonatomic, strong) void (^contentHandler)
8
+ (UNNotificationContent *contentToDeliver);
9
+ @property(nonatomic, strong) UNNotificationRequest *receivedRequest;
10
+ @property(nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
10
11
 
11
12
  @end
12
13
 
13
14
  @implementation NotificationService
14
15
 
15
- - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
16
- self.receivedRequest = request;
17
- self.contentHandler = contentHandler;
18
- self.bestAttemptContent = [request.content mutableCopy];
19
- [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
20
- withMutableNotificationContent:self.bestAttemptContent
21
- withContentHandler:self.contentHandler];
16
+ - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
17
+ withContentHandler:
18
+ (void (^)(UNNotificationContent *_Nonnull))
19
+ contentHandler {
20
+ self.receivedRequest = request;
21
+ self.contentHandler = contentHandler;
22
+ self.bestAttemptContent = [request.content mutableCopy];
23
+ [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
24
+ withMutableNotificationContent:self.bestAttemptContent
25
+ withContentHandler:self.contentHandler];
22
26
  }
23
27
 
24
28
  - (void)serviceExtensionTimeWillExpire {
25
- [OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent];
26
- self.contentHandler(self.bestAttemptContent);
29
+ [OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest
30
+ withMutableNotificationContent:self.bestAttemptContent];
31
+ self.contentHandler(self.bestAttemptContent);
27
32
  }
28
33
 
29
34
  @end
@@ -0,0 +1 @@
1
+ export declare function updatePodfile(iosPath: string): Promise<void>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * OneSignalPluginProps refer to the properties set by the user in their app config file (e.g: app.json)
3
+ */
4
+ export type OneSignalPluginProps = {
5
+ /**
6
+ * (required) Used to configure APNs environment entitlement. "development" or "production"
7
+ */
8
+ mode: 'development' | 'production';
9
+ /**
10
+ * (optional) Used to configure Apple Team ID. You can find your Apple Team ID by running expo credentials:manager e.g: "91SW8A37CR"
11
+ */
12
+ devTeam?: string;
13
+ /**
14
+ * (optional) Target IPHONEOS_DEPLOYMENT_TARGET value to be used when adding the iOS NSE. A deployment target is nothing more than
15
+ * 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".
16
+ */
17
+ iPhoneDeploymentTarget?: string;
18
+ /**
19
+ * (optional) The small notification icons for Android. Images will be automatically scaled up/down, the recommended size
20
+ * is 96x96 to always scale down.
21
+ */
22
+ smallIcons?: string[];
23
+ /**
24
+ * (optional) The accent color to use for notification icons on Android. Must be a valid Android color resource, for example: "#FF0000"
25
+ */
26
+ smallIconAccentColor?: string;
27
+ /**
28
+ * (optional) The large notification icons for Android. Images will be automatically scaled up/down to 256x256.
29
+ */
30
+ largeIcons?: string[];
31
+ /**
32
+ * (optional) The local path to a custom Notification Service Extension (NSE), written in Objective-C. The NSE will typically start as a copy
33
+ * of the default NSE found at (support/serviceExtensionFiles/NotificationService.m, then altered to support any custom
34
+ * logic required.
35
+ */
36
+ iosNSEFilePath?: string;
37
+ /**
38
+ * (optional) Used to configure a custom iOS app group name. If not provided, defaults to "group.{ios.bundleIdentifier}.onesignal".
39
+ * @see https://documentation.onesignal.com/docs/ios-sdk-setup#step-3-create-an-app-group
40
+ */
41
+ appGroupName?: string;
42
+ /**
43
+ * (optional) Used to configure a custom bundle identifier suffix for the iOS Notification Service Extension.
44
+ * The full bundle identifier will be "{ios.bundleIdentifier}.{nseBundleIdentifier}".
45
+ * If not provided, defaults to "OneSignalNotificationServiceExtension".
46
+ */
47
+ nseBundleIdentifier?: string;
48
+ /**
49
+ * (optional) If true, the iOS Notification Service Extension (NSE) will not be added to the project.
50
+ * The NSE is required for badges, confirmed delivery, media attachments, and action buttons.
51
+ * Only disable if you only need basic push notifications.
52
+ */
53
+ disableNSE?: boolean;
54
+ };
55
+ export declare const ONESIGNAL_PLUGIN_PROPS: string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Mode = exports.ONESIGNAL_PLUGIN_PROPS = void 0;
3
+ exports.ONESIGNAL_PLUGIN_PROPS = void 0;
4
4
  exports.ONESIGNAL_PLUGIN_PROPS = [
5
5
  'mode',
6
6
  'devTeam',
@@ -11,9 +11,5 @@ exports.ONESIGNAL_PLUGIN_PROPS = [
11
11
  'smallIconAccentColor',
12
12
  'appGroupName',
13
13
  'nseBundleIdentifier',
14
+ 'disableNSE',
14
15
  ];
15
- var Mode;
16
- (function (Mode) {
17
- Mode["Dev"] = "development";
18
- Mode["Prod"] = "production";
19
- })(Mode || (exports.Mode = Mode = {}));
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "onesignal-expo-plugin",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Some Changez",
5
5
  "main": "./app.plugin.js",
6
+ "types": "./build/types/types.d.ts",
6
7
  "files": [
7
8
  "build",
8
9
  "app.plugin.js"
@@ -10,11 +11,15 @@
10
11
  "scripts": {
11
12
  "test": "bun test",
12
13
  "test:coverage": "bun test --coverage",
13
- "build": "bun run lint && rm -rf build && tsc && cp -a src/support/serviceExtensionFiles build/support/",
14
- "format:check": "prettier --check \"**/*.{ts,tsx}\" --ignore-path .prettierignore",
15
- "format:fix": "prettier --write \"**/*.{ts,tsx}\" --ignore-path .prettierignore",
14
+ "build": "rm -rf build && tsc && cp -a src/support/serviceExtensionFiles build/support/",
15
+ "format:spotless": "./examples/demo/android/gradlew spotlessApply",
16
+ "format:prettier": "prettier --write \"**/*.{ts,tsx}\" --ignore-path .gitignore",
17
+ "format": "concurrently \"bun run format:spotless\" \"bun run format:prettier\"",
18
+ "format:check:spotless": "./examples/demo/android/gradlew spotlessCheck",
19
+ "format:check:prettier": "prettier --check \"**/*.{ts,tsx}\" --ignore-path .gitignore",
20
+ "format:check": "concurrently \"bun run format:check:spotless\" \"bun run format:check:prettier\"",
16
21
  "lint": "oxlint src examples && bun run format:check",
17
- "lint:fix": "oxlint src examples --fix && bun run format:fix"
22
+ "lint:fix": "oxlint src examples --fix && bun run format"
18
23
  },
19
24
  "repository": {
20
25
  "type": "git",
@@ -42,6 +47,7 @@
42
47
  "homepage": "https://github.com/OneSignal/onesignal-expo-plugin#readme",
43
48
  "devDependencies": {
44
49
  "@types/bun": "^1.3.9",
50
+ "concurrently": "^9.2.1",
45
51
  "expo-module-scripts": "^5.0.8",
46
52
  "oxlint": "^1.43.0",
47
53
  "prettier": "^3.8.1",