codeplay-common 4.9.9 → 4.10.1

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,11 +1,90 @@
1
- // Version 6.5: migrate AdMob files to ZIP-distributed folder packages.
2
- // Version 6.5: recreate failed WebViews, defer background recovery, and suppress foreground recovery toasts.
1
+ // Version 6.7: deferred IAP startup, ownership-safe ads, and unified store preparation.
2
+ // Version 6.7: migrate AdMob files to ZIP-distributed folder packages.
3
+ // Version 6.7: recreate failed WebViews, defer background recovery, and suppress foreground recovery toasts.
3
4
  const fs = require('fs');
4
5
  const path = require('path');
5
6
  const plist = require('plist');
6
7
 
8
+ // Preserve comments, strings, and custom tree-shaking objects/functions.
9
+ // Only migrate the explicit boolean opt-out used by older Codeplay configs.
10
+ const migrateViteTreeShaking = (content) => content.replace(
11
+ /\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|\btreeshake([ \t]*:[ \t]*)false\b/g,
12
+ (match, separator) => separator === undefined ? match : `treeshake${separator}true`
13
+ );
14
+
7
15
 
8
16
 
17
+ // BEGIN IAP BUILD MIGRATION
18
+ const updateBuildEntrypoints = (scripts) => require('./project-scripts.cjs').updateBuildScripts(scripts);
19
+
20
+ const migrateIapStartup = (content, bootstrapImport) => {
21
+ let next = content;
22
+ const bootstrapPattern = /import\s*\{\s*initIAP\s*\}\s*from\s*['"][^'"]*\/IAP-bootstrap\.js['"]\s*;?/;
23
+ if (!bootstrapPattern.test(next)) {
24
+ next = next.replace(/import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/g,
25
+ (match, names, quote, source) => {
26
+ const imports = names.split(',').map(name => name.trim()).filter(Boolean);
27
+ if (!imports.includes('initIAP')) return match;
28
+ const remaining = imports.filter(name => name !== 'initIAP');
29
+ return remaining.length ? `import { ${remaining.join(', ')} } from ${quote}${source}${quote};` : '';
30
+ });
31
+ next = next.replace(/<script>\s*\r?\n/, match => `${match}import { initIAP } from '${bootstrapImport}';\n`);
32
+ }
33
+ if (!/\binitIAP\s*\(/.test(next)) {
34
+ const component = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
35
+ if (!component.test(next)) throw new Error('Unsupported Home component: cannot schedule IAP safely.');
36
+ next = next.replace(component, '$1 initIAP();\n');
37
+ }
38
+ return next;
39
+ };
40
+ // Identify existing Pro controls without replacing an application's Home layout.
41
+ // App-specific controls can opt in with the codeplay-iap-pro class.
42
+ const migrateHomeIapVisibility = (content, stateImport) => {
43
+ const template = content.match(/<template>[\s\S]*?<\/template>/);
44
+ if (!template) return content;
45
+ const stack = [];
46
+ const controls = new Map();
47
+ const tags = /<!--[\s\S]*?-->|<\/?[\w-]+\b(?:[^"'<>]|"[^"]*"|'[^']*')*>/g;
48
+ for (const match of template[0].matchAll(tags)) {
49
+ const tag = match[0];
50
+ if (tag.startsWith('<!--')) continue;
51
+ const name = tag.match(/^<\/?([\w-]+)/)[1].toLowerCase();
52
+ if (tag.startsWith('</')) {
53
+ const index = stack.map(item => item.name).lastIndexOf(name);
54
+ if (index >= 0) stack.length = index;
55
+ continue;
56
+ }
57
+ const classMatch = tag.match(/\bclass\s*=\s*(["'])([\s\S]*?)\1/);
58
+ const classes = classMatch?.[2] || '';
59
+ const node = { name, tag, index: template.index + match.index, classes };
60
+ const clickable = item => /(?:@click|\bdata-iap-pro)\s*=/.test(item.tag) || ['a', 'button'].includes(item.name) || /\b(?:link|codeplay-iap-pro)\b/.test(item.classes);
61
+ if (/\b(?:trPro|clsSubscribeBtn|codeplay-iap-pro)\b/.test(classes) || /@click\s*=\s*["']\$\{\s*subscribeOrProLink\s*\}/.test(tag)) {
62
+ const control = clickable(node) ? node : [...stack].reverse().find(clickable) || (/\bclsSubscribeBtn\b/.test(classes) ? node : null);
63
+ if (control) controls.set(control.index, control);
64
+ }
65
+ if (!/\/\s*>$/.test(tag) && !['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'].includes(name)) stack.push(node);
66
+ }
67
+ if (!controls.size) return content;
68
+ const gate = stateImport ? "${isIAPEnabledForCurrentStore() ? '' : 'display-none'}" : "${false ? '' : 'display-none'}";
69
+ let next = content;
70
+ for (const control of [...controls.values()].sort((a, b) => b.index - a.index)) {
71
+ const classes = control.classes
72
+ .replace(/\$\{(?:isIAPEnabledForCurrentStore\(\)|false)\s*\?\s*''\s*:\s*'display-none'\s*\}/g, '')
73
+ .split(/\s+/).filter(name => name && !/^hideFor(?:Mi|Vivo|Huawei|Oppo|Amazon|Samsung|Playstore|PlayStore|Ios|iOS)$/.test(name) && name !== 'codeplay-iap-pro');
74
+ const value = `${classes.join(' ')} codeplay-iap-pro ${gate}`.trim();
75
+ const tag = /\bclass\s*=/.test(control.tag)
76
+ ? control.tag.replace(/\bclass\s*=\s*(["'])([\s\S]*?)\1/, () => `class="${value}"`)
77
+ : control.tag.replace(/^<[\w-]+/, match => `${match} class="${value}"`);
78
+ next = next.slice(0, control.index) + tag + next.slice(control.index + control.tag.length);
79
+ }
80
+ if (stateImport && !/import\s*\{[^}]*\bisIAPEnabledForCurrentStore\b[^}]*\}\s*from\s*['"][^'"]*\/IAP-state\.js['"]/.test(next)) {
81
+ if (!next.includes('<script>')) throw new Error('Cannot migrate Pro visibility: Home has no script block.');
82
+ next = next.replace(/<script>(?:[ \t]*\r?\n)?/, match => `${match}import { isIAPEnabledForCurrentStore } from '${stateImport}';\n`);
83
+ }
84
+ return next;
85
+ };
86
+ // END IAP BUILD MIGRATION
87
+
9
88
  const { execSync } = require("child_process");
10
89
 
11
90
 
@@ -95,10 +174,10 @@ const getLatestVersionedFileName = (dir, pattern) => {
95
174
  /* const requiredPlugins = [
96
175
 
97
176
  { pattern: /backbutton-(\d+\.\d+)\.js$/, minVersion: '2.0', required: true, baseDir: 'js',mandatoryUpdate: true},
98
-
177
+
99
178
 
100
179
  { pattern: /common-(\d+\.\d+)(?:-beta-(\d+))?\.js$/, minVersion: '6.0', required: true, baseDir: 'js',mandatoryUpdate: true },
101
-
180
+
102
181
  { pattern: /localization_settings-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
103
182
  { pattern: /localization-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: true },
104
183
  { pattern: /localNotification-(\d+\.\d+)\.js$/, minVersion: '2.2', required: true, baseDir: 'js',mandatoryUpdate: false },
@@ -110,8 +189,8 @@ const getLatestVersionedFileName = (dir, pattern) => {
110
189
  { pattern: /video-player-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: false },
111
190
  { pattern: /image-cropper-(\d+\.\d+)\.js$/, minVersion: '1.1', required: true, baseDir: 'js',mandatoryUpdate: false },
112
191
  { pattern: /common-(\d+\.\d+)\.less$/, minVersion: '1.6', required: true, baseDir: 'assets/css',mandatoryUpdate: false },
113
-
114
-
192
+
193
+
115
194
  // New folders
116
195
  { pattern: /IAP-(\d+\.\d+)$/, minVersion: '2.8', isFolder: true , required: true, baseDir: 'js/Ads',mandatoryUpdate: true },
117
196
  { pattern: /editor-(\d+\.\d+)$/, minVersion: '1.9', isFolder: true, required: true, baseDir: 'js',mandatoryUpdate: true },
@@ -120,11 +199,11 @@ const getLatestVersionedFileName = (dir, pattern) => {
120
199
 
121
200
 
122
201
  { pattern: /certificatejs-(\d+\.\d+)$/, minVersion: '1.6', isFolder: true , required: true, baseDir: 'certificate',mandatoryUpdate: true }
123
-
202
+
124
203
  ]; */
125
204
 
126
205
 
127
- const ROOT_DIR = path.join(__dirname, "..", "src");
206
+ const ROOT_DIR = path.join(process.cwd(), "src");
128
207
 
129
208
  function requireOrInstall(packageName) {
130
209
  try {
@@ -230,6 +309,7 @@ function loadRequiredPlugins() {
230
309
  !/^admob-(?:emi-)?nextgen$/i.test(String(p.name || '')) && !/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
231
310
  ).map(p => ({
232
311
  ...p,
312
+ minVersion: p.name === 'IAP' && compareVersionStrings(p.minVersion, '4.6') < 0 ? '4.6' : p.minVersion,
233
313
  pattern: new RegExp(p.pattern)
234
314
  }));
235
315
 
@@ -289,6 +369,12 @@ function getLatestVersion(packageName) {
289
369
 
290
370
  function checkPackageVersion() {
291
371
  const packageName = 'codeplay-common';
372
+ const appPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
373
+ const declaredPackage = appPackage.dependencies?.[packageName] || appPackage.devDependencies?.[packageName] || '';
374
+ if (/^(?:file:|link:|workspace:)/.test(declaredPackage)) {
375
+ console.log('Using local codeplay-common source; skipping registry replacement.');
376
+ return;
377
+ }
292
378
  const installedVersion = getInstalledVersion(packageName);
293
379
  const latestVersion = getLatestVersion(packageName);
294
380
 
@@ -298,9 +384,9 @@ function checkPackageVersion() {
298
384
  return;
299
385
  }
300
386
 
301
- if (installedVersion !== latestVersion) {
387
+ if (compareVersionStrings(installedVersion, latestVersion) < 0) {
302
388
  console.log(`${packageName} is outdated (installed: ${installedVersion}, latest: ${latestVersion}). Updating now...`);
303
-
389
+
304
390
  try {
305
391
  execSync(`npm uninstall ${packageName}`, { stdio: 'inherit' });
306
392
  execSync(`npm install ${packageName}`, { stdio: 'inherit' });
@@ -424,7 +510,7 @@ const checkAppUniqueId=()=>{
424
510
 
425
511
  if (!orientation) {
426
512
  logErrorMessage+='❌ Missing android.ORIENTATION option in capacitor.config.json.\n';
427
- }
513
+ }
428
514
 
429
515
  else if(orientation!="portrait" && orientation!="landscape" && orientation!="auto")
430
516
  {
@@ -555,34 +641,19 @@ const getRelativeModuleImport = (sourceFile, targetFile) => {
555
641
  return relativePath;
556
642
  };
557
643
 
558
- const addInitIapToExistingImport = (content) => {
559
- const iapImportRegex = /import\s*\{([^}]*)\}\s*from\s*(['"])([^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js)\2\s*;?/;
560
- const match = content.match(iapImportRegex);
561
- if (!match || /\binitIAP\b/.test(match[1])) return content;
562
-
563
- const importNames = match[1].trim();
564
- const nextImportNames = importNames ? `initIAP, ${importNames}` : "initIAP";
565
- return content.replace(iapImportRegex, `import { ${nextImportNames} } from ${match[2]}${match[3]}${match[2]};`);
566
- };
567
-
568
- const addInitIapCall = (content) => {
569
- if (/\binitIAP\s*\(/.test(content)) return content;
570
-
571
- const pageInitRegex = /(\$on\(\s*(['"])pageInit\2\s*,\s*(?:async\s*)?\(\)\s*=>\s*\{\s*\r?\n)/;
572
- if (pageInitRegex.test(content)) {
573
- return content.replace(pageInitRegex, "$1 initIAP();\n");
574
- }
575
-
576
- const componentStartRegex = /(export\s+default\s*\([^)]*\)\s*=>\s*\{\s*\r?\n)/;
577
- if (componentStartRegex.test(content)) {
578
- return content.replace(componentStartRegex, "$1 initIAP();\n");
579
- }
580
-
581
- throw new Error("Unable to find a Framework7 component or pageInit lifecycle for IAP startup.");
582
- };
583
-
584
644
  const ensureIapStartupOnHomePage = () => {
585
645
  const iapConfig = getAdmobIapConfig()?.IAP;
646
+ const visibilityHome = getHomePagePath();
647
+ const visibilityIap = getLatestIapDir();
648
+ const statePath = visibilityIap && path.join(visibilityIap, 'IAP-state.js');
649
+ if (visibilityHome) {
650
+ const original = fs.readFileSync(visibilityHome, 'utf8');
651
+ const next = migrateHomeIapVisibility(original, statePath && fs.existsSync(statePath) ? getRelativeModuleImport(visibilityHome, statePath) : null);
652
+ if (next !== original) {
653
+ fs.writeFileSync(visibilityHome, next, 'utf8');
654
+ console.log(`✅ Updated shared Pro-button visibility in ${path.relative(process.cwd(), visibilityHome)}.`);
655
+ }
656
+ }
586
657
  if (!isAnyIapStoreEnabled(iapConfig)) {
587
658
  console.log("ℹ️ IAP is disabled for every store. AdMob will use direct startup.");
588
659
  return;
@@ -605,26 +676,15 @@ const ensureIapStartupOnHomePage = () => {
605
676
 
606
677
  let content = fs.readFileSync(homePagePath, "utf8");
607
678
  const originalContent = content;
608
- const staticInitImportRegex = /import\s*\{[^}]*\binitIAP\b[^}]*\}\s*from\s*['"][^'"]*\/IAP-\d+(?:\.\d+)*\/IAP-check-And-LoadAd\.js['"]\s*;?/;
609
-
610
- content = addInitIapToExistingImport(content);
611
-
612
- if (!staticInitImportRegex.test(content)) {
613
- const relativeImport = getRelativeModuleImport(homePagePath, iapModulePath);
614
- const scriptStartRegex = /<script>\s*\r?\n/;
615
- if (!scriptStartRegex.test(content)) {
616
- throw new Error(`Unable to find the script block in ${homePagePath}`);
617
- }
618
- content = content.replace(scriptStartRegex, `$&import { initIAP } from '${relativeImport}';\n`);
619
- }
620
-
621
- content = addInitIapCall(content);
679
+ const bootstrapPath = path.join(latestIapDir, 'IAP-bootstrap.js');
680
+ if (!fs.existsSync(bootstrapPath)) throw new Error('IAP 4.6 or newer is required for deferred startup.');
681
+ content = migrateIapStartup(content, getRelativeModuleImport(homePagePath, bootstrapPath));
622
682
 
623
683
  if (content !== originalContent) {
624
684
  fs.writeFileSync(homePagePath, content, "utf8");
625
- console.log(`✅ Added direct IAP startup to ${path.relative(process.cwd(), homePagePath)}.`);
685
+ console.log(`✅ Added background IAP startup to ${path.relative(process.cwd(), homePagePath)}.`);
626
686
  } else {
627
- console.log(`ℹ️ Direct IAP startup already configured in ${path.relative(process.cwd(), homePagePath)}.`);
687
+ console.log(`ℹ️ Background IAP startup already configured in ${path.relative(process.cwd(), homePagePath)}.`);
628
688
  }
629
689
  };
630
690
 
@@ -647,7 +707,7 @@ const ensureIapStartupOnHomePage = () => {
647
707
  //const path = require("path");
648
708
  //const { execSync } = require("child_process");
649
709
 
650
- const jsDir = path.join(__dirname, "..", "src", "js");
710
+ const jsDir = path.join(process.cwd(), "src", "js");
651
711
 
652
712
  // 🔍 Detect OLD structure
653
713
  const oldEditorDirs = fs.readdirSync(jsDir)
@@ -792,9 +852,9 @@ else {
792
852
 
793
853
  const saveToGalleryAndSaveFileCheck_iOS = async () => {
794
854
 
795
- const SOURCE_ROOT = path.resolve(__dirname, '../src');
855
+ const SOURCE_ROOT = path.resolve(process.cwd(), 'src');
796
856
  const EXCLUDED_DIR = path.join(SOURCE_ROOT, 'js', 'Ads');
797
- const ANDROID_MANIFEST_PATH = path.resolve(__dirname, '../android/app/src/main/AndroidManifest.xml');
857
+ const ANDROID_MANIFEST_PATH = path.resolve(process.cwd(), 'android/app/src/main/AndroidManifest.xml');
798
858
 
799
859
 
800
860
  // Skip comments and unrelated strings; match static/dynamic imports, re-exports and require.
@@ -816,7 +876,7 @@ You are using a direct version-based path like: editor/editor-x.x/editor.js
816
876
 
817
877
  👉 Please use the proper alias or updated import method.
818
878
  Example: import { ... } from '@editor'
819
-
879
+
820
880
  ⚠️ Do not use version-based paths in imports.
821
881
  👉 Please add this manually in vite.config.js:
822
882
 
@@ -838,7 +898,7 @@ const SKIP_FILES = [
838
898
 
839
899
 
840
900
 
841
- const STATUSBAR_FILE = path.resolve(__dirname, '../src/js/common-configuration.js');
901
+ const STATUSBAR_FILE = path.resolve(process.cwd(), 'src/js/common-configuration.js');
842
902
  const STATUSBAR_REGEX = /^(?!\s*\/\/).*Capacitor\.Plugins\.StatusBar\.setStyle/m;
843
903
 
844
904
 
@@ -1151,7 +1211,7 @@ const routes = [
1151
1211
  },
1152
1212
  }]
1153
1213
  `);
1154
-
1214
+
1155
1215
  badImports.forEach(({ line, number }) => {
1156
1216
  console.error(`${number}: ${line}`);
1157
1217
  });
@@ -1394,8 +1454,8 @@ if (updated) {
1394
1454
 
1395
1455
  // Build the path dynamically like you requested
1396
1456
  const gradlePath = path.join(
1397
- process.cwd(),
1398
- 'android',
1457
+ process.cwd(),
1458
+ 'android',
1399
1459
  'build.gradle'
1400
1460
  );
1401
1461
 
@@ -1614,11 +1674,11 @@ function validateAndroidBuildOptions() {
1614
1674
  const targetAppId=config.appId
1615
1675
 
1616
1676
  const buildOptions = config.android?.buildOptions;
1617
-
1677
+
1618
1678
  if (!buildOptions) {
1619
1679
  console.log('❌ Missing android.buildOptions in capacitor.config.json.');
1620
1680
  process.exit(1);
1621
- }
1681
+ }
1622
1682
 
1623
1683
  const requiredProps = [
1624
1684
  'keystorePath',
@@ -1630,13 +1690,13 @@ function validateAndroidBuildOptions() {
1630
1690
  ];
1631
1691
 
1632
1692
  const missing = requiredProps.filter(prop => !buildOptions[prop]);
1633
-
1693
+
1634
1694
  if (missing.length > 0) {
1635
1695
  console.log('❌ Missing properties android.buildOptions in capacitor.config.json.');
1636
1696
  process.exit(1);
1637
1697
  }
1638
1698
 
1639
-
1699
+
1640
1700
  const keystorePath=buildOptions.keystorePath
1641
1701
  const keyFileName = path.basename(keystorePath);
1642
1702
 
@@ -1826,7 +1886,7 @@ try {
1826
1886
  _admobConfig = getAdMobConfig();
1827
1887
 
1828
1888
 
1829
-
1889
+
1830
1890
 
1831
1891
 
1832
1892
  // Proceed only if ADMOB_ENABLED is true
@@ -2170,7 +2230,9 @@ async function syncAgentInstructions() {
2170
2230
 
2171
2231
  const zipName = `${AGENT_INSTRUCTIONS_ZIP_PREFIX}-${remoteVersion}.zip`;
2172
2232
  const url = `https://htmlcodeplay.com/code-play-plugin/${zipName}`;
2173
- const tempRoot = fs.mkdtempSync(path.join(require("os").tmpdir(), "codeplay-agents-"));
2233
+ const agentTempRoot = path.join(process.cwd(), "agent-temp", "agent-instructions");
2234
+ fs.mkdirSync(agentTempRoot, { recursive: true });
2235
+ const tempRoot = fs.mkdtempSync(path.join(agentTempRoot, "codeplay-agents-"));
2174
2236
  const zipPath = path.join(tempRoot, zipName);
2175
2237
  const extractPath = path.join(tempRoot, "extracted");
2176
2238
 
@@ -2248,7 +2310,9 @@ if (baseName === "common") {
2248
2310
  if (ext === ".less") pluginKey = "common-less";
2249
2311
  }
2250
2312
 
2251
- const latestVersion = versions[pluginKey];
2313
+ const advertisedVersion = versions[pluginKey];
2314
+ const latestVersion = baseName === 'IAP' && (!advertisedVersion || compareVersionStrings(advertisedVersion, pluginDef.minVersion) < 0)
2315
+ ? pluginDef.minVersion : advertisedVersion;
2252
2316
 
2253
2317
  if (!latestVersion) {
2254
2318
  console.log(`❌ No version entry for ${baseName}`);
@@ -2269,12 +2333,17 @@ if (pluginDef.isFolder) {
2269
2333
 
2270
2334
  if (!(await urlExists(url))) return false;
2271
2335
 
2272
- fs.rmSync(oldPath, { recursive: true, force: true });
2273
-
2274
- await downloadAndExtractZip(url, newPath);
2275
-
2336
+ const stagingRoot = path.join(process.cwd(), 'agent-temp', 'iap-package-sync');
2337
+ fs.mkdirSync(stagingRoot, { recursive: true });
2338
+ const staging = fs.mkdtempSync(path.join(stagingRoot, 'package-'));
2339
+ await downloadAndExtractZip(url, staging);
2340
+ if (baseName === 'IAP' && ['IAP-check-And-LoadAd.js', 'IAP-bootstrap.js', 'IAP-state.js', 'IAP-store.js'].some(name => !fs.existsSync(path.join(staging, name)))) throw new Error('Invalid IAP archive');
2341
+ if (fs.existsSync(newPath)) throw new Error('Replacement folder already exists; existing sources preserved.');
2342
+ fs.renameSync(staging, newPath);
2343
+ sourceFileInventory = null;
2276
2344
  updateImports(pluginInfo.name, `${baseName}-${latestVersion}`);
2277
2345
 
2346
+ fs.rmSync(oldPath, { recursive: true, force: true });
2278
2347
  // ✅ ADD THIS
2279
2348
  writeUpdateLine(`${pluginInfo.name} -> ${baseName}-${latestVersion}`);
2280
2349
 
@@ -2352,7 +2421,7 @@ existingFiles.forEach(file => {
2352
2421
  fs.unlinkSync(oldPath);
2353
2422
 
2354
2423
  console.log(`🗑 Removed old file → ${file}`);
2355
- //writeUpdateLine(`Removed old file: ${file}`);
2424
+ //writeUpdateLine(`Removed old file: ${file}`);
2356
2425
  }
2357
2426
 
2358
2427
  });
@@ -2415,7 +2484,7 @@ async function loadPluginVersions() {
2415
2484
  if (!plugin.name) return;
2416
2485
 
2417
2486
  if (versions[plugin.name]) {
2418
- plugin.minVersion = versions[plugin.name];
2487
+ if (compareVersionStrings(versions[plugin.name], plugin.minVersion) > 0) plugin.minVersion = versions[plugin.name];
2419
2488
  }
2420
2489
 
2421
2490
  });
@@ -2518,7 +2587,7 @@ function checkPlugins() {
2518
2587
  } */
2519
2588
 
2520
2589
 
2521
-
2590
+
2522
2591
 
2523
2592
 
2524
2593
  if (hasMandatoryUpdate) {
@@ -2625,14 +2694,14 @@ if (hasMandatoryUpdate) {
2625
2694
 
2626
2695
 
2627
2696
 
2628
- const localizationBaseDir = path.join(__dirname, "..", "src", "js", "localization");
2697
+ const localizationBaseDir = path.join(process.cwd(), "src", "js", "localization");
2629
2698
 
2630
2699
  // ======================================================
2631
2700
  // 🌐 LOCALIZATION CHECK (FULLY DYNAMIC)
2632
2701
  // ======================================================
2633
2702
 
2634
2703
 
2635
- const jsRootDir = path.join(__dirname, "..", "src", "js");
2704
+ const jsRootDir = path.join(process.cwd(), "src", "js");
2636
2705
 
2637
2706
  // 🔍 Detect OLD localization files in root js/
2638
2707
  const oldLocalizationFiles = fs.readdirSync(jsRootDir)
@@ -2876,6 +2945,17 @@ function getViteConfigPath() {
2876
2945
  .find(filePath => fs.existsSync(filePath));
2877
2946
  };
2878
2947
 
2948
+ const syncViteTreeShaking = () => {
2949
+ const configPath = getViteConfigPath();
2950
+ if (!configPath) return;
2951
+ const current = fs.readFileSync(configPath, 'utf8');
2952
+ const next = migrateViteTreeShaking(current);
2953
+ if (next !== current) {
2954
+ fs.writeFileSync(configPath, next, 'utf8');
2955
+ console.log('✅ Enabled Vite tree shaking for common JavaScript and other unused exports.');
2956
+ }
2957
+ };
2958
+
2879
2959
  const getLatestIapDir = () => {
2880
2960
  const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2881
2961
 
@@ -3713,6 +3793,7 @@ const ensureIapDesignInCapacitorConfig = (iapConfig) => {
3713
3793
  };
3714
3794
 
3715
3795
  const getCurrentStoreId = () => {
3796
+ if (buildPlatform === 'ios') return 6;
3716
3797
  const envStoreId = Number(process.env.VITE_STORE_ID);
3717
3798
  if (Number.isInteger(envStoreId) && envStoreId > 0) return envStoreId;
3718
3799
 
@@ -3900,6 +3981,17 @@ const syncRevenueCatIapSetup = () => {
3900
3981
  console.log(`ℹ️ RevenueCat package is not required for store id ${storeId}.`);
3901
3982
  }
3902
3983
 
3984
+ const samsungEnabled = storeId === 2 && iapConfig.samsung === true;
3985
+ const samsungPackagePath = path.join(process.cwd(), 'node_modules', 'cordova-plugin-samsungiap', 'package.json');
3986
+ const samsungVersion = fs.existsSync(samsungPackagePath) ? JSON.parse(fs.readFileSync(samsungPackagePath, 'utf8')).version : '0';
3987
+ if (samsungEnabled && (!isPackageAvailable('cordova-plugin-samsungiap') || compareVersionStrings(samsungVersion, '2.0.0') < 0)) {
3988
+ runNpmCommand('npm install cordova-plugin-samsungiap@^2.0.0');
3989
+ packageChanged = true;
3990
+ } else if (!samsungEnabled && isPackageAvailable('cordova-plugin-samsungiap')) {
3991
+ runNpmCommand('npm uninstall cordova-plugin-samsungiap');
3992
+ packageChanged = true;
3993
+ }
3994
+ ensureAndroidPermission('com.samsung.android.iap.permission.BILLING', samsungEnabled);
3903
3995
  ensureAndroidPermission("com.android.vending.BILLING", store?.usesGoogleBilling === true && revenueCatEnabledForCurrentStore);
3904
3996
 
3905
3997
  if (iapConfig.samsung === true && revenueCatEnabled) {
@@ -4169,8 +4261,8 @@ const validateAndRestoreSignDetails=()=>{
4169
4261
 
4170
4262
 
4171
4263
  const filePath = path.join(
4172
- __dirname,
4173
- "../node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
4264
+ process.cwd(),
4265
+ "node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java"
4174
4266
  );
4175
4267
 
4176
4268
  const SYSTEM_BARS_PATCH_MARKER = "CODEPLAY_KEYBOARD_INSET_FIX";
@@ -4388,21 +4480,28 @@ function syncAndroidCordovaResourceKeep() {
4388
4480
  }
4389
4481
 
4390
4482
  async function main() {
4483
+ const buildPackage = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
4484
+ const buildScripts = updateBuildEntrypoints(buildPackage.scripts || {});
4485
+ if (JSON.stringify(buildScripts) !== JSON.stringify(buildPackage.scripts)) {
4486
+ buildPackage.scripts = buildScripts;
4487
+ fs.writeFileSync(packageJsonPath, JSON.stringify(buildPackage, null, 2) + '\n');
4488
+ }
4391
4489
  validateThemeFolderLocation();
4392
4490
  validateAndRestoreSignDetails();
4393
4491
  ensureMandatoryCapacitorPlugins();
4394
4492
 
4395
4493
  await loadPluginVersions(); // 🔥 NEW
4396
4494
  await syncAgentInstructions();
4495
+ await checkPlugins();
4397
4496
 
4398
4497
  await syncAdmobNextgenMigration();
4399
4498
  syncCodeplaySystemBarsPackage();
4400
4499
  syncSystemBarsSafeAreaMigration();
4401
- await checkPlugins();
4402
4500
  ensureIapStartupOnHomePage();
4403
4501
  syncRevenueCatIapSetup();
4404
4502
  syncFirebaseAnalyticsSetup();
4405
4503
  checkAndupdateDropInViteConfig();
4504
+ syncViteTreeShaking();
4406
4505
  checkAdmobConfigurationProperty();
4407
4506
  syncAndroidAdIdPermission();
4408
4507
  syncAndroidBuildOptimization();