codeplay-common 4.1.3 → 4.1.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.
package/README.md CHANGED
@@ -11,6 +11,9 @@ Make it to ionic project
11
11
  Donate to get full code including many common functions
12
12
  https://ko-fi.com/codeplay
13
13
 
14
+ Version 4.1.4
15
+ hardcoded version is removed for the admob-emi-nextgen
16
+
14
17
 
15
18
  Version 4.1.3
16
19
  "consentDebug": false automatically adds if not
@@ -14,12 +14,51 @@ const { readFileSync } = require("fs");
14
14
  const ENABLE_AUTO_UPDATE = true;
15
15
  const USE_LIVE_SERVER_VERSION = true;
16
16
 
17
- const configPath = path.join(process.cwd(), 'capacitor.config.json');
18
- const packageJsonPath = path.join(process.cwd(), 'package.json');
19
- const updateLogFile = path.join(process.cwd(), "", "plugin-update-log.txt");
20
- const ADMOB_NEXTGEN_FILE = "admob-emi-nextgen-1.4.js";
21
- const ADMOB_NEXTGEN_CONFIG = "admob-ad-configuration-nextgen.json";
22
- const ADMOB_OLD_CONFIG = "admob-ad-configuration.json";
17
+ const configPath = path.join(process.cwd(), 'capacitor.config.json');
18
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
19
+ const updateLogFile = path.join(process.cwd(), "", "plugin-update-log.txt");
20
+ const ADMOB_NEXTGEN_PLUGIN_NAME = "admob-emi-nextgen";
21
+ const ADMOB_NEXTGEN_FILE_PATTERN = new RegExp(`^${ADMOB_NEXTGEN_PLUGIN_NAME}-\\d+(?:\\.\\d+)*\\.js$`);
22
+ const ADMOB_NEXTGEN_CONFIG = "admob-ad-configuration-nextgen.json";
23
+ const ADMOB_OLD_CONFIG = "admob-ad-configuration.json";
24
+
25
+ const parseVersionParts = (version) => String(version || "0")
26
+ .trim()
27
+ .split(".")
28
+ .map(part => Number(part) || 0);
29
+
30
+ const extractVersionFromFileName = (fileName) => {
31
+ const match = String(fileName).match(/(\d+(?:\.\d+)*)/);
32
+ return match?.[1] || "0";
33
+ };
34
+
35
+ const compareVersionStrings = (versionA, versionB) => {
36
+ const aParts = parseVersionParts(versionA);
37
+ const bParts = parseVersionParts(versionB);
38
+ const maxParts = Math.max(aParts.length, bParts.length);
39
+
40
+ for (let i = 0; i < maxParts; i++) {
41
+ const diff = (aParts[i] || 0) - (bParts[i] || 0);
42
+ if (diff !== 0) return diff;
43
+ }
44
+ return 0;
45
+ };
46
+
47
+ const getLatestVersionedFileName = (dir, pattern) => {
48
+ if (!fs.existsSync(dir)) return null;
49
+
50
+ const matches = fs.readdirSync(dir).filter((name) => pattern.test(name));
51
+ if (!matches.length) return null;
52
+
53
+ return matches.sort((a, b) => {
54
+ const versionA = extractVersionFromFileName(a);
55
+ const versionB = extractVersionFromFileName(b);
56
+ return compareVersionStrings(versionB, versionA);
57
+ })[0];
58
+ };
59
+
60
+ const getLatestAdmobNextgenFileName = (adsDir) =>
61
+ getLatestVersionedFileName(adsDir, ADMOB_NEXTGEN_FILE_PATTERN);
23
62
 
24
63
  // Expected plugin list with minimum versions
25
64
  /* const requiredPlugins = [
@@ -1219,7 +1258,7 @@ function checkAndCopyResources() {
1219
1258
 
1220
1259
 
1221
1260
 
1222
- function getAdMobConfig() {
1261
+ function getAdMobConfig() {
1223
1262
  if (!fileExists(configPath)) {
1224
1263
  throw new Error('❌ capacitor.config.json not found. Ensure this is a Capacitor project.');
1225
1264
  }
@@ -1229,9 +1268,9 @@ function getAdMobConfig() {
1229
1268
  ? JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
1230
1269
  : {};
1231
1270
 
1232
- const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
1233
- const nextGenAdmobConfig = packageJson.admob || {};
1234
- const admobJsonAppIds = getAdmobJsonAppIds();
1271
+ const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
1272
+ const nextGenAdmobConfig = packageJson.admob || {};
1273
+ const admobJsonAppIds = getAdmobJsonAppIds();
1235
1274
 
1236
1275
  if (!legacyAdmobConfig && !nextGenAdmobConfig) {
1237
1276
  throw new Error('❌ AdMob configuration is missing in package.json or capacitor.config.json.');
@@ -1245,8 +1284,8 @@ function getAdMobConfig() {
1245
1284
  return { ADMOB_ENABLED: false };
1246
1285
  }
1247
1286
 
1248
- const androidAppId = admobJsonAppIds.androidAppId || nextGenAdmobConfig.androidAppId || legacyAdmobConfig.APP_ID_ANDROID;
1249
- const iosAppId = admobJsonAppIds.iosAppId || nextGenAdmobConfig.iosAppId || legacyAdmobConfig.APP_ID_IOS;
1287
+ const androidAppId = admobJsonAppIds.androidAppId || nextGenAdmobConfig.androidAppId || legacyAdmobConfig.APP_ID_ANDROID;
1288
+ const iosAppId = admobJsonAppIds.iosAppId || nextGenAdmobConfig.iosAppId || legacyAdmobConfig.APP_ID_IOS;
1250
1289
  const userTrackingDescription =
1251
1290
  nextGenAdmobConfig.userTrackingDescription ||
1252
1291
  legacyAdmobConfig.USER_TRACKING_DESCRIPTION ||
@@ -1265,18 +1304,18 @@ function getAdMobConfig() {
1265
1304
  };
1266
1305
  }
1267
1306
 
1268
- function syncNextGenAdmobPackageJsonFromCapacitorConfig() {
1269
- if (!fileExists(configPath) || !fileExists(packageJsonPath)) {
1270
- return;
1271
- }
1272
-
1273
- const capacitorConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1274
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
1275
-
1276
- const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
1277
- const admobJsonAppIds = getAdmobJsonAppIds();
1278
- const androidAppId = admobJsonAppIds.androidAppId || legacyAdmobConfig.APP_ID_ANDROID;
1279
- const iosAppId = admobJsonAppIds.iosAppId || legacyAdmobConfig.APP_ID_IOS;
1307
+ function syncNextGenAdmobPackageJsonFromCapacitorConfig() {
1308
+ if (!fileExists(configPath) || !fileExists(packageJsonPath)) {
1309
+ return;
1310
+ }
1311
+
1312
+ const capacitorConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1313
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
1314
+
1315
+ const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
1316
+ const admobJsonAppIds = getAdmobJsonAppIds();
1317
+ const androidAppId = admobJsonAppIds.androidAppId || legacyAdmobConfig.APP_ID_ANDROID;
1318
+ const iosAppId = admobJsonAppIds.iosAppId || legacyAdmobConfig.APP_ID_IOS;
1280
1319
 
1281
1320
  if (!androidAppId || !iosAppId) {
1282
1321
  return;
@@ -1324,11 +1363,11 @@ function syncNextGenAdmobPackageJsonFromCapacitorConfig() {
1324
1363
  }
1325
1364
 
1326
1365
  packageJson.admob = mergedAdmobConfig;
1327
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
1328
- console.log(admobJsonAppIds.androidAppId || admobJsonAppIds.iosAppId
1329
- ? '✅ package.json AdMob settings synced from AdMob configuration JSON'
1330
- : '✅ package.json AdMob settings synced from capacitor.config.json');
1331
- }
1366
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
1367
+ console.log(admobJsonAppIds.androidAppId || admobJsonAppIds.iosAppId
1368
+ ? '✅ package.json AdMob settings synced from AdMob configuration JSON'
1369
+ : '✅ package.json AdMob settings synced from capacitor.config.json');
1370
+ }
1332
1371
 
1333
1372
  function validateAndroidBuildOptions() {
1334
1373
 
@@ -1614,54 +1653,54 @@ const https = require("https");
1614
1653
  /**
1615
1654
  * Check if file exists on server using HEAD request
1616
1655
  */
1617
- function urlExists(url) {
1618
- return new Promise(resolve => {
1619
- const req = https.request(url, { method: "HEAD" }, res => {
1620
- res.resume();
1621
- resolve(res.statusCode === 200);
1622
- });
1623
-
1624
- req.on("error", () => resolve(false));
1625
- req.setTimeout(8000, () => {
1626
- req.destroy();
1627
- resolve(false);
1628
- });
1629
- req.end();
1630
- });
1631
- }
1656
+ function urlExists(url) {
1657
+ return new Promise(resolve => {
1658
+ const req = https.request(url, { method: "HEAD" }, res => {
1659
+ res.resume();
1660
+ resolve(res.statusCode === 200);
1661
+ });
1662
+
1663
+ req.on("error", () => resolve(false));
1664
+ req.setTimeout(8000, () => {
1665
+ req.destroy();
1666
+ resolve(false);
1667
+ });
1668
+ req.end();
1669
+ });
1670
+ }
1632
1671
 
1633
1672
  /**
1634
1673
  * Download file from server
1635
1674
  */
1636
- function downloadFile(url, dest) {
1637
- return new Promise((resolve, reject) => {
1638
- const file = fs.createWriteStream(dest);
1639
-
1640
- const req = https.get(url, response => {
1641
- if (response.statusCode !== 200) {
1642
- response.resume();
1643
- file.close(() => fs.unlink(dest, () => {}));
1644
- reject("Download failed");
1645
- return;
1646
- }
1647
-
1648
- response.pipe(file);
1675
+ function downloadFile(url, dest) {
1676
+ return new Promise((resolve, reject) => {
1677
+ const file = fs.createWriteStream(dest);
1678
+
1679
+ const req = https.get(url, response => {
1680
+ if (response.statusCode !== 200) {
1681
+ response.resume();
1682
+ file.close(() => fs.unlink(dest, () => {}));
1683
+ reject("Download failed");
1684
+ return;
1685
+ }
1686
+
1687
+ response.pipe(file);
1649
1688
 
1650
1689
  file.on("finish", () => {
1651
1690
  file.close(resolve);
1652
1691
  });
1653
- }).on("error", err => {
1654
- fs.unlink(dest, () => {});
1655
- reject(err);
1656
- });
1657
-
1658
- req.setTimeout(30000, () => {
1659
- req.destroy();
1660
- file.close(() => fs.unlink(dest, () => {}));
1661
- reject(new Error(`Download timed out: ${url}`));
1662
- });
1663
- });
1664
- }
1692
+ }).on("error", err => {
1693
+ fs.unlink(dest, () => {});
1694
+ reject(err);
1695
+ });
1696
+
1697
+ req.setTimeout(30000, () => {
1698
+ req.destroy();
1699
+ file.close(() => fs.unlink(dest, () => {}));
1700
+ reject(new Error(`Download timed out: ${url}`));
1701
+ });
1702
+ });
1703
+ }
1665
1704
 
1666
1705
  /**
1667
1706
  * Update imports across src folder
@@ -1806,6 +1845,16 @@ async function fetchVersions() {
1806
1845
 
1807
1846
 
1808
1847
 
1848
+ async function getLatestRemoteAdmobNextgenFileName() {
1849
+ const versions = await fetchVersions();
1850
+ if (!versions || typeof versions !== "object") return null;
1851
+
1852
+ const remoteVersion = String(versions[ADMOB_NEXTGEN_PLUGIN_NAME] || "").trim();
1853
+ if (!/^\d+(?:\.\d+)*$/.test(remoteVersion)) return null;
1854
+
1855
+ return `${ADMOB_NEXTGEN_PLUGIN_NAME}-${remoteVersion}.js`;
1856
+ }
1857
+
1809
1858
  async function autoUpdatePlugin(pluginDef, pluginInfo) {
1810
1859
 
1811
1860
  const versions = await fetchVersions();
@@ -2558,26 +2607,13 @@ const syncAdmobAliasInViteConfig = () => {
2558
2607
  return;
2559
2608
  }
2560
2609
 
2561
- const nextGenFiles = fs.readdirSync(adsDir)
2562
- .filter(name => /^admob-emi-nextgen-\d+(\.\d+)*\.js$/.test(name))
2563
- .sort((a, b) => {
2564
- const versionA = a.match(/(\d+(?:\.\d+)*)/)[1].split(".").map(Number);
2565
- const versionB = b.match(/(\d+(?:\.\d+)*)/)[1].split(".").map(Number);
2566
-
2567
- for (let i = 0; i < Math.max(versionA.length, versionB.length); i++) {
2568
- const diff = (versionB[i] || 0) - (versionA[i] || 0);
2569
- if (diff !== 0) return diff;
2570
- }
2571
-
2572
- return 0;
2573
- });
2610
+ const nextGenFile = getLatestAdmobNextgenFileName(adsDir);
2574
2611
 
2575
- if (nextGenFiles.length === 0) {
2612
+ if (!nextGenFile) {
2576
2613
  console.log("ℹ️ No admob-emi-nextgen-x.x.js file found. Keeping existing @admob alias.");
2577
2614
  return;
2578
2615
  }
2579
2616
 
2580
- const nextGenFile = nextGenFiles[0];
2581
2617
  const nextGenRelativePath = `./src/js/Ads/${nextGenFile}`;
2582
2618
 
2583
2619
  let viteContent = fs.readFileSync(viteConfigPath, "utf8");
@@ -2694,287 +2730,303 @@ const sourceImportsPackage = (packageName, ignoredFilePath) => {
2694
2730
  return scan(sourceDir);
2695
2731
  };
2696
2732
 
2697
- const runNpmCommand = (command) => {
2698
- console.log(`🚀 ${command}`);
2699
- execSync(command, { stdio: "inherit" });
2700
- };
2701
-
2702
- const ADMOB_NEXTGEN_DEFAULTS = {
2703
- VERSION: "1.6",
2704
- ios: { nativeid: "" },
2705
- android: { nativeid: "" },
2706
- config: {
2707
- bannerStartupDelayMs: "",
2708
- interstitialStartupDelayMs: "",
2709
- appOpenLoadOnColdStart: "",
2710
- appOpenStartupDelayMs: "",
2711
- useAndroidPreloadAds: true,
2712
- useAndroidBannerPreloadAds: false,
2713
- preloadBufferSize: 1,
2714
- consentDebug: false
2715
- },
2716
- testid: {
2717
- nativeid: "",
2718
- nativeid_android: "ca-app-pub-3940256099942544/2247696110",
2719
- nativeid_ios: "ca-app-pub-3940256099942544/3986624511"
2720
- }
2721
- };
2722
-
2723
- function getAdmobJsonPath() {
2724
- const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2725
- const possiblePaths = [
2726
- path.join(adsDir, ADMOB_NEXTGEN_CONFIG),
2727
- path.join(adsDir, ADMOB_OLD_CONFIG)
2728
- ];
2729
-
2730
- return possiblePaths.find(fileExists);
2731
- }
2732
-
2733
- function readJsonSafe(filePath) {
2734
- try {
2735
- return filePath && fileExists(filePath)
2736
- ? JSON.parse(fs.readFileSync(filePath, "utf8"))
2737
- : null;
2738
- } catch {
2739
- return null;
2740
- }
2741
- }
2742
-
2743
- function pickFirstValue(...values) {
2744
- return values.find(value => typeof value === "string" && value.trim() !== "") || "";
2745
- }
2746
-
2747
- function getAdmobJsonAppIds(config = readJsonSafe(getAdmobJsonPath())) {
2748
- return {
2749
- androidAppId: pickFirstValue(
2750
- config?.androidAppId,
2751
- config?.android_app_id,
2752
- config?.android?.appId,
2753
- config?.android?.appid,
2754
- config?.android?.applicationId
2755
- ),
2756
- iosAppId: pickFirstValue(
2757
- config?.iosAppId,
2758
- config?.ios_app_id,
2759
- config?.ios?.appId,
2760
- config?.ios?.appid,
2761
- config?.ios?.applicationId
2762
- )
2763
- };
2764
- }
2765
-
2766
- const mergeObjects = (template, source) => {
2767
- if (!template || typeof template !== "object" || Array.isArray(template)) {
2768
- return source !== undefined ? source : template;
2769
- }
2770
-
2771
- const output = { ...template };
2772
-
2773
- if (!source || typeof source !== "object" || Array.isArray(source)) {
2774
- return output;
2775
- }
2776
-
2777
- Object.keys(source).forEach(key => {
2778
- if (
2779
- template[key] &&
2780
- typeof template[key] === "object" &&
2781
- !Array.isArray(template[key]) &&
2782
- source[key] &&
2783
- typeof source[key] === "object" &&
2784
- !Array.isArray(source[key])
2785
- ) {
2786
- output[key] = mergeObjects(template[key], source[key]);
2787
- } else if (key !== "VERSION") {
2788
- output[key] = source[key];
2789
- }
2790
- });
2791
-
2792
- return output;
2793
- };
2794
-
2795
- const hasObjectKeys = (value) => {
2796
- return value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length > 0;
2797
- };
2798
-
2799
- const buildNextgenAdmobConfigFromOldConfig = (templateConfig, existingNextgenConfig, oldConfig) => {
2800
- const mergedConfig = mergeObjects(templateConfig, mergeObjects(existingNextgenConfig, oldConfig));
2801
-
2802
- if (hasObjectKeys(oldConfig)) {
2803
- if (hasObjectKeys(oldConfig.ios)) {
2804
- mergedConfig.ios = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.ios, oldConfig.ios);
2805
- }
2806
-
2807
- if (hasObjectKeys(oldConfig.android)) {
2808
- mergedConfig.android = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.android, oldConfig.android);
2809
- }
2810
-
2811
- if (hasObjectKeys(oldConfig.testid)) {
2812
- mergedConfig.testid = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.testid, oldConfig.testid);
2813
- }
2814
-
2815
- if (hasObjectKeys(oldConfig.IAP)) {
2816
- mergedConfig.IAP = oldConfig.IAP;
2817
- }
2818
-
2819
- if (hasObjectKeys(oldConfig.config)) {
2820
- const templateRuntimeConfig = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.config, templateConfig.config || {});
2821
- const existingRuntimeConfig = existingNextgenConfig.config || {};
2822
- mergedConfig.config = mergeObjects(templateRuntimeConfig, mergeObjects(existingRuntimeConfig, oldConfig.config));
2823
- }
2824
- }
2825
-
2826
- mergedConfig.VERSION = templateConfig.VERSION || ADMOB_NEXTGEN_DEFAULTS.VERSION;
2827
-
2828
- return mergedConfig;
2829
- };
2830
-
2831
- const syncAdmobNextgenPackage = () => {
2832
- if (!fs.existsSync(packageJsonPath)) {
2833
- console.warn("⚠️ package.json not found. Skipping AdMob nextgen package sync.");
2834
- return;
2835
- }
2836
-
2837
- if (isPackageAvailable("emi-indo-cordova-plugin-admob")) {
2838
- runNpmCommand("npm uninstall emi-indo-cordova-plugin-admob");
2839
- } else {
2840
- console.log("ℹ️ emi-indo-cordova-plugin-admob is not installed.");
2841
- }
2842
-
2843
- if (!isPackageAvailable("capacitor-admob-nextgen")) {
2844
- runNpmCommand("npm install capacitor-admob-nextgen");
2845
- } else {
2846
- console.log("ℹ️ capacitor-admob-nextgen is already installed.");
2847
- }
2848
- };
2849
-
2850
- const downloadOptionalCodeplayFile = async (fileName, destPath) => {
2851
- const url = `https://htmlcodeplay.com/code-play-plugin/${fileName}`;
2852
-
2853
- if (!(await urlExists(url))) {
2854
- return false;
2855
- }
2856
-
2857
- await downloadFile(url, destPath);
2858
- console.log(`⬇ Downloaded → ${fileName}`);
2859
- return true;
2860
- };
2861
-
2862
- const syncAdmobConfigImports = () => {
2863
- const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2864
- if (!fs.existsSync(adsDir)) return;
2865
-
2866
- const scan = (dir) => {
2867
- fs.readdirSync(dir, { withFileTypes: true }).forEach(entry => {
2868
- const fullPath = path.join(dir, entry.name);
2869
-
2870
- if (entry.isDirectory()) {
2871
- scan(fullPath);
2872
- return;
2873
- }
2874
-
2875
- if (!/\.(js|mjs|ts|f7)$/.test(entry.name) || entry.name.endsWith(".min.js")) return;
2876
-
2877
- let content = fs.readFileSync(fullPath, "utf8");
2878
- if (!content.includes(ADMOB_OLD_CONFIG)) return;
2879
-
2880
- content = content.split(ADMOB_OLD_CONFIG).join(ADMOB_NEXTGEN_CONFIG);
2881
- fs.writeFileSync(fullPath, content, "utf8");
2882
- console.log(`✏️ Updated AdMob config import in ${path.relative(process.cwd(), fullPath)}`);
2883
- });
2884
- };
2885
-
2886
- scan(adsDir);
2887
- };
2888
-
2889
- const ensureAdmobNextgenFiles = async () => {
2890
- const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2891
- if (!fs.existsSync(adsDir)) {
2892
- console.log("ℹ️ Ads folder not found. Skipping AdMob nextgen file sync.");
2893
- return;
2894
- }
2895
-
2896
- const nextgenPath = path.join(adsDir, ADMOB_NEXTGEN_FILE);
2897
- const nextgenConfigPath = path.join(adsDir, ADMOB_NEXTGEN_CONFIG);
2898
- const oldConfigPath = path.join(adsDir, ADMOB_OLD_CONFIG);
2899
- const tempTemplatePath = path.join(adsDir, `${ADMOB_NEXTGEN_CONFIG}.template`);
2900
-
2901
- if (!fs.existsSync(nextgenPath)) {
2902
- const downloaded = await downloadOptionalCodeplayFile(ADMOB_NEXTGEN_FILE, nextgenPath);
2903
- if (!downloaded) {
2904
- console.error(`❌ ${ADMOB_NEXTGEN_FILE} missing and live download failed.`);
2905
- process.exit(1);
2906
- }
2907
- }
2908
-
2909
- let templateConfig = ADMOB_NEXTGEN_DEFAULTS;
2910
-
2911
- if (await downloadOptionalCodeplayFile(ADMOB_NEXTGEN_CONFIG, tempTemplatePath)) {
2912
- templateConfig = JSON.parse(fs.readFileSync(tempTemplatePath, "utf8"));
2913
- fs.unlinkSync(tempTemplatePath);
2914
- } else if (fs.existsSync(nextgenConfigPath)) {
2915
- templateConfig = mergeObjects(ADMOB_NEXTGEN_DEFAULTS, JSON.parse(fs.readFileSync(nextgenConfigPath, "utf8")));
2916
- }
2917
-
2918
- const oldConfig = fs.existsSync(oldConfigPath)
2919
- ? JSON.parse(fs.readFileSync(oldConfigPath, "utf8"))
2920
- : {};
2921
- const existingNextgenConfig = fs.existsSync(nextgenConfigPath)
2922
- ? JSON.parse(fs.readFileSync(nextgenConfigPath, "utf8"))
2923
- : {};
2924
-
2925
- const mergedConfig = buildNextgenAdmobConfigFromOldConfig(templateConfig, existingNextgenConfig, oldConfig);
2926
-
2927
- const capacitorConfig = readJsonSafe(configPath) || {};
2928
- const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
2929
- const mergedAppIds = getAdmobJsonAppIds(mergedConfig);
2930
- const androidAppId = mergedAppIds.androidAppId || legacyAdmobConfig.APP_ID_ANDROID || "";
2931
- const iosAppId = mergedAppIds.iosAppId || legacyAdmobConfig.APP_ID_IOS || "";
2932
-
2933
- if (androidAppId && !mergedAppIds.androidAppId) {
2934
- mergedConfig.androidAppId = androidAppId;
2935
- }
2936
-
2937
- if (iosAppId && !mergedAppIds.iosAppId) {
2938
- mergedConfig.iosAppId = iosAppId;
2939
- }
2940
-
2941
- fs.writeFileSync(nextgenConfigPath, JSON.stringify(mergedConfig, null, 2) + "\n", "utf8");
2942
- syncAdmobConfigImports();
2943
- console.log("✅ AdMob nextgen files and configuration are ready.");
2944
- };
2945
-
2946
- const syncAdmobNextgenMigration = async () => {
2947
- syncAdmobNextgenPackage();
2948
- await ensureAdmobNextgenFiles();
2949
- syncAdmobAliasInViteConfig();
2950
- };
2951
-
2952
- const syncSystemBarsSafeAreaMigration = () => {
2953
- if (isPackageAvailable("@capacitor-community/safe-area")) {
2954
- runNpmCommand("npm uninstall @capacitor-community/safe-area");
2955
- } else {
2956
- console.log("ℹ️ @capacitor-community/safe-area is not installed.");
2957
- }
2958
-
2959
- if (!fs.existsSync(configPath)) {
2960
- console.warn("⚠️ capacitor.config.json not found. Skipping SystemBars config sync.");
2961
- return;
2962
- }
2963
-
2964
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
2965
- if (!config.plugins) config.plugins = {};
2966
- if (!config.plugins.SystemBars) config.plugins.SystemBars = {};
2967
-
2968
- if (config.plugins.SystemBars.insetsHandling !== "css") {
2969
- config.plugins.SystemBars.insetsHandling = "css";
2970
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
2971
- console.log('✅ capacitor.config.json SystemBars.insetsHandling set to "css".');
2972
- } else {
2973
- console.log('ℹ️ capacitor.config.json SystemBars.insetsHandling already "css".');
2974
- }
2975
- };
2976
-
2977
- const ensureFirebaseAnalyticsWrapper = (analyticsEnabled) => {
2733
+ const runNpmCommand = (command) => {
2734
+ console.log(`🚀 ${command}`);
2735
+ execSync(command, { stdio: "inherit" });
2736
+ };
2737
+
2738
+ const ADMOB_NEXTGEN_DEFAULTS = {
2739
+ VERSION: "1.6",
2740
+ ios: { nativeid: "" },
2741
+ android: { nativeid: "" },
2742
+ config: {
2743
+ bannerStartupDelayMs: "",
2744
+ interstitialStartupDelayMs: "",
2745
+ appOpenLoadOnColdStart: "",
2746
+ appOpenStartupDelayMs: "",
2747
+ useAndroidPreloadAds: true,
2748
+ useAndroidBannerPreloadAds: false,
2749
+ preloadBufferSize: 1,
2750
+ consentDebug: false
2751
+ },
2752
+ testid: {
2753
+ nativeid: "",
2754
+ nativeid_android: "ca-app-pub-3940256099942544/2247696110",
2755
+ nativeid_ios: "ca-app-pub-3940256099942544/3986624511"
2756
+ }
2757
+ };
2758
+
2759
+ function getAdmobJsonPath() {
2760
+ const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2761
+ const possiblePaths = [
2762
+ path.join(adsDir, ADMOB_NEXTGEN_CONFIG),
2763
+ path.join(adsDir, ADMOB_OLD_CONFIG)
2764
+ ];
2765
+
2766
+ return possiblePaths.find(fileExists);
2767
+ }
2768
+
2769
+ function readJsonSafe(filePath) {
2770
+ try {
2771
+ return filePath && fileExists(filePath)
2772
+ ? JSON.parse(fs.readFileSync(filePath, "utf8"))
2773
+ : null;
2774
+ } catch {
2775
+ return null;
2776
+ }
2777
+ }
2778
+
2779
+ function pickFirstValue(...values) {
2780
+ return values.find(value => typeof value === "string" && value.trim() !== "") || "";
2781
+ }
2782
+
2783
+ function getAdmobJsonAppIds(config = readJsonSafe(getAdmobJsonPath())) {
2784
+ return {
2785
+ androidAppId: pickFirstValue(
2786
+ config?.androidAppId,
2787
+ config?.android_app_id,
2788
+ config?.android?.appId,
2789
+ config?.android?.appid,
2790
+ config?.android?.applicationId
2791
+ ),
2792
+ iosAppId: pickFirstValue(
2793
+ config?.iosAppId,
2794
+ config?.ios_app_id,
2795
+ config?.ios?.appId,
2796
+ config?.ios?.appid,
2797
+ config?.ios?.applicationId
2798
+ )
2799
+ };
2800
+ }
2801
+
2802
+ const mergeObjects = (template, source) => {
2803
+ if (!template || typeof template !== "object" || Array.isArray(template)) {
2804
+ return source !== undefined ? source : template;
2805
+ }
2806
+
2807
+ const output = { ...template };
2808
+
2809
+ if (!source || typeof source !== "object" || Array.isArray(source)) {
2810
+ return output;
2811
+ }
2812
+
2813
+ Object.keys(source).forEach(key => {
2814
+ if (
2815
+ template[key] &&
2816
+ typeof template[key] === "object" &&
2817
+ !Array.isArray(template[key]) &&
2818
+ source[key] &&
2819
+ typeof source[key] === "object" &&
2820
+ !Array.isArray(source[key])
2821
+ ) {
2822
+ output[key] = mergeObjects(template[key], source[key]);
2823
+ } else if (key !== "VERSION") {
2824
+ output[key] = source[key];
2825
+ }
2826
+ });
2827
+
2828
+ return output;
2829
+ };
2830
+
2831
+ const hasObjectKeys = (value) => {
2832
+ return value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length > 0;
2833
+ };
2834
+
2835
+ const buildNextgenAdmobConfigFromOldConfig = (templateConfig, existingNextgenConfig, oldConfig) => {
2836
+ const mergedConfig = mergeObjects(templateConfig, mergeObjects(existingNextgenConfig, oldConfig));
2837
+
2838
+ if (hasObjectKeys(oldConfig)) {
2839
+ if (hasObjectKeys(oldConfig.ios)) {
2840
+ mergedConfig.ios = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.ios, oldConfig.ios);
2841
+ }
2842
+
2843
+ if (hasObjectKeys(oldConfig.android)) {
2844
+ mergedConfig.android = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.android, oldConfig.android);
2845
+ }
2846
+
2847
+ if (hasObjectKeys(oldConfig.testid)) {
2848
+ mergedConfig.testid = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.testid, oldConfig.testid);
2849
+ }
2850
+
2851
+ if (hasObjectKeys(oldConfig.IAP)) {
2852
+ mergedConfig.IAP = oldConfig.IAP;
2853
+ }
2854
+
2855
+ if (hasObjectKeys(oldConfig.config)) {
2856
+ const templateRuntimeConfig = mergeObjects(ADMOB_NEXTGEN_DEFAULTS.config, templateConfig.config || {});
2857
+ const existingRuntimeConfig = existingNextgenConfig.config || {};
2858
+ mergedConfig.config = mergeObjects(templateRuntimeConfig, mergeObjects(existingRuntimeConfig, oldConfig.config));
2859
+ }
2860
+ }
2861
+
2862
+ mergedConfig.VERSION = templateConfig.VERSION || ADMOB_NEXTGEN_DEFAULTS.VERSION;
2863
+
2864
+ return mergedConfig;
2865
+ };
2866
+
2867
+ const syncAdmobNextgenPackage = () => {
2868
+ if (!fs.existsSync(packageJsonPath)) {
2869
+ console.warn("⚠️ package.json not found. Skipping AdMob nextgen package sync.");
2870
+ return;
2871
+ }
2872
+
2873
+ if (isPackageAvailable("emi-indo-cordova-plugin-admob")) {
2874
+ runNpmCommand("npm uninstall emi-indo-cordova-plugin-admob");
2875
+ } else {
2876
+ console.log("ℹ️ emi-indo-cordova-plugin-admob is not installed.");
2877
+ }
2878
+
2879
+ if (!isPackageAvailable("capacitor-admob-nextgen")) {
2880
+ runNpmCommand("npm install capacitor-admob-nextgen");
2881
+ } else {
2882
+ console.log("ℹ️ capacitor-admob-nextgen is already installed.");
2883
+ }
2884
+ };
2885
+
2886
+ const downloadOptionalCodeplayFile = async (fileName, destPath) => {
2887
+ const url = `https://htmlcodeplay.com/code-play-plugin/${fileName}`;
2888
+
2889
+ if (!(await urlExists(url))) {
2890
+ return false;
2891
+ }
2892
+
2893
+ await downloadFile(url, destPath);
2894
+ console.log(`⬇ Downloaded → ${fileName}`);
2895
+ return true;
2896
+ };
2897
+
2898
+ const syncAdmobConfigImports = () => {
2899
+ const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2900
+ if (!fs.existsSync(adsDir)) return;
2901
+
2902
+ const scan = (dir) => {
2903
+ fs.readdirSync(dir, { withFileTypes: true }).forEach(entry => {
2904
+ const fullPath = path.join(dir, entry.name);
2905
+
2906
+ if (entry.isDirectory()) {
2907
+ scan(fullPath);
2908
+ return;
2909
+ }
2910
+
2911
+ if (!/\.(js|mjs|ts|f7)$/.test(entry.name) || entry.name.endsWith(".min.js")) return;
2912
+
2913
+ let content = fs.readFileSync(fullPath, "utf8");
2914
+ if (!content.includes(ADMOB_OLD_CONFIG)) return;
2915
+
2916
+ content = content.split(ADMOB_OLD_CONFIG).join(ADMOB_NEXTGEN_CONFIG);
2917
+ fs.writeFileSync(fullPath, content, "utf8");
2918
+ console.log(`✏️ Updated AdMob config import in ${path.relative(process.cwd(), fullPath)}`);
2919
+ });
2920
+ };
2921
+
2922
+ scan(adsDir);
2923
+ };
2924
+
2925
+ const ensureAdmobNextgenFiles = async () => {
2926
+ const adsDir = path.join(process.cwd(), "src", "js", "Ads");
2927
+ if (!fs.existsSync(adsDir)) {
2928
+ console.log("ℹ️ Ads folder not found. Skipping AdMob nextgen file sync.");
2929
+ return;
2930
+ }
2931
+
2932
+ const localNextgenFile = getLatestAdmobNextgenFileName(adsDir);
2933
+ const remoteNextgenFile = await getLatestRemoteAdmobNextgenFileName();
2934
+ const nextgenFile = (() => {
2935
+ if (!localNextgenFile) return remoteNextgenFile;
2936
+ if (!remoteNextgenFile) return localNextgenFile;
2937
+
2938
+ const localVersion = extractVersionFromFileName(localNextgenFile);
2939
+ const remoteVersion = extractVersionFromFileName(remoteNextgenFile);
2940
+ return compareVersionStrings(remoteVersion, localVersion) > 0 ? remoteNextgenFile : localNextgenFile;
2941
+ })();
2942
+
2943
+ if (!nextgenFile) {
2944
+ console.error("❌ No local or remote admob-emi-nextgen file found for sync.");
2945
+ process.exit(1);
2946
+ }
2947
+
2948
+ const nextgenPath = path.join(adsDir, nextgenFile);
2949
+ const nextgenConfigPath = path.join(adsDir, ADMOB_NEXTGEN_CONFIG);
2950
+ const oldConfigPath = path.join(adsDir, ADMOB_OLD_CONFIG);
2951
+ const tempTemplatePath = path.join(adsDir, `${ADMOB_NEXTGEN_CONFIG}.template`);
2952
+
2953
+ if (!fs.existsSync(nextgenPath)) {
2954
+ const downloaded = await downloadOptionalCodeplayFile(nextgenFile, nextgenPath);
2955
+ if (!downloaded) {
2956
+ console.error(`❌ ${nextgenFile} missing and live download failed.`);
2957
+ process.exit(1);
2958
+ }
2959
+ }
2960
+
2961
+ let templateConfig = ADMOB_NEXTGEN_DEFAULTS;
2962
+
2963
+ if (await downloadOptionalCodeplayFile(ADMOB_NEXTGEN_CONFIG, tempTemplatePath)) {
2964
+ templateConfig = JSON.parse(fs.readFileSync(tempTemplatePath, "utf8"));
2965
+ fs.unlinkSync(tempTemplatePath);
2966
+ } else if (fs.existsSync(nextgenConfigPath)) {
2967
+ templateConfig = mergeObjects(ADMOB_NEXTGEN_DEFAULTS, JSON.parse(fs.readFileSync(nextgenConfigPath, "utf8")));
2968
+ }
2969
+
2970
+ const oldConfig = fs.existsSync(oldConfigPath)
2971
+ ? JSON.parse(fs.readFileSync(oldConfigPath, "utf8"))
2972
+ : {};
2973
+ const existingNextgenConfig = fs.existsSync(nextgenConfigPath)
2974
+ ? JSON.parse(fs.readFileSync(nextgenConfigPath, "utf8"))
2975
+ : {};
2976
+
2977
+ const mergedConfig = buildNextgenAdmobConfigFromOldConfig(templateConfig, existingNextgenConfig, oldConfig);
2978
+
2979
+ const capacitorConfig = readJsonSafe(configPath) || {};
2980
+ const legacyAdmobConfig = capacitorConfig.plugins?.AdMob || {};
2981
+ const mergedAppIds = getAdmobJsonAppIds(mergedConfig);
2982
+ const androidAppId = mergedAppIds.androidAppId || legacyAdmobConfig.APP_ID_ANDROID || "";
2983
+ const iosAppId = mergedAppIds.iosAppId || legacyAdmobConfig.APP_ID_IOS || "";
2984
+
2985
+ if (androidAppId && !mergedAppIds.androidAppId) {
2986
+ mergedConfig.androidAppId = androidAppId;
2987
+ }
2988
+
2989
+ if (iosAppId && !mergedAppIds.iosAppId) {
2990
+ mergedConfig.iosAppId = iosAppId;
2991
+ }
2992
+
2993
+ fs.writeFileSync(nextgenConfigPath, JSON.stringify(mergedConfig, null, 2) + "\n", "utf8");
2994
+ syncAdmobConfigImports();
2995
+ console.log("✅ AdMob nextgen files and configuration are ready.");
2996
+ };
2997
+
2998
+ const syncAdmobNextgenMigration = async () => {
2999
+ syncAdmobNextgenPackage();
3000
+ await ensureAdmobNextgenFiles();
3001
+ syncAdmobAliasInViteConfig();
3002
+ };
3003
+
3004
+ const syncSystemBarsSafeAreaMigration = () => {
3005
+ if (isPackageAvailable("@capacitor-community/safe-area")) {
3006
+ runNpmCommand("npm uninstall @capacitor-community/safe-area");
3007
+ } else {
3008
+ console.log("ℹ️ @capacitor-community/safe-area is not installed.");
3009
+ }
3010
+
3011
+ if (!fs.existsSync(configPath)) {
3012
+ console.warn("⚠️ capacitor.config.json not found. Skipping SystemBars config sync.");
3013
+ return;
3014
+ }
3015
+
3016
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
3017
+ if (!config.plugins) config.plugins = {};
3018
+ if (!config.plugins.SystemBars) config.plugins.SystemBars = {};
3019
+
3020
+ if (config.plugins.SystemBars.insetsHandling !== "css") {
3021
+ config.plugins.SystemBars.insetsHandling = "css";
3022
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
3023
+ console.log('✅ capacitor.config.json SystemBars.insetsHandling set to "css".');
3024
+ } else {
3025
+ console.log('ℹ️ capacitor.config.json SystemBars.insetsHandling already "css".');
3026
+ }
3027
+ };
3028
+
3029
+ const ensureFirebaseAnalyticsWrapper = (analyticsEnabled) => {
2978
3030
  const analyticsDir = getLatestIapDir();
2979
3031
  const legacyAnalyticsDir = path.join(process.cwd(), "src", "js", "analytics");
2980
3032
  const legacyAnalyticsFile = path.join(legacyAnalyticsDir, "firebase-analytics.js");
@@ -3520,10 +3572,10 @@ const checkAdmobConfigurationProperty=()=>{
3520
3572
 
3521
3573
 
3522
3574
  const REQUIRED_CONFIG_KEYS = [
3523
- "isKidsApp",
3524
- "isTesting",
3525
- "consentDebug",
3526
- "isConsoleLogEnabled",
3575
+ "isKidsApp",
3576
+ "isTesting",
3577
+ "consentDebug",
3578
+ "isConsoleLogEnabled",
3527
3579
  "bannerEnabled",
3528
3580
  "interstitialEnabled",
3529
3581
  "appOpenEnabled",
@@ -3639,9 +3691,9 @@ function ensureGitignoreEntry(entry) {
3639
3691
  ensureGitignoreEntry('buildCodeplay/');
3640
3692
 
3641
3693
 
3642
- // ======================================================
3643
- // Validate theme folder location (src/js/theme is NOT allowed)
3644
- // ======================================================
3694
+ // ======================================================
3695
+ // Validate theme folder location (src/js/theme is NOT allowed)
3696
+ // ======================================================
3645
3697
 
3646
3698
  function validateThemeFolderLocation() {
3647
3699
  const oldThemePath = path.join(process.cwd(), 'src', 'js', 'theme');
@@ -3671,7 +3723,7 @@ function validateThemeFolderLocation() {
3671
3723
  console.log('✅ Theme folder structure validated (src/theme).');
3672
3724
  }
3673
3725
  }
3674
- const validateAndRestoreSignDetails=()=>{
3726
+ const validateAndRestoreSignDetails=()=>{
3675
3727
 
3676
3728
  // Read config file
3677
3729
  const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
@@ -3703,7 +3755,7 @@ const validateAndRestoreSignDetails=()=>{
3703
3755
 
3704
3756
  }
3705
3757
 
3706
- //################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin START ###############################
3758
+ //################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin START ###############################
3707
3759
 
3708
3760
 
3709
3761
  const filePath = path.join(
@@ -3809,34 +3861,34 @@ function patchFile() {
3809
3861
  console.log("✅ SystemBars.java patched with Codeplay keyboard inset fix!");
3810
3862
  }
3811
3863
 
3812
- //patchFile();
3813
-
3814
- //################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin END ###############################
3815
-
3816
- async function main() {
3817
- validateThemeFolderLocation();
3818
- validateAndRestoreSignDetails();
3819
- execSync('node buildCodeplay/fix-onesignal-plugin.js', { stdio: 'inherit' });
3820
-
3821
- await loadPluginVersions(); // 🔥 NEW
3822
-
3823
- await syncAdmobNextgenMigration();
3824
- syncSystemBarsSafeAreaMigration();
3825
- await checkPlugins();
3826
- syncRevenueCatIapSetup();
3827
- syncFirebaseAnalyticsSetup();
3828
- checkAndupdateDropInViteConfig();
3829
- checkAdmobConfigurationProperty();
3830
- }
3831
-
3832
- main().catch(err => {
3833
- console.error(err?.message || err);
3834
- process.exit(1);
3835
- });
3836
-
3837
-
3838
-
3839
-
3864
+ //patchFile();
3865
+
3866
+ //################################## SystemBars.java update for "@capacitor/android": "^8.3.0" plugin END ###############################
3867
+
3868
+ async function main() {
3869
+ validateThemeFolderLocation();
3870
+ validateAndRestoreSignDetails();
3871
+ execSync('node buildCodeplay/fix-onesignal-plugin.js', { stdio: 'inherit' });
3872
+
3873
+ await loadPluginVersions(); // 🔥 NEW
3874
+
3875
+ await syncAdmobNextgenMigration();
3876
+ syncSystemBarsSafeAreaMigration();
3877
+ await checkPlugins();
3878
+ syncRevenueCatIapSetup();
3879
+ syncFirebaseAnalyticsSetup();
3880
+ checkAndupdateDropInViteConfig();
3881
+ checkAdmobConfigurationProperty();
3882
+ }
3883
+
3884
+ main().catch(err => {
3885
+ console.error(err?.message || err);
3886
+ process.exit(1);
3887
+ });
3888
+
3889
+
3890
+
3891
+
3840
3892
  /*
3841
3893
  Release Notes
3842
3894
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeplay-common",
3
- "version": "4.1.3",
3
+ "version": "4.1.4",
4
4
  "description": "Common build scripts and files",
5
5
  "scripts": {
6
6
  "postinstall": "node scripts/sync-files.js",