codeplay-common 4.7.5 → 4.7.7
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/.gitattributes +2 -2
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -21
- package/README.md +145 -120
- package/RELEASE_NOTES.md +15 -0
- package/files/buildCodeplay/{codeplayBeforeBuild-6.3.js → codeplayBeforeBuild-6.4.js} +313 -335
- package/files/buildCodeplay/release-sync.config.json +4 -4
- package/files/finalrelease +49 -49
- package/files/generate-ai-promo-video.js +23 -23
- package/files/iap-install-2.js +145 -145
- package/files/ionic.config.json +6 -6
- package/files/scripts/setup-baseline-profile.js +262 -262
- package/files/scripts-screenshot/screenshot/background-decorations.js +120 -120
- package/files/scripts-screenshot/screenshot/frame-samples.js +117 -117
- package/files/take-screen-image.js +49 -15
- package/files/take-screen-video.js +644 -644
- package/package.json +15 -15
- package/scripts/sync-files.js +106 -102
- package/scripts/uninstall.js +109 -109
|
@@ -10,13 +10,37 @@ const { execSync } = require("child_process");
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
const { readFileSync } = require("fs");
|
|
13
|
+
const readline = require('readline');
|
|
14
|
+
|
|
15
|
+
// Await import confirmation before continuing the remaining build steps.
|
|
16
|
+
(async () => {
|
|
17
|
+
|
|
18
|
+
// Standalone builds default to Android on every host OS.
|
|
19
|
+
// npm run build:ios explicitly selects iOS through CODEPLAY_BUILD_PLATFORM.
|
|
20
|
+
const buildPlatform = String(process.env.CODEPLAY_BUILD_PLATFORM || '').trim().toLowerCase() || 'android';
|
|
21
|
+
|
|
22
|
+
if (!['android', 'ios'].includes(buildPlatform)) {
|
|
23
|
+
console.error(`❌ Unsupported build target: ${buildPlatform}. Expected android or ios.`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
13
26
|
|
|
14
27
|
const ENABLE_AUTO_UPDATE = true;
|
|
15
28
|
const USE_LIVE_SERVER_VERSION = true;
|
|
16
29
|
|
|
30
|
+
// Reuse directory traversal; refresh after generators or plugin downloads alter src.
|
|
31
|
+
let sourceFileInventory = null;
|
|
32
|
+
function getSourceFiles() {
|
|
33
|
+
if (!sourceFileInventory) {
|
|
34
|
+
const sourceRoot = path.join(process.cwd(), 'src');
|
|
35
|
+
sourceFileInventory = fs.existsSync(sourceRoot) ? walkSync(sourceRoot) : [];
|
|
36
|
+
}
|
|
37
|
+
return sourceFileInventory;
|
|
38
|
+
}
|
|
39
|
+
|
|
17
40
|
const configPath = path.join(process.cwd(), 'capacitor.config.json');
|
|
18
41
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
19
42
|
const updateLogFile = path.join(process.cwd(), "", "plugin-update-log.txt");
|
|
43
|
+
const ONESIGNAL_PLUGIN_NAME = "onesignal-cordova-plugin";
|
|
20
44
|
const ADMOB_NEXTGEN_PLUGIN_NAME = "admob-emi-nextgen";
|
|
21
45
|
const ADMOB_NEXTGEN_FILE_PATTERN = new RegExp(`^${ADMOB_NEXTGEN_PLUGIN_NAME}-\\d+(?:\\.\\d+)*\\.js$`);
|
|
22
46
|
const ADMOB_NEXTGEN_CONFIG = "admob-ad-configuration-nextgen.json";
|
|
@@ -25,7 +49,10 @@ const AGENT_INSTRUCTIONS_VERSION_KEY = "agents";
|
|
|
25
49
|
const AGENT_INSTRUCTIONS_ZIP_PREFIX = "agents";
|
|
26
50
|
const AGENT_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
27
51
|
const AGENT_INSTRUCTIONS_DIR = "AGENTS";
|
|
28
|
-
const AGENT_INSTRUCTIONS_VERSION_FILE = ".codeplay-version";
|
|
52
|
+
const AGENT_INSTRUCTIONS_VERSION_FILE = ".codeplay-version";
|
|
53
|
+
|
|
54
|
+
// Remove the retired plugin before any validation, patching or package updates.
|
|
55
|
+
removeOneSignalPlugin();
|
|
29
56
|
|
|
30
57
|
const parseVersionParts = (version) => String(version || "0")
|
|
31
58
|
.trim()
|
|
@@ -77,7 +104,6 @@ const getLatestAdmobNextgenFileName = (adsDir) =>
|
|
|
77
104
|
{ pattern: /localization-(\d+\.\d+)\.js$/, minVersion: '1.5', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
78
105
|
{ pattern: /localNotification-(\d+\.\d+)\.js$/, minVersion: '2.2', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
79
106
|
{ pattern: /localNotification_AppSettings-(\d+\.\d+)\.js$/, minVersion: '1.0', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
80
|
-
{ pattern: /onesignal-(\d+\.\d+)\.js$/, minVersion: '2.3', required: true, baseDir: 'js',mandatoryUpdate: false },
|
|
81
107
|
{ pattern: /saveToGalleryAndSaveAnyFile-(\d+\.\d+)(-ios)?\.js$/, minVersion: '3.1', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
82
108
|
{ pattern: /Ads[\/\\]admob-emi-(\d+\.\d+)\.js$/, minVersion: '3.7', required: true, baseDir: 'js',mandatoryUpdate: true },
|
|
83
109
|
|
|
@@ -200,7 +226,10 @@ function loadRequiredPlugins() {
|
|
|
200
226
|
|
|
201
227
|
const json = JSON.parse(fs.readFileSync(versionsFile, "utf8"));
|
|
202
228
|
|
|
203
|
-
|
|
229
|
+
// OneSignal is retired; do not download its legacy helpers again.
|
|
230
|
+
return json.plugins.filter(p =>
|
|
231
|
+
!/^onesignal(?:-|$)/i.test(String(p.name || '')) && !/onesignal/i.test(String(p.pattern || ''))
|
|
232
|
+
).map(p => ({
|
|
204
233
|
...p,
|
|
205
234
|
pattern: new RegExp(p.pattern)
|
|
206
235
|
}));
|
|
@@ -760,38 +789,43 @@ else {
|
|
|
760
789
|
|
|
761
790
|
|
|
762
791
|
|
|
763
|
-
// saveToGalleryAndSaveAnyFile
|
|
764
|
-
|
|
765
|
-
const os = require('os');
|
|
766
|
-
|
|
767
|
-
const saveToGalleryAndSaveFileCheck_iOS = () => {
|
|
768
|
-
|
|
769
|
-
// List of paths to scan
|
|
770
|
-
const SCAN_PATHS = [
|
|
771
|
-
path.resolve(__dirname, '../src/certificate'),
|
|
772
|
-
path.resolve(__dirname, '../src/pages'),
|
|
773
|
-
path.resolve(__dirname, '../src/js'),
|
|
774
|
-
path.resolve(__dirname, '../src/app.f7')
|
|
775
|
-
];
|
|
792
|
+
// Validate saveToGalleryAndSaveAnyFile imports for the build platform START
|
|
776
793
|
|
|
777
|
-
|
|
778
|
-
const EXCLUDED_DIR = path.resolve(__dirname, '../src/js/Ads');
|
|
794
|
+
const saveToGalleryAndSaveFileCheck_iOS = async () => {
|
|
779
795
|
|
|
796
|
+
const SOURCE_ROOT = path.resolve(__dirname, '../src');
|
|
797
|
+
const EXCLUDED_DIR = path.join(SOURCE_ROOT, 'js', 'Ads');
|
|
780
798
|
const ANDROID_MANIFEST_PATH = path.resolve(__dirname, '../android/app/src/main/AndroidManifest.xml');
|
|
781
799
|
|
|
782
800
|
|
|
783
|
-
//
|
|
784
|
-
const
|
|
801
|
+
// Skip comments and unrelated strings; match static/dynamic imports, re-exports and require.
|
|
802
|
+
const COMMENT_OR_STRING_REGEX = /\/\/[^\r\n]*|\/\*[\s\S]*?\*\/|(['"`])(?:\\[\s\S]|(?!\1)[^\\])*\1/g;
|
|
803
|
+
const IMPORT_REGEX = /(['"`])(?:\\[\s\S]|(?!\1)[^\\])*\1|\b(?:import\s+(?:[^;'"`]*?\s+from\s*)?|export\s+[^;'"`]*?\s+from\s*|(?:import|require)\s*\(\s*)(['"])([^'"\r\n]+)\2/g;
|
|
804
|
+
const SAVE_FILE_REGEX = /^(.*[\/\\])?(saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*)(-ios)?(\.js)?([?#].*)?$/;
|
|
805
|
+
const pendingChanges = [];
|
|
785
806
|
|
|
786
|
-
|
|
787
|
-
const
|
|
807
|
+
const ALLOWED_EXTENSIONS = ['.js', '.mjs', '.ts', '.f7'];
|
|
808
|
+
const referencedVersions = new Set();
|
|
809
|
+
let aliasImportFound = false;
|
|
810
|
+
let hasForbiddenEditorImport = false;
|
|
811
|
+
const FORBIDDEN_REGEX = /editor\/editor-\d+(\.\d+)+/;
|
|
812
|
+
const ERROR_MESSAGE = `const ERROR_MESSAGE = ❌ Invalid import detected!
|
|
788
813
|
|
|
814
|
+
You are using a direct version-based path like: editor/editor-x.x/editor.js
|
|
789
815
|
|
|
816
|
+
🚫 This is NOT allowed.
|
|
790
817
|
|
|
818
|
+
👉 Please use the proper alias or updated import method.
|
|
819
|
+
Example: import { ... } from '@editor'
|
|
820
|
+
|
|
821
|
+
⚠️ Do not use version-based paths in imports.
|
|
822
|
+
👉 Please add this manually in vite.config.js:
|
|
791
823
|
|
|
824
|
+
alias: {
|
|
825
|
+
'@editor': path.resolve(__dirname, './src/js/editor/editor-x.x')
|
|
826
|
+
}`
|
|
792
827
|
|
|
793
|
-
const
|
|
794
|
-
const isMac = os.platform() === 'darwin';
|
|
828
|
+
const isIOSBuild = buildPlatform === 'ios';
|
|
795
829
|
|
|
796
830
|
let iosImportFound = false;
|
|
797
831
|
let androidImportFound = false;
|
|
@@ -809,13 +843,7 @@ const STATUSBAR_FILE = path.resolve(__dirname, '../src/js/common-configuration.j
|
|
|
809
843
|
const STATUSBAR_REGEX = /^(?!\s*\/\/).*Capacitor\.Plugins\.StatusBar\.setStyle/m;
|
|
810
844
|
|
|
811
845
|
|
|
812
|
-
|
|
813
|
-
path.resolve(__dirname, '../src/js/onesignal-settings.js')
|
|
814
|
-
];
|
|
815
|
-
const ONESIGNAL_VERSION_REGEX = /^onesignal-\d+(\.\d+)*\.js$/;
|
|
816
|
-
|
|
817
|
-
function scanDirectory(dir) {
|
|
818
|
-
|
|
846
|
+
function scanSourceFile(dir) {
|
|
819
847
|
/*
|
|
820
848
|
//######################### DO NOT DELETE THIS - START [Appid base validation] #####################################
|
|
821
849
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
@@ -824,132 +852,187 @@ function scanDirectory(dir) {
|
|
|
824
852
|
//######################### DO NOT DELETE THIS - END [Appid base validation] #####################################
|
|
825
853
|
*/
|
|
826
854
|
|
|
827
|
-
const stat = fs.statSync(dir);
|
|
828
|
-
|
|
829
|
-
if (stat.isFile()) {
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
855
|
const baseName = path.basename(dir);
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
console.error(`📁 Move it to: src/js/onesignal/`);
|
|
853
|
-
console.error(`📄 File: ${dir}\n`);
|
|
854
|
-
process.exit(1);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
// 🚨 Special check ONLY for common-configuration.js
|
|
856
|
+
const isGalleryScope = ['certificate', 'pages', 'js'].some(folder =>
|
|
857
|
+
dir.startsWith(path.join(SOURCE_ROOT, folder) + path.sep)
|
|
858
|
+
) || dir === path.join(SOURCE_ROOT, 'app.f7');
|
|
859
|
+
const shouldCheckGallery = isGalleryScope && !dir.startsWith(EXCLUDED_DIR + path.sep)
|
|
860
|
+
&& !dir.split(path.sep).includes('node_modules') && !SKIP_FILES.includes(baseName)
|
|
861
|
+
&& ALLOWED_EXTENSIONS.some(ext => dir.endsWith(ext));
|
|
862
|
+
const shouldCheckEditor = /\.(js|ts|f7)$/.test(dir);
|
|
863
|
+
const shouldCheckOneSignal = /\.(js|mjs|cjs|ts|tsx|jsx|f7)$/.test(dir);
|
|
864
|
+
if (!shouldCheckGallery && !shouldCheckEditor && !shouldCheckOneSignal) return;
|
|
865
|
+
|
|
866
|
+
const content = fs.readFileSync(dir, 'utf8');
|
|
867
|
+
if (shouldCheckEditor) {
|
|
868
|
+
content.split('\n').forEach((line, index) => {
|
|
869
|
+
if (!FORBIDDEN_REGEX.test(line)) return;
|
|
870
|
+
console.error(`❌ Forbidden import found:\nFile: ${dir}\nLine: ${index + 1}\nCode: ${line.trim()}\n`, ERROR_MESSAGE);
|
|
871
|
+
hasForbiddenEditorImport = true;
|
|
872
|
+
});
|
|
873
|
+
}
|
|
859
874
|
if (dir === STATUSBAR_FILE) {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
// 🧹 Remove ALL comments (single-line + multi-line)
|
|
863
|
-
const contentWithoutComments = content
|
|
864
|
-
.replace(/\/\/.*$/gm, '') // remove // comments
|
|
865
|
-
.replace(/\/\*[\s\S]*?\*\//g, ''); // remove /* */ comments
|
|
866
|
-
|
|
867
|
-
// ✅ Now check only real code
|
|
875
|
+
const contentWithoutComments = content.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
868
876
|
if (contentWithoutComments.includes('Capacitor.Plugins.StatusBar.setStyle')) {
|
|
869
|
-
|
|
870
|
-
console.error(`🚫 iOS status bar is controlled via other methods. Remove this line.`);
|
|
871
|
-
console.error(`📄 File: ${dir}\n`);
|
|
872
|
-
process.exit(1);
|
|
877
|
+
throw new Error(`❌ StatusBar.setStyle should NOT be used in common-configuration.js. File: ${dir}`);
|
|
873
878
|
}
|
|
874
879
|
}
|
|
875
880
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
+
const code = content.replace(COMMENT_OR_STRING_REGEX, (match, quote) =>
|
|
882
|
+
quote ? match : match.replace(/[^\r\n]/g, ' ')
|
|
883
|
+
);
|
|
884
|
+
const replacements = [];
|
|
885
|
+
IMPORT_REGEX.lastIndex = 0;
|
|
886
|
+
let imported;
|
|
887
|
+
while ((imported = IMPORT_REGEX.exec(code)) !== null) {
|
|
888
|
+
if (!imported[3]) continue;
|
|
889
|
+
const importPath = imported[3];
|
|
890
|
+
if (importPath === ONESIGNAL_PLUGIN_NAME || importPath.startsWith(ONESIGNAL_PLUGIN_NAME + '/')) {
|
|
891
|
+
throw new Error(`❌ OneSignal was removed, but ${dir} still imports ${importPath}. Remove that import and its initialization before building.`);
|
|
892
|
+
}
|
|
893
|
+
if (!shouldCheckGallery) continue;
|
|
894
|
+
if (/^@saveGallery[?#]/.test(importPath)) {
|
|
895
|
+
throw new Error(`❌ ${importPath} in ${dir} requires a dedicated Vite alias for its query/hash suffix.`);
|
|
896
|
+
}
|
|
897
|
+
if (importPath === '@saveGallery') {
|
|
898
|
+
aliasImportFound = true;
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
const fileMatch = importPath.match(SAVE_FILE_REGEX);
|
|
902
|
+
if (!fileMatch) continue;
|
|
903
|
+
if (fileMatch[5]) {
|
|
904
|
+
throw new Error(`❌ Cannot migrate ${importPath} in ${dir} to a plain @saveGallery alias: its query/hash suffix requires a dedicated Vite alias.`);
|
|
905
|
+
}
|
|
906
|
+
referencedVersions.add(fileMatch[2]);
|
|
907
|
+
const nextImportPath = '@saveGallery';
|
|
908
|
+
const offset = imported.index + imported[0].lastIndexOf(imported[2] + importPath + imported[2]) + 1;
|
|
909
|
+
replacements.push({ offset, importPath, nextImportPath });
|
|
881
910
|
}
|
|
882
911
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
912
|
+
if (replacements.length) {
|
|
913
|
+
let nextContent = content;
|
|
914
|
+
for (const replacement of [...replacements].reverse()) {
|
|
915
|
+
nextContent = nextContent.slice(0, replacement.offset) + replacement.nextImportPath
|
|
916
|
+
+ nextContent.slice(replacement.offset + replacement.importPath.length);
|
|
917
|
+
}
|
|
918
|
+
pendingChanges.push({ filePath: dir, content, nextContent, replacements });
|
|
919
|
+
}
|
|
920
|
+
}
|
|
886
921
|
|
|
887
|
-
|
|
922
|
+
// One source content pass handles gallery migration, retired OneSignal imports, StatusBar and editor validation.
|
|
923
|
+
for (const sourceFile of getSourceFiles()) scanSourceFile(sourceFile);
|
|
924
|
+
if (hasForbiddenEditorImport) throw new Error('🚫 Build failed due to forbidden editor imports.');
|
|
925
|
+
console.log('✅ No forbidden editor imports found.');
|
|
888
926
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
927
|
+
if (referencedVersions.size || aliasImportFound) {
|
|
928
|
+
const viteConfigPath = getViteConfigPath();
|
|
929
|
+
if (!viteConfigPath) throw new Error('❌ Cannot configure @saveGallery: vite.config.js or vite.config.mjs is missing.');
|
|
930
|
+
const viteContent = fs.readFileSync(viteConfigPath, 'utf8');
|
|
931
|
+
const viteCode = viteContent.replace(COMMENT_OR_STRING_REGEX, (match, quote) =>
|
|
932
|
+
quote ? match : match.replace(/[^\r\n]/g, ' ')
|
|
933
|
+
);
|
|
934
|
+
const aliasRegex = /(['"])@saveGallery\1\s*:\s*path\.resolve\(\s*__dirname\s*,\s*(['"])([^'"]+)\2\s*\)/g;
|
|
935
|
+
const aliasMatches = [...viteCode.matchAll(aliasRegex)];
|
|
936
|
+
if (aliasMatches.length > 1) throw new Error('❌ Multiple active @saveGallery alias entries found. Keep one entry.');
|
|
937
|
+
const aliasMatch = aliasMatches[0];
|
|
938
|
+
if (!aliasMatch && /['"]@saveGallery['"]\s*:/.test(viteCode)) {
|
|
939
|
+
throw new Error('❌ Unsupported @saveGallery alias format. Use path.resolve(__dirname, a literal file path).');
|
|
940
|
+
}
|
|
941
|
+
if (aliasImportFound && aliasMatch) {
|
|
942
|
+
const existingName = path.basename(aliasMatch[3]).match(SAVE_FILE_REGEX);
|
|
943
|
+
if (!existingName) throw new Error('❌ @saveGallery must point to a versioned saveToGalleryAndSaveAnyFile helper.');
|
|
944
|
+
referencedVersions.add(existingName[2]);
|
|
945
|
+
}
|
|
946
|
+
if (!referencedVersions.size) {
|
|
947
|
+
const jsDir = path.join(SOURCE_ROOT, 'js');
|
|
948
|
+
const pattern = isIOSBuild ? /^saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*-ios\.js$/ : /^saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*\.js$/;
|
|
949
|
+
const latestFile = getLatestVersionedFileName(jsDir, pattern);
|
|
950
|
+
if (!latestFile) throw new Error(`❌ No ${buildPlatform} save-gallery helper found in src/js.`);
|
|
951
|
+
referencedVersions.add(latestFile.match(SAVE_FILE_REGEX)[2]);
|
|
952
|
+
}
|
|
953
|
+
if (referencedVersions.size !== 1) {
|
|
954
|
+
throw new Error(`❌ @saveGallery cannot represent multiple helper versions: ${[...referencedVersions].join(', ')}. Align them before building.`);
|
|
955
|
+
}
|
|
956
|
+
const baseName = [...referencedVersions][0];
|
|
957
|
+
const targetRelativePath = `./src/js/${baseName}${isIOSBuild ? '-ios' : ''}.js`;
|
|
958
|
+
const targetPath = path.resolve(path.dirname(viteConfigPath), targetRelativePath);
|
|
959
|
+
if (!fs.existsSync(targetPath)) throw new Error(`❌ Cannot configure @saveGallery: target file does not exist: ${targetPath}`);
|
|
960
|
+
const aliasEntry = `'@saveGallery': path.resolve(__dirname, '${targetRelativePath}')`;
|
|
961
|
+
let nextViteContent = viteContent;
|
|
962
|
+
if (aliasMatch) {
|
|
963
|
+
if (path.resolve(path.dirname(viteConfigPath), aliasMatch[3]) !== targetPath) {
|
|
964
|
+
nextViteContent = viteContent.slice(0, aliasMatch.index) + aliasEntry + viteContent.slice(aliasMatch.index + aliasMatch[0].length);
|
|
900
965
|
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
|
|
966
|
+
} else {
|
|
967
|
+
const aliasHeader = /\balias\s*:\s*\{/g.exec(viteCode);
|
|
968
|
+
const resolveHeader = /\bresolve\s*:\s*\{/g.exec(viteCode);
|
|
969
|
+
const returnHeader = /\breturn\s*\{/g.exec(viteCode);
|
|
970
|
+
const newline = viteContent.includes('\r\n') ? '\r\n' : '\n';
|
|
971
|
+
const header = aliasHeader || resolveHeader || returnHeader;
|
|
972
|
+
if (!header || (!aliasHeader && /\balias\s*:/.test(viteCode))) {
|
|
973
|
+
throw new Error('❌ Cannot safely insert @saveGallery in this Vite config. Add a resolve.alias object first.');
|
|
974
|
+
}
|
|
975
|
+
const insert = aliasHeader ? `${newline} ${aliasEntry},`
|
|
976
|
+
: resolveHeader ? `${newline} alias: { ${aliasEntry} },`
|
|
977
|
+
: `${newline} resolve: { alias: { ${aliasEntry} } },`;
|
|
978
|
+
const offset = header.index + header[0].length;
|
|
979
|
+
nextViteContent = viteContent.slice(0, offset) + insert + viteContent.slice(offset);
|
|
980
|
+
}
|
|
981
|
+
nextViteContent = ensureImportOrRequire(nextViteContent, 'path', "import path from 'path';", "const path = require('path');");
|
|
982
|
+
if (nextViteContent !== viteContent) {
|
|
983
|
+
pendingChanges.unshift({ filePath: viteConfigPath, content: viteContent, nextContent: nextViteContent,
|
|
984
|
+
replacements: [{ importPath: aliasMatch ? aliasMatch[3] : '(missing @saveGallery alias)', nextImportPath: targetRelativePath }] });
|
|
985
|
+
}
|
|
986
|
+
if (isIOSBuild) iosImportFound = true;
|
|
987
|
+
else androidImportFound = true;
|
|
988
|
+
}
|
|
904
989
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
990
|
+
if (pendingChanges.length) {
|
|
991
|
+
console.warn(`\n⚠️ WARNING: This build is considered ${isIOSBuild ? 'iOS' : 'Android'}.`);
|
|
992
|
+
console.warn('The following source imports and Vite alias targets will be changed:');
|
|
993
|
+
for (const change of pendingChanges) {
|
|
994
|
+
console.warn(`\n📄 ${change.filePath}`);
|
|
995
|
+
for (const replacement of change.replacements) {
|
|
996
|
+
console.warn(` ${replacement.importPath} → ${replacement.nextImportPath}`);
|
|
908
997
|
}
|
|
909
998
|
}
|
|
910
|
-
}
|
|
911
999
|
|
|
1000
|
+
const confirmed = await new Promise(resolve => {
|
|
1001
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1002
|
+
rl.on('close', () => resolve(false));
|
|
1003
|
+
rl.on('SIGINT', () => { resolve(false); rl.close(); });
|
|
1004
|
+
rl.question('\nPress Enter or type y to apply these changes and continue; any other answer cancels: ', answer => {
|
|
1005
|
+
const normalizedAnswer = answer.trim().toLowerCase();
|
|
1006
|
+
resolve(normalizedAnswer === '' || normalizedAnswer === 'y');
|
|
1007
|
+
rl.close();
|
|
1008
|
+
});
|
|
1009
|
+
});
|
|
1010
|
+
if (!confirmed) throw new Error('❌ Build cancelled. No import filenames were changed.');
|
|
912
1011
|
|
|
913
|
-
//
|
|
914
|
-
for (
|
|
915
|
-
|
|
916
|
-
|
|
1012
|
+
// Check every source again before writing so edits made while awaiting confirmation are preserved.
|
|
1013
|
+
for (const change of pendingChanges) {
|
|
1014
|
+
if (fs.readFileSync(change.filePath, 'utf8') !== change.content) {
|
|
1015
|
+
throw new Error(`❌ Source changed while awaiting confirmation: ${change.filePath}. Build cancelled; run it again.`);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
for (const change of pendingChanges) {
|
|
1019
|
+
fs.writeFileSync(change.filePath, change.nextContent, 'utf8');
|
|
1020
|
+
console.log(`✅ Updated platform imports in: ${change.filePath}`);
|
|
917
1021
|
}
|
|
918
1022
|
}
|
|
919
1023
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
return;
|
|
926
|
-
} */
|
|
927
|
-
|
|
928
|
-
//scanDirectory(ROOT_DIR);
|
|
929
|
-
|
|
930
|
-
// iOS Checks
|
|
931
|
-
/* if (isMac && !iosImportFound) {
|
|
932
|
-
console.warn(`⚠️ WARNING: You're on macOS but no iOS version (saveToGalleryAndSaveAnyFile-x.x-ios.js) found.`);
|
|
933
|
-
process.exit(1);
|
|
934
|
-
} else if (isMac && iosImportFound) {
|
|
935
|
-
console.log('✅ iOS version detected for macOS build.');
|
|
936
|
-
} else if (!iosImportFound) {
|
|
937
|
-
console.log('✅ No iOS-specific imports detected for non-macOS.');
|
|
938
|
-
} */
|
|
939
|
-
|
|
940
|
-
// ✅ Only care if iOS import is found in NON-mac systems
|
|
941
|
-
if (iosImportFound && !isMac) {
|
|
942
|
-
console.error(`\n❌ ERROR: iOS-specific file is imported in non-macOS environment.`);
|
|
943
|
-
process.exit(1);
|
|
944
|
-
} else if (iosImportFound && isMac) {
|
|
945
|
-
console.log('✅ iOS import detected (valid for macOS build).');
|
|
1024
|
+
// The alias selects exactly one helper for the target platform.
|
|
1025
|
+
if (iosImportFound) {
|
|
1026
|
+
console.log('✅ iOS import detected (valid for iOS build).');
|
|
1027
|
+
} else if (androidImportFound) {
|
|
1028
|
+
console.log('✅ Android import detected (valid for Android build).');
|
|
946
1029
|
} else {
|
|
947
|
-
console.log('✅ No
|
|
1030
|
+
console.log('✅ No platform-specific saveToGalleryAndSaveAnyFile imports found.');
|
|
948
1031
|
}
|
|
949
1032
|
|
|
950
1033
|
|
|
951
1034
|
// Android Checks
|
|
952
|
-
if (androidImportFound) {
|
|
1035
|
+
if (buildPlatform === 'android' && androidImportFound) {
|
|
953
1036
|
console.log("📱 Android version of saveToGalleryAndSaveAnyFile detected. Checking AndroidManifest.xml...");
|
|
954
1037
|
|
|
955
1038
|
if (!fs.existsSync(ANDROID_MANIFEST_PATH)) {
|
|
@@ -980,8 +1063,8 @@ if (iosImportFound && !isMac) {
|
|
|
980
1063
|
}
|
|
981
1064
|
};
|
|
982
1065
|
|
|
983
|
-
saveToGalleryAndSaveFileCheck_iOS();
|
|
984
|
-
// saveToGalleryAndSaveAnyFile
|
|
1066
|
+
await saveToGalleryAndSaveFileCheck_iOS();
|
|
1067
|
+
// Validate saveToGalleryAndSaveAnyFile imports for the build platform END
|
|
985
1068
|
|
|
986
1069
|
|
|
987
1070
|
|
|
@@ -1701,7 +1784,6 @@ validateAndroidBuildOptions();
|
|
|
1701
1784
|
// Check all the codeplays plugins version START
|
|
1702
1785
|
|
|
1703
1786
|
|
|
1704
|
-
const readline = require('readline');
|
|
1705
1787
|
|
|
1706
1788
|
|
|
1707
1789
|
//const srcDir = path.join(__dirname, 'src');
|
|
@@ -1720,20 +1802,15 @@ function compareVersions(v1, v2) {
|
|
|
1720
1802
|
}
|
|
1721
1803
|
|
|
1722
1804
|
function walkSync(dir, filelist = []) {
|
|
1723
|
-
fs.readdirSync(dir)
|
|
1724
|
-
const fullPath = path.join(dir,
|
|
1725
|
-
const
|
|
1726
|
-
if (
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
filelist.push(fullPath);
|
|
1730
|
-
}
|
|
1731
|
-
});
|
|
1805
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
1806
|
+
const fullPath = path.join(dir, entry.name);
|
|
1807
|
+
const isDirectory = entry.isDirectory() || (entry.isSymbolicLink() && fs.statSync(fullPath).isDirectory());
|
|
1808
|
+
if (isDirectory) walkSync(fullPath, filelist);
|
|
1809
|
+
else filelist.push(fullPath);
|
|
1810
|
+
}
|
|
1732
1811
|
return filelist;
|
|
1733
1812
|
}
|
|
1734
1813
|
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
1814
|
function getSearchRoot(plugin) {
|
|
1738
1815
|
return path.join(srcDir, plugin.baseDir || 'js');
|
|
1739
1816
|
}
|
|
@@ -1788,6 +1865,7 @@ function urlExists(url) {
|
|
|
1788
1865
|
* Download file from server
|
|
1789
1866
|
*/
|
|
1790
1867
|
function downloadFile(url, dest) {
|
|
1868
|
+
if (path.resolve(dest).startsWith(path.join(process.cwd(), 'src') + path.sep)) sourceFileInventory = null;
|
|
1791
1869
|
return new Promise((resolve, reject) => {
|
|
1792
1870
|
const file = fs.createWriteStream(dest);
|
|
1793
1871
|
|
|
@@ -1839,6 +1917,8 @@ const VITE_ALIAS_ONLY = [
|
|
|
1839
1917
|
function updateImports(oldName, newName) {
|
|
1840
1918
|
|
|
1841
1919
|
const projectRoot = process.cwd();
|
|
1920
|
+
const oldSaveHelper = oldName.match(/^(saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*)(?:-ios)?\.js$/);
|
|
1921
|
+
const newSaveHelper = newName.match(/^(saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*)(?:-ios)?\.js$/);
|
|
1842
1922
|
|
|
1843
1923
|
const filesToScan = [
|
|
1844
1924
|
path.join(projectRoot, "vite.config.js"),
|
|
@@ -1854,9 +1934,23 @@ function updateImports(oldName, newName) {
|
|
|
1854
1934
|
|
|
1855
1935
|
let content = fs.readFileSync(file, "utf8");
|
|
1856
1936
|
|
|
1857
|
-
if (content.includes(oldName)) {
|
|
1937
|
+
if (content.includes(oldName) || (oldSaveHelper && newSaveHelper && content.includes('@saveGallery'))) {
|
|
1858
1938
|
|
|
1859
1939
|
content = content.split(oldName).join(newName);
|
|
1940
|
+
// Plugin updates can replace an iOS filename with the generic new filename.
|
|
1941
|
+
// Keep the centralized save-gallery alias aligned with the selected build.
|
|
1942
|
+
content = content.replace(/(['"]@saveGallery['"]\s*:\s*path\.resolve\(\s*__dirname\s*,\s*['"])([^'"]+)(['"]\s*\))/g,
|
|
1943
|
+
(match, prefix, target, suffix) => {
|
|
1944
|
+
if (!/saveToGalleryAndSaveAnyFile-\d+(?:\.\d+)*(?:-ios)?\.js$/.test(target)) return match;
|
|
1945
|
+
if (oldSaveHelper && newSaveHelper && target.includes(oldSaveHelper[1])) {
|
|
1946
|
+
target = target.replace(oldSaveHelper[1], newSaveHelper[1]);
|
|
1947
|
+
}
|
|
1948
|
+
const nextTarget = target.replace(/(?:-ios)?\.js$/, buildPlatform === 'ios' ? '-ios.js' : '.js');
|
|
1949
|
+
if (!fs.existsSync(path.resolve(path.dirname(file), nextTarget))) {
|
|
1950
|
+
throw new Error(`❌ Updated @saveGallery target is missing: ${nextTarget}`);
|
|
1951
|
+
}
|
|
1952
|
+
return prefix + nextTarget + suffix;
|
|
1953
|
+
});
|
|
1860
1954
|
|
|
1861
1955
|
fs.writeFileSync(file, content);
|
|
1862
1956
|
|
|
@@ -1865,47 +1959,16 @@ function updateImports(oldName, newName) {
|
|
|
1865
1959
|
|
|
1866
1960
|
});
|
|
1867
1961
|
|
|
1868
|
-
//
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
if (stat.isDirectory()) {
|
|
1880
|
-
walk(full);
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
else if (
|
|
1884
|
-
(full.endsWith(".js") ||
|
|
1885
|
-
full.endsWith(".f7") ||
|
|
1886
|
-
full.endsWith(".mjs")) &&
|
|
1887
|
-
!full.endsWith(".min.js")
|
|
1888
|
-
) {
|
|
1889
|
-
|
|
1890
|
-
let content = fs.readFileSync(full, "utf8");
|
|
1891
|
-
|
|
1892
|
-
if (content.includes(oldName)) {
|
|
1893
|
-
|
|
1894
|
-
content = content.split(oldName).join(newName);
|
|
1895
|
-
|
|
1896
|
-
fs.writeFileSync(full, content);
|
|
1897
|
-
|
|
1898
|
-
console.log(`✏️ Updated import in ${path.relative(projectRoot, full)}`);
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
}
|
|
1902
|
-
|
|
1903
|
-
});
|
|
1904
|
-
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
if (fs.existsSync(srcDir)) {
|
|
1908
|
-
walk(srcDir);
|
|
1962
|
+
// Downloads invalidate the inventory; content-only edits reuse it.
|
|
1963
|
+
for (const full of getSourceFiles()) {
|
|
1964
|
+
const relativePath = path.relative(srcDir, full);
|
|
1965
|
+
if (relativePath.split(path.sep).some(part => ['node_modules', 'android', 'ios', 'dist', '.git'].includes(part))) continue;
|
|
1966
|
+
if (!/\.(js|f7|mjs)$/.test(full) || full.endsWith('.min.js')) continue;
|
|
1967
|
+
let content = fs.readFileSync(full, 'utf8');
|
|
1968
|
+
if (!content.includes(oldName)) continue;
|
|
1969
|
+
content = content.split(oldName).join(newName);
|
|
1970
|
+
fs.writeFileSync(full, content);
|
|
1971
|
+
console.log(`✏️ Updated import in ${path.relative(projectRoot, full)}`);
|
|
1909
1972
|
}
|
|
1910
1973
|
|
|
1911
1974
|
}
|
|
@@ -2299,7 +2362,7 @@ async function loadPluginVersions() {
|
|
|
2299
2362
|
let hasMandatoryUpdate = false;
|
|
2300
2363
|
function checkPlugins() {
|
|
2301
2364
|
return new Promise(async (resolve, reject) => {
|
|
2302
|
-
const files =
|
|
2365
|
+
const files = getSourceFiles();
|
|
2303
2366
|
const outdatedPlugins = [];
|
|
2304
2367
|
let hasMandatoryUpdate = false;
|
|
2305
2368
|
|
|
@@ -2635,6 +2698,7 @@ Expected:
|
|
|
2635
2698
|
console.log(`🚀 Executing ${runJsPath}...`);
|
|
2636
2699
|
|
|
2637
2700
|
execSync(`node "${runJsPath}"`, { stdio: "inherit" });
|
|
2701
|
+
sourceFileInventory = null;
|
|
2638
2702
|
}
|
|
2639
2703
|
|
|
2640
2704
|
} else {
|
|
@@ -2659,96 +2723,6 @@ Expected:
|
|
|
2659
2723
|
|
|
2660
2724
|
|
|
2661
2725
|
|
|
2662
|
-
//editor-x.x import old style check and stop execution START
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
// Match: editor/editor-2.3, editor/editor-2.3.1, etc.
|
|
2667
|
-
const FORBIDDEN_REGEX = /editor\/editor-\d+(\.\d+)+/;
|
|
2668
|
-
|
|
2669
|
-
let hasError = false;
|
|
2670
|
-
|
|
2671
|
-
const ERROR_MESSAGE = `const ERROR_MESSAGE = ❌ Invalid import detected!
|
|
2672
|
-
|
|
2673
|
-
You are using a direct version-based path like: editor/editor-x.x/editor.js
|
|
2674
|
-
|
|
2675
|
-
🚫 This is NOT allowed.
|
|
2676
|
-
|
|
2677
|
-
👉 Please use the proper alias or updated import method.
|
|
2678
|
-
Example: import { ... } from '@editor'
|
|
2679
|
-
|
|
2680
|
-
⚠️ Do not use version-based paths in imports.
|
|
2681
|
-
👉 Please add this manually in vite.config.js:
|
|
2682
|
-
|
|
2683
|
-
alias: {
|
|
2684
|
-
'@editor': path.resolve(__dirname, './src/js/editor/editor-x.x')
|
|
2685
|
-
}`
|
|
2686
|
-
|
|
2687
|
-
function scanDir(dir) {
|
|
2688
|
-
const files = fs.readdirSync(dir);
|
|
2689
|
-
|
|
2690
|
-
for (const file of files) {
|
|
2691
|
-
const fullPath = path.join(dir, file);
|
|
2692
|
-
const stat = fs.statSync(fullPath);
|
|
2693
|
-
|
|
2694
|
-
if (stat.isDirectory()) {
|
|
2695
|
-
scanDir(fullPath);
|
|
2696
|
-
} else if (file.endsWith(".js") || file.endsWith(".ts") || file.endsWith(".f7")) {
|
|
2697
|
-
const content = fs.readFileSync(fullPath, "utf-8");
|
|
2698
|
-
|
|
2699
|
-
const lines = content.split("\n");
|
|
2700
|
-
|
|
2701
|
-
lines.forEach((line, index) => {
|
|
2702
|
-
if (FORBIDDEN_REGEX.test(line)) {
|
|
2703
|
-
console.error(
|
|
2704
|
-
`❌ Forbidden import found:\nFile: ${fullPath}\nLine: ${index + 1}\nCode: ${line.trim()}\n`,
|
|
2705
|
-
ERROR_MESSAGE
|
|
2706
|
-
);
|
|
2707
|
-
hasError = true;
|
|
2708
|
-
}
|
|
2709
|
-
});
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
}
|
|
2713
|
-
|
|
2714
|
-
// Run scan
|
|
2715
|
-
scanDir(ROOT_DIR);
|
|
2716
|
-
|
|
2717
|
-
// Throw error (exit process)
|
|
2718
|
-
if (hasError) {
|
|
2719
|
-
console.error("🚫 Build failed due to forbidden editor imports.");
|
|
2720
|
-
process.exit(1);
|
|
2721
|
-
} else {
|
|
2722
|
-
console.log("✅ No forbidden imports found.");
|
|
2723
|
-
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
//editor-x.x import old style check and stop execution START
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
// Check all the codeplays plugins version START
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
// ====================================================================
|
|
2747
|
-
// AUTO-ADD esbuild.drop: ['console','debugger'] to vite.config.js / mjs
|
|
2748
|
-
// ====================================================================
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
2726
|
const checkAndupdateDropInViteConfig = () => {
|
|
2753
2727
|
|
|
2754
2728
|
const possibleFiles = [
|
|
@@ -2869,7 +2843,7 @@ const syncAdmobAliasInViteConfig = () => {
|
|
|
2869
2843
|
};
|
|
2870
2844
|
|
|
2871
2845
|
|
|
2872
|
-
|
|
2846
|
+
function getViteConfigPath() {
|
|
2873
2847
|
const possibleFiles = [
|
|
2874
2848
|
"vite.config.mjs",
|
|
2875
2849
|
"vite.config.js"
|
|
@@ -2919,7 +2893,7 @@ const getAnalyticsConfig = () => {
|
|
|
2919
2893
|
};
|
|
2920
2894
|
};
|
|
2921
2895
|
|
|
2922
|
-
|
|
2896
|
+
function isPackageAvailable(packageName) {
|
|
2923
2897
|
if (!fs.existsSync(packageJsonPath)) return false;
|
|
2924
2898
|
|
|
2925
2899
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -2927,47 +2901,43 @@ const isPackageAvailable = (packageName) => {
|
|
|
2927
2901
|
return Boolean(
|
|
2928
2902
|
packageJson.dependencies?.[packageName] ||
|
|
2929
2903
|
packageJson.devDependencies?.[packageName] ||
|
|
2904
|
+
packageJson.optionalDependencies?.[packageName] ||
|
|
2905
|
+
packageJson.peerDependencies?.[packageName] ||
|
|
2930
2906
|
fs.existsSync(path.join(process.cwd(), "node_modules", packageName, "package.json"))
|
|
2931
2907
|
);
|
|
2932
2908
|
};
|
|
2933
2909
|
|
|
2934
2910
|
const sourceImportsPackage = (packageName, ignoredFilePath) => {
|
|
2935
|
-
const sourceDir = path.join(process.cwd(), "src");
|
|
2936
|
-
if (!fs.existsSync(sourceDir)) return false;
|
|
2937
|
-
|
|
2938
2911
|
const escapedPackage = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2939
2912
|
const importRegex = new RegExp(`(?:from\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]|import\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]|import\\s*\\(\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]\\s*\\)|require\\s*\\(\\s*['"]${escapedPackage}(?:/[^'"]*)?['"]\\s*\\))`);
|
|
2940
2913
|
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
continue;
|
|
2947
|
-
}
|
|
2948
|
-
|
|
2949
|
-
if (entry.isDirectory()) {
|
|
2950
|
-
if (scan(fullPath)) return true;
|
|
2951
|
-
continue;
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
|
-
if (!/\.(js|mjs|cjs|ts|tsx|jsx|f7)$/.test(entry.name)) continue;
|
|
2955
|
-
|
|
2956
|
-
const content = fs.readFileSync(fullPath, "utf8");
|
|
2957
|
-
if (importRegex.test(content)) return true;
|
|
2958
|
-
}
|
|
2959
|
-
|
|
2960
|
-
return false;
|
|
2961
|
-
};
|
|
2962
|
-
|
|
2963
|
-
return scan(sourceDir);
|
|
2914
|
+
return getSourceFiles().some(fullPath => {
|
|
2915
|
+
if (ignoredFilePath && path.resolve(fullPath) === path.resolve(ignoredFilePath)) return false;
|
|
2916
|
+
if (!/\.(js|mjs|cjs|ts|tsx|jsx|f7)$/.test(fullPath)) return false;
|
|
2917
|
+
return importRegex.test(fs.readFileSync(fullPath, 'utf8'));
|
|
2918
|
+
});
|
|
2964
2919
|
};
|
|
2965
2920
|
|
|
2966
|
-
|
|
2921
|
+
function runNpmCommand(command) {
|
|
2967
2922
|
console.log(`🚀 ${command}`);
|
|
2968
2923
|
execSync(command, { stdio: "inherit" });
|
|
2969
2924
|
};
|
|
2970
2925
|
|
|
2926
|
+
function removeOneSignalPlugin() {
|
|
2927
|
+
if (!isPackageAvailable(ONESIGNAL_PLUGIN_NAME)) {
|
|
2928
|
+
console.log('ℹ️ OneSignal is not installed. Skipping removal.');
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
console.warn(`⚠️ WARNING: ${ONESIGNAL_PLUGIN_NAME} was found. OneSignal is retired and will be uninstalled automatically.`);
|
|
2933
|
+
runNpmCommand(`npm uninstall ${ONESIGNAL_PLUGIN_NAME}`);
|
|
2934
|
+
if (isPackageAvailable(ONESIGNAL_PLUGIN_NAME)) {
|
|
2935
|
+
throw new Error(`❌ ${ONESIGNAL_PLUGIN_NAME} is still declared or installed after npm uninstall. Build stopped; check dependent packages.`);
|
|
2936
|
+
}
|
|
2937
|
+
sourceFileInventory = null;
|
|
2938
|
+
console.log(`✅ Uninstalled ${ONESIGNAL_PLUGIN_NAME}.`);
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2971
2941
|
const CODEPLAY_SYSTEM_BARS_PLUGIN = "capacitor-codeplay-system-bars";
|
|
2972
2942
|
|
|
2973
2943
|
const syncCodeplaySystemBarsPackage = () => {
|
|
@@ -3180,27 +3150,17 @@ const syncAdmobConfigImports = () => {
|
|
|
3180
3150
|
const adsDir = path.join(process.cwd(), "src", "js", "Ads");
|
|
3181
3151
|
if (!fs.existsSync(adsDir)) return;
|
|
3182
3152
|
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
let content = fs.readFileSync(fullPath, "utf8");
|
|
3195
|
-
if (!content.includes(ADMOB_OLD_CONFIG)) return;
|
|
3196
|
-
|
|
3197
|
-
content = content.split(ADMOB_OLD_CONFIG).join(ADMOB_NEXTGEN_CONFIG);
|
|
3198
|
-
fs.writeFileSync(fullPath, content, "utf8");
|
|
3199
|
-
console.log(`✏️ Updated AdMob config import in ${path.relative(process.cwd(), fullPath)}`);
|
|
3200
|
-
});
|
|
3201
|
-
};
|
|
3153
|
+
// Downloads invalidate the inventory; content-only migrations reuse it.
|
|
3154
|
+
for (const fullPath of getSourceFiles()) {
|
|
3155
|
+
if (!fullPath.startsWith(adsDir + path.sep)) continue;
|
|
3156
|
+
if (!/\.(js|mjs|ts|f7)$/.test(fullPath) || fullPath.endsWith('.min.js')) continue;
|
|
3157
|
+
let content = fs.readFileSync(fullPath, 'utf8');
|
|
3158
|
+
if (!content.includes(ADMOB_OLD_CONFIG)) continue;
|
|
3159
|
+
content = content.split(ADMOB_OLD_CONFIG).join(ADMOB_NEXTGEN_CONFIG);
|
|
3160
|
+
fs.writeFileSync(fullPath, content, 'utf8');
|
|
3161
|
+
console.log(`✏️ Updated AdMob config import in ${path.relative(process.cwd(), fullPath)}`);
|
|
3162
|
+
}
|
|
3202
3163
|
|
|
3203
|
-
scan(adsDir);
|
|
3204
3164
|
};
|
|
3205
3165
|
|
|
3206
3166
|
const ensureAdmobNextgenFiles = async () => {
|
|
@@ -3273,6 +3233,7 @@ const ensureAdmobNextgenFiles = async () => {
|
|
|
3273
3233
|
mergedConfig.iosAppId = iosAppId;
|
|
3274
3234
|
}
|
|
3275
3235
|
|
|
3236
|
+
if (!fs.existsSync(nextgenConfigPath)) sourceFileInventory = null;
|
|
3276
3237
|
fs.writeFileSync(nextgenConfigPath, JSON.stringify(mergedConfig, null, 2) + "\n", "utf8");
|
|
3277
3238
|
syncAdmobConfigImports();
|
|
3278
3239
|
console.log("✅ AdMob nextgen files and configuration are ready.");
|
|
@@ -3448,7 +3409,9 @@ export const trackConsumablePurchased = trackEvent;
|
|
|
3448
3409
|
`;
|
|
3449
3410
|
|
|
3450
3411
|
const nextContent = analyticsEnabled ? activeWrapper : noopWrapper;
|
|
3451
|
-
const
|
|
3412
|
+
const analyticsFileExists = fs.existsSync(analyticsFile);
|
|
3413
|
+
const currentContent = analyticsFileExists ? fs.readFileSync(analyticsFile, "utf8") : "";
|
|
3414
|
+
if (!analyticsFileExists) sourceFileInventory = null;
|
|
3452
3415
|
|
|
3453
3416
|
if (currentContent !== nextContent) {
|
|
3454
3417
|
fs.writeFileSync(analyticsFile, nextContent, "utf8");
|
|
@@ -3459,6 +3422,7 @@ export const trackConsumablePurchased = trackEvent;
|
|
|
3459
3422
|
|
|
3460
3423
|
if (fs.existsSync(legacyAnalyticsFile)) {
|
|
3461
3424
|
fs.unlinkSync(legacyAnalyticsFile);
|
|
3425
|
+
sourceFileInventory = null;
|
|
3462
3426
|
console.log("✅ Removed old Firebase analytics wrapper: src/js/analytics/firebase-analytics.js");
|
|
3463
3427
|
}
|
|
3464
3428
|
|
|
@@ -3540,7 +3504,7 @@ const syncFirebaseAnalyticsPodfile = () => {
|
|
|
3540
3504
|
}
|
|
3541
3505
|
};
|
|
3542
3506
|
|
|
3543
|
-
|
|
3507
|
+
function ensureImportOrRequire(content, moduleName, esmLine, cjsLine) {
|
|
3544
3508
|
const escaped = moduleName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3545
3509
|
if (new RegExp(`from\\s*['"]${escaped}['"]|require\\s*\\(\\s*['"]${escaped}['"]\\s*\\)`).test(content)) {
|
|
3546
3510
|
return content;
|
|
@@ -4033,11 +3997,12 @@ if (compareVersion(admobConfigInJson.VERSION, admobConfigMinVersion) < 0) {
|
|
|
4033
3997
|
|
|
4034
3998
|
|
|
4035
3999
|
|
|
4036
|
-
function ensureGitignoreEntry(entry) {
|
|
4000
|
+
function ensureGitignoreEntry(entry, shouldIgnore = true) {
|
|
4037
4001
|
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
4038
4002
|
|
|
4039
4003
|
// If .gitignore doesn't exist, create it
|
|
4040
4004
|
if (!fs.existsSync(gitignorePath)) {
|
|
4005
|
+
if (!shouldIgnore) return;
|
|
4041
4006
|
fs.writeFileSync(gitignorePath, `${entry}\n`, 'utf8');
|
|
4042
4007
|
console.log(`✅ .gitignore created and added: ${entry}`);
|
|
4043
4008
|
return;
|
|
@@ -4045,6 +4010,18 @@ function ensureGitignoreEntry(entry) {
|
|
|
4045
4010
|
|
|
4046
4011
|
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
4047
4012
|
|
|
4013
|
+
if (!shouldIgnore) {
|
|
4014
|
+
const normalizedEntry = entry.replace(/^\/|\/$/g, '');
|
|
4015
|
+
const nextContent = content.split(/(?<=\n)/).filter(line =>
|
|
4016
|
+
line.trim().replace(/^\/|\/$/g, '') !== normalizedEntry
|
|
4017
|
+
).join('');
|
|
4018
|
+
if (nextContent !== content) {
|
|
4019
|
+
fs.writeFileSync(gitignorePath, nextContent, 'utf8');
|
|
4020
|
+
console.log(`✅ Removed from .gitignore: ${entry}`);
|
|
4021
|
+
}
|
|
4022
|
+
return;
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4048
4025
|
// Normalize lines (trim + remove trailing slashes for comparison)
|
|
4049
4026
|
const lines = content
|
|
4050
4027
|
.split(/\r?\n/)
|
|
@@ -4069,7 +4046,8 @@ function ensureGitignoreEntry(entry) {
|
|
|
4069
4046
|
}
|
|
4070
4047
|
|
|
4071
4048
|
|
|
4072
|
-
ensureGitignoreEntry('buildCodeplay/');
|
|
4049
|
+
ensureGitignoreEntry('buildCodeplay/', false);
|
|
4050
|
+
ensureGitignoreEntry('agent-temp/');
|
|
4073
4051
|
|
|
4074
4052
|
|
|
4075
4053
|
// ======================================================
|
|
@@ -4249,7 +4227,6 @@ function patchFile() {
|
|
|
4249
4227
|
async function main() {
|
|
4250
4228
|
validateThemeFolderLocation();
|
|
4251
4229
|
validateAndRestoreSignDetails();
|
|
4252
|
-
execSync('node buildCodeplay/fix-onesignal-plugin.js', { stdio: 'inherit' });
|
|
4253
4230
|
|
|
4254
4231
|
await loadPluginVersions(); // 🔥 NEW
|
|
4255
4232
|
await syncAgentInstructions();
|
|
@@ -4265,7 +4242,8 @@ async function main() {
|
|
|
4265
4242
|
checkAdmobConfigurationProperty();
|
|
4266
4243
|
}
|
|
4267
4244
|
|
|
4268
|
-
main()
|
|
4245
|
+
await main();
|
|
4246
|
+
})().catch(err => {
|
|
4269
4247
|
console.error(err?.message || err);
|
|
4270
4248
|
process.exit(1);
|
|
4271
4249
|
});
|