@qore-id/react-native-qoreid-sdk 2.0.1 โ 2.1.0-rc
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/RNQoreIdSdk.podspec +9 -3
- package/android/build.gradle +2 -0
- package/android/src/main/java/com/qoreid/reactnativeqoreidsdk/RNQoreIdSdkModule.kt +26 -27
- package/app.plugin.js +30 -0
- package/ios/RNQoreIdSdk.h +0 -13
- package/ios/RNQoreIdSdk.mm +19 -10
- package/ios/ViewController.swift +10 -10
- package/package.json +25 -4
- package/scripts/android/setupQoreid.gradle.kts +225 -0
- package/scripts/ios/qoreid_sdk_pods.rb +365 -0
- package/scripts/js/android-setup.js +37 -0
- package/scripts/js/ios-setup.js +71 -0
- package/scripts/js/setup.js +10 -0
- package/scripts/js/uninstall-android.js +36 -0
- package/scripts/js/uninstall-ios.js +42 -0
- package/scripts/js/uninstall.js +10 -0
- package/scripts/js/utils.js +213 -0
- package/scripts/qoreid.config.json +1 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# qoreid_sdk_pods.rb
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'xcodeproj'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
def log(msg)
|
|
7
|
+
Pod::UI.puts "[QOREID] #{msg}"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def warn(msg)
|
|
11
|
+
Pod::UI.warn "[QOREID] #{msg}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def qoreid_sdk_post_install(installer)
|
|
15
|
+
sandbox_root = installer.sandbox.root.to_s
|
|
16
|
+
project_root = sandbox_root.sub(/\/Pods$/, "")
|
|
17
|
+
|
|
18
|
+
app_target = installer.aggregate_targets.first.name.sub(/^Pods-/, "")
|
|
19
|
+
log "Detected app target: #{app_target}"
|
|
20
|
+
|
|
21
|
+
ios_path = File.join(project_root, app_target)
|
|
22
|
+
|
|
23
|
+
app_delegate_swift = File.join(ios_path, "AppDelegate.swift")
|
|
24
|
+
app_delegate_m = File.join(ios_path, "AppDelegate.m")
|
|
25
|
+
scene_delegate_swift = File.join(ios_path, "SceneDelegate.swift")
|
|
26
|
+
info_plist_path = File.join(ios_path, "Info.plist")
|
|
27
|
+
|
|
28
|
+
log "๐ Running iOS auto-configuration..."
|
|
29
|
+
|
|
30
|
+
# ------------------------------
|
|
31
|
+
# Detect AppDelegate file
|
|
32
|
+
# ------------------------------
|
|
33
|
+
if File.exist?(app_delegate_swift)
|
|
34
|
+
modify_app_delegate_swift(app_delegate_swift)
|
|
35
|
+
elsif File.exist?(app_delegate_m)
|
|
36
|
+
modify_app_delegate_objc(app_delegate_m)
|
|
37
|
+
else
|
|
38
|
+
warn "โ ๏ธ No AppDelegate.swift or AppDelegate.m found."
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# ------------------------------
|
|
42
|
+
# Create SceneDelegate.swift
|
|
43
|
+
# ------------------------------
|
|
44
|
+
if File.exist?(scene_delegate_swift)
|
|
45
|
+
log "โ๏ธ SceneDelegate.swift already exists."
|
|
46
|
+
else
|
|
47
|
+
create_scene_delegate_swift(scene_delegate_swift)
|
|
48
|
+
log "๐ SceneDelegate.swift created."
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
# NEW: Add to Xcode project
|
|
52
|
+
add_file_to_xcode_project(installer, scene_delegate_swift, app_target)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ------------------------------
|
|
56
|
+
# Update Info.plist
|
|
57
|
+
# ------------------------------
|
|
58
|
+
# Ensure the file exists
|
|
59
|
+
if File.exist?(info_plist_path)
|
|
60
|
+
update_info_plist(info_plist_path)
|
|
61
|
+
else
|
|
62
|
+
warn "โ ๏ธ Info.plist not found at path: #{info_plist_path}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
log "๐ iOS setup complete."
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ==============================================================
|
|
70
|
+
# MODIFY APPDELEGATE (SWIFT)
|
|
71
|
+
# ==============================================================
|
|
72
|
+
|
|
73
|
+
def modify_app_delegate_swift(path)
|
|
74
|
+
content = File.read(path)
|
|
75
|
+
|
|
76
|
+
if content.include?("configurationForConnecting")
|
|
77
|
+
log "โ๏ธ AppDelegate.swift already configured โ skipping."
|
|
78
|
+
return
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
insertion = <<-SWIFT
|
|
82
|
+
|
|
83
|
+
// MARK: - QoreID Scene Support
|
|
84
|
+
func application(_ application: UIApplication,
|
|
85
|
+
configurationForConnecting connectingSceneSession: UISceneSession,
|
|
86
|
+
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
|
87
|
+
let config = UISceneConfiguration(name: "Default Configuration",
|
|
88
|
+
sessionRole: connectingSceneSession.role)
|
|
89
|
+
config.delegateClass = SceneDelegate.self
|
|
90
|
+
return config
|
|
91
|
+
}
|
|
92
|
+
SWIFT
|
|
93
|
+
|
|
94
|
+
# New Regex: Finds the class definition and its content, up to the closing brace.
|
|
95
|
+
# The use of `.*?` makes the matching non-greedy, stopping at the first logical match.
|
|
96
|
+
# We look for the final brace of the AppDelegate class specifically.
|
|
97
|
+
app_delegate_regex = /(\s+class\s+AppDelegate[^{]*\{[\s\S]*?)(\n^\})/m
|
|
98
|
+
|
|
99
|
+
# Search for the class block start and stop
|
|
100
|
+
if content.match(app_delegate_regex)
|
|
101
|
+
# The insertion point should be the line just before the final `}` of the AppDelegate.
|
|
102
|
+
# We replace the final closing brace with the new code followed by the closing brace.
|
|
103
|
+
# We use a pattern that finds the opening brace of AppDelegate and captures the content
|
|
104
|
+
# inside, making the capture non-greedy until it finds the first `}` on its own line.
|
|
105
|
+
|
|
106
|
+
# Pattern:
|
|
107
|
+
# 1. `class AppDelegate ... {` (captured in group 1: `\\1`)
|
|
108
|
+
# 2. `[\s\S]*?` (all content, non-greedy)
|
|
109
|
+
# 3. `^\}` (the final closing brace on a new line, captured in group 2: `\\2`)
|
|
110
|
+
|
|
111
|
+
# We use a simplified and more direct approach by looking for the content
|
|
112
|
+
# and replacing the LAST line of the AppDelegate class body before its closing brace.
|
|
113
|
+
|
|
114
|
+
# Find content from 'class AppDelegate' up to its final '}'
|
|
115
|
+
# We use a more robust search pattern focusing on the end of the class.
|
|
116
|
+
# (Group 1: everything up to the last line before '}', Group 2: the final '}')
|
|
117
|
+
replacement_successful = content.sub!(
|
|
118
|
+
app_delegate_regex,
|
|
119
|
+
"\\1\n#{insertion}\n\\2"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
content = comment_out_rn_start_method(content)
|
|
123
|
+
|
|
124
|
+
if replacement_successful
|
|
125
|
+
File.write(path, content)
|
|
126
|
+
log "๐ง Added Scene configuration to AppDelegate.swift inside AppDelegate class"
|
|
127
|
+
else
|
|
128
|
+
log "โ ๏ธ Could not perform targeted substitution"
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
log "โ ๏ธ Could not find AppDelegate class โ Scene snippet not inserted"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def comment_out_rn_start_method(content)
|
|
136
|
+
rn_start_regx = /factory.startReactNative\([\s\S]*?\)/
|
|
137
|
+
if content.match?(rn_start_regx)
|
|
138
|
+
content = content.sub!(rn_start_regx, "")
|
|
139
|
+
end
|
|
140
|
+
content
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# ==============================================================
|
|
144
|
+
# MODIFY APPDELEGATE (OBJECTIVE-C)
|
|
145
|
+
# ==============================================================
|
|
146
|
+
|
|
147
|
+
def modify_app_delegate_objc(path)
|
|
148
|
+
content = File.read(path)
|
|
149
|
+
|
|
150
|
+
if content.include?("configurationForConnectingSceneSession")
|
|
151
|
+
log "โ๏ธ AppDelegate.m already configured โ skipping."
|
|
152
|
+
return
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
insertion = <<-OBJC
|
|
156
|
+
|
|
157
|
+
// MARK: - QoreID Scene Support
|
|
158
|
+
- (UISceneConfiguration *)application:(UIApplication *)application
|
|
159
|
+
configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession
|
|
160
|
+
options:(UISceneConnectionOptions *)options {
|
|
161
|
+
UISceneConfiguration *configuration =
|
|
162
|
+
[[UISceneConfiguration alloc] initWithName:@"Default Configuration"
|
|
163
|
+
sessionRole:connectingSceneSession.role];
|
|
164
|
+
configuration.delegateClass = [SceneDelegate class];
|
|
165
|
+
return configuration;
|
|
166
|
+
}
|
|
167
|
+
OBJC
|
|
168
|
+
|
|
169
|
+
content.sub!(/@end\s*\z/, "#{insertion}\n@end")
|
|
170
|
+
|
|
171
|
+
File.write(path, content)
|
|
172
|
+
log "๐ง Added Scene configuration to AppDelegate.m"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ==============================================================
|
|
177
|
+
# CREATE SCENEDELEGATE.SWIFT
|
|
178
|
+
# ==============================================================
|
|
179
|
+
|
|
180
|
+
def create_scene_delegate_swift(path)
|
|
181
|
+
# Load RN_APP_NAME from qoreid.config.json
|
|
182
|
+
relative_path = File.join(File.dirname(__FILE__), '..', 'qoreid.config.json')
|
|
183
|
+
file_contents = File.read(relative_path)
|
|
184
|
+
app_name = JSON.parse(file_contents)['RN_APP_NAME'] || "main"
|
|
185
|
+
|
|
186
|
+
template = <<-SWIFT
|
|
187
|
+
import UIKit
|
|
188
|
+
|
|
189
|
+
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
190
|
+
|
|
191
|
+
var window: UIWindow?
|
|
192
|
+
|
|
193
|
+
func scene(_ scene: UIScene,
|
|
194
|
+
willConnectTo session: UISceneSession,
|
|
195
|
+
options connectionOptions: UIScene.ConnectionOptions) {
|
|
196
|
+
|
|
197
|
+
guard let windowScene = scene as? UIWindowScene else { return }
|
|
198
|
+
|
|
199
|
+
let window = UIWindow(windowScene: windowScene)
|
|
200
|
+
|
|
201
|
+
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
|
202
|
+
guard let factory = appDelegate.reactNativeFactory else {
|
|
203
|
+
fatalError("React Native factory not initialized")
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let rootView = factory.rootViewFactory.view(
|
|
207
|
+
withModuleName: "#{app_name}",
|
|
208
|
+
initialProperties: [:],
|
|
209
|
+
launchOptions: nil
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
let viewController = UIViewController()
|
|
213
|
+
viewController.view = rootView
|
|
214
|
+
|
|
215
|
+
let navController = UINavigationController(rootViewController: viewController)
|
|
216
|
+
navController.setNavigationBarHidden(true, animated: false)
|
|
217
|
+
|
|
218
|
+
window.rootViewController = navController
|
|
219
|
+
window.makeKeyAndVisible()
|
|
220
|
+
|
|
221
|
+
self.window = window
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
SWIFT
|
|
225
|
+
|
|
226
|
+
File.write(path, template)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def add_file_to_xcode_project(installer, file_path, target_name)
|
|
231
|
+
project = installer.pods_project
|
|
232
|
+
|
|
233
|
+
# WARNING: This path calculation is fragile and assumes a specific file hierarchy.
|
|
234
|
+
app_project_path = project.path.dirname + "../#{target_name}.xcodeproj"
|
|
235
|
+
|
|
236
|
+
unless File.exist?(app_project_path)
|
|
237
|
+
warn "โ ๏ธ Application Xcode project not found at calculated path: #{app_project_path}"
|
|
238
|
+
return
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
app_project = Xcodeproj::Project.open(app_project_path)
|
|
242
|
+
app_target = app_project.targets.find { |t| t.name == target_name }
|
|
243
|
+
|
|
244
|
+
if app_target.nil?
|
|
245
|
+
warn "โ ๏ธ Could not find Xcode target: #{target_name}"
|
|
246
|
+
return
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# 1. Find or create the target group (usually matching the target_name folder)
|
|
250
|
+
group = app_project.main_group.find_subpath(target_name, true)
|
|
251
|
+
group.set_source_tree('SOURCE_ROOT')
|
|
252
|
+
|
|
253
|
+
# 2. Determine relative path for file reference
|
|
254
|
+
begin
|
|
255
|
+
# Get path relative to the .xcodeproj directory
|
|
256
|
+
rel_path = Pathname.new(file_path).relative_path_from(app_project.path.dirname).to_s
|
|
257
|
+
rescue
|
|
258
|
+
# Fallback to absolute path if calculation fails
|
|
259
|
+
rel_path = file_path
|
|
260
|
+
warn "โ ๏ธ Could not calculate relative path for #{file_path}. Using absolute path."
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# 3. Create file reference (or find existing one if already added)
|
|
264
|
+
# NOTE: Xcodeproj will not create a duplicate reference if one with the same path exists in the group.
|
|
265
|
+
file_ref = group.new_file(rel_path)
|
|
266
|
+
|
|
267
|
+
# 4. Add file reference to the target's build phases
|
|
268
|
+
file_basename = File.basename(file_path)
|
|
269
|
+
|
|
270
|
+
# Check if the file reference is already associated with the target's Source Build Phase.
|
|
271
|
+
# This is the correct, though verbose, check for Swift/Obj-C source files.
|
|
272
|
+
is_already_a_source = app_target.source_build_phase.files.any? { |f| f.file_ref.path == file_ref.path }
|
|
273
|
+
|
|
274
|
+
if is_already_a_source
|
|
275
|
+
log "File #{file_basename} is already referenced by the Source Build Phase. Skipping addition."
|
|
276
|
+
else
|
|
277
|
+
# Use the preferred method which handles all build phases (.swift, .h, .m, resources)
|
|
278
|
+
begin
|
|
279
|
+
app_target.add_file_references([file_ref])
|
|
280
|
+
rescue => e
|
|
281
|
+
# Fallback if add_file_references fails
|
|
282
|
+
warn "โ Primary method failed. Attempting to force Source membership: #{e.message}"
|
|
283
|
+
|
|
284
|
+
# Manual fallback to ensure it is added to Compile Sources if it is a Swift file
|
|
285
|
+
if file_path.end_with?('.swift')
|
|
286
|
+
app_target.source_build_phase.add_file_reference(file_ref)
|
|
287
|
+
log "Forced addition to Compile Sources build phase."
|
|
288
|
+
else
|
|
289
|
+
warn "File type not recognized for forced Source/Resource addition."
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# 5. Guaranteed Save
|
|
295
|
+
begin
|
|
296
|
+
app_project.save
|
|
297
|
+
rescue => e
|
|
298
|
+
warn "โ Failed to save Xcode project: #{e.message}"
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# ==============================================================
|
|
303
|
+
# UPDATE INFOPLIST (if needed)
|
|
304
|
+
# ==============================================================
|
|
305
|
+
|
|
306
|
+
# Function to update Info.plist with Scene Manifest configuration.
|
|
307
|
+
# This logic checks for the key and inserts the required XML structure
|
|
308
|
+
# before the final </dict> tag of the root plist dictionary.
|
|
309
|
+
def update_info_plist(path)
|
|
310
|
+
content = File.read(path)
|
|
311
|
+
|
|
312
|
+
# 1. Define the XML snippet to insert
|
|
313
|
+
insertion = <<-XML
|
|
314
|
+
<key>UIApplicationSceneManifest</key>
|
|
315
|
+
<dict>
|
|
316
|
+
<key>UIApplicationSupportsMultipleScenes</key>
|
|
317
|
+
<false/>
|
|
318
|
+
<key>UISceneConfigurations</key>
|
|
319
|
+
<dict>
|
|
320
|
+
<key>UIWindowSceneSessionRoleApplication</key>
|
|
321
|
+
<array>
|
|
322
|
+
<dict>
|
|
323
|
+
<key>UISceneClassName</key>
|
|
324
|
+
<string>UIWindowScene</string>
|
|
325
|
+
<key>UISceneDelegateClassName</key>
|
|
326
|
+
<string>SceneDelegate</string>
|
|
327
|
+
<key>UISceneConfigurationName</key>
|
|
328
|
+
<string>Default Configuration</string>
|
|
329
|
+
</dict>
|
|
330
|
+
</array>
|
|
331
|
+
</dict>
|
|
332
|
+
</dict>
|
|
333
|
+
XML
|
|
334
|
+
|
|
335
|
+
# 2. Check if the configuration already exists
|
|
336
|
+
if content.include?("<key>UIApplicationSceneManifest</key>")
|
|
337
|
+
log "โ๏ธ Info.plist already contains UIApplicationSceneManifest โ skipping."
|
|
338
|
+
return
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# 3. Find the injection point: the final closing </dict> before </plist>
|
|
342
|
+
# We use a pattern that specifically targets the `</dict>` tag that is followed
|
|
343
|
+
# by `</plist>` (potentially with leading whitespace). This ensures we are
|
|
344
|
+
# inside the root dictionary.
|
|
345
|
+
|
|
346
|
+
# The regex captures:
|
|
347
|
+
# Group 1 (\\1): The closing </dict> tag
|
|
348
|
+
# Group 2 (\\2): The closing </plist> tag
|
|
349
|
+
|
|
350
|
+
# We look for the last instance of </dict> followed by </plist> at the end of the file.
|
|
351
|
+
|
|
352
|
+
# We escape the `<` and `>` tags for regex safety.
|
|
353
|
+
final_dict_regex = /<\/dict>(\s*)<\/plist>/m
|
|
354
|
+
|
|
355
|
+
# Perform the substitution: inject the insertion before the closing </dict>
|
|
356
|
+
replacement_successful = content.sub!(final_dict_regex, "#{insertion}\\1</dict>\\2</plist>")
|
|
357
|
+
|
|
358
|
+
if replacement_successful
|
|
359
|
+
File.write(path, content)
|
|
360
|
+
log "๐ง Added UIApplicationSceneManifest configuration to Info.plist."
|
|
361
|
+
else
|
|
362
|
+
log "โ ๏ธ Failed to find the final </dict> tag in Info.plist for substitution."
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
const {
|
|
6
|
+
sharedEnv,
|
|
7
|
+
extractAndroidNamespace,
|
|
8
|
+
patchExpoAndroidGeneratedAutolinking,
|
|
9
|
+
} = require('./utils');
|
|
10
|
+
|
|
11
|
+
const androidPath = path.join(process.cwd(), 'android');
|
|
12
|
+
|
|
13
|
+
// execute ./gradlew removeQoreidSetup from android directory
|
|
14
|
+
const gradlewPath = process.platform === 'win32' ? 'gradlew.bat' : './gradlew';
|
|
15
|
+
const gradlewFullPath = path.join(androidPath, gradlewPath);
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(gradlewFullPath)) {
|
|
18
|
+
console.error(
|
|
19
|
+
'Gradle wrapper not found. Are you in the root of a React Native project?'
|
|
20
|
+
);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
console.log('๐ง Setting up Android Qoreid SDK...');
|
|
26
|
+
const androidNamespace = extractAndroidNamespace();
|
|
27
|
+
sharedEnv.set(androidNamespace, 'FULL_ANDROID_NAMESPACE');
|
|
28
|
+
const command = sharedEnv.getCommand('FULL_ANDROID_NAMESPACE');
|
|
29
|
+
execSync(`${command ? command + ' && ' : ''}${gradlewFullPath} setupQoreid`, {
|
|
30
|
+
cwd: androidPath,
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
});
|
|
33
|
+
androidNamespace && patchExpoAndroidGeneratedAutolinking(androidNamespace);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Error during Android setup:', error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { injectAppName } = require('./utils');
|
|
6
|
+
|
|
7
|
+
const podfilePath = path.join(process.cwd(), 'ios', 'Podfile');
|
|
8
|
+
const requiredLinePath =
|
|
9
|
+
"require_relative '../node_modules/@qore-id/react-native-qoreid-sdk/scripts/ios/qoreid_sdk_pods.rb'";
|
|
10
|
+
|
|
11
|
+
const postInstallLine = 'qoreid_sdk_post_install(installer)';
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(podfilePath)) {
|
|
14
|
+
console.error(
|
|
15
|
+
'Podfile not found. Are you in the root of a React Native project?'
|
|
16
|
+
);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
injectAppName();
|
|
21
|
+
|
|
22
|
+
let podfileContent = fs.readFileSync(podfilePath, 'utf8');
|
|
23
|
+
|
|
24
|
+
// Check and add the require_relative line if it's not present
|
|
25
|
+
if (!podfileContent.includes(requiredLinePath)) {
|
|
26
|
+
podfileContent = `${requiredLinePath}\n` + podfileContent;
|
|
27
|
+
console.log('โ
Added Qoreid require_relative line to Podfile');
|
|
28
|
+
} else {
|
|
29
|
+
console.log('โน๏ธ Qoreid require_relative line already exists in Podfile');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Check and add the post_install call if it's not present
|
|
33
|
+
if (!podfileContent.includes(postInstallLine)) {
|
|
34
|
+
// Find the post_install block
|
|
35
|
+
const postInstallIndex = podfileContent.indexOf(
|
|
36
|
+
'post_install do |installer|'
|
|
37
|
+
);
|
|
38
|
+
if (postInstallIndex !== -1) {
|
|
39
|
+
// Find the end of the post_install block
|
|
40
|
+
const endOfPostInstallIndex = podfileContent.indexOf(
|
|
41
|
+
'end',
|
|
42
|
+
postInstallIndex
|
|
43
|
+
);
|
|
44
|
+
if (endOfPostInstallIndex !== -1) {
|
|
45
|
+
// Insert the post_install call before the end of the block
|
|
46
|
+
podfileContent =
|
|
47
|
+
podfileContent.slice(0, endOfPostInstallIndex) +
|
|
48
|
+
` ${postInstallLine}\n` +
|
|
49
|
+
podfileContent.slice(endOfPostInstallIndex);
|
|
50
|
+
console.log('โ
Added Qoreid post_install call to Podfile');
|
|
51
|
+
} else {
|
|
52
|
+
console.error(
|
|
53
|
+
'Could not find the end of the post_install block in Podfile.',
|
|
54
|
+
'Add the line manually: ' + postInstallLine
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
console.error(
|
|
60
|
+
'post_install block not found in Podfile. Please ensure your Podfile has a post_install block.'
|
|
61
|
+
);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.log('โน๏ธ Qoreid post_install call already exists in Podfile');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Write the updated content back to the Podfile
|
|
69
|
+
fs.writeFileSync(podfilePath, podfileContent, 'utf8');
|
|
70
|
+
|
|
71
|
+
console.log('โ
iOS Qoreid SDK setup complete!');
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { removeQoreIdExpoPlugin } = require('./utils');
|
|
5
|
+
|
|
6
|
+
removeQoreIdExpoPlugin();
|
|
7
|
+
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const androidPath = path.join(cwd, 'android');
|
|
10
|
+
|
|
11
|
+
// execute ./gradlew removeQoreidSetup from android directory
|
|
12
|
+
const gradlewPath = process.platform === 'win32' ? 'gradlew.bat' : './gradlew';
|
|
13
|
+
const gradlewFullPath = path.join(androidPath, gradlewPath);
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(gradlewFullPath)) {
|
|
16
|
+
console.warn(
|
|
17
|
+
'Gradle wrapper not found. Are you in the root of a React Native project?'
|
|
18
|
+
);
|
|
19
|
+
// exit with success to avoid showing an error in the terminal/CI
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { execSync } = require('child_process');
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
console.log('๐งน Rolling back Android Qoreid setup...');
|
|
27
|
+
execSync(`${gradlewFullPath} removeQoreidSetup`, {
|
|
28
|
+
cwd: androidPath,
|
|
29
|
+
stdio: 'inherit',
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error during Android rollback:', error);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log('๐งน Android rollback complete!');
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { removeQoreIdExpoPlugin } = require('./utils');
|
|
5
|
+
|
|
6
|
+
removeQoreIdExpoPlugin();
|
|
7
|
+
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
|
|
10
|
+
const podfilePath = path.join(cwd, 'ios', 'Podfile');
|
|
11
|
+
const requiredLinePath =
|
|
12
|
+
"require_relative '../node_modules/@qore-id/react-native-qoreid-sdk/scripts/ios/qoreid_sdk_pods.rb'";
|
|
13
|
+
const postInstallLine = 'qoreid_sdk_post_install(installer)';
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(podfilePath)) {
|
|
16
|
+
console.error(
|
|
17
|
+
'Podfile not found. Are you in the root of a React Native project?'
|
|
18
|
+
);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let podfileContent = fs.readFileSync(podfilePath, 'utf8');
|
|
23
|
+
|
|
24
|
+
// Remove the require_relative line if it exists
|
|
25
|
+
const requireLineRegex = new RegExp(
|
|
26
|
+
`^\\s*${requiredLinePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`,
|
|
27
|
+
'm'
|
|
28
|
+
);
|
|
29
|
+
podfileContent = podfileContent.replace(requireLineRegex, '');
|
|
30
|
+
|
|
31
|
+
// Remove the post_install call if it exists
|
|
32
|
+
const postInstallRegex = new RegExp(
|
|
33
|
+
`^\\s*${postInstallLine.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`,
|
|
34
|
+
'm'
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
podfileContent = podfileContent.replace(postInstallRegex, '');
|
|
38
|
+
|
|
39
|
+
// Write the updated content back to the Podfile
|
|
40
|
+
fs.writeFileSync(podfilePath, podfileContent, 'utf8');
|
|
41
|
+
|
|
42
|
+
console.log('๐งน iOS Qoreid SDK uninstallation complete!');
|