react-native-notify-kit 10.3.2 → 10.4.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.
Files changed (39) hide show
  1. package/README.md +102 -12
  2. package/app.plugin.js +3 -0
  3. package/cli/dist/commands/initNse.js +8 -9
  4. package/cli/dist/commands/initNse.js.map +1 -1
  5. package/cli/dist/lib/detectProject.d.ts +1 -4
  6. package/cli/dist/lib/detectProject.js +3 -32
  7. package/cli/dist/lib/detectProject.js.map +1 -1
  8. package/cli/dist/lib/initNseCore.d.ts +8 -0
  9. package/cli/dist/lib/initNseCore.js +197 -0
  10. package/cli/dist/lib/initNseCore.js.map +1 -0
  11. package/cli/dist/lib/patchPodfile.d.ts +9 -0
  12. package/cli/dist/lib/patchPodfile.js +22 -15
  13. package/cli/dist/lib/patchPodfile.js.map +1 -1
  14. package/cli/dist/lib/patchXcodeProject.d.ts +16 -0
  15. package/cli/dist/lib/patchXcodeProject.js +54 -26
  16. package/cli/dist/lib/patchXcodeProject.js.map +1 -1
  17. package/cli/dist/lib/writeTemplates.js +5 -14
  18. package/cli/dist/lib/writeTemplates.js.map +1 -1
  19. package/dist/version.d.ts +1 -1
  20. package/dist/version.js +1 -1
  21. package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +6 -0
  22. package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +95 -20
  23. package/ios/NotifeeCore/NotifeeCore.m +13 -0
  24. package/ios/RNNotifee/NotifeeApiModule.mm +7 -0
  25. package/ios/RNNotifee/NotifeeExtensionHelper.h +2 -2
  26. package/ios/RNNotifee/NotifeeExtensionHelper.m +1 -0
  27. package/package.json +16 -3
  28. package/plugin/build/android/withNotifyKitAndroidManifest.js +236 -0
  29. package/plugin/build/index.js +62 -0
  30. package/plugin/build/ios/withNotifyKitIosNseAppExtension.js +142 -0
  31. package/plugin/build/ios/withNotifyKitIosNseFiles.js +79 -0
  32. package/plugin/build/ios/withNotifyKitIosNsePodfile.js +130 -0
  33. package/plugin/build/ios/withNotifyKitIosNseXcodeProject.js +49 -0
  34. package/plugin/build/options.js +224 -0
  35. package/plugin/build/shared/nse/index.js +7 -0
  36. package/plugin/build/shared/nse/initNseCore.js +220 -0
  37. package/plugin/build/shared/nse/patchPodfile.js +261 -0
  38. package/plugin/build/shared/nse/patchXcodeProject.js +199 -0
  39. package/src/version.ts +1 -1
@@ -15,13 +15,13 @@
15
15
  *
16
16
  */
17
17
 
18
+ #import <Foundation/Foundation.h>
19
+
18
20
  #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || \
19
21
  __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_14
20
22
  #import <UserNotifications/UserNotifications.h>
21
23
  #endif
22
24
 
23
- #import "NotifeeCore.h"
24
-
25
25
  NS_ASSUME_NONNULL_BEGIN
26
26
  @interface NotifeeExtensionHelper : NSObject
27
27
 
@@ -16,6 +16,7 @@
16
16
  */
17
17
 
18
18
  #import "NotifeeExtensionHelper.h"
19
+ #import "../NotifeeCore/NotifeeCore.h"
19
20
 
20
21
  @implementation NotifeeExtensionHelper
21
22
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "react-native-notify-kit",
3
- "version": "10.3.2",
3
+ "version": "10.4.0",
4
4
  "author": "Marco Crupi",
5
- "description": "Maintained Notifee-compatible fork for React Native advanced local notifications for Android & iOS.",
5
+ "description": "Maintained Notifee-compatible React Native notifications library for Android, iOS, FCM Mode, rich notifications, foreground services, and Expo CNG development builds.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "bin": "./cli/bin/react-native-notify-kit",
@@ -11,6 +11,8 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "default": "./dist/index.js"
13
13
  },
14
+ "./app.plugin": "./app.plugin.js",
15
+ "./app.plugin.js": "./app.plugin.js",
14
16
  "./server": {
15
17
  "types": "./server/dist/index.d.ts",
16
18
  "default": "./server/dist/index.js"
@@ -30,7 +32,7 @@
30
32
  "build:watch": "tsc --watch",
31
33
  "test:server": "jest --config jest.config.server.js",
32
34
  "prepare": "yarn run build",
33
- "prepack": "bash ../../scripts/prepack-cli.sh",
35
+ "prepack": "cd ../.. && bash build_ios_core.sh && bash scripts/verify-ios-core-generation.sh && bash scripts/prepack-cli.sh",
34
36
  "postpack": "rm -rf cli",
35
37
  "prepublishOnly": "cd ../.. && yarn run build:core",
36
38
  "format:android": "google-java-format --replace -i $(find . -type f -name \"*.java\" ! -path \"*/node_modules/*\" ! -path \"*/generated/*\")",
@@ -59,8 +61,14 @@
59
61
  "xcode": "^3.0.1"
60
62
  },
61
63
  "peerDependencies": {
64
+ "expo": "*",
62
65
  "react-native": ">=0.73.0"
63
66
  },
67
+ "peerDependenciesMeta": {
68
+ "expo": {
69
+ "optional": true
70
+ }
71
+ },
64
72
  "codegenConfig": {
65
73
  "name": "NotifeeSpec",
66
74
  "type": "modules",
@@ -87,7 +95,10 @@
87
95
  "ios",
88
96
  "firebase",
89
97
  "fcm",
98
+ "expo",
99
+ "expo-cng",
90
100
  "notifee",
101
+ "rich-notifications",
91
102
  "notifications"
92
103
  ],
93
104
  "publishConfig": {
@@ -103,6 +114,8 @@
103
114
  "!/src/__mocks__",
104
115
  "/dist",
105
116
  "/lib",
117
+ "/app.plugin.js",
118
+ "/plugin/build",
106
119
  "/*.podspec",
107
120
  "/jest-mock.js",
108
121
  "/react-native.config.js",
@@ -0,0 +1,236 @@
1
+ 'use strict';
2
+
3
+ const NOTIFY_KIT_FOREGROUND_SERVICE_NAME = 'app.notifee.core.ForegroundService';
4
+ const ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY =
5
+ 'android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE';
6
+
7
+ const ANDROID_FOREGROUND_SERVICE_PERMISSION = 'android.permission.FOREGROUND_SERVICE';
8
+
9
+ const ANDROID_FOREGROUND_SERVICE_TYPE_PERMISSIONS = {
10
+ camera: 'android.permission.FOREGROUND_SERVICE_CAMERA',
11
+ connectedDevice: 'android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE',
12
+ dataSync: 'android.permission.FOREGROUND_SERVICE_DATA_SYNC',
13
+ health: 'android.permission.FOREGROUND_SERVICE_HEALTH',
14
+ location: 'android.permission.FOREGROUND_SERVICE_LOCATION',
15
+ mediaPlayback: 'android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK',
16
+ mediaProjection: 'android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION',
17
+ microphone: 'android.permission.FOREGROUND_SERVICE_MICROPHONE',
18
+ phoneCall: 'android.permission.FOREGROUND_SERVICE_PHONE_CALL',
19
+ remoteMessaging: 'android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING',
20
+ specialUse: 'android.permission.FOREGROUND_SERVICE_SPECIAL_USE',
21
+ systemExempted: 'android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED',
22
+ };
23
+
24
+ function withNotifyKitAndroidManifest(config, foregroundServiceOptions) {
25
+ if (!foregroundServiceOptions.enabled) {
26
+ return config;
27
+ }
28
+
29
+ const { withAndroidManifest } = requireExpoConfigPlugins();
30
+
31
+ return withAndroidManifest(config, modConfig => {
32
+ applyNotifyKitAndroidForegroundServiceManifest(
33
+ modConfig.modResults,
34
+ foregroundServiceOptions,
35
+ );
36
+
37
+ return modConfig;
38
+ });
39
+ }
40
+
41
+ function applyNotifyKitAndroidForegroundServiceManifest(
42
+ androidManifest,
43
+ foregroundServiceOptions,
44
+ ) {
45
+ ensurePermission(androidManifest, ANDROID_FOREGROUND_SERVICE_PERMISSION);
46
+
47
+ for (const permission of resolveTypeSpecificPermissions(foregroundServiceOptions.types)) {
48
+ ensurePermission(androidManifest, permission);
49
+ }
50
+
51
+ const application = ensureMainApplication(androidManifest);
52
+ const service = ensureNotifyKitForegroundService(application);
53
+ service.$ = {
54
+ ...service.$,
55
+ 'android:name': NOTIFY_KIT_FOREGROUND_SERVICE_NAME,
56
+ 'android:exported': 'false',
57
+ 'android:foregroundServiceType': foregroundServiceOptions.types.join('|'),
58
+ };
59
+
60
+ if (foregroundServiceOptions.types.includes('specialUse')) {
61
+ if (foregroundServiceOptions.specialUseSubtype === undefined) {
62
+ throw new Error(
63
+ '[react-native-notify-kit] android.foregroundService.specialUseSubtype is required when types includes specialUse.',
64
+ );
65
+ }
66
+
67
+ upsertSpecialUseProperty(service, foregroundServiceOptions.specialUseSubtype);
68
+ } else {
69
+ removeSpecialUseProperty(service);
70
+ }
71
+
72
+ return androidManifest;
73
+ }
74
+
75
+ function resolveTypeSpecificPermissions(types) {
76
+ const permissions = [];
77
+
78
+ for (const type of types) {
79
+ const permission = ANDROID_FOREGROUND_SERVICE_TYPE_PERMISSIONS[type];
80
+ if (permission !== undefined && !permissions.includes(permission)) {
81
+ permissions.push(permission);
82
+ }
83
+ }
84
+
85
+ return permissions;
86
+ }
87
+
88
+ function ensurePermission(androidManifest, permissionName) {
89
+ const manifest = ensureManifestRoot(androidManifest);
90
+ const permissions = ensureArrayProperty(
91
+ manifest,
92
+ 'uses-permission',
93
+ '[react-native-notify-kit] AndroidManifest.xml uses-permission must be an array.',
94
+ );
95
+
96
+ const hasPermission = permissions.some(
97
+ permission => permission.$ && permission.$['android:name'] === permissionName,
98
+ );
99
+
100
+ if (!hasPermission) {
101
+ permissions.push({
102
+ $: {
103
+ 'android:name': permissionName,
104
+ },
105
+ });
106
+ }
107
+ }
108
+
109
+ function ensureMainApplication(androidManifest) {
110
+ const manifest = ensureManifestRoot(androidManifest);
111
+ const applications = ensureArrayProperty(
112
+ manifest,
113
+ 'application',
114
+ '[react-native-notify-kit] AndroidManifest.xml application must be an array.',
115
+ );
116
+
117
+ if (applications.length === 0) {
118
+ applications.push({});
119
+ }
120
+
121
+ return applications[0];
122
+ }
123
+
124
+ function ensureNotifyKitForegroundService(application) {
125
+ const services = ensureArrayProperty(
126
+ application,
127
+ 'service',
128
+ '[react-native-notify-kit] AndroidManifest.xml application.service must be an array.',
129
+ );
130
+ const existingService = services.find(
131
+ service =>
132
+ service.$ && service.$['android:name'] === NOTIFY_KIT_FOREGROUND_SERVICE_NAME,
133
+ );
134
+
135
+ if (existingService !== undefined) {
136
+ return existingService;
137
+ }
138
+
139
+ const service = {
140
+ $: {
141
+ 'android:name': NOTIFY_KIT_FOREGROUND_SERVICE_NAME,
142
+ },
143
+ };
144
+ services.push(service);
145
+
146
+ return service;
147
+ }
148
+
149
+ function upsertSpecialUseProperty(service, subtype) {
150
+ const properties = ensureArrayProperty(
151
+ service,
152
+ 'property',
153
+ '[react-native-notify-kit] AndroidManifest.xml service.property must be an array.',
154
+ );
155
+ const existingProperty = properties.find(
156
+ property =>
157
+ property.$ &&
158
+ property.$['android:name'] === ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY,
159
+ );
160
+
161
+ if (existingProperty !== undefined) {
162
+ existingProperty.$ = {
163
+ ...existingProperty.$,
164
+ 'android:name': ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY,
165
+ 'android:value': subtype,
166
+ };
167
+ return;
168
+ }
169
+
170
+ properties.push({
171
+ $: {
172
+ 'android:name': ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY,
173
+ 'android:value': subtype,
174
+ },
175
+ });
176
+ }
177
+
178
+ function removeSpecialUseProperty(service) {
179
+ if (service.property === undefined) {
180
+ return;
181
+ }
182
+
183
+ service.property = service.property.filter(
184
+ property =>
185
+ property.$ &&
186
+ property.$['android:name'] !== ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY,
187
+ );
188
+
189
+ if (service.property.length === 0) {
190
+ delete service.property;
191
+ }
192
+ }
193
+
194
+ function ensureManifestRoot(androidManifest) {
195
+ if (androidManifest.manifest === undefined) {
196
+ androidManifest.manifest = {};
197
+ }
198
+
199
+ return androidManifest.manifest;
200
+ }
201
+
202
+ function ensureArrayProperty(object, key, errorMessage) {
203
+ const value = object[key];
204
+
205
+ if (value === undefined) {
206
+ const nextValue = [];
207
+ object[key] = nextValue;
208
+ return nextValue;
209
+ }
210
+
211
+ if (!Array.isArray(value)) {
212
+ throw new Error(errorMessage);
213
+ }
214
+
215
+ return value;
216
+ }
217
+
218
+ function requireExpoConfigPlugins() {
219
+ try {
220
+ return require('expo/config-plugins');
221
+ } catch (error) {
222
+ try {
223
+ return require(require.resolve('expo/config-plugins', { paths: [process.cwd()] }));
224
+ } catch {
225
+ throw error;
226
+ }
227
+ }
228
+ }
229
+
230
+ module.exports = {
231
+ NOTIFY_KIT_FOREGROUND_SERVICE_NAME,
232
+ ANDROID_SPECIAL_USE_FGS_SUBTYPE_PROPERTY,
233
+ withNotifyKitAndroidManifest,
234
+ applyNotifyKitAndroidForegroundServiceManifest,
235
+ resolveTypeSpecificPermissions,
236
+ };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const { createRunOncePlugin } = requireExpoConfigPlugins();
4
+ const { normalizeNotifyKitPluginOptions } = require('./options');
5
+ const {
6
+ withNotifyKitAndroidManifest,
7
+ } = require('./android/withNotifyKitAndroidManifest');
8
+ const {
9
+ withNotifyKitIosNseAppExtension,
10
+ } = require('./ios/withNotifyKitIosNseAppExtension');
11
+ const {
12
+ withNotifyKitIosNseFiles,
13
+ } = require('./ios/withNotifyKitIosNseFiles');
14
+ const {
15
+ withNotifyKitIosNsePodfile,
16
+ } = require('./ios/withNotifyKitIosNsePodfile');
17
+ const {
18
+ withNotifyKitIosNseXcodeProject,
19
+ } = require('./ios/withNotifyKitIosNseXcodeProject');
20
+ const pkg = require('../../package.json');
21
+
22
+ function withNotifyKit(config, props = {}) {
23
+ const options = normalizeNotifyKitPluginOptions(props);
24
+ const foregroundServiceOptions = options.android.foregroundService;
25
+ const nseOptions = options.ios.notificationServiceExtension;
26
+ const configWithAndroidManifest = withNotifyKitAndroidManifest(
27
+ config,
28
+ foregroundServiceOptions,
29
+ );
30
+ const configWithAppExtension = withNotifyKitIosNseAppExtension(
31
+ configWithAndroidManifest,
32
+ nseOptions,
33
+ );
34
+ const configWithFiles = withNotifyKitIosNseFiles(configWithAppExtension, nseOptions);
35
+ const configWithXcodeProject = withNotifyKitIosNseXcodeProject(configWithFiles, nseOptions);
36
+
37
+ return withNotifyKitIosNsePodfile(configWithXcodeProject, nseOptions);
38
+ }
39
+
40
+ const plugin = createRunOncePlugin(withNotifyKit, pkg.name, pkg.version);
41
+
42
+ module.exports = plugin;
43
+ module.exports.default = plugin;
44
+ module.exports.withNotifyKit = withNotifyKit;
45
+ module.exports.normalizeNotifyKitPluginOptions = normalizeNotifyKitPluginOptions;
46
+ module.exports.withNotifyKitAndroidManifest = withNotifyKitAndroidManifest;
47
+ module.exports.withNotifyKitIosNseAppExtension = withNotifyKitIosNseAppExtension;
48
+ module.exports.withNotifyKitIosNseFiles = withNotifyKitIosNseFiles;
49
+ module.exports.withNotifyKitIosNseXcodeProject = withNotifyKitIosNseXcodeProject;
50
+ module.exports.withNotifyKitIosNsePodfile = withNotifyKitIosNsePodfile;
51
+
52
+ function requireExpoConfigPlugins() {
53
+ try {
54
+ return require('expo/config-plugins');
55
+ } catch (error) {
56
+ try {
57
+ return require(require.resolve('expo/config-plugins', { paths: [process.cwd()] }));
58
+ } catch {
59
+ throw error;
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,142 @@
1
+ 'use strict';
2
+
3
+ function withNotifyKitIosNseAppExtension(config, nseOptions) {
4
+ if (!nseOptions.enabled) {
5
+ return config;
6
+ }
7
+
8
+ const bundleIdentifier = resolveNotifyKitIosNseBundleIdentifier(config, nseOptions);
9
+ const currentAppExtensions = getCurrentAppExtensions(config);
10
+ const nextAppExtensions = upsertNotifyKitIosNseAppExtension(currentAppExtensions, {
11
+ targetName: nseOptions.targetName,
12
+ bundleIdentifier,
13
+ });
14
+
15
+ return {
16
+ ...config,
17
+ extra: setNestedAppExtensions(config.extra, nextAppExtensions),
18
+ };
19
+ }
20
+
21
+ function resolveNotifyKitIosNseBundleIdentifier(config, nseOptions) {
22
+ const hostBundleIdentifier = config.ios && config.ios.bundleIdentifier;
23
+ if (!hostBundleIdentifier) {
24
+ throw new Error(
25
+ '[react-native-notify-kit] ios.bundleIdentifier is required when ios.notificationServiceExtension.enabled is true.',
26
+ );
27
+ }
28
+
29
+ return `${hostBundleIdentifier}${nseOptions.bundleSuffix}`;
30
+ }
31
+
32
+ function upsertNotifyKitIosNseAppExtension(appExtensions, nextExtension) {
33
+ const nextAppExtensions = [];
34
+ let didUpsert = false;
35
+
36
+ for (const appExtension of appExtensions) {
37
+ if (!isPlainObject(appExtension)) {
38
+ throw new Error(
39
+ '[react-native-notify-kit] extra.eas.build.experimental.ios.appExtensions must contain objects.',
40
+ );
41
+ }
42
+
43
+ if (appExtension.targetName === nextExtension.targetName) {
44
+ if (
45
+ appExtension.bundleIdentifier !== undefined &&
46
+ appExtension.bundleIdentifier !== nextExtension.bundleIdentifier
47
+ ) {
48
+ throw new Error(
49
+ `[react-native-notify-kit] EAS app extension targetName '${nextExtension.targetName}' already uses bundleIdentifier '${appExtension.bundleIdentifier}'. ` +
50
+ `Expected '${nextExtension.bundleIdentifier}'.`,
51
+ );
52
+ }
53
+
54
+ if (!didUpsert) {
55
+ nextAppExtensions.push({
56
+ ...appExtension,
57
+ targetName: nextExtension.targetName,
58
+ bundleIdentifier: nextExtension.bundleIdentifier,
59
+ });
60
+ didUpsert = true;
61
+ }
62
+ continue;
63
+ }
64
+
65
+ if (appExtension.bundleIdentifier === nextExtension.bundleIdentifier) {
66
+ throw new Error(
67
+ `[react-native-notify-kit] EAS app extension bundleIdentifier '${nextExtension.bundleIdentifier}' already belongs to targetName '${appExtension.targetName}'. ` +
68
+ `Expected '${nextExtension.targetName}'.`,
69
+ );
70
+ }
71
+
72
+ nextAppExtensions.push(appExtension);
73
+ }
74
+
75
+ if (!didUpsert) {
76
+ nextAppExtensions.push({
77
+ targetName: nextExtension.targetName,
78
+ bundleIdentifier: nextExtension.bundleIdentifier,
79
+ });
80
+ }
81
+
82
+ return nextAppExtensions;
83
+ }
84
+
85
+ function getCurrentAppExtensions(config) {
86
+ const appExtensions = getObject(config.extra)?.eas;
87
+ const build = getObject(appExtensions)?.build;
88
+ const experimental = getObject(build)?.experimental;
89
+ const ios = getObject(experimental)?.ios;
90
+ const currentAppExtensions = getObject(ios)?.appExtensions;
91
+
92
+ if (currentAppExtensions === undefined) {
93
+ return [];
94
+ }
95
+
96
+ if (!Array.isArray(currentAppExtensions)) {
97
+ throw new Error(
98
+ '[react-native-notify-kit] extra.eas.build.experimental.ios.appExtensions must be an array.',
99
+ );
100
+ }
101
+
102
+ return currentAppExtensions;
103
+ }
104
+
105
+ function setNestedAppExtensions(currentExtra, appExtensions) {
106
+ const extra = getObject(currentExtra) ?? {};
107
+ const eas = getObject(extra.eas) ?? {};
108
+ const build = getObject(eas.build) ?? {};
109
+ const experimental = getObject(build.experimental) ?? {};
110
+ const ios = getObject(experimental.ios) ?? {};
111
+
112
+ return {
113
+ ...extra,
114
+ eas: {
115
+ ...eas,
116
+ build: {
117
+ ...build,
118
+ experimental: {
119
+ ...experimental,
120
+ ios: {
121
+ ...ios,
122
+ appExtensions,
123
+ },
124
+ },
125
+ },
126
+ },
127
+ };
128
+ }
129
+
130
+ function getObject(value) {
131
+ return isPlainObject(value) ? value : null;
132
+ }
133
+
134
+ function isPlainObject(value) {
135
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
136
+ }
137
+
138
+ module.exports = {
139
+ withNotifyKitIosNseAppExtension,
140
+ resolveNotifyKitIosNseBundleIdentifier,
141
+ upsertNotifyKitIosNseAppExtension,
142
+ };
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const {
7
+ renderNotificationServiceSwift,
8
+ renderNseEntitlementsPlist,
9
+ renderNseInfoPlist,
10
+ } = require('../shared/nse/initNseCore');
11
+
12
+ function withNotifyKitIosNseFiles(config, nseOptions) {
13
+ if (!nseOptions.enabled) {
14
+ return config;
15
+ }
16
+
17
+ const { withDangerousMod } = requireExpoConfigPlugins();
18
+
19
+ return withDangerousMod(config, [
20
+ 'ios',
21
+ modConfig => {
22
+ writeNotifyKitIosNseFiles(
23
+ modConfig.modRequest.platformProjectRoot,
24
+ nseOptions.targetName,
25
+ );
26
+ return modConfig;
27
+ },
28
+ ]);
29
+ }
30
+
31
+ function writeNotifyKitIosNseFiles(platformProjectRoot, targetName) {
32
+ const targetDir = path.join(platformProjectRoot, targetName);
33
+ fs.mkdirSync(targetDir, { recursive: true });
34
+
35
+ writeFileIfMissingOrIdentical(
36
+ path.join(targetDir, 'NotificationService.swift'),
37
+ renderNotificationServiceSwift(),
38
+ );
39
+ writeFileIfMissingOrIdentical(
40
+ path.join(targetDir, 'Info.plist'),
41
+ renderNseInfoPlist({ targetName }),
42
+ );
43
+ writeFileIfMissingOrIdentical(
44
+ path.join(targetDir, `${targetName}.entitlements`),
45
+ renderNseEntitlementsPlist(),
46
+ );
47
+ }
48
+
49
+ function writeFileIfMissingOrIdentical(filePath, contents) {
50
+ if (fs.existsSync(filePath)) {
51
+ const currentContents = fs.readFileSync(filePath, 'utf8');
52
+ if (currentContents !== contents) {
53
+ throw new Error(
54
+ `[react-native-notify-kit] Refusing to overwrite existing ${filePath}. ` +
55
+ 'Delete it or make it match the generated NotifyKit NSE template.',
56
+ );
57
+ }
58
+ return;
59
+ }
60
+
61
+ fs.writeFileSync(filePath, contents, 'utf8');
62
+ }
63
+
64
+ function requireExpoConfigPlugins() {
65
+ try {
66
+ return require('expo/config-plugins');
67
+ } catch (error) {
68
+ try {
69
+ return require(require.resolve('expo/config-plugins', { paths: [process.cwd()] }));
70
+ } catch {
71
+ throw error;
72
+ }
73
+ }
74
+ }
75
+
76
+ module.exports = {
77
+ withNotifyKitIosNseFiles,
78
+ writeNotifyKitIosNseFiles,
79
+ };