codeplay-common 4.6.2 → 4.6.4

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.
@@ -1,21 +1,21 @@
1
- /*
2
- Can be run like
3
- node finalrelease
4
- node finalrelease 1
5
- node finalrelease "1,2,7"
6
- */
7
-
8
- import { existsSync, readFileSync, readdirSync, promises, constants, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
9
- import { join, resolve } from 'path';
10
- import { execSync } from 'child_process';
11
- import { createInterface } from 'readline';
12
-
13
- import { fileURLToPath } from 'url';
14
- import { dirname } from 'path';
15
-
16
- /* const path = require('path');
17
- const fs = require('fs'); */
18
-
1
+ /*
2
+ Can be run like
3
+ node finalrelease
4
+ node finalrelease 1
5
+ node finalrelease "1,2,7"
6
+ */
7
+
8
+ import { existsSync, readFileSync, readdirSync, promises, constants, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
9
+ import { join, resolve } from 'path';
10
+ import { execSync } from 'child_process';
11
+ import { createInterface } from 'readline';
12
+
13
+ import { fileURLToPath } from 'url';
14
+ import { dirname } from 'path';
15
+
16
+ /* const path = require('path');
17
+ const fs = require('fs'); */
18
+
19
19
  import fs from 'fs';
20
20
  import path from 'path';
21
21
 
@@ -138,45 +138,45 @@ checkProductionAdmobAlias();
138
138
 
139
139
  // Define a mapping between store IDs and store names
140
140
  /* const storeNames = {
141
- "1": "PlayStore",
142
- "2": "SamsungStore",
143
- "7": "AmazonStore"
144
- }; */
145
-
146
-
147
- const isOnlyOneAPK = true; // 🔥 change to false for normal behavior
148
-
149
- const storeNames = {
150
- "1": "PlayStore",
151
- "2": "SamsungStore",
152
- "7": "AmazonStore",
153
-
154
- "3": "MiStore",
155
- "4": "HuaweiStore",
156
- "5": "OppoStore",
157
- //"6": "iOSStore",
158
- "8": "VivoStore"
159
- };
160
-
161
-
162
- //1=> PlayStore 2=> SamsungStore 3=>MiStore 4=>HuaweiStore 5=>OppoStore 6=>iOSStore 7=> AmazonStore 8=> VivoStore
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
- let isAdmobFound = false;
171
-
172
- const amazonMinSdkVersion=24;
173
-
174
- const androidManifestPath = join("android", "app", "src", "main", "AndroidManifest.xml");
175
-
176
-
177
- const configPath = path.join(process.cwd(), 'capacitor.config.json');
178
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
179
-
141
+ "1": "PlayStore",
142
+ "2": "SamsungStore",
143
+ "7": "AmazonStore"
144
+ }; */
145
+
146
+
147
+ const isOnlyOneAPK = true; // 🔥 change to false for normal behavior
148
+
149
+ const storeNames = {
150
+ "1": "PlayStore",
151
+ "2": "SamsungStore",
152
+ "7": "AmazonStore",
153
+
154
+ "3": "MiStore",
155
+ "4": "HuaweiStore",
156
+ "5": "OppoStore",
157
+ //"6": "iOSStore",
158
+ "8": "VivoStore"
159
+ };
160
+
161
+
162
+ //1=> PlayStore 2=> SamsungStore 3=>MiStore 4=>HuaweiStore 5=>OppoStore 6=>iOSStore 7=> AmazonStore 8=> VivoStore
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+ let isAdmobFound = false;
171
+
172
+ const amazonMinSdkVersion=24;
173
+
174
+ const androidManifestPath = join("android", "app", "src", "main", "AndroidManifest.xml");
175
+
176
+
177
+ const configPath = path.join(process.cwd(), 'capacitor.config.json');
178
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
179
+
180
180
  const _appUniqueId = config.android?.APP_UNIQUE_ID;
181
181
  const _appName=config.appName;
182
182
  const _appPackageId=config.appId;
@@ -214,489 +214,489 @@ function restoreFlowchartStoreApi() {
214
214
  writeFileSync(FLOWCHART_SHARED_PATH, flowchartSharedOriginal, 'utf8');
215
215
  }
216
216
  }
217
-
218
-
219
-
217
+
218
+
219
+
220
220
  function fileExists(filePath) {
221
- return existsSync(filePath);
222
- }
223
-
224
-
225
- const ffmpegPluginXmlPath = path.join(__dirname, 'node_modules', 'codeplay-fmpg', 'plugin.xml');
226
- const capacitorConfigPath = join(process.cwd(), 'capacitor.config.json');
227
-
228
-
229
-
230
- function isFfmpegUsed() {
231
- try {
232
- const xmlContent = fs.readFileSync(ffmpegPluginXmlPath, 'utf8');
233
- // Simple check: if plugin.xml exists and contains <plugin> tag (or any FFmpeg-specific tag)
234
- return /<plugin\b/.test(xmlContent);
235
- } catch (err) {
236
- console.log('⚠️ FFmpeg plugin not found:', err.message);
237
- return false;
238
- }
239
- }
240
-
241
- const _isffmpegUsed = isFfmpegUsed();
242
-
243
- function getAdMobConfig() {
244
- if (!fileExists(capacitorConfigPath)) {
245
- throw new Error('❌ capacitor.config.json not found. Ensure this is a Capacitor project.');
246
- }
247
-
248
- const config = JSON.parse(readFileSync(capacitorConfigPath, 'utf8'));
249
- const admobConfig = config.plugins?.AdMob;
250
-
251
- //_appPackageId=config.appId;
252
-
253
- if (!admobConfig) {
254
- throw new Error('❌ AdMob configuration is missing in capacitor.config.json.');
255
- }
256
-
257
- // Default to true if ADMOB_ENABLED is not specified
258
- const isEnabled = admobConfig.ADMOB_ENABLED !== false;
259
-
260
- if (!isEnabled) {
261
- return { ADMOB_ENABLED: false }; // Skip further validation
262
- }
263
-
264
- if (!admobConfig.APP_ID_ANDROID || !admobConfig.APP_ID_IOS) {
265
- throw new Error(' ❌ AdMob configuration is incomplete. Ensure APP_ID_ANDROID and APP_ID_IOS are defined.');
266
- }
267
-
268
- return {
269
- ADMOB_ENABLED: true,
270
- APP_ID_ANDROID: admobConfig.APP_ID_ANDROID,
271
- APP_ID_IOS: admobConfig.APP_ID_IOS,
272
- USE_LITE_ADS: admobConfig.USE_LITE_ADS === "lite",
273
- };
274
- }
275
-
276
-
277
-
278
- const _capacitorConfig = getAdMobConfig();
279
-
280
- const _isADMOB_ENABLED=_capacitorConfig.ADMOB_ENABLED;
281
- isAdmobFound = _isADMOB_ENABLED;
282
-
283
- // Proceed only if ADMOB_ENABLED is true
284
- //if (_capacitorConfig.ADMOB_ENABLED)
285
-
286
-
287
- const admobConfigPath = join('src', 'js','Ads', 'admob-ad-configuration-nextgen.json');
288
- let admobConfig;
289
-
290
- if (_isADMOB_ENABLED)
291
- {
292
- try
293
- {
294
- admobConfig = JSON.parse(readFileSync(admobConfigPath, 'utf8'));
295
- }
296
- catch (err)
297
- {
298
- console.error("❌ Failed to read admob-ad-configuration.json", err);
299
- process.exit(1);
300
- }
301
- }
302
-
303
-
304
-
305
-
306
-
307
- function updateIOSVersion(versionCode, versionName) {
308
-
309
- const pbxprojPath = join("ios", "App", "App.xcodeproj", "project.pbxproj");
310
-
311
- // 🔥 Single check only
312
- if (!existsSync(pbxprojPath)) {
313
- console.warn("⚠️ iOS project not found, skipping version update");
314
- return;
315
- }
316
-
317
-
318
- let content = readFileSync(pbxprojPath, 'utf8');
319
-
320
- // Update MARKETING_VERSION
321
- content = content.replace(
322
- /MARKETING_VERSION = .*?;/g,
323
- `MARKETING_VERSION = ${versionName};`
324
- );
325
-
326
- // Update CURRENT_PROJECT_VERSION
327
- /* content = content.replace(
328
- /CURRENT_PROJECT_VERSION = .*?;/g,
329
- `CURRENT_PROJECT_VERSION = ${versionCode};`
330
- ); */
331
-
332
- writeFileSync(pbxprojPath, content, 'utf8');
333
-
334
- console.log(`🍏 iOS updated via Xcode settings → version: ${versionName}, build: ${versionCode}`);
335
- }
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
- const checkCommonFileStoreId=()=>{
358
- const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
359
- let viteConfigPath;
360
- for (const configFile of possibleConfigFiles) {
361
- const fullPath = resolve( configFile);
362
- if (existsSync(fullPath)) {
363
- viteConfigPath = fullPath;
364
- break;
365
- }
366
- }
367
-
368
- if (!viteConfigPath) {
369
- console.error('❌ Error: No vite.config.mjs or vite.config.js file found.');
370
- process.exit(1);
371
- }
372
-
373
- try {
374
- // Read vite config file
375
- const viteConfigContent = readFileSync(viteConfigPath, 'utf-8');
376
-
377
- // Extract @common alias path
378
- const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
379
- const match = viteConfigContent.match(aliasPattern);
380
-
381
- if (!match) {
382
- console.error(`❌ Error: @common alias not found in ${viteConfigPath}`);
383
- process.exit(1);
384
- }
385
-
386
- const commonFilePath = match[1];
387
- const resolvedCommonPath = resolve(__dirname, commonFilePath);
388
-
389
- // Read the common file content
390
- if (!existsSync(resolvedCommonPath)) {
391
- console.error(`❌ Error: Resolved common file does not exist: ${resolvedCommonPath}`);
392
- process.exit(1);
393
- }
394
-
395
- const commonFileContent = readFileSync(resolvedCommonPath, 'utf-8');
396
-
397
- // Check for the _storeid export line
398
- const storeIdPattern = /export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*1\s*;/;
399
- if (!storeIdPattern.test(commonFileContent)) {
400
- console.error(`❌ Error: _storeid value is wrong in ${commonFilePath}`);
401
- process.exit(1);
402
- }
403
-
404
- console.log(commonFilePath,'Success - No problem found');
405
- } catch (error) {
406
- console.error('❌ Error:', error);
407
- process.exit(1);
408
- }
409
-
410
- }
411
-
412
- const checkIsTestingInAdmob=()=>{
413
-
414
- if (admobConfig.config && admobConfig.config.isTesting === true) {
415
- console.error(`❌ Problem found while generating the AAB file. Please change "isTesting: true" to "isTesting: false" in the "admob-ad-configuration-nextgen.json" file.`);
416
- process.exit(1); // Exit with an error code to halt the process
417
- } else {
418
- console.log('✅ No problem found. "isTesting" is either already false or not defined.');
419
- }
420
- }
421
-
422
- const checkIsAdsDisableByReturnStatement=()=>{
423
-
424
-
425
- const adsFolder = join('src', 'js', 'Ads');
426
- const filePattern = /^admob-emi-nextgen-(\d+\.)+\d+\.js$/;
427
-
428
- // Step 1: Find the admob file
429
- const files = readdirSync(adsFolder);
430
- const admobFile = files.find(f => filePattern.test(f));
431
-
432
- if (!admobFile) {
433
- console.log('❌ No Admob nextgen file found.');
434
- process.exit(1);
435
- }
436
-
437
- const filePath = join(adsFolder, admobFile);
438
- const content = readFileSync(filePath, 'utf-8');
439
-
440
- // Step 2: Extract the adsOnDeviceReady function body
441
- const functionRegex = /async\s+function\s+adsOnDeviceReady\s*\([^)]*\)\s*{([\s\S]*?)^}/m;
442
- const match = content.match(functionRegex);
443
-
444
- if (!match) {
445
- console.log(`❌ Function 'adsOnDeviceReady' not found in file: ${admobFile}`);
446
- process.exit(1);
447
- }
448
-
449
- const body = match[1];
450
- const lines = body.split('\n').map(line => line.trim());
451
-
452
- // Step 3: Skip blank lines and comments, get the first real code line
453
- let firstCodeLine = '';
454
- for (const line of lines) {
455
- if (line === '' || line.startsWith('//')) continue;
456
- firstCodeLine = line;
457
- break;
458
- }
459
-
460
- // Step 4: Block if it's any of the unwanted returns
461
- const badReturnPattern = /^return\s*(true|false)?\s*;?$/;
462
-
463
- if (badReturnPattern.test(firstCodeLine)) {
464
- console.log(`❌ BLOCKED in file '${admobFile}': First active line in 'adsOnDeviceReady' is '${firstCodeLine}'`);
465
- process.exit(2);
466
- } else {
467
- console.log(`✅ Safe: No early return (true/false) found in 'adsOnDeviceReady' of file '${admobFile}'.`);
468
- }
469
- }
470
-
471
-
472
-
473
- const addPermission_AD_ID=async()=>{
474
-
475
- if (isAdmobFound) {
476
- if (existsSync(androidManifestPath)) {
477
- let manifestContent = readFileSync(androidManifestPath, 'utf8');
478
- let modified = false;
479
-
480
- // --- Step 1: Ensure AD_ID permission exists ---
481
- const adIdPermission = '<uses-permission android:name="com.google.android.gms.permission.AD_ID" />';
482
- if (!manifestContent.includes(adIdPermission)) {
483
- console.log("📄 AD_ID permission not found. Adding to AndroidManifest.xml.");
484
- manifestContent = manifestContent.replace('</manifest>', ` ${adIdPermission}\n</manifest>`);
485
- console.log("✅ AD_ID permission added successfully.");
486
- modified = true;
487
- } else {
488
- console.log("ℹ️ AD_ID permission already exists in AndroidManifest.xml.");
489
- }
490
-
491
- // --- Step 2: Ensure OPTIMIZE_AD_LOADING meta-data exists ---
492
- const optimizeAdMeta = `<meta-data android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING" android:value="true" />`;
493
-
494
- if (!manifestContent.includes(optimizeAdMeta)) {
495
- console.log("📄 OPTIMIZE_AD_LOADING meta-data not found. Adding to AndroidManifest.xml.");
496
-
497
- const appTagPattern = /<application[^>]*>/;
498
- if (appTagPattern.test(manifestContent)) {
499
- manifestContent = manifestContent.replace(appTagPattern, match => `${match}\n ${optimizeAdMeta}`);
500
- console.log("✅ OPTIMIZE_AD_LOADING meta-data added successfully.");
501
- modified = true;
502
- } else {
503
- console.error("❌ <application> tag not found in AndroidManifest.xml.");
504
- }
505
- } else {
506
- console.log("ℹ️ OPTIMIZE_AD_LOADING meta-data already exists in AndroidManifest.xml.");
507
- }
508
-
509
- // --- Step 3: Write only if modified ---
510
- if (modified) {
511
- writeFileSync(androidManifestPath, manifestContent, 'utf8');
512
- console.log("💾 AndroidManifest.xml updated successfully.");
513
- } else {
514
- console.log("✅ No changes needed. AndroidManifest.xml is up to date.");
515
- }
516
-
517
- } else {
518
- console.error("❌ AndroidManifest.xml not found at the specified path.");
519
- }
520
- } else {
521
- console.log("\x1b[33m%s\x1b[0m", "⚠️ No AdMob found, so AD_ID permission and meta-data were not added");
522
- }
523
-
524
-
525
-
526
-
527
-
528
-
529
- }
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
- checkCommonFileStoreId();
542
-
543
-
544
-
545
- if (_isADMOB_ENABLED)
546
- {
547
- checkIsTestingInAdmob();
548
- checkIsAdsDisableByReturnStatement()
549
-
550
- await addPermission_AD_ID()
551
- }
552
-
553
-
554
-
555
- let originalReleaseType, originalSigningType;
556
-
557
- function readCapacitorConfig() {
558
- return JSON.parse(fs.readFileSync(capacitorConfigPath, 'utf8'));
559
- }
560
-
561
- function writeCapacitorConfig(config) {
562
- fs.writeFileSync(capacitorConfigPath, JSON.stringify(config, null, 2), 'utf8');
563
- }
564
-
565
- /* function updateCapacitorConfig(releaseType, signingType) {
566
- const config = readCapacitorConfig();
567
-
568
- // Save original values once
569
- if (originalReleaseType === undefined) originalReleaseType = config.android?.buildOptions?.releaseType || '';
570
- if (originalSigningType === undefined) originalSigningType = config.android?.buildOptions?.signingType || '';
571
-
572
- // Update values
573
- config.android = config.android || {};
574
- config.android.buildOptions = config.android.buildOptions || {};
575
- config.android.buildOptions.releaseType = releaseType;
576
- config.android.buildOptions.signingType = signingType;
577
-
578
- writeCapacitorConfig(config);
579
- console.log(`ℹ️ capacitor.config.json updated: releaseType=${releaseType}, signingType=${signingType}`);
580
- } */
581
-
582
- /* function restoreCapacitorConfig() {
583
- const config = readCapacitorConfig();
584
- if (originalReleaseType !== undefined) config.android.buildOptions.releaseType = originalReleaseType;
585
- if (originalSigningType !== undefined) config.android.buildOptions.signingType = originalSigningType;
586
- writeCapacitorConfig(config);
587
- console.log(`✅ capacitor.config.json restored to original values.`);
588
- }
589
-
590
- process.on('SIGINT', () => {
591
- console.log('\n⚠️ Detected Ctrl+C, restoring capacitor.config.json...');
592
- restoreCapacitorConfig();
593
- process.exit(0);
594
- });
595
-
596
- process.on('exit', () => {
597
- restoreCapacitorConfig();
598
- }); */
599
-
600
-
601
-
602
- const { playstore, samsung, amazon } = (_isADMOB_ENABLED && admobConfig.IAP) ? admobConfig.IAP : { playstore: false, samsung: false, amazon: false };
603
- console.log(`ℹ️ IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
604
-
605
-
606
-
607
-
608
-
609
-
610
- // Get the store ID from the command line arguments
611
- /* const storeIdArg = ["2","3"]//process.argv[2]; // Get the store ID from the command line
612
- const storeIds = storeIdArg ? storeIdArg : Object.keys(storeNames);//["1", "2", "7"]; // If a specific ID is provided, use it; otherwise, use all store IDs
613
-
614
- debugger; */
615
-
616
- let storeIdArg = process.argv[2]; // command-line argument
617
- let storeIds;
618
-
619
- if (storeIdArg) {
620
- try {
621
- // Try parsing as JSON array first
622
- const parsed = JSON.parse(storeIdArg);
623
- if (Array.isArray(parsed)) {
624
- storeIds = parsed.map(String); // ensure strings
625
- } else {
626
- storeIds = [parsed.toString()];
627
- }
628
- } catch (e) {
629
- // Not JSON, assume comma-separated string
630
- storeIds = storeIdArg.split(",").map(s => s.trim());
631
- }
632
- } else {
633
- // No argument, use all store IDs
634
- storeIds = Object.keys(storeNames);
635
- }
636
-
637
-
638
- // 🔥 If only one APK mode, override APK storeIds
639
- /* if (isOnlyOneAPK) {
640
- console.log("⚡ isOnlyOneAPK enabled → Only MiStore (3) will be used for APK build");
641
- storeIds = ["3"]; // Only MiStore
642
- } */
643
-
644
- // Store the original minSdkVersion globally
645
- let originalMinSdkVersion;
646
-
647
- // Remove any existing AAB files before starting the build process
648
- const aabDirectory = join("android", "app", "build", "outputs", "bundle", "release");
649
- if (existsSync(aabDirectory)) {
650
- const files = readdirSync(aabDirectory).filter(file => file.endsWith('.aab'));
651
- files.forEach(file => {
652
- const filePath = join(aabDirectory, file);
653
- unlinkSync(filePath);
654
- console.log(`ℹ️ Deleted existing AAB file: ${file}`);
655
- });
656
- }
657
-
658
- const aabOutputDir = join("AAB");
659
- if (!existsSync(aabOutputDir)) {
660
- mkdirSync(aabOutputDir);
661
- console.log(`Created directory: ${aabOutputDir}`);
662
- }
663
-
664
- if (existsSync(aabOutputDir)) {
665
- const files = readdirSync(aabOutputDir).filter(
666
- file => file.endsWith('.aab') || file.endsWith('.apk')
667
- );
668
-
669
- files.forEach(file => {
670
- const filePath = join(aabOutputDir, file);
671
- unlinkSync(filePath);
672
- console.log(`Deleted existing build file: ${file}`);
673
- });
674
- }
675
-
676
-
677
- // Extract version code and version name from build.gradle
678
- const gradleFilePath = join("android", "app", "build.gradle");
679
- const gradleContent = readFileSync(gradleFilePath, 'utf8');
680
-
681
- // Return the character range of a Gradle block, allowing nested blocks inside it.
221
+ return existsSync(filePath);
222
+ }
223
+
224
+
225
+ const ffmpegPluginXmlPath = path.join(__dirname, 'node_modules', 'codeplay-fmpg', 'plugin.xml');
226
+ const capacitorConfigPath = join(process.cwd(), 'capacitor.config.json');
227
+
228
+
229
+
230
+ function isFfmpegUsed() {
231
+ try {
232
+ const xmlContent = fs.readFileSync(ffmpegPluginXmlPath, 'utf8');
233
+ // Simple check: if plugin.xml exists and contains <plugin> tag (or any FFmpeg-specific tag)
234
+ return /<plugin\b/.test(xmlContent);
235
+ } catch (err) {
236
+ console.log('⚠️ FFmpeg plugin not found:', err.message);
237
+ return false;
238
+ }
239
+ }
240
+
241
+ const _isffmpegUsed = isFfmpegUsed();
242
+
243
+ function getAdMobConfig() {
244
+ if (!fileExists(capacitorConfigPath)) {
245
+ throw new Error('❌ capacitor.config.json not found. Ensure this is a Capacitor project.');
246
+ }
247
+
248
+ const config = JSON.parse(readFileSync(capacitorConfigPath, 'utf8'));
249
+ const admobConfig = config.plugins?.AdMob;
250
+
251
+ //_appPackageId=config.appId;
252
+
253
+ if (!admobConfig) {
254
+ throw new Error('❌ AdMob configuration is missing in capacitor.config.json.');
255
+ }
256
+
257
+ // Default to true if ADMOB_ENABLED is not specified
258
+ const isEnabled = admobConfig.ADMOB_ENABLED !== false;
259
+
260
+ if (!isEnabled) {
261
+ return { ADMOB_ENABLED: false }; // Skip further validation
262
+ }
263
+
264
+ if (!admobConfig.APP_ID_ANDROID || !admobConfig.APP_ID_IOS) {
265
+ throw new Error(' ❌ AdMob configuration is incomplete. Ensure APP_ID_ANDROID and APP_ID_IOS are defined.');
266
+ }
267
+
268
+ return {
269
+ ADMOB_ENABLED: true,
270
+ APP_ID_ANDROID: admobConfig.APP_ID_ANDROID,
271
+ APP_ID_IOS: admobConfig.APP_ID_IOS,
272
+ USE_LITE_ADS: admobConfig.USE_LITE_ADS === "lite",
273
+ };
274
+ }
275
+
276
+
277
+
278
+ const _capacitorConfig = getAdMobConfig();
279
+
280
+ const _isADMOB_ENABLED=_capacitorConfig.ADMOB_ENABLED;
281
+ isAdmobFound = _isADMOB_ENABLED;
282
+
283
+ // Proceed only if ADMOB_ENABLED is true
284
+ //if (_capacitorConfig.ADMOB_ENABLED)
285
+
286
+
287
+ const admobConfigPath = join('src', 'js','Ads', 'admob-ad-configuration-nextgen.json');
288
+ let admobConfig;
289
+
290
+ if (_isADMOB_ENABLED)
291
+ {
292
+ try
293
+ {
294
+ admobConfig = JSON.parse(readFileSync(admobConfigPath, 'utf8'));
295
+ }
296
+ catch (err)
297
+ {
298
+ console.error("❌ Failed to read admob-ad-configuration.json", err);
299
+ process.exit(1);
300
+ }
301
+ }
302
+
303
+
304
+
305
+
306
+
307
+ function updateIOSVersion(versionCode, versionName) {
308
+
309
+ const pbxprojPath = join("ios", "App", "App.xcodeproj", "project.pbxproj");
310
+
311
+ // 🔥 Single check only
312
+ if (!existsSync(pbxprojPath)) {
313
+ console.warn("⚠️ iOS project not found, skipping version update");
314
+ return;
315
+ }
316
+
317
+
318
+ let content = readFileSync(pbxprojPath, 'utf8');
319
+
320
+ // Update MARKETING_VERSION
321
+ content = content.replace(
322
+ /MARKETING_VERSION = .*?;/g,
323
+ `MARKETING_VERSION = ${versionName};`
324
+ );
325
+
326
+ // Update CURRENT_PROJECT_VERSION
327
+ /* content = content.replace(
328
+ /CURRENT_PROJECT_VERSION = .*?;/g,
329
+ `CURRENT_PROJECT_VERSION = ${versionCode};`
330
+ ); */
331
+
332
+ writeFileSync(pbxprojPath, content, 'utf8');
333
+
334
+ console.log(`🍏 iOS updated via Xcode settings → version: ${versionName}, build: ${versionCode}`);
335
+ }
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+ const checkCommonFileStoreId=()=>{
358
+ const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
359
+ let viteConfigPath;
360
+ for (const configFile of possibleConfigFiles) {
361
+ const fullPath = resolve( configFile);
362
+ if (existsSync(fullPath)) {
363
+ viteConfigPath = fullPath;
364
+ break;
365
+ }
366
+ }
367
+
368
+ if (!viteConfigPath) {
369
+ console.error('❌ Error: No vite.config.mjs or vite.config.js file found.');
370
+ process.exit(1);
371
+ }
372
+
373
+ try {
374
+ // Read vite config file
375
+ const viteConfigContent = readFileSync(viteConfigPath, 'utf-8');
376
+
377
+ // Extract @common alias path
378
+ const aliasPattern = /'@common':\s*path\.resolve\(__dirname,\s*'(.+?)'\)/;
379
+ const match = viteConfigContent.match(aliasPattern);
380
+
381
+ if (!match) {
382
+ console.error(`❌ Error: @common alias not found in ${viteConfigPath}`);
383
+ process.exit(1);
384
+ }
385
+
386
+ const commonFilePath = match[1];
387
+ const resolvedCommonPath = resolve(__dirname, commonFilePath);
388
+
389
+ // Read the common file content
390
+ if (!existsSync(resolvedCommonPath)) {
391
+ console.error(`❌ Error: Resolved common file does not exist: ${resolvedCommonPath}`);
392
+ process.exit(1);
393
+ }
394
+
395
+ const commonFileContent = readFileSync(resolvedCommonPath, 'utf-8');
396
+
397
+ // Check for the _storeid export line
398
+ const storeIdPattern = /export\s+let\s+_storeid\s*=\s*import\.meta\.env\.VITE_STORE_ID\s*\|\|\s*1\s*;/;
399
+ if (!storeIdPattern.test(commonFileContent)) {
400
+ console.error(`❌ Error: _storeid value is wrong in ${commonFilePath}`);
401
+ process.exit(1);
402
+ }
403
+
404
+ console.log(commonFilePath,'Success - No problem found');
405
+ } catch (error) {
406
+ console.error('❌ Error:', error);
407
+ process.exit(1);
408
+ }
409
+
410
+ }
411
+
412
+ const checkIsTestingInAdmob=()=>{
413
+
414
+ if (admobConfig.config && admobConfig.config.isTesting === true) {
415
+ console.error(`❌ Problem found while generating the AAB file. Please change "isTesting: true" to "isTesting: false" in the "admob-ad-configuration-nextgen.json" file.`);
416
+ process.exit(1); // Exit with an error code to halt the process
417
+ } else {
418
+ console.log('✅ No problem found. "isTesting" is either already false or not defined.');
419
+ }
420
+ }
421
+
422
+ const checkIsAdsDisableByReturnStatement=()=>{
423
+
424
+
425
+ const adsFolder = join('src', 'js', 'Ads');
426
+ const filePattern = /^admob-emi-nextgen-(\d+\.)+\d+\.js$/;
427
+
428
+ // Step 1: Find the admob file
429
+ const files = readdirSync(adsFolder);
430
+ const admobFile = files.find(f => filePattern.test(f));
431
+
432
+ if (!admobFile) {
433
+ console.log('❌ No Admob nextgen file found.');
434
+ process.exit(1);
435
+ }
436
+
437
+ const filePath = join(adsFolder, admobFile);
438
+ const content = readFileSync(filePath, 'utf-8');
439
+
440
+ // Step 2: Extract the adsOnDeviceReady function body
441
+ const functionRegex = /async\s+function\s+adsOnDeviceReady\s*\([^)]*\)\s*{([\s\S]*?)^}/m;
442
+ const match = content.match(functionRegex);
443
+
444
+ if (!match) {
445
+ console.log(`❌ Function 'adsOnDeviceReady' not found in file: ${admobFile}`);
446
+ process.exit(1);
447
+ }
448
+
449
+ const body = match[1];
450
+ const lines = body.split('\n').map(line => line.trim());
451
+
452
+ // Step 3: Skip blank lines and comments, get the first real code line
453
+ let firstCodeLine = '';
454
+ for (const line of lines) {
455
+ if (line === '' || line.startsWith('//')) continue;
456
+ firstCodeLine = line;
457
+ break;
458
+ }
459
+
460
+ // Step 4: Block if it's any of the unwanted returns
461
+ const badReturnPattern = /^return\s*(true|false)?\s*;?$/;
462
+
463
+ if (badReturnPattern.test(firstCodeLine)) {
464
+ console.log(`❌ BLOCKED in file '${admobFile}': First active line in 'adsOnDeviceReady' is '${firstCodeLine}'`);
465
+ process.exit(2);
466
+ } else {
467
+ console.log(`✅ Safe: No early return (true/false) found in 'adsOnDeviceReady' of file '${admobFile}'.`);
468
+ }
469
+ }
470
+
471
+
472
+
473
+ const addPermission_AD_ID=async()=>{
474
+
475
+ if (isAdmobFound) {
476
+ if (existsSync(androidManifestPath)) {
477
+ let manifestContent = readFileSync(androidManifestPath, 'utf8');
478
+ let modified = false;
479
+
480
+ // --- Step 1: Ensure AD_ID permission exists ---
481
+ const adIdPermission = '<uses-permission android:name="com.google.android.gms.permission.AD_ID" />';
482
+ if (!manifestContent.includes(adIdPermission)) {
483
+ console.log("📄 AD_ID permission not found. Adding to AndroidManifest.xml.");
484
+ manifestContent = manifestContent.replace('</manifest>', ` ${adIdPermission}\n</manifest>`);
485
+ console.log("✅ AD_ID permission added successfully.");
486
+ modified = true;
487
+ } else {
488
+ console.log("ℹ️ AD_ID permission already exists in AndroidManifest.xml.");
489
+ }
490
+
491
+ // --- Step 2: Ensure OPTIMIZE_AD_LOADING meta-data exists ---
492
+ const optimizeAdMeta = `<meta-data android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING" android:value="true" />`;
493
+
494
+ if (!manifestContent.includes(optimizeAdMeta)) {
495
+ console.log("📄 OPTIMIZE_AD_LOADING meta-data not found. Adding to AndroidManifest.xml.");
496
+
497
+ const appTagPattern = /<application[^>]*>/;
498
+ if (appTagPattern.test(manifestContent)) {
499
+ manifestContent = manifestContent.replace(appTagPattern, match => `${match}\n ${optimizeAdMeta}`);
500
+ console.log("✅ OPTIMIZE_AD_LOADING meta-data added successfully.");
501
+ modified = true;
502
+ } else {
503
+ console.error("❌ <application> tag not found in AndroidManifest.xml.");
504
+ }
505
+ } else {
506
+ console.log("ℹ️ OPTIMIZE_AD_LOADING meta-data already exists in AndroidManifest.xml.");
507
+ }
508
+
509
+ // --- Step 3: Write only if modified ---
510
+ if (modified) {
511
+ writeFileSync(androidManifestPath, manifestContent, 'utf8');
512
+ console.log("💾 AndroidManifest.xml updated successfully.");
513
+ } else {
514
+ console.log("✅ No changes needed. AndroidManifest.xml is up to date.");
515
+ }
516
+
517
+ } else {
518
+ console.error("❌ AndroidManifest.xml not found at the specified path.");
519
+ }
520
+ } else {
521
+ console.log("\x1b[33m%s\x1b[0m", "⚠️ No AdMob found, so AD_ID permission and meta-data were not added");
522
+ }
523
+
524
+
525
+
526
+
527
+
528
+
529
+ }
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+ checkCommonFileStoreId();
542
+
543
+
544
+
545
+ if (_isADMOB_ENABLED)
546
+ {
547
+ checkIsTestingInAdmob();
548
+ checkIsAdsDisableByReturnStatement()
549
+
550
+ await addPermission_AD_ID()
551
+ }
552
+
553
+
554
+
555
+ let originalReleaseType, originalSigningType;
556
+
557
+ function readCapacitorConfig() {
558
+ return JSON.parse(fs.readFileSync(capacitorConfigPath, 'utf8'));
559
+ }
560
+
561
+ function writeCapacitorConfig(config) {
562
+ fs.writeFileSync(capacitorConfigPath, JSON.stringify(config, null, 2), 'utf8');
563
+ }
564
+
565
+ /* function updateCapacitorConfig(releaseType, signingType) {
566
+ const config = readCapacitorConfig();
567
+
568
+ // Save original values once
569
+ if (originalReleaseType === undefined) originalReleaseType = config.android?.buildOptions?.releaseType || '';
570
+ if (originalSigningType === undefined) originalSigningType = config.android?.buildOptions?.signingType || '';
571
+
572
+ // Update values
573
+ config.android = config.android || {};
574
+ config.android.buildOptions = config.android.buildOptions || {};
575
+ config.android.buildOptions.releaseType = releaseType;
576
+ config.android.buildOptions.signingType = signingType;
577
+
578
+ writeCapacitorConfig(config);
579
+ console.log(`ℹ️ capacitor.config.json updated: releaseType=${releaseType}, signingType=${signingType}`);
580
+ } */
581
+
582
+ /* function restoreCapacitorConfig() {
583
+ const config = readCapacitorConfig();
584
+ if (originalReleaseType !== undefined) config.android.buildOptions.releaseType = originalReleaseType;
585
+ if (originalSigningType !== undefined) config.android.buildOptions.signingType = originalSigningType;
586
+ writeCapacitorConfig(config);
587
+ console.log(`✅ capacitor.config.json restored to original values.`);
588
+ }
589
+
590
+ process.on('SIGINT', () => {
591
+ console.log('\n⚠️ Detected Ctrl+C, restoring capacitor.config.json...');
592
+ restoreCapacitorConfig();
593
+ process.exit(0);
594
+ });
595
+
596
+ process.on('exit', () => {
597
+ restoreCapacitorConfig();
598
+ }); */
599
+
600
+
601
+
602
+ const { playstore, samsung, amazon } = (_isADMOB_ENABLED && admobConfig.IAP) ? admobConfig.IAP : { playstore: false, samsung: false, amazon: false };
603
+ console.log(`ℹ️ IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
604
+
605
+
606
+
607
+
608
+
609
+
610
+ // Get the store ID from the command line arguments
611
+ /* const storeIdArg = ["2","3"]//process.argv[2]; // Get the store ID from the command line
612
+ const storeIds = storeIdArg ? storeIdArg : Object.keys(storeNames);//["1", "2", "7"]; // If a specific ID is provided, use it; otherwise, use all store IDs
613
+
614
+ debugger; */
615
+
616
+ let storeIdArg = process.argv[2]; // command-line argument
617
+ let storeIds;
618
+
619
+ if (storeIdArg) {
620
+ try {
621
+ // Try parsing as JSON array first
622
+ const parsed = JSON.parse(storeIdArg);
623
+ if (Array.isArray(parsed)) {
624
+ storeIds = parsed.map(String); // ensure strings
625
+ } else {
626
+ storeIds = [parsed.toString()];
627
+ }
628
+ } catch (e) {
629
+ // Not JSON, assume comma-separated string
630
+ storeIds = storeIdArg.split(",").map(s => s.trim());
631
+ }
632
+ } else {
633
+ // No argument, use all store IDs
634
+ storeIds = Object.keys(storeNames);
635
+ }
636
+
637
+
638
+ // 🔥 If only one APK mode, override APK storeIds
639
+ /* if (isOnlyOneAPK) {
640
+ console.log("⚡ isOnlyOneAPK enabled → Only MiStore (3) will be used for APK build");
641
+ storeIds = ["3"]; // Only MiStore
642
+ } */
643
+
644
+ // Store the original minSdkVersion globally
645
+ let originalMinSdkVersion;
646
+
647
+ // Remove any existing AAB files before starting the build process
648
+ const aabDirectory = join("android", "app", "build", "outputs", "bundle", "release");
649
+ if (existsSync(aabDirectory)) {
650
+ const files = readdirSync(aabDirectory).filter(file => file.endsWith('.aab'));
651
+ files.forEach(file => {
652
+ const filePath = join(aabDirectory, file);
653
+ unlinkSync(filePath);
654
+ console.log(`ℹ️ Deleted existing AAB file: ${file}`);
655
+ });
656
+ }
657
+
658
+ const aabOutputDir = join("AAB");
659
+ if (!existsSync(aabOutputDir)) {
660
+ mkdirSync(aabOutputDir);
661
+ console.log(`Created directory: ${aabOutputDir}`);
662
+ }
663
+
664
+ if (existsSync(aabOutputDir)) {
665
+ const files = readdirSync(aabOutputDir).filter(
666
+ file => file.endsWith('.aab') || file.endsWith('.apk')
667
+ );
668
+
669
+ files.forEach(file => {
670
+ const filePath = join(aabOutputDir, file);
671
+ unlinkSync(filePath);
672
+ console.log(`Deleted existing build file: ${file}`);
673
+ });
674
+ }
675
+
676
+
677
+ // Extract version code and version name from build.gradle
678
+ const gradleFilePath = join("android", "app", "build.gradle");
679
+ const gradleContent = readFileSync(gradleFilePath, 'utf8');
680
+
681
+ // Return the character range of a Gradle block, allowing nested blocks inside it.
682
682
  function findGradleBlock(content, headerPattern) {
683
- const headerMatch = content.match(headerPattern);
684
- if (!headerMatch) return null;
685
- const openingBrace = content.indexOf('{', headerMatch.index + headerMatch[0].length);
686
- if (openingBrace === -1) return null;
687
- let depth = 0;
688
- let quote = null;
689
- for (let index = openingBrace; index < content.length; index += 1) {
690
- const character = content[index];
691
- const previous = content[index - 1];
692
- if (quote) {
693
- if (character === quote && previous !== '\\') quote = null;
694
- continue;
695
- }
696
- if (character === '\"' || character === "'") quote = character;
697
- else if (character === '{') depth += 1;
698
- else if (character === '}' && --depth === 0) return { start: openingBrace + 1, end: index };
699
- }
683
+ const headerMatch = content.match(headerPattern);
684
+ if (!headerMatch) return null;
685
+ const openingBrace = content.indexOf('{', headerMatch.index + headerMatch[0].length);
686
+ if (openingBrace === -1) return null;
687
+ let depth = 0;
688
+ let quote = null;
689
+ for (let index = openingBrace; index < content.length; index += 1) {
690
+ const character = content[index];
691
+ const previous = content[index - 1];
692
+ if (quote) {
693
+ if (character === quote && previous !== '\\') quote = null;
694
+ continue;
695
+ }
696
+ if (character === '\"' || character === "'") quote = character;
697
+ else if (character === '{') depth += 1;
698
+ else if (character === '}' && --depth === 0) return { start: openingBrace + 1, end: index };
699
+ }
700
700
  return null;
701
701
  }
702
702
 
@@ -734,273 +734,273 @@ function setAmazonWindowExtensionsDependency(enabled, { cleanup = false } = {})
734
734
  }
735
735
 
736
736
  const versionCodeMatch = gradleContent.match(/versionCode\s+(\d+)/);
737
- const versionNameMatch = gradleContent.match(/versionName\s+"([^"]+)"/);
738
-
739
- const versionCode = versionCodeMatch ? versionCodeMatch[1] : '';
740
- const versionName = versionNameMatch ? versionNameMatch[1] : '';
741
-
742
- // Display the current versionCode and versionName
743
- console.log(`Current versionCode: ${versionCode}`);
744
- console.log(`Current versionName: ${versionName}`);
745
-
746
- // Create an interface for user input
747
- const rl = createInterface({
748
- input: process.stdin,
749
- output: process.stdout
750
- });
751
-
752
- // Ask for new versionCode
753
- rl.question('Enter new versionCode (press enter to keep current): ', (newVersionCode) => {
754
- const finalVersionCode = newVersionCode || versionCode; // Use existing if no input
755
-
756
- // Ask for new versionName
757
- rl.question('Enter new versionName (press enter to keep current): ', (newVersionName) => {
758
- const finalVersionName = newVersionName || versionName; // Use existing if no input
759
-
760
- // Log the final version details
761
- console.log(`📦 Final versionCode: ${finalVersionCode}`);
762
- console.log(`📝 Final versionName: ${finalVersionName}`);
763
-
764
-
765
- updateIOSVersion(finalVersionCode, finalVersionName);
766
-
767
- // Update build.gradle with the new version details
768
- let updatedGradleContent = gradleContent
769
- .replace(/versionCode\s+\d+/, `versionCode ${finalVersionCode}`)
770
- .replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"`);
771
-
772
- // Check if resConfigs "en" already exists
773
- const resConfigsLine = ' resConfigs "en"';
774
- if (!updatedGradleContent.includes(resConfigsLine)) {
775
- // Add resConfigs "en" below versionName
776
- updatedGradleContent = updatedGradleContent.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"\n${resConfigsLine}`);
777
- } else {
778
- console.log('ℹ️ resConfigs "en" already exists in build.gradle.');
779
- }
780
-
781
-
782
-
783
- // List of package IDs for which minify should be false
784
-
785
-
786
- // Determine desired minify value
787
- const desiredMinify = !_isffmpegUsed;
788
-
789
- // Check if minifyEnabled is already present
790
- if (/minifyEnabled\s+(true|false)/.test(updatedGradleContent)) {
791
- // Replace existing value with desired
792
- updatedGradleContent = updatedGradleContent.replace(/minifyEnabled\s+(true|false)/, `minifyEnabled ${desiredMinify}`);
793
- console.log(`Replaced minifyEnabled with ${desiredMinify}.`);
794
- } else if (/buildTypes\s*{[\s\S]*?release\s*{/.test(updatedGradleContent)) {
795
- // Insert minifyEnabled if not present
796
- updatedGradleContent = updatedGradleContent.replace(
797
- /(buildTypes\s*{[\s\S]*?release\s*{)/,
798
- `$1\n minifyEnabled ${desiredMinify}`
799
- );
800
- console.log(`✅ Inserted minifyEnabled ${desiredMinify} into release block.`);
801
- } else {
802
- console.log('⚠️ Warning: buildTypes > release block not found. minifyEnabled was not added.');
803
- }
804
-
805
- // Add native debug symbols for release AABs, but leave any existing setting untouched.
806
- const releaseBlock = findGradleBlock(updatedGradleContent, /buildTypes\s*\{[\s\S]*?\brelease\s*/);
807
- if (releaseBlock) {
808
- const releaseContent = updatedGradleContent.slice(releaseBlock.start, releaseBlock.end);
809
- if (/\bdebugSymbolLevel\b/.test(releaseContent)) {
810
- console.log('ℹ️ debugSymbolLevel already exists in buildTypes.release; leaving it unchanged.');
811
- } else {
812
- const ndkBlock = `\n ndk {\n debugSymbolLevel 'FULL'\n }`;
813
- updatedGradleContent = updatedGradleContent.slice(0, releaseBlock.end)
814
- + ndkBlock
815
- + updatedGradleContent.slice(releaseBlock.end);
816
- console.log("✅ Added debugSymbolLevel 'FULL' to buildTypes.release.");
817
- }
818
- } else {
819
- console.log('⚠️ Warning: buildTypes.release block not found. debugSymbolLevel was not added.');
820
- }
821
-
822
-
823
-
824
-
825
-
826
-
827
- // Write the updated gradle content back to build.gradle
828
- writeFileSync(gradleFilePath, updatedGradleContent, 'utf8');
829
- console.log(`✅ Updated build.gradle with versionCode: ${finalVersionCode}, versionName: ${finalVersionName}, resConfigs "en" and "minifyEnabled true"`);
830
-
831
- storeIds.forEach((id) => {
832
- console.log(`ℹ️ Building for Store ID ${id}`);
833
-
834
- // Set the environment variable for store ID
835
- process.env.VITE_STORE_ID = id;
836
-
837
- // Conditionally set the new file name
838
- let newFileName;
839
- let storeName = storeNames[id];
840
-
841
-
842
- if (
843
- isOnlyOneAPK &&
844
- ["OppoStore", "VivoStore"].includes(storeName)
845
- ) {
846
- console.log(`⏭ Skipping ${storeName} because isOnlyOneAPK is enabled`);
847
- return; // skip this iteration only
848
- }
849
-
850
-
851
- managePackages(storeName);
852
-
853
- // 🔥 Only change filename logic — nothing else touched
854
- if (isOnlyOneAPK && ["MiStore","OppoStore","VivoStore"].includes(storeName)) {
855
-
856
- newFileName =
857
- `${_appUniqueId}_${_appName.replaceAll(" ","_")}-VI_MI_OPPO-b${finalVersionCode}-v${finalVersionName.replace(/\./g,'_')}.aab`;
858
-
859
- }
860
- else if (storeName === "SamsungStore") {
861
-
862
- newFileName =
863
- `${_appUniqueId}_${_appName.replaceAll(" ","_")}-${(storeName.toUpperCase()).replace("STORE","")}-b${finalVersionCode}-v${finalVersionName.replace(/\./g,'_')}.aab`;
864
-
865
- }
866
- else {
867
-
868
- newFileName =
869
- `${_appUniqueId}_${_appName.replaceAll(" ","_")}-${(storeName.toUpperCase()).replace("STORE","")}-b${finalVersionCode}-v${finalVersionName}.aab`;
870
-
871
- }
872
-
873
- //storeName="amazon"
874
- const checkFullPath = join("AAB", newFileName); // Update to point to the new AAB directory
875
-
876
- // Modify minSdkVersion in variables.gradle for SamsungStore
877
- const variablesGradleFilePath = join("android", "variables.gradle");
878
- let variablesGradleContent = readFileSync(variablesGradleFilePath, 'utf8');
879
-
880
- // Extract the current minSdkVersion
881
- const minSdkVersionMatch = variablesGradleContent.match(/minSdkVersion\s*=\s*(\d+)/);
882
- const currentMinSdkVersion = minSdkVersionMatch ? parseInt(minSdkVersionMatch[1], 10) : null;
883
-
884
- // Store the original minSdkVersion (only on the first iteration)
885
- if (!originalMinSdkVersion) {
886
- originalMinSdkVersion = currentMinSdkVersion;
887
- }
737
+ const versionNameMatch = gradleContent.match(/versionName\s+"([^"]+)"/);
738
+
739
+ const versionCode = versionCodeMatch ? versionCodeMatch[1] : '';
740
+ const versionName = versionNameMatch ? versionNameMatch[1] : '';
741
+
742
+ // Display the current versionCode and versionName
743
+ console.log(`Current versionCode: ${versionCode}`);
744
+ console.log(`Current versionName: ${versionName}`);
745
+
746
+ // Create an interface for user input
747
+ const rl = createInterface({
748
+ input: process.stdin,
749
+ output: process.stdout
750
+ });
751
+
752
+ // Ask for new versionCode
753
+ rl.question('Enter new versionCode (press enter to keep current): ', (newVersionCode) => {
754
+ const finalVersionCode = newVersionCode || versionCode; // Use existing if no input
755
+
756
+ // Ask for new versionName
757
+ rl.question('Enter new versionName (press enter to keep current): ', (newVersionName) => {
758
+ const finalVersionName = newVersionName || versionName; // Use existing if no input
759
+
760
+ // Log the final version details
761
+ console.log(`📦 Final versionCode: ${finalVersionCode}`);
762
+ console.log(`📝 Final versionName: ${finalVersionName}`);
763
+
764
+
765
+ updateIOSVersion(finalVersionCode, finalVersionName);
766
+
767
+ // Update build.gradle with the new version details
768
+ let updatedGradleContent = gradleContent
769
+ .replace(/versionCode\s+\d+/, `versionCode ${finalVersionCode}`)
770
+ .replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"`);
771
+
772
+ // Check if resConfigs "en" already exists
773
+ const resConfigsLine = ' resConfigs "en"';
774
+ if (!updatedGradleContent.includes(resConfigsLine)) {
775
+ // Add resConfigs "en" below versionName
776
+ updatedGradleContent = updatedGradleContent.replace(/versionName\s+"[^"]+"/, `versionName "${finalVersionName}"\n${resConfigsLine}`);
777
+ } else {
778
+ console.log('ℹ️ resConfigs "en" already exists in build.gradle.');
779
+ }
780
+
781
+
782
+
783
+ // List of package IDs for which minify should be false
784
+
785
+
786
+ // Determine desired minify value
787
+ const desiredMinify = !_isffmpegUsed;
788
+
789
+ // Check if minifyEnabled is already present
790
+ if (/minifyEnabled\s+(true|false)/.test(updatedGradleContent)) {
791
+ // Replace existing value with desired
792
+ updatedGradleContent = updatedGradleContent.replace(/minifyEnabled\s+(true|false)/, `minifyEnabled ${desiredMinify}`);
793
+ console.log(`Replaced minifyEnabled with ${desiredMinify}.`);
794
+ } else if (/buildTypes\s*{[\s\S]*?release\s*{/.test(updatedGradleContent)) {
795
+ // Insert minifyEnabled if not present
796
+ updatedGradleContent = updatedGradleContent.replace(
797
+ /(buildTypes\s*{[\s\S]*?release\s*{)/,
798
+ `$1\n minifyEnabled ${desiredMinify}`
799
+ );
800
+ console.log(`✅ Inserted minifyEnabled ${desiredMinify} into release block.`);
801
+ } else {
802
+ console.log('⚠️ Warning: buildTypes > release block not found. minifyEnabled was not added.');
803
+ }
804
+
805
+ // Add native debug symbols for release AABs, but leave any existing setting untouched.
806
+ const releaseBlock = findGradleBlock(updatedGradleContent, /buildTypes\s*\{[\s\S]*?\brelease\s*/);
807
+ if (releaseBlock) {
808
+ const releaseContent = updatedGradleContent.slice(releaseBlock.start, releaseBlock.end);
809
+ if (/\bdebugSymbolLevel\b/.test(releaseContent)) {
810
+ console.log('ℹ️ debugSymbolLevel already exists in buildTypes.release; leaving it unchanged.');
811
+ } else {
812
+ const ndkBlock = `\n ndk {\n debugSymbolLevel 'FULL'\n }`;
813
+ updatedGradleContent = updatedGradleContent.slice(0, releaseBlock.end)
814
+ + ndkBlock
815
+ + updatedGradleContent.slice(releaseBlock.end);
816
+ console.log("✅ Added debugSymbolLevel 'FULL' to buildTypes.release.");
817
+ }
818
+ } else {
819
+ console.log('⚠️ Warning: buildTypes.release block not found. debugSymbolLevel was not added.');
820
+ }
821
+
822
+
823
+
824
+
825
+
826
+
827
+ // Write the updated gradle content back to build.gradle
828
+ writeFileSync(gradleFilePath, updatedGradleContent, 'utf8');
829
+ console.log(`✅ Updated build.gradle with versionCode: ${finalVersionCode}, versionName: ${finalVersionName}, resConfigs "en" and "minifyEnabled true"`);
830
+
831
+ storeIds.forEach((id) => {
832
+ console.log(`ℹ️ Building for Store ID ${id}`);
833
+
834
+ // Set the environment variable for store ID
835
+ process.env.VITE_STORE_ID = id;
836
+
837
+ // Conditionally set the new file name
838
+ let newFileName;
839
+ let storeName = storeNames[id];
840
+
841
+
842
+ if (
843
+ isOnlyOneAPK &&
844
+ ["OppoStore", "VivoStore"].includes(storeName)
845
+ ) {
846
+ console.log(`⏭ Skipping ${storeName} because isOnlyOneAPK is enabled`);
847
+ return; // skip this iteration only
848
+ }
849
+
850
+
851
+ managePackages(storeName);
852
+
853
+ // 🔥 Only change filename logic — nothing else touched
854
+ if (isOnlyOneAPK && ["MiStore","OppoStore","VivoStore"].includes(storeName)) {
855
+
856
+ newFileName =
857
+ `${_appUniqueId}_${_appName.replaceAll(" ","_")}-VI_MI_OPPO-b${finalVersionCode}-v${finalVersionName.replace(/\./g,'_')}.aab`;
858
+
859
+ }
860
+ else if (storeName === "SamsungStore") {
861
+
862
+ newFileName =
863
+ `${_appUniqueId}_${_appName.replaceAll(" ","_")}-${(storeName.toUpperCase()).replace("STORE","")}-b${finalVersionCode}-v${finalVersionName.replace(/\./g,'_')}.aab`;
864
+
865
+ }
866
+ else {
867
+
868
+ newFileName =
869
+ `${_appUniqueId}_${_appName.replaceAll(" ","_")}-${(storeName.toUpperCase()).replace("STORE","")}-b${finalVersionCode}-v${finalVersionName}.aab`;
870
+
871
+ }
872
+
873
+ //storeName="amazon"
874
+ const checkFullPath = join("AAB", newFileName); // Update to point to the new AAB directory
875
+
876
+ // Modify minSdkVersion in variables.gradle for SamsungStore
877
+ const variablesGradleFilePath = join("android", "variables.gradle");
878
+ let variablesGradleContent = readFileSync(variablesGradleFilePath, 'utf8');
879
+
880
+ // Extract the current minSdkVersion
881
+ const minSdkVersionMatch = variablesGradleContent.match(/minSdkVersion\s*=\s*(\d+)/);
882
+ const currentMinSdkVersion = minSdkVersionMatch ? parseInt(minSdkVersionMatch[1], 10) : null;
883
+
884
+ // Store the original minSdkVersion (only on the first iteration)
885
+ if (!originalMinSdkVersion) {
886
+ originalMinSdkVersion = currentMinSdkVersion;
887
+ }
888
888
  try {
889
889
  applyFlowchartStoreApi(id);
890
890
  const shouldIncludeAmazonWindowExtensions = String(id) === '7' && amazon === true;
891
891
  setAmazonWindowExtensionsDependency(shouldIncludeAmazonWindowExtensions);
892
892
  // Modify the minSdkVersion based on the store
893
-
894
-
895
- if(currentMinSdkVersion==23 || currentMinSdkVersion==24)
896
- {
897
- if (storeName === "SamsungStore" || storeName === "PlayStore" ||
898
- //_appPackageId=="vfx.green.editor" || _appPackageId=="audio.music.sound.editor" || _appPackageId=="video.to.gif.maker"
899
-
900
- //ffmpegUsedPackages.includes(_appPackageId)
901
- _isffmpegUsed
902
- ) {
903
- if (currentMinSdkVersion !== 24) {
904
- variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
905
- console.log('minSdkVersion updated to 24 for SamsungStore & PlayStore');
906
- writeFileSync(variablesGradleFilePath, variablesGradleContent);
907
- }
908
- } else {
909
- // For PlayStore and AmazonStore, ensure minSdkVersion is originalMinSdkVersion
910
- //if (currentMinSdkVersion !== originalMinSdkVersion) {
911
- variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, `minSdkVersion = ${amazonMinSdkVersion}`);
912
- console.log(`minSdkVersion reverted to ${amazonMinSdkVersion} for ${storeName}`);
913
- writeFileSync(variablesGradleFilePath, variablesGradleContent);
914
- //}
915
- }
916
- }
917
-
918
-
919
- // Run the Node.js script to modify plugin.xml
920
- if (isAdmobFound) {
921
- const modifyPluginXmlPath = join('buildCodeplay', 'modify-plugin-xml.js');
922
- if (existsSync(modifyPluginXmlPath)) {
923
- execSync(`node ${modifyPluginXmlPath}`, { stdio: 'inherit' });
924
- } else {
925
- console.log("\x1b[33m%s\x1b[0m", "⚠️ modify-plugin-xml.js not found. Skipping old AdMob plugin.xml modification.");
926
- }
927
- } else {
928
- console.log("\x1b[33m%s\x1b[0m", "Seems to Pro Version [No ads found]");
929
- }
930
-
931
- // Run the Vite build
932
- execSync(`npm run build:storeid${id}`, { stdio: 'inherit' });
933
-
934
-
935
-
936
-
937
-
938
-
939
- // Copy the built files to the appropriate folder
940
- const src = join("www");
941
- const dest = join("android", "app", "src", "main", "assets", "public");
942
-
943
- // Copy the web build with Node so releases work on every platform.
944
- fs.cpSync(src, dest, { recursive: true, force: true });
945
-
946
- // Build Android AAB file
947
- //child_process.execSync('cd android && ./gradlew bundleRelease', { stdio: 'inherit' });
948
-
949
-
950
- // Build Android AAB or APK file based on store
951
- console.log(`🏗️ Building release for ${storeName}...`);
952
-
953
- /* let buildType = "AAB";
954
- if (["VivoStore", "OppoStore", "MiStore"].includes(storeName)) {
955
- buildType = "APK";
956
- } */
957
-
958
-
959
- // Determine build type and signing type per store
960
- let buildType = ["VivoStore","OppoStore","MiStore"].includes(storeName) ? "APK" : "AAB";
961
- let signingType = buildType === "APK" ? "apksigner" : "jarsigner";
962
-
963
- // Update capacitor.config.json for this store - This is not needed
964
- //updateCapacitorConfig(buildType, signingType);
965
-
966
-
967
-
968
- /* execSync('npx cap sync android', { stdio: 'inherit' });
969
- execSync(`npx cap build android --androidreleasetype=${buildType}`, { stdio: 'inherit' }); */
970
-
971
-
972
- execSync('npx cap sync android', { stdio: 'inherit' });
973
-
974
- if (buildType === "APK") {
975
- console.log("📦 Using custom Node signing script for APK build...");
976
- execSync('node buildCodeplay/apk-store-builder.js', { stdio: 'inherit' });
977
- } else {
978
- execSync(`npx cap build android --androidreleasetype=${buildType}`, { stdio: 'inherit' });
979
- }
980
-
981
-
982
-
983
- // Determine output paths
984
- let oldFilePath;
985
- let newExt = buildType === "APK" ? "apk" : "aab";
986
-
987
- if (buildType === "APK") {
988
- //oldFilePath = join("android", "app", "build", "outputs", "apk", "release", "app-release-signed.apk");
989
- oldFilePath = join("android", "app", "build", "outputs", "apk", "release", "app-release.apk");
990
- } else {
991
- oldFilePath = join("android", "app", "build", "outputs", "bundle", "release", "app-release-signed.aab");
992
- }
993
-
994
- const checkFullPath = join("AAB", newFileName.replace(/\.aab$/, `.${newExt}`));
995
-
996
- // Rename the output file
997
- if (existsSync(oldFilePath)) {
998
- renameSync(oldFilePath, checkFullPath);
999
- console.log(`✅ Renamed output ${newExt.toUpperCase()} file to: ${path.basename(checkFullPath)}`);
1000
- } else {
1001
- console.error(`❌ ${newExt.toUpperCase()} file not found after build.`);
1002
- }
1003
-
893
+
894
+
895
+ if(currentMinSdkVersion==23 || currentMinSdkVersion==24)
896
+ {
897
+ if (storeName === "SamsungStore" || storeName === "PlayStore" ||
898
+ //_appPackageId=="vfx.green.editor" || _appPackageId=="audio.music.sound.editor" || _appPackageId=="video.to.gif.maker"
899
+
900
+ //ffmpegUsedPackages.includes(_appPackageId)
901
+ _isffmpegUsed
902
+ ) {
903
+ if (currentMinSdkVersion !== 24) {
904
+ variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, 'minSdkVersion = 24');
905
+ console.log('minSdkVersion updated to 24 for SamsungStore & PlayStore');
906
+ writeFileSync(variablesGradleFilePath, variablesGradleContent);
907
+ }
908
+ } else {
909
+ // For PlayStore and AmazonStore, ensure minSdkVersion is originalMinSdkVersion
910
+ //if (currentMinSdkVersion !== originalMinSdkVersion) {
911
+ variablesGradleContent = variablesGradleContent.replace(/minSdkVersion\s*=\s*\d+/, `minSdkVersion = ${amazonMinSdkVersion}`);
912
+ console.log(`minSdkVersion reverted to ${amazonMinSdkVersion} for ${storeName}`);
913
+ writeFileSync(variablesGradleFilePath, variablesGradleContent);
914
+ //}
915
+ }
916
+ }
917
+
918
+
919
+ // Run the Node.js script to modify plugin.xml
920
+ if (isAdmobFound) {
921
+ const modifyPluginXmlPath = join('buildCodeplay', 'modify-plugin-xml.js');
922
+ if (existsSync(modifyPluginXmlPath)) {
923
+ execSync(`node ${modifyPluginXmlPath}`, { stdio: 'inherit' });
924
+ } else {
925
+ console.log("\x1b[33m%s\x1b[0m", "⚠️ modify-plugin-xml.js not found. Skipping old AdMob plugin.xml modification.");
926
+ }
927
+ } else {
928
+ console.log("\x1b[33m%s\x1b[0m", "Seems to Pro Version [No ads found]");
929
+ }
930
+
931
+ // Run the Vite build
932
+ execSync(`npm run build:storeid${id}`, { stdio: 'inherit' });
933
+
934
+
935
+
936
+
937
+
938
+
939
+ // Copy the built files to the appropriate folder
940
+ const src = join("www");
941
+ const dest = join("android", "app", "src", "main", "assets", "public");
942
+
943
+ // Copy the web build with Node so releases work on every platform.
944
+ fs.cpSync(src, dest, { recursive: true, force: true });
945
+
946
+ // Build Android AAB file
947
+ //child_process.execSync('cd android && ./gradlew bundleRelease', { stdio: 'inherit' });
948
+
949
+
950
+ // Build Android AAB or APK file based on store
951
+ console.log(`🏗️ Building release for ${storeName}...`);
952
+
953
+ /* let buildType = "AAB";
954
+ if (["VivoStore", "OppoStore", "MiStore"].includes(storeName)) {
955
+ buildType = "APK";
956
+ } */
957
+
958
+
959
+ // Determine build type and signing type per store
960
+ let buildType = ["VivoStore","OppoStore","MiStore"].includes(storeName) ? "APK" : "AAB";
961
+ let signingType = buildType === "APK" ? "apksigner" : "jarsigner";
962
+
963
+ // Update capacitor.config.json for this store - This is not needed
964
+ //updateCapacitorConfig(buildType, signingType);
965
+
966
+
967
+
968
+ /* execSync('npx cap sync android', { stdio: 'inherit' });
969
+ execSync(`npx cap build android --androidreleasetype=${buildType}`, { stdio: 'inherit' }); */
970
+
971
+
972
+ execSync('npx cap sync android', { stdio: 'inherit' });
973
+
974
+ if (buildType === "APK") {
975
+ console.log("📦 Using custom Node signing script for APK build...");
976
+ execSync('node buildCodeplay/apk-store-builder.js', { stdio: 'inherit' });
977
+ } else {
978
+ execSync(`npx cap build android --androidreleasetype=${buildType}`, { stdio: 'inherit' });
979
+ }
980
+
981
+
982
+
983
+ // Determine output paths
984
+ let oldFilePath;
985
+ let newExt = buildType === "APK" ? "apk" : "aab";
986
+
987
+ if (buildType === "APK") {
988
+ //oldFilePath = join("android", "app", "build", "outputs", "apk", "release", "app-release-signed.apk");
989
+ oldFilePath = join("android", "app", "build", "outputs", "apk", "release", "app-release.apk");
990
+ } else {
991
+ oldFilePath = join("android", "app", "build", "outputs", "bundle", "release", "app-release-signed.aab");
992
+ }
993
+
994
+ const checkFullPath = join("AAB", newFileName.replace(/\.aab$/, `.${newExt}`));
995
+
996
+ // Rename the output file
997
+ if (existsSync(oldFilePath)) {
998
+ renameSync(oldFilePath, checkFullPath);
999
+ console.log(`✅ Renamed output ${newExt.toUpperCase()} file to: ${path.basename(checkFullPath)}`);
1000
+ } else {
1001
+ console.error(`❌ ${newExt.toUpperCase()} file not found after build.`);
1002
+ }
1003
+
1004
1004
  } catch (error) {
1005
1005
  console.error(`❌ Error during build for Store ID ${id}:`, error);
1006
1006
  restoreFlowchartStoreApi();
@@ -1014,172 +1014,172 @@ rl.question('Enter new versionCode (press enter to keep current): ', (newVersion
1014
1014
  cleanup: String(id) === '7' && amazon === true,
1015
1015
  });
1016
1016
  }
1017
- });
1018
-
1019
- rl.close(); // Close the readline interface after all operations
1020
- });
1021
- });
1022
-
1023
-
1024
-
1025
-
1026
-
1027
- function managePackages(store) {
1028
- console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
1029
-
1030
- let install = "";
1031
- let uninstall = "";
1032
-
1033
-
1034
-
1035
- let manifestContent = readFileSync(androidManifestPath, 'utf-8');
1036
-
1037
- const permissionsToRemove = [
1038
- 'com.android.vending.BILLING',
1039
- 'com.samsung.android.iap.permission.BILLING'
1040
- ];
1041
-
1042
-
1043
- permissionsToRemove.forEach(permission => {
1044
- const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
1045
- if (permissionRegex.test(manifestContent)) {
1046
- manifestContent = manifestContent.replace(permissionRegex, '');
1047
- console.log(`✅ Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
1048
- }
1049
- });
1050
-
1051
- // Write the updated content back to the file
1052
- writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1053
-
1054
-
1055
-
1056
- if ((playstore && store === "PlayStore") || (amazon && store === "AmazonStore")) {
1057
- install = '@revenuecat/purchases-capacitor';
1058
- uninstall = 'cordova-plugin-samsungiap';
1059
-
1060
- // Update AndroidManifest.xml for PlayStore
1017
+ });
1018
+
1019
+ rl.close(); // Close the readline interface after all operations
1020
+ });
1021
+ });
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+ function managePackages(store) {
1028
+ console.log(`IAP Configurations - PlayStore: ${playstore}, Samsung: ${samsung}, Amazon: ${amazon}`);
1029
+
1030
+ let install = "";
1031
+ let uninstall = "";
1032
+
1033
+
1034
+
1035
+ let manifestContent = readFileSync(androidManifestPath, 'utf-8');
1036
+
1037
+ const permissionsToRemove = [
1038
+ 'com.android.vending.BILLING',
1039
+ 'com.samsung.android.iap.permission.BILLING'
1040
+ ];
1041
+
1042
+
1043
+ permissionsToRemove.forEach(permission => {
1044
+ const permissionRegex = new RegExp(`^\\s*<uses-permission\\s+android:name="${permission}"\\s*/?>\\s*[\r\n]?`, 'm');
1045
+ if (permissionRegex.test(manifestContent)) {
1046
+ manifestContent = manifestContent.replace(permissionRegex, '');
1047
+ console.log(`✅ Removed <uses-permission android:name="${permission}" /> from AndroidManifest.xml`);
1048
+ }
1049
+ });
1050
+
1051
+ // Write the updated content back to the file
1052
+ writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1053
+
1054
+
1055
+
1056
+ if ((playstore && store === "PlayStore") || (amazon && store === "AmazonStore")) {
1057
+ install = '@revenuecat/purchases-capacitor';
1058
+ uninstall = 'cordova-plugin-samsungiap';
1059
+
1060
+ // Update AndroidManifest.xml for PlayStore
1061
1061
  if (playstore && store === "PlayStore")
1062
1062
  updateAndroidManifest(store,
1063
1063
  '<uses-permission android:name="com.android.vending.BILLING" />');
1064
-
1065
- } else if (samsung && store === "SamsungStore") {
1066
- install = 'cordova-plugin-samsungiap';
1067
- uninstall = '@revenuecat/purchases-capacitor';
1068
-
1069
- // Update AndroidManifest.xml for SamsungStore
1070
- updateAndroidManifest(store,
1071
- '<uses-permission android:name="com.samsung.android.iap.permission.BILLING" />');
1072
-
1073
- } else {
1074
- console.log("No valid store specified or no configurations found. Both plugins will be uninstalled.");
1075
- try {
1076
- execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
1077
- execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
1078
- console.log(`✅ Both plugins uninstalled successfully.`);
1079
- } catch (err) {
1080
- console.error("❌ Error uninstalling plugins:", err);
1081
- }
1082
- return;
1083
- }
1084
-
1085
- console.log(`⚠️ Installing ${install} and uninstalling ${uninstall} for ${store}...`);
1086
- try {
1087
- if (install) {
1088
- execSync(`npm install ${install}`, { stdio: 'inherit' });
1089
- }
1090
- if (uninstall) {
1091
- execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
1092
- }
1093
- console.log(`✅ ${install} installed and ${uninstall} uninstalled successfully.`);
1094
- } catch (err) {
1095
- console.error(`❌ Error managing packages for ${store}:`, err);
1096
- }
1097
- }
1098
-
1099
-
1100
-
1101
- function updateAndroidManifest(store, addPermission) {
1102
- try {
1103
- if (!existsSync(androidManifestPath)) {
1104
- console.error("❌ AndroidManifest.xml file not found!");
1105
- return;
1106
- }
1107
-
1108
- // Read the content of the AndroidManifest.xml
1109
- let manifestContent = readFileSync(androidManifestPath, 'utf-8');
1110
-
1111
- // Normalize line endings to `\n` for consistent processing
1112
- manifestContent = manifestContent.replace(/\r\n/g, '\n');
1113
-
1114
- // Check if the permission is already present
1115
- if (manifestContent.includes(addPermission.trim())) {
1116
- console.log(`${addPermission} is already in the AndroidManifest.xml. Skipping addition.`);
1117
- return; // Skip if the permission is already present
1118
- }
1119
-
1120
- // Insert the permission before the closing </manifest> tag
1121
- const closingTag = '</manifest>';
1122
- const formattedPermission = ` ${addPermission.trim()}\n`;
1123
- if (manifestContent.includes(closingTag)) {
1124
- manifestContent = manifestContent.replace(
1125
- closingTag,
1126
- `${formattedPermission}${closingTag}`
1127
- );
1128
- console.log(`✅ Added ${addPermission} before </manifest> tag.`);
1129
- } else {
1130
- console.warn(`⚠️ </manifest> tag not found. Adding ${addPermission} at the end of the file.`);
1131
- manifestContent += `\n${formattedPermission}`;
1132
- }
1133
-
1134
- // Normalize line endings back to `\r\n` and write the updated content
1135
- manifestContent = manifestContent.replace(/\n/g, '\r\n');
1136
- writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1137
- console.log(`✅ AndroidManifest.xml updated successfully for ${store}`);
1138
- } catch (err) {
1139
- console.error(`❌ Error updating AndroidManifest.xml for ${store}:`, err);
1140
- }
1141
- }
1142
-
1143
-
1144
-
1145
- /* restoreCapacitorConfig();
1146
- console.log("🏁 All builds completed, capacitor.config.json restored."); */
1147
-
1148
-
1149
- /* function updateAndroidManifest1(store, addPermission) {
1150
- try {
1151
- if (!fs.existsSync(androidManifestPath)) {
1152
- console.error("AndroidManifest.xml file not found!");
1153
- return;
1154
- }
1155
-
1156
- let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
1157
-
1158
-
1159
-
1160
- // Add the required permission if not already present
1161
- if (!manifestContent.includes(addPermission)) {
1162
- const manifestLines = manifestContent.split('\n');
1163
- const insertIndex = manifestLines.findIndex(line => line.trim().startsWith('<application'));
1164
- if (insertIndex > -1) {
1165
- manifestLines.splice(insertIndex, 0, ` ${addPermission}`);
1166
- manifestContent = manifestLines.join('\n');
1167
- console.log(`Added ${addPermission} to AndroidManifest.xml`);
1168
- }
1169
- }
1170
-
1171
- // Write the updated content back to the file
1172
- fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1173
- console.log(`AndroidManifest.xml updated successfully for ${store}`);
1174
- } catch (err) {
1175
- console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
1176
- }
1177
- } */
1178
-
1179
-
1180
-
1181
-
1182
-
1183
-
1184
-
1185
-
1064
+
1065
+ } else if (samsung && store === "SamsungStore") {
1066
+ install = 'cordova-plugin-samsungiap';
1067
+ uninstall = '@revenuecat/purchases-capacitor';
1068
+
1069
+ // Update AndroidManifest.xml for SamsungStore
1070
+ updateAndroidManifest(store,
1071
+ '<uses-permission android:name="com.samsung.android.iap.permission.BILLING" />');
1072
+
1073
+ } else {
1074
+ console.log("No valid store specified or no configurations found. Both plugins will be uninstalled.");
1075
+ try {
1076
+ execSync(`npm uninstall cordova-plugin-samsungiap`, { stdio: 'inherit' });
1077
+ execSync(`npm uninstall @revenuecat/purchases-capacitor`, { stdio: 'inherit' });
1078
+ console.log(`✅ Both plugins uninstalled successfully.`);
1079
+ } catch (err) {
1080
+ console.error("❌ Error uninstalling plugins:", err);
1081
+ }
1082
+ return;
1083
+ }
1084
+
1085
+ console.log(`⚠️ Installing ${install} and uninstalling ${uninstall} for ${store}...`);
1086
+ try {
1087
+ if (install) {
1088
+ execSync(`npm install ${install}`, { stdio: 'inherit' });
1089
+ }
1090
+ if (uninstall) {
1091
+ execSync(`npm uninstall ${uninstall}`, { stdio: 'inherit' });
1092
+ }
1093
+ console.log(`✅ ${install} installed and ${uninstall} uninstalled successfully.`);
1094
+ } catch (err) {
1095
+ console.error(`❌ Error managing packages for ${store}:`, err);
1096
+ }
1097
+ }
1098
+
1099
+
1100
+
1101
+ function updateAndroidManifest(store, addPermission) {
1102
+ try {
1103
+ if (!existsSync(androidManifestPath)) {
1104
+ console.error("❌ AndroidManifest.xml file not found!");
1105
+ return;
1106
+ }
1107
+
1108
+ // Read the content of the AndroidManifest.xml
1109
+ let manifestContent = readFileSync(androidManifestPath, 'utf-8');
1110
+
1111
+ // Normalize line endings to `\n` for consistent processing
1112
+ manifestContent = manifestContent.replace(/\r\n/g, '\n');
1113
+
1114
+ // Check if the permission is already present
1115
+ if (manifestContent.includes(addPermission.trim())) {
1116
+ console.log(`${addPermission} is already in the AndroidManifest.xml. Skipping addition.`);
1117
+ return; // Skip if the permission is already present
1118
+ }
1119
+
1120
+ // Insert the permission before the closing </manifest> tag
1121
+ const closingTag = '</manifest>';
1122
+ const formattedPermission = ` ${addPermission.trim()}\n`;
1123
+ if (manifestContent.includes(closingTag)) {
1124
+ manifestContent = manifestContent.replace(
1125
+ closingTag,
1126
+ `${formattedPermission}${closingTag}`
1127
+ );
1128
+ console.log(`✅ Added ${addPermission} before </manifest> tag.`);
1129
+ } else {
1130
+ console.warn(`⚠️ </manifest> tag not found. Adding ${addPermission} at the end of the file.`);
1131
+ manifestContent += `\n${formattedPermission}`;
1132
+ }
1133
+
1134
+ // Normalize line endings back to `\r\n` and write the updated content
1135
+ manifestContent = manifestContent.replace(/\n/g, '\r\n');
1136
+ writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1137
+ console.log(`✅ AndroidManifest.xml updated successfully for ${store}`);
1138
+ } catch (err) {
1139
+ console.error(`❌ Error updating AndroidManifest.xml for ${store}:`, err);
1140
+ }
1141
+ }
1142
+
1143
+
1144
+
1145
+ /* restoreCapacitorConfig();
1146
+ console.log("🏁 All builds completed, capacitor.config.json restored."); */
1147
+
1148
+
1149
+ /* function updateAndroidManifest1(store, addPermission) {
1150
+ try {
1151
+ if (!fs.existsSync(androidManifestPath)) {
1152
+ console.error("AndroidManifest.xml file not found!");
1153
+ return;
1154
+ }
1155
+
1156
+ let manifestContent = fs.readFileSync(androidManifestPath, 'utf-8');
1157
+
1158
+
1159
+
1160
+ // Add the required permission if not already present
1161
+ if (!manifestContent.includes(addPermission)) {
1162
+ const manifestLines = manifestContent.split('\n');
1163
+ const insertIndex = manifestLines.findIndex(line => line.trim().startsWith('<application'));
1164
+ if (insertIndex > -1) {
1165
+ manifestLines.splice(insertIndex, 0, ` ${addPermission}`);
1166
+ manifestContent = manifestLines.join('\n');
1167
+ console.log(`Added ${addPermission} to AndroidManifest.xml`);
1168
+ }
1169
+ }
1170
+
1171
+ // Write the updated content back to the file
1172
+ fs.writeFileSync(androidManifestPath, manifestContent, 'utf-8');
1173
+ console.log(`AndroidManifest.xml updated successfully for ${store}`);
1174
+ } catch (err) {
1175
+ console.error(`Error updating AndroidManifest.xml for ${store}:`, err);
1176
+ }
1177
+ } */
1178
+
1179
+
1180
+
1181
+
1182
+
1183
+
1184
+
1185
+