react-native-notify-kit 10.4.0 → 10.4.2
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.
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/RNNotifee/NotifeeApiModule.h +1 -2
- package/ios/RNNotifee/NotifeeApiModule.mm +5 -1
- package/package.json +1 -1
- package/plugin/build/ios/withNotifyKitIosNseFiles.js +51 -3
- package/plugin/build/ios/withNotifyKitIosNsePodfile.js +217 -18
- package/plugin/build/ios/withNotifyKitIosNseXcodeProject.js +17 -0
- package/plugin/build/shared/nse/initNseCore.js +13 -3
- package/plugin/build/shared/nse/patchPodfile.js +107 -13
- package/plugin/build/shared/nse/patchXcodeProject.js +130 -24
- package/src/version.ts +1 -1
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "10.4.
|
|
1
|
+
export declare const version = "10.4.2";
|
package/dist/version.js
CHANGED
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
#import <Foundation/Foundation.h>
|
|
19
19
|
#import <NotifeeSpec/NotifeeSpec.h>
|
|
20
20
|
#import <React/RCTEventEmitter.h>
|
|
21
|
-
#import "NotifeeCore.h"
|
|
22
21
|
|
|
23
|
-
@interface NotifeeApiModule : RCTEventEmitter <NativeNotifeeModuleSpec
|
|
22
|
+
@interface NotifeeApiModule : RCTEventEmitter <NativeNotifeeModuleSpec>
|
|
24
23
|
|
|
25
24
|
@end
|
|
@@ -18,7 +18,11 @@
|
|
|
18
18
|
#import "NotifeeApiModule.h"
|
|
19
19
|
#import <React/RCTUtils.h>
|
|
20
20
|
#import <UIKit/UIKit.h>
|
|
21
|
-
#import "NotifeeCore+UNUserNotificationCenter.h"
|
|
21
|
+
#import "../NotifeeCore/NotifeeCore+UNUserNotificationCenter.h"
|
|
22
|
+
#import "../NotifeeCore/NotifeeCore.h"
|
|
23
|
+
|
|
24
|
+
@interface NotifeeApiModule () <NotifeeCoreDelegate>
|
|
25
|
+
@end
|
|
22
26
|
|
|
23
27
|
@interface NotifeeCoreUNUserNotificationCenter (Rechain)
|
|
24
28
|
- (void)rechainUserNotificationCenterDelegate;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-notify-kit",
|
|
3
|
-
"version": "10.4.
|
|
3
|
+
"version": "10.4.2",
|
|
4
4
|
"author": "Marco Crupi",
|
|
5
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",
|
|
@@ -4,11 +4,16 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
|
+
DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
8
|
+
DEFAULT_NSE_MARKETING_VERSION,
|
|
7
9
|
renderNotificationServiceSwift,
|
|
8
10
|
renderNseEntitlementsPlist,
|
|
9
11
|
renderNseInfoPlist,
|
|
10
12
|
} = require('../shared/nse/initNseCore');
|
|
11
13
|
|
|
14
|
+
const MARKETING_VERSION_MARKER = '__NOTIFYKIT_NSE_MARKETING_VERSION__';
|
|
15
|
+
const CURRENT_PROJECT_VERSION_MARKER = '__NOTIFYKIT_NSE_CURRENT_PROJECT_VERSION__';
|
|
16
|
+
|
|
12
17
|
function withNotifyKitIosNseFiles(config, nseOptions) {
|
|
13
18
|
if (!nseOptions.enabled) {
|
|
14
19
|
return config;
|
|
@@ -22,13 +27,21 @@ function withNotifyKitIosNseFiles(config, nseOptions) {
|
|
|
22
27
|
writeNotifyKitIosNseFiles(
|
|
23
28
|
modConfig.modRequest.platformProjectRoot,
|
|
24
29
|
nseOptions.targetName,
|
|
30
|
+
resolveNseVersionOptions(modConfig),
|
|
25
31
|
);
|
|
26
32
|
return modConfig;
|
|
27
33
|
},
|
|
28
34
|
]);
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
function writeNotifyKitIosNseFiles(
|
|
37
|
+
function writeNotifyKitIosNseFiles(
|
|
38
|
+
platformProjectRoot,
|
|
39
|
+
targetName,
|
|
40
|
+
versionOptions = {
|
|
41
|
+
marketingVersion: DEFAULT_NSE_MARKETING_VERSION,
|
|
42
|
+
currentProjectVersion: DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
43
|
+
},
|
|
44
|
+
) {
|
|
32
45
|
const targetDir = path.join(platformProjectRoot, targetName);
|
|
33
46
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
34
47
|
|
|
@@ -38,7 +51,8 @@ function writeNotifyKitIosNseFiles(platformProjectRoot, targetName) {
|
|
|
38
51
|
);
|
|
39
52
|
writeFileIfMissingOrIdentical(
|
|
40
53
|
path.join(targetDir, 'Info.plist'),
|
|
41
|
-
renderNseInfoPlist({ targetName }),
|
|
54
|
+
renderNseInfoPlist({ targetName, ...versionOptions }),
|
|
55
|
+
contents => isGeneratedNseInfoPlist(contents, targetName),
|
|
42
56
|
);
|
|
43
57
|
writeFileIfMissingOrIdentical(
|
|
44
58
|
path.join(targetDir, `${targetName}.entitlements`),
|
|
@@ -46,10 +60,44 @@ function writeNotifyKitIosNseFiles(platformProjectRoot, targetName) {
|
|
|
46
60
|
);
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
function
|
|
63
|
+
function resolveNseVersionOptions(config) {
|
|
64
|
+
return {
|
|
65
|
+
marketingVersion: optionalString(config.version) ?? DEFAULT_NSE_MARKETING_VERSION,
|
|
66
|
+
currentProjectVersion:
|
|
67
|
+
optionalString(config.ios?.buildNumber) ?? DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function optionalString(value) {
|
|
72
|
+
return typeof value === 'string' ? value : undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isGeneratedNseInfoPlist(contents, targetName) {
|
|
76
|
+
const templateWithMarkers = renderNseInfoPlist({
|
|
77
|
+
targetName,
|
|
78
|
+
marketingVersion: MARKETING_VERSION_MARKER,
|
|
79
|
+
currentProjectVersion: CURRENT_PROJECT_VERSION_MARKER,
|
|
80
|
+
});
|
|
81
|
+
const escapedTemplate = escapeRegExp(templateWithMarkers)
|
|
82
|
+
.replace(MARKETING_VERSION_MARKER, '[^<]*')
|
|
83
|
+
.replace(CURRENT_PROJECT_VERSION_MARKER, '[^<]*');
|
|
84
|
+
|
|
85
|
+
return new RegExp(`^${escapedTemplate}$`).test(contents);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function escapeRegExp(value) {
|
|
89
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function writeFileIfMissingOrIdentical(filePath, contents, canOverwrite) {
|
|
50
93
|
if (fs.existsSync(filePath)) {
|
|
51
94
|
const currentContents = fs.readFileSync(filePath, 'utf8');
|
|
52
95
|
if (currentContents !== contents) {
|
|
96
|
+
if (canOverwrite?.(currentContents)) {
|
|
97
|
+
fs.writeFileSync(filePath, contents, 'utf8');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
53
101
|
throw new Error(
|
|
54
102
|
`[react-native-notify-kit] Refusing to overwrite existing ${filePath}. ` +
|
|
55
103
|
'Delete it or make it match the generated NotifyKit NSE template.',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
|
|
5
6
|
const { patchPodfileForNotifyKitNse } = require('../shared/nse/patchPodfile');
|
|
@@ -14,11 +15,12 @@ function withNotifyKitIosNsePodfile(config, nseOptions) {
|
|
|
14
15
|
|
|
15
16
|
return withPodfile(config, modConfig => {
|
|
16
17
|
const { projectRoot, platformProjectRoot } = modConfig.modRequest;
|
|
17
|
-
const packagePathFromIos = resolveNotifyKitPackagePathFromIos(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const packagePathFromIos = resolveNotifyKitPackagePathFromIos(projectRoot, platformProjectRoot);
|
|
19
|
+
const hostUseFrameworks = detectPodfileUseFrameworks(modConfig.modResults.contents, {
|
|
20
|
+
ignoredTargetName: nseOptions.targetName,
|
|
21
|
+
podfileProperties: readExpoPodfileProperties(platformProjectRoot),
|
|
22
|
+
env: process.env,
|
|
23
|
+
});
|
|
22
24
|
const useFrameworks = resolveNseUseFrameworks(hostUseFrameworks, configuredUseFrameworks);
|
|
23
25
|
const result = patchPodfileForNotifyKitNse(modConfig.modResults.contents, {
|
|
24
26
|
targetName: nseOptions.targetName,
|
|
@@ -45,30 +47,56 @@ function normalizePodfilePath(filePath) {
|
|
|
45
47
|
return filePath.replace(/\\/g, '/');
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
function detectPodfileUseFrameworks(contents) {
|
|
49
|
-
|
|
50
|
+
function detectPodfileUseFrameworks(contents, optionsOrIgnoredTargetName) {
|
|
51
|
+
const options =
|
|
52
|
+
typeof optionsOrIgnoredTargetName === 'string'
|
|
53
|
+
? { ignoredTargetName: optionsOrIgnoredTargetName }
|
|
54
|
+
: (optionsOrIgnoredTargetName ?? {});
|
|
55
|
+
const targetBlocks = findTargetBlocks(contents);
|
|
56
|
+
const firstHostTarget = targetBlocks.find(
|
|
57
|
+
block => block.targetName !== options.ignoredTargetName,
|
|
58
|
+
);
|
|
59
|
+
let globalUseFrameworks = false;
|
|
60
|
+
let hostUseFrameworks = false;
|
|
61
|
+
let charIndex = 0;
|
|
50
62
|
|
|
51
63
|
for (const line of contents.split('\n')) {
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
64
|
+
const detectedUseFrameworks = parseUseFrameworksLine(line, options);
|
|
65
|
+
if (detectedUseFrameworks === null) {
|
|
66
|
+
charIndex += line.length + 1;
|
|
54
67
|
continue;
|
|
55
68
|
}
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
const targetBlock = findMostSpecificTargetBlock(targetBlocks, charIndex);
|
|
71
|
+
if (!targetBlock) {
|
|
72
|
+
globalUseFrameworks = mergeUseFrameworksDetection(globalUseFrameworks, detectedUseFrameworks);
|
|
73
|
+
} else if (targetBlock === firstHostTarget) {
|
|
74
|
+
hostUseFrameworks = mergeUseFrameworksDetection(hostUseFrameworks, detectedUseFrameworks);
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
charIndex += line.length + 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return hostUseFrameworks !== false ? hostUseFrameworks : globalUseFrameworks;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function readExpoPodfileProperties(platformProjectRoot) {
|
|
84
|
+
const propertiesPath = path.join(platformProjectRoot, 'Podfile.properties.json');
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const parsed = JSON.parse(fs.readFileSync(propertiesPath, 'utf8'));
|
|
88
|
+
return isPlainObject(parsed) ? parsed : {};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (isFileNotFoundError(error)) {
|
|
91
|
+
return {};
|
|
66
92
|
}
|
|
67
93
|
|
|
68
|
-
|
|
94
|
+
throw error;
|
|
69
95
|
}
|
|
96
|
+
}
|
|
70
97
|
|
|
71
|
-
|
|
98
|
+
function isFileNotFoundError(error) {
|
|
99
|
+
return isPlainObject(error) && error.code === 'ENOENT';
|
|
72
100
|
}
|
|
73
101
|
|
|
74
102
|
function resolveNseUseFrameworks(hostUseFrameworks, configuredUseFrameworks) {
|
|
@@ -110,6 +138,177 @@ function isPlainObject(value) {
|
|
|
110
138
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
111
139
|
}
|
|
112
140
|
|
|
141
|
+
function findTargetBlocks(contents) {
|
|
142
|
+
const targetPattern = /^[ \t]*target\s+['"]([^'"]+)['"]\s+do\b.*$/gm;
|
|
143
|
+
const blocks = [];
|
|
144
|
+
let match;
|
|
145
|
+
|
|
146
|
+
while ((match = targetPattern.exec(contents)) !== null) {
|
|
147
|
+
const endLineStart = findMatchingRubyBlockEnd(contents, match.index);
|
|
148
|
+
if (endLineStart === -1) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
blocks.push({
|
|
153
|
+
targetName: match[1],
|
|
154
|
+
startIndex: match.index,
|
|
155
|
+
endIndex: findLineEnd(contents, endLineStart),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return blocks;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function findMostSpecificTargetBlock(targetBlocks, charIndex) {
|
|
163
|
+
return targetBlocks
|
|
164
|
+
.filter(block => charIndex >= block.startIndex && charIndex < block.endIndex)
|
|
165
|
+
.sort((a, b) => b.startIndex - a.startIndex)[0];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function parseUseFrameworksLine(line, options) {
|
|
169
|
+
const stripped = stripRubyLineComment(line).trim();
|
|
170
|
+
if (!/^use_frameworks!(?:\s|$)/.test(stripped)) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!isUseFrameworksConditionActive(stripped, options)) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const podfilePropertyLinkage = getPodfilePropertyUseFrameworksLinkage(stripped, options);
|
|
179
|
+
if (podfilePropertyLinkage !== null) {
|
|
180
|
+
return podfilePropertyLinkage;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const envLinkage = getEnvUseFrameworksLinkage(stripped, options);
|
|
184
|
+
if (envLinkage !== null) {
|
|
185
|
+
return envLinkage;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (/:linkage\s*=>\s*:static\b/.test(stripped) || /\blinkage:\s*:static\b/.test(stripped)) {
|
|
189
|
+
return 'static';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (/:linkage\s*=>\s*:dynamic\b/.test(stripped) || /\blinkage:\s*:dynamic\b/.test(stripped)) {
|
|
193
|
+
return 'dynamic';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function mergeUseFrameworksDetection(current, detected) {
|
|
200
|
+
return detected;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function isUseFrameworksConditionActive(strippedLine, options) {
|
|
204
|
+
const condition = strippedLine.match(/\s+if\s+(.+)$/)?.[1]?.trim();
|
|
205
|
+
if (!condition) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const podfilePropertyName = getPodfilePropertyName(condition);
|
|
210
|
+
if (podfilePropertyName !== null) {
|
|
211
|
+
return isRubyTruthy(options.podfileProperties?.[podfilePropertyName]);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const envName = getEnvName(condition);
|
|
215
|
+
if (envName !== null) {
|
|
216
|
+
return isRubyTruthy(options.env?.[envName]);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function getPodfilePropertyUseFrameworksLinkage(strippedLine, options) {
|
|
223
|
+
const propertyName = strippedLine.match(
|
|
224
|
+
/(?:\:linkage\s*=>|linkage:)\s*podfile_properties\[['"]([^'"]+)['"]\](?:\.to_sym)?/,
|
|
225
|
+
)?.[1];
|
|
226
|
+
|
|
227
|
+
return propertyName
|
|
228
|
+
? normalizeUseFrameworksValue(options.podfileProperties?.[propertyName])
|
|
229
|
+
: null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function getEnvUseFrameworksLinkage(strippedLine, options) {
|
|
233
|
+
const envName = strippedLine.match(
|
|
234
|
+
/(?:\:linkage\s*=>|linkage:)\s*ENV\[['"]([^'"]+)['"]\](?:\.to_sym)?/,
|
|
235
|
+
)?.[1];
|
|
236
|
+
|
|
237
|
+
return envName ? normalizeUseFrameworksValue(options.env?.[envName]) : null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function normalizeUseFrameworksValue(value) {
|
|
241
|
+
if (value === 'static' || value === 'dynamic' || value === true) {
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function getPodfilePropertyName(expression) {
|
|
249
|
+
return expression.match(/^podfile_properties\[['"]([^'"]+)['"]\]$/)?.[1] ?? null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function getEnvName(expression) {
|
|
253
|
+
return expression.match(/^ENV\[['"]([^'"]+)['"]\]$/)?.[1] ?? null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function isRubyTruthy(value) {
|
|
257
|
+
return value !== undefined && value !== null && value !== false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function findLineEnd(content, lineStartIndex) {
|
|
261
|
+
const newlineIndex = content.indexOf('\n', lineStartIndex);
|
|
262
|
+
return newlineIndex === -1 ? content.length : newlineIndex + 1;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function findMatchingRubyBlockEnd(content, startIndex) {
|
|
266
|
+
const afterStart = content.slice(startIndex);
|
|
267
|
+
const lines = afterStart.split('\n');
|
|
268
|
+
let depth = 0;
|
|
269
|
+
let charIndex = startIndex;
|
|
270
|
+
|
|
271
|
+
for (const line of lines) {
|
|
272
|
+
const trimmed = stripRubyLineComment(line).trim();
|
|
273
|
+
|
|
274
|
+
depth += countRubyBlockOpeners(trimmed);
|
|
275
|
+
|
|
276
|
+
if (trimmed === 'end') {
|
|
277
|
+
depth--;
|
|
278
|
+
if (depth === 0) {
|
|
279
|
+
return charIndex;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
charIndex += line.length + 1;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return -1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function countRubyBlockOpeners(line) {
|
|
290
|
+
if (line.length === 0) {
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const startsWithKeywordBlock = /^(if|unless|case|begin|while|until|for|def|class|module)\b/.test(
|
|
295
|
+
line,
|
|
296
|
+
);
|
|
297
|
+
if (startsWithKeywordBlock) {
|
|
298
|
+
return 1;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (/\bdo\b(\s*\|[^|]*\|)?\s*$/.test(line)) {
|
|
302
|
+
return 1;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function stripRubyLineComment(line) {
|
|
309
|
+
return line.replace(/#.*$/, '');
|
|
310
|
+
}
|
|
311
|
+
|
|
113
312
|
function requireExpoConfigPlugins() {
|
|
114
313
|
try {
|
|
115
314
|
return require('expo/config-plugins');
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const {
|
|
4
|
+
DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
5
|
+
DEFAULT_NSE_MARKETING_VERSION,
|
|
6
|
+
} = require('../shared/nse/initNseCore');
|
|
3
7
|
const {
|
|
4
8
|
patchXcodeProjectForNotifyKitNse,
|
|
5
9
|
} = require('../shared/nse/patchXcodeProject');
|
|
@@ -20,6 +24,7 @@ function withNotifyKitIosNseXcodeProject(config, nseOptions) {
|
|
|
20
24
|
targetName: nseOptions.targetName,
|
|
21
25
|
bundleIdentifier,
|
|
22
26
|
parentTargetName: modConfig.modRequest.projectName,
|
|
27
|
+
...resolveNseVersionOptions(modConfig),
|
|
23
28
|
});
|
|
24
29
|
|
|
25
30
|
if (result.didChange && !result.hostTargetUuid) {
|
|
@@ -32,6 +37,18 @@ function withNotifyKitIosNseXcodeProject(config, nseOptions) {
|
|
|
32
37
|
});
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
function resolveNseVersionOptions(config) {
|
|
41
|
+
return {
|
|
42
|
+
marketingVersion: optionalString(config.version) ?? DEFAULT_NSE_MARKETING_VERSION,
|
|
43
|
+
currentProjectVersion:
|
|
44
|
+
optionalString(config.ios?.buildNumber) ?? DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function optionalString(value) {
|
|
49
|
+
return typeof value === 'string' ? value : undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
35
52
|
function requireExpoConfigPlugins() {
|
|
36
53
|
try {
|
|
37
54
|
return require('expo/config-plugins');
|
|
@@ -4,6 +4,8 @@ const NSE_TARGET_NAME_PATTERN = /^[A-Za-z0-9_\-.]+$/;
|
|
|
4
4
|
const NSE_BUNDLE_SUFFIX_PATTERN = /^\.[A-Za-z0-9\-.]+$/;
|
|
5
5
|
|
|
6
6
|
const PRODUCT_BUNDLE_IDENTIFIER_PLACEHOLDER = '$(PRODUCT_BUNDLE_IDENTIFIER:default)';
|
|
7
|
+
const DEFAULT_NSE_MARKETING_VERSION = '1.0';
|
|
8
|
+
const DEFAULT_NSE_CURRENT_PROJECT_VERSION = '1';
|
|
7
9
|
|
|
8
10
|
const NOTIFICATION_SERVICE_SWIFT = String.raw`import Foundation
|
|
9
11
|
import UserNotifications
|
|
@@ -124,9 +126,9 @@ const NSE_INFO_PLIST_TEMPLATE = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
124
126
|
\t<key>CFBundlePackageType</key>
|
|
125
127
|
\t<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
|
126
128
|
\t<key>CFBundleShortVersionString</key>
|
|
127
|
-
\t<string>
|
|
129
|
+
\t<string>{{MARKETING_VERSION}}</string>
|
|
128
130
|
\t<key>CFBundleVersion</key>
|
|
129
|
-
\t<string>
|
|
131
|
+
\t<string>{{CURRENT_PROJECT_VERSION}}</string>
|
|
130
132
|
\t<key>NSExtension</key>
|
|
131
133
|
\t<dict>
|
|
132
134
|
\t\t<key>NSExtensionPointIdentifier</key>
|
|
@@ -185,7 +187,13 @@ function renderNotificationServiceSwift() {
|
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
function renderNseInfoPlist(options) {
|
|
188
|
-
|
|
190
|
+
const marketingVersion = options.marketingVersion ?? DEFAULT_NSE_MARKETING_VERSION;
|
|
191
|
+
const currentProjectVersion =
|
|
192
|
+
options.currentProjectVersion ?? DEFAULT_NSE_CURRENT_PROJECT_VERSION;
|
|
193
|
+
|
|
194
|
+
return NSE_INFO_PLIST_TEMPLATE.replace(/\{\{TARGET_NAME\}\}/g, options.targetName)
|
|
195
|
+
.replace(/\{\{MARKETING_VERSION\}\}/g, marketingVersion)
|
|
196
|
+
.replace(/\{\{CURRENT_PROJECT_VERSION\}\}/g, currentProjectVersion);
|
|
189
197
|
}
|
|
190
198
|
|
|
191
199
|
function renderNseEntitlementsPlist() {
|
|
@@ -211,6 +219,8 @@ function toRfc1034Identifier(value) {
|
|
|
211
219
|
}
|
|
212
220
|
|
|
213
221
|
module.exports = {
|
|
222
|
+
DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
223
|
+
DEFAULT_NSE_MARKETING_VERSION,
|
|
214
224
|
deriveNseBundleIdentifier,
|
|
215
225
|
renderNotificationServiceSwift,
|
|
216
226
|
renderNseEntitlementsPlist,
|
|
@@ -12,19 +12,34 @@ function patchPodfileForNotifyKitNse(podfileText, options) {
|
|
|
12
12
|
const placement = options.placement ?? 'nested';
|
|
13
13
|
const useFrameworks = options.useFrameworks ?? false;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const existingNseTarget = findUncommentedTargetBlock(patched, options.targetName);
|
|
16
|
+
|
|
17
|
+
if (!existingNseTarget) {
|
|
18
|
+
if (!hasUncommentedTarget(patched, options.targetName)) {
|
|
19
|
+
const withNseTarget = insertNseTarget(
|
|
20
|
+
patched,
|
|
21
|
+
options.targetName,
|
|
22
|
+
packagePathFromIos,
|
|
23
|
+
placement,
|
|
24
|
+
useFrameworks,
|
|
25
|
+
);
|
|
26
|
+
if (withNseTarget === null) {
|
|
27
|
+
return { contents: patched, didChange: changed };
|
|
28
|
+
}
|
|
29
|
+
patched = withNseTarget;
|
|
30
|
+
changed = true;
|
|
31
|
+
}
|
|
32
|
+
} else if (placement === 'topLevel') {
|
|
33
|
+
const withUpdatedNseTarget = updateTopLevelNseTargetBlock(
|
|
17
34
|
patched,
|
|
18
|
-
|
|
35
|
+
existingNseTarget,
|
|
19
36
|
packagePathFromIos,
|
|
20
|
-
placement,
|
|
21
37
|
useFrameworks,
|
|
22
38
|
);
|
|
23
|
-
if (
|
|
24
|
-
|
|
39
|
+
if (withUpdatedNseTarget !== patched) {
|
|
40
|
+
patched = withUpdatedNseTarget;
|
|
41
|
+
changed = true;
|
|
25
42
|
}
|
|
26
|
-
patched = withNseTarget;
|
|
27
|
-
changed = true;
|
|
28
43
|
}
|
|
29
44
|
|
|
30
45
|
const withRnfbPatch = ensureRnfbPostInstallPatch(patched);
|
|
@@ -66,7 +81,7 @@ function insertNseTarget(content, targetName, packagePathFromIos, placement, use
|
|
|
66
81
|
|
|
67
82
|
function buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrameworks) {
|
|
68
83
|
if (placement === 'topLevel') {
|
|
69
|
-
const useFrameworksLine = buildUseFrameworksLine(useFrameworks);
|
|
84
|
+
const useFrameworksLine = buildUseFrameworksLine(useFrameworks, ' ');
|
|
70
85
|
|
|
71
86
|
return (
|
|
72
87
|
`target '${targetName}' do\n` +
|
|
@@ -84,17 +99,57 @@ function buildNseTargetBlock(targetName, packagePathFromIos, placement, useFrame
|
|
|
84
99
|
);
|
|
85
100
|
}
|
|
86
101
|
|
|
87
|
-
function
|
|
102
|
+
function updateTopLevelNseTargetBlock(content, targetBlock, packagePathFromIos, useFrameworks) {
|
|
103
|
+
const originalBlock = content.slice(targetBlock.startIndex, targetBlock.endIndex);
|
|
104
|
+
const hasTrailingNewline = originalBlock.endsWith('\n');
|
|
105
|
+
const blockWithoutTrailingNewline = hasTrailingNewline
|
|
106
|
+
? originalBlock.slice(0, -1)
|
|
107
|
+
: originalBlock;
|
|
108
|
+
const lines = blockWithoutTrailingNewline.split('\n');
|
|
109
|
+
|
|
110
|
+
if (lines.length < 2) {
|
|
111
|
+
return content;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const targetLine = lines[0];
|
|
115
|
+
const endLine = lines[lines.length - 1];
|
|
116
|
+
const targetIndent = targetLine.match(/^[ \t]*/)?.[0] ?? '';
|
|
117
|
+
const bodyIndent = `${targetIndent} `;
|
|
118
|
+
const generatedLines = [
|
|
119
|
+
...buildUseFrameworksLine(useFrameworks, bodyIndent).trimEnd().split('\n').filter(Boolean),
|
|
120
|
+
`${bodyIndent}pod 'RNNotifeeCore', :path => '${packagePathFromIos}'`,
|
|
121
|
+
];
|
|
122
|
+
const preservedBodyLines = lines
|
|
123
|
+
.slice(1, -1)
|
|
124
|
+
.filter(line => !isUncommentedUseFrameworksLine(line))
|
|
125
|
+
.filter(line => !isUncommentedRnNotifeeCorePodLine(line))
|
|
126
|
+
.filter(line => !isUncommentedSearchPathInheritanceLine(line));
|
|
127
|
+
const updatedBlock =
|
|
128
|
+
[targetLine, ...generatedLines, ...preservedBodyLines, endLine].join('\n') +
|
|
129
|
+
(hasTrailingNewline ? '\n' : '');
|
|
130
|
+
|
|
131
|
+
if (updatedBlock === originalBlock) {
|
|
132
|
+
return content;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
content.slice(0, targetBlock.startIndex) +
|
|
137
|
+
updatedBlock +
|
|
138
|
+
content.slice(targetBlock.endIndex)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function buildUseFrameworksLine(useFrameworks, indent) {
|
|
88
143
|
if (useFrameworks === 'static') {
|
|
89
|
-
return
|
|
144
|
+
return `${indent}use_frameworks! :linkage => :static\n`;
|
|
90
145
|
}
|
|
91
146
|
|
|
92
147
|
if (useFrameworks === 'dynamic') {
|
|
93
|
-
return
|
|
148
|
+
return `${indent}use_frameworks! :linkage => :dynamic\n`;
|
|
94
149
|
}
|
|
95
150
|
|
|
96
151
|
if (useFrameworks === true) {
|
|
97
|
-
return
|
|
152
|
+
return `${indent}use_frameworks!\n`;
|
|
98
153
|
}
|
|
99
154
|
|
|
100
155
|
return '';
|
|
@@ -241,6 +296,45 @@ function stripRubyLineComment(line) {
|
|
|
241
296
|
return line.replace(/#.*$/, '');
|
|
242
297
|
}
|
|
243
298
|
|
|
299
|
+
function findUncommentedTargetBlock(content, targetName) {
|
|
300
|
+
const pattern = new RegExp(
|
|
301
|
+
`^[ \\t]*target\\s+['"]${escapeRegex(targetName)}['"]\\s+do\\b.*$`,
|
|
302
|
+
'gm',
|
|
303
|
+
);
|
|
304
|
+
let match;
|
|
305
|
+
|
|
306
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
307
|
+
const line = match[0];
|
|
308
|
+
if (stripRubyLineComment(line).trim().length === 0) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const endLineStart = findMatchingRubyBlockEnd(content, match.index);
|
|
313
|
+
if (endLineStart === -1) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
startIndex: match.index,
|
|
319
|
+
endIndex: findLineEnd(content, endLineStart),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function isUncommentedUseFrameworksLine(line) {
|
|
327
|
+
return /^use_frameworks!(?:\s|$)/.test(stripRubyLineComment(line).trim());
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function isUncommentedRnNotifeeCorePodLine(line) {
|
|
331
|
+
return /^pod\s+['"]RNNotifeeCore['"](?:\s|,|$)/.test(stripRubyLineComment(line).trim());
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function isUncommentedSearchPathInheritanceLine(line) {
|
|
335
|
+
return /^inherit!\s+:search_paths\b/.test(stripRubyLineComment(line).trim());
|
|
336
|
+
}
|
|
337
|
+
|
|
244
338
|
function hasUncommentedTarget(content, targetName) {
|
|
245
339
|
const pattern = new RegExp(`target\\s+['"]${escapeRegex(targetName)}['"]`);
|
|
246
340
|
for (const line of content.split('\n')) {
|
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
|
+
const {
|
|
5
|
+
DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
6
|
+
DEFAULT_NSE_MARKETING_VERSION,
|
|
7
|
+
} = require('./initNseCore');
|
|
4
8
|
|
|
5
9
|
function patchXcodeProjectForNotifyKitNse(proj, options) {
|
|
6
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
targetName,
|
|
12
|
+
bundleIdentifier,
|
|
13
|
+
parentTargetName,
|
|
14
|
+
deploymentTarget = '15.1',
|
|
15
|
+
marketingVersion = DEFAULT_NSE_MARKETING_VERSION,
|
|
16
|
+
currentProjectVersion = DEFAULT_NSE_CURRENT_PROJECT_VERSION,
|
|
17
|
+
} = options;
|
|
7
18
|
const warnings = [];
|
|
19
|
+
const existingTargetUuid = findTargetByName(proj, targetName);
|
|
20
|
+
|
|
21
|
+
if (existingTargetUuid) {
|
|
22
|
+
const didChange = setBuildSettings(
|
|
23
|
+
proj,
|
|
24
|
+
existingTargetUuid,
|
|
25
|
+
targetName,
|
|
26
|
+
bundleIdentifier,
|
|
27
|
+
deploymentTarget,
|
|
28
|
+
marketingVersion,
|
|
29
|
+
currentProjectVersion,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (!didChange) {
|
|
33
|
+
return { didChange: false, warnings };
|
|
34
|
+
}
|
|
8
35
|
|
|
9
|
-
|
|
10
|
-
|
|
36
|
+
return {
|
|
37
|
+
didChange: true,
|
|
38
|
+
targetUuid: existingTargetUuid,
|
|
39
|
+
hostTargetUuid: findHostTarget(proj, parentTargetName) ?? undefined,
|
|
40
|
+
warnings,
|
|
41
|
+
};
|
|
11
42
|
}
|
|
12
43
|
|
|
13
44
|
const target = proj.addTarget(targetName, 'app_extension', targetName);
|
|
@@ -40,7 +71,15 @@ function patchXcodeProjectForNotifyKitNse(proj, options) {
|
|
|
40
71
|
stripRnfbInfoPlistInputPath(proj, hostUuid);
|
|
41
72
|
}
|
|
42
73
|
|
|
43
|
-
setBuildSettings(
|
|
74
|
+
setBuildSettings(
|
|
75
|
+
proj,
|
|
76
|
+
targetUuid,
|
|
77
|
+
targetName,
|
|
78
|
+
bundleIdentifier,
|
|
79
|
+
deploymentTarget,
|
|
80
|
+
marketingVersion,
|
|
81
|
+
currentProjectVersion,
|
|
82
|
+
);
|
|
44
83
|
|
|
45
84
|
return {
|
|
46
85
|
didChange: true,
|
|
@@ -81,34 +120,101 @@ function findTargetByName(proj, name) {
|
|
|
81
120
|
return null;
|
|
82
121
|
}
|
|
83
122
|
|
|
84
|
-
function targetExists(proj, name) {
|
|
85
|
-
return findTargetByName(proj, name) !== null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
123
|
function getTargetProductUuid(target) {
|
|
89
124
|
const productReference = target.pbxNativeTarget && target.pbxNativeTarget.productReference;
|
|
90
125
|
return typeof productReference === 'string' ? productReference : undefined;
|
|
91
126
|
}
|
|
92
127
|
|
|
93
|
-
function setBuildSettings(
|
|
128
|
+
function setBuildSettings(
|
|
129
|
+
proj,
|
|
130
|
+
targetUuid,
|
|
131
|
+
targetName,
|
|
132
|
+
bundleId,
|
|
133
|
+
deploymentTarget,
|
|
134
|
+
marketingVersion,
|
|
135
|
+
currentProjectVersion,
|
|
136
|
+
) {
|
|
137
|
+
let didChange = false;
|
|
138
|
+
|
|
139
|
+
for (const settings of getTargetBuildSettings(proj, targetUuid, targetName)) {
|
|
140
|
+
didChange =
|
|
141
|
+
setBuildSetting(settings, 'INFOPLIST_FILE', `"${targetName}/Info.plist"`) || didChange;
|
|
142
|
+
didChange =
|
|
143
|
+
setBuildSetting(settings, 'PRODUCT_BUNDLE_IDENTIFIER', `"${bundleId}"`) || didChange;
|
|
144
|
+
didChange = setBuildSetting(settings, 'TARGETED_DEVICE_FAMILY', `"1,2"`) || didChange;
|
|
145
|
+
didChange =
|
|
146
|
+
setBuildSetting(settings, 'IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget) || didChange;
|
|
147
|
+
didChange = setBuildSetting(settings, 'MARKETING_VERSION', marketingVersion) || didChange;
|
|
148
|
+
didChange =
|
|
149
|
+
setBuildSetting(settings, 'CURRENT_PROJECT_VERSION', currentProjectVersion) || didChange;
|
|
150
|
+
didChange = setBuildSetting(settings, 'SWIFT_VERSION', '5.0') || didChange;
|
|
151
|
+
didChange =
|
|
152
|
+
setBuildSetting(
|
|
153
|
+
settings,
|
|
154
|
+
'CODE_SIGN_ENTITLEMENTS',
|
|
155
|
+
`"${targetName}/${targetName}.entitlements"`,
|
|
156
|
+
) || didChange;
|
|
157
|
+
didChange = setBuildSetting(settings, 'GENERATE_INFOPLIST_FILE', 'NO') || didChange;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return didChange;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getTargetBuildSettings(proj, targetUuid, targetName) {
|
|
164
|
+
const target = proj.pbxNativeTargetSection()[targetUuid];
|
|
165
|
+
const buildConfigurationListUuid = target && target.buildConfigurationList;
|
|
94
166
|
const configs = proj.pbxXCBuildConfigurationSection();
|
|
167
|
+
const settingsByConfigurationList = getBuildSettingsFromConfigurationList(
|
|
168
|
+
proj,
|
|
169
|
+
typeof buildConfigurationListUuid === 'string' ? buildConfigurationListUuid : undefined,
|
|
170
|
+
configs,
|
|
171
|
+
);
|
|
95
172
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
173
|
+
if (settingsByConfigurationList.length > 0) {
|
|
174
|
+
return settingsByConfigurationList;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return Object.entries(configs)
|
|
178
|
+
.filter(([, value]) => typeof value === 'object' && value !== null)
|
|
179
|
+
.map(([, value]) => value)
|
|
180
|
+
.filter(config => {
|
|
181
|
+
const settings = config.buildSettings;
|
|
182
|
+
return settings?.PRODUCT_NAME === `"${targetName}"`;
|
|
183
|
+
})
|
|
184
|
+
.map(config => config.buildSettings);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getBuildSettingsFromConfigurationList(proj, buildConfigurationListUuid, configs) {
|
|
188
|
+
if (!buildConfigurationListUuid) {
|
|
189
|
+
return [];
|
|
111
190
|
}
|
|
191
|
+
|
|
192
|
+
const configurationLists = proj.hash.project.objects.XCConfigurationList;
|
|
193
|
+
const configurationList = configurationLists && configurationLists[buildConfigurationListUuid];
|
|
194
|
+
const buildConfigurations = Array.isArray(configurationList?.buildConfigurations)
|
|
195
|
+
? configurationList.buildConfigurations
|
|
196
|
+
: [];
|
|
197
|
+
|
|
198
|
+
return buildConfigurations
|
|
199
|
+
.map(ref => ref?.value)
|
|
200
|
+
.filter(uuid => typeof uuid === 'string')
|
|
201
|
+
.map(uuid => configs[uuid])
|
|
202
|
+
.filter(config => typeof config === 'object' && config !== null)
|
|
203
|
+
.map(config => {
|
|
204
|
+
if (typeof config.buildSettings !== 'object' || config.buildSettings === null) {
|
|
205
|
+
config.buildSettings = {};
|
|
206
|
+
}
|
|
207
|
+
return config.buildSettings;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function setBuildSetting(settings, key, value) {
|
|
212
|
+
if (settings[key] === value) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
settings[key] = value;
|
|
217
|
+
return true;
|
|
112
218
|
}
|
|
113
219
|
|
|
114
220
|
function fixProductFileReference(proj, targetName) {
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '10.4.
|
|
2
|
+
export const version = '10.4.2';
|