u2a 3.5.5 → 3.5.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/README.md +1 -1
- package/package.json +9 -4
- package/src/commands/configure.js +184 -184
- package/src/utils/app.js +243 -243
- package/src/utils/appGenerator.js +124 -124
- package/src/utils/builder.js +125 -125
- package/src/utils/config.js +3 -3
- package/src/utils/logger.js +1 -1
- package/src/utils/noroot.js +41 -41
- package/src/utils/osIntegration.js +187 -187
- package/src/utils/postinstall.js +156 -156
- package/src/utils/sanitize.js +20 -20
- package/src/utils/securexec.js +12 -12
- package/src/utils/settings.js +114 -114
- package/src/utils/upgradeLA.js +140 -140
- package/src/utils/url.js +12 -9
- package/src/utils/versionCheck.js +149 -149
- package/.github/workflows/npm-publish.yml +0 -22
package/src/utils/upgradeLA.js
CHANGED
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
//seems still a bit unstable, thats why this feature is disabled by default
|
|
2
|
-
//enable with 'u2a configure autoupgrade enable'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const { readDB } = require('./config');
|
|
9
|
-
const Logger = require('./logger');
|
|
10
|
-
const { createApp } = require('../commands/create');
|
|
11
|
-
const { removeApp } = require('../commands/remove');
|
|
12
|
-
const { getSetting } = require('./settings');
|
|
13
|
-
|
|
14
|
-
const logger = new Logger('upgradeLA');
|
|
15
|
-
|
|
16
|
-
function isCoreUpdate(currentVersion, newVersion) {
|
|
17
|
-
try {
|
|
18
|
-
const [currentSecurity, currentCore, currentFeature] = currentVersion.split('.').map(Number);
|
|
19
|
-
const [newSecurity, newCore, newFeature] = newVersion.split('.').map(Number);
|
|
20
|
-
|
|
21
|
-
return (currentSecurity !== newSecurity || currentCore !== newCore);
|
|
22
|
-
} catch (err) {
|
|
23
|
-
logger.debug(`Error comparing versions: ${currentVersion} vs ${newVersion}`, err.message);
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function extractDimensionsFromMainJs(mainJsPath) {
|
|
29
|
-
try {
|
|
30
|
-
if (!fs.existsSync(mainJsPath)) {
|
|
31
|
-
logger.warn(`main.js file not found at ${mainJsPath}`);
|
|
32
|
-
return { width: 1200, height: 800 };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const mainJsContent = fs.readFileSync(mainJsPath, 'utf8');
|
|
36
|
-
|
|
37
|
-
const widthMatch = mainJsContent.match(/const\s+WINDOW_WIDTH\s*=\s*(\d+)/);
|
|
38
|
-
const width = widthMatch ? parseInt(widthMatch[1], 10) : 1200;
|
|
39
|
-
|
|
40
|
-
const heightMatch = mainJsContent.match(/const\s+WINDOW_HEIGHT\s*=\s*(\d+)/);
|
|
41
|
-
const height = heightMatch ? parseInt(heightMatch[1], 10) : 800;
|
|
42
|
-
|
|
43
|
-
logger.debug(`Extracted dimensions from main.js: ${width}x${height}`);
|
|
44
|
-
return { width, height };
|
|
45
|
-
} catch (err) {
|
|
46
|
-
logger.debug(`Error extracting dimensions from main.js: ${mainJsPath}`, err.message);
|
|
47
|
-
return { width: 1200, height: 800 };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function upgradeLocalApp(appName, appData) {
|
|
52
|
-
logger.debug(`Upgrading local app: ${appName}`);
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
const { url, path: appPath, icon } = appData;
|
|
56
|
-
|
|
57
|
-
const mainJsPath = path.join(appPath, 'main.js');
|
|
58
|
-
const { width, height } = extractDimensionsFromMainJs(mainJsPath);
|
|
59
|
-
|
|
60
|
-
const options = {
|
|
61
|
-
name: appName,
|
|
62
|
-
width: width,
|
|
63
|
-
height: height,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
if (icon)
|
|
67
|
-
options.icon = icon;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
await removeApp(appName, false);
|
|
71
|
-
logger.debug(`Removed existing app: ${appName}`);
|
|
72
|
-
|
|
73
|
-
await createApp(url, options);
|
|
74
|
-
logger.debug(`Successfully upgraded: ${appName}`);
|
|
75
|
-
|
|
76
|
-
return true;
|
|
77
|
-
} catch (err) {
|
|
78
|
-
logger.debug(`Failed to upgrade ${appName}`, err.message);
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function upgradeLocalApps(currentVersion, newVersion) {
|
|
84
|
-
logger.debug(`Checking for local apps that need upgrading`);
|
|
85
|
-
|
|
86
|
-
const autoUpgradeEnabled = getSetting('autoupgrade_localapps');
|
|
87
|
-
if (!autoUpgradeEnabled) {
|
|
88
|
-
logger.debug(`Automatic upgrade for local apps is disabled. Skipping upgrades.`);
|
|
89
|
-
return { skipped: true, reason: 'disabled', upgraded: 0, failed: 0, total: 0 };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (!isCoreUpdate(currentVersion, newVersion)) {
|
|
93
|
-
logger.debug(`Not a core update (${currentVersion} → ${newVersion}). Skipping local app upgrades.`);
|
|
94
|
-
return { skipped: true, reason: 'not-core-update', upgraded: 0, failed: 0, total: 0 };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const db = readDB();
|
|
99
|
-
const apps = Object.keys(db);
|
|
100
|
-
const stats = { skipped: false, upgraded: 0, failed: 0, total: apps.length };
|
|
101
|
-
|
|
102
|
-
logger.debug(`Found ${apps.length} local apps to check for upgrade`);
|
|
103
|
-
|
|
104
|
-
for (const appName of apps) {
|
|
105
|
-
const appData = db[appName];
|
|
106
|
-
|
|
107
|
-
if (!appData.path || !fs.existsSync(appData.path)) { //skips if no path but shouldnt happen
|
|
108
|
-
logger.debug(`Skipping ${appName}: Not a local app or path doesn't exist`);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const success = await upgradeLocalApp(appName, appData);
|
|
113
|
-
if (success) {
|
|
114
|
-
stats.upgraded++;
|
|
115
|
-
} else {
|
|
116
|
-
stats.failed++;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
logger.debug(`Local apps upgrade completed: ${stats.upgraded} upgraded, ${stats.failed} failed, ${apps.length - stats.upgraded - stats.failed} skipped`);
|
|
121
|
-
return stats;
|
|
122
|
-
} catch (err) {
|
|
123
|
-
logger.debug(`Error upgrading local apps`, err.message);
|
|
124
|
-
return { skipped: false, upgraded: 0, failed: 0, total: 0, error: err.message };
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function upgrade(currentVersion, newVersion) {
|
|
129
|
-
logger.debug(`Starting local apps upgrade check: ${currentVersion} → ${newVersion}`);
|
|
130
|
-
|
|
131
|
-
if (currentVersion === '0.0.0') {
|
|
132
|
-
logger.debug('New installation detected, no apps to upgrade');
|
|
133
|
-
return { skipped: true, reason: 'new-install' };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return await upgradeLocalApps(currentVersion, newVersion);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = {
|
|
140
|
-
upgrade
|
|
1
|
+
//seems still a bit unstable, thats why this feature is disabled by default
|
|
2
|
+
//enable with 'u2a configure autoupgrade enable'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { readDB } = require('./config');
|
|
9
|
+
const Logger = require('./logger');
|
|
10
|
+
const { createApp } = require('../commands/create');
|
|
11
|
+
const { removeApp } = require('../commands/remove');
|
|
12
|
+
const { getSetting } = require('./settings');
|
|
13
|
+
|
|
14
|
+
const logger = new Logger('upgradeLA');
|
|
15
|
+
|
|
16
|
+
function isCoreUpdate(currentVersion, newVersion) {
|
|
17
|
+
try {
|
|
18
|
+
const [currentSecurity, currentCore, currentFeature] = currentVersion.split('.').map(Number);
|
|
19
|
+
const [newSecurity, newCore, newFeature] = newVersion.split('.').map(Number);
|
|
20
|
+
|
|
21
|
+
return (currentSecurity !== newSecurity || currentCore !== newCore);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
logger.debug(`Error comparing versions: ${currentVersion} vs ${newVersion}`, err.message);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function extractDimensionsFromMainJs(mainJsPath) {
|
|
29
|
+
try {
|
|
30
|
+
if (!fs.existsSync(mainJsPath)) {
|
|
31
|
+
logger.warn(`main.js file not found at ${mainJsPath}`);
|
|
32
|
+
return { width: 1200, height: 800 };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const mainJsContent = fs.readFileSync(mainJsPath, 'utf8');
|
|
36
|
+
|
|
37
|
+
const widthMatch = mainJsContent.match(/const\s+WINDOW_WIDTH\s*=\s*(\d+)/);
|
|
38
|
+
const width = widthMatch ? parseInt(widthMatch[1], 10) : 1200;
|
|
39
|
+
|
|
40
|
+
const heightMatch = mainJsContent.match(/const\s+WINDOW_HEIGHT\s*=\s*(\d+)/);
|
|
41
|
+
const height = heightMatch ? parseInt(heightMatch[1], 10) : 800;
|
|
42
|
+
|
|
43
|
+
logger.debug(`Extracted dimensions from main.js: ${width}x${height}`);
|
|
44
|
+
return { width, height };
|
|
45
|
+
} catch (err) {
|
|
46
|
+
logger.debug(`Error extracting dimensions from main.js: ${mainJsPath}`, err.message);
|
|
47
|
+
return { width: 1200, height: 800 };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function upgradeLocalApp(appName, appData) {
|
|
52
|
+
logger.debug(`Upgrading local app: ${appName}`);
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const { url, path: appPath, icon } = appData;
|
|
56
|
+
|
|
57
|
+
const mainJsPath = path.join(appPath, 'main.js');
|
|
58
|
+
const { width, height } = extractDimensionsFromMainJs(mainJsPath);
|
|
59
|
+
|
|
60
|
+
const options = {
|
|
61
|
+
name: appName,
|
|
62
|
+
width: width,
|
|
63
|
+
height: height,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
if (icon)
|
|
67
|
+
options.icon = icon;
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
await removeApp(appName, false);
|
|
71
|
+
logger.debug(`Removed existing app: ${appName}`);
|
|
72
|
+
|
|
73
|
+
await createApp(url, options);
|
|
74
|
+
logger.debug(`Successfully upgraded: ${appName}`);
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
} catch (err) {
|
|
78
|
+
logger.debug(`Failed to upgrade ${appName}`, err.message);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function upgradeLocalApps(currentVersion, newVersion) {
|
|
84
|
+
logger.debug(`Checking for local apps that need upgrading`);
|
|
85
|
+
|
|
86
|
+
const autoUpgradeEnabled = getSetting('autoupgrade_localapps');
|
|
87
|
+
if (!autoUpgradeEnabled) {
|
|
88
|
+
logger.debug(`Automatic upgrade for local apps is disabled. Skipping upgrades.`);
|
|
89
|
+
return { skipped: true, reason: 'disabled', upgraded: 0, failed: 0, total: 0 };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!isCoreUpdate(currentVersion, newVersion)) {
|
|
93
|
+
logger.debug(`Not a core update (${currentVersion} → ${newVersion}). Skipping local app upgrades.`);
|
|
94
|
+
return { skipped: true, reason: 'not-core-update', upgraded: 0, failed: 0, total: 0 };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const db = readDB();
|
|
99
|
+
const apps = Object.keys(db);
|
|
100
|
+
const stats = { skipped: false, upgraded: 0, failed: 0, total: apps.length };
|
|
101
|
+
|
|
102
|
+
logger.debug(`Found ${apps.length} local apps to check for upgrade`);
|
|
103
|
+
|
|
104
|
+
for (const appName of apps) {
|
|
105
|
+
const appData = db[appName];
|
|
106
|
+
|
|
107
|
+
if (!appData.path || !fs.existsSync(appData.path)) { //skips if no path but shouldnt happen
|
|
108
|
+
logger.debug(`Skipping ${appName}: Not a local app or path doesn't exist`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const success = await upgradeLocalApp(appName, appData);
|
|
113
|
+
if (success) {
|
|
114
|
+
stats.upgraded++;
|
|
115
|
+
} else {
|
|
116
|
+
stats.failed++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
logger.debug(`Local apps upgrade completed: ${stats.upgraded} upgraded, ${stats.failed} failed, ${apps.length - stats.upgraded - stats.failed} skipped`);
|
|
121
|
+
return stats;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
logger.debug(`Error upgrading local apps`, err.message);
|
|
124
|
+
return { skipped: false, upgraded: 0, failed: 0, total: 0, error: err.message };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function upgrade(currentVersion, newVersion) {
|
|
129
|
+
logger.debug(`Starting local apps upgrade check: ${currentVersion} → ${newVersion}`);
|
|
130
|
+
|
|
131
|
+
if (currentVersion === '0.0.0') {
|
|
132
|
+
logger.debug('New installation detected, no apps to upgrade');
|
|
133
|
+
return { skipped: true, reason: 'new-install' };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return await upgradeLocalApps(currentVersion, newVersion);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
upgrade
|
|
141
141
|
};
|
package/src/utils/url.js
CHANGED
|
@@ -2,15 +2,18 @@ const axios = require('axios');
|
|
|
2
2
|
const { sanitizeInput } = require('./sanitize');
|
|
3
3
|
|
|
4
4
|
async function normalizeUrl(url) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
const sanitizedUrl = sanitizeInput(url);
|
|
6
|
+
|
|
7
|
+
if (sanitizedUrl.startsWith('http://') || sanitizedUrl.startsWith('https://')) {
|
|
8
|
+
return sanitizedUrl;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
await axios.get('https://' + sanitizedUrl);
|
|
13
|
+
return 'https://' + sanitizedUrl;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return 'http://' + sanitizedUrl;
|
|
12
16
|
}
|
|
13
|
-
return sanitizeInput(url);
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
function getDomainName(url) {
|
|
@@ -25,4 +28,4 @@ function getDomainName(url) {
|
|
|
25
28
|
module.exports = {
|
|
26
29
|
normalizeUrl,
|
|
27
30
|
getDomainName
|
|
28
|
-
};
|
|
31
|
+
};
|
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
|
-
const { version } = require('../../package.json');
|
|
3
|
-
const Logger = require('./logger');
|
|
4
|
-
const { getSetting } = require('./settings');
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
|
|
7
|
-
const logger = new Logger('version-check');
|
|
8
|
-
|
|
9
|
-
// types of updates based on pattern arount lines 90 of this file
|
|
10
|
-
const UPDATE_TYPES = {
|
|
11
|
-
NONE: 'none',
|
|
12
|
-
SECURITY: 'security',
|
|
13
|
-
CORE: 'core',
|
|
14
|
-
FEATURE: 'feature'
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
async function checkVersion(silent = false, forceCheck = false) {
|
|
18
|
-
//check if version check is enabled in settings
|
|
19
|
-
const versionCheckEnabled = getSetting('version_check');
|
|
20
|
-
|
|
21
|
-
//if version check is disabled and not forcing skip the check (btw idk why i made forcecheck)
|
|
22
|
-
if (!versionCheckEnabled && !forceCheck) {
|
|
23
|
-
logger.debug('Version check is disabled in settings');
|
|
24
|
-
return {
|
|
25
|
-
current: version,
|
|
26
|
-
latest: null,
|
|
27
|
-
needsUpdate: false,
|
|
28
|
-
updateType: UPDATE_TYPES.NONE,
|
|
29
|
-
skipped: true,
|
|
30
|
-
reason: 'version_check disabled in settings'
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
logger.debug('Started version check');
|
|
36
|
-
const response = await axios.get('https://urltoapp.xyz/api/v1/getlastest', {
|
|
37
|
-
timeout: 1000
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const latestVersion = response.data.trim();
|
|
41
|
-
logger.debug(`Version retrieved: ${latestVersion}`);
|
|
42
|
-
|
|
43
|
-
const versionComparison = compareVersions(version, latestVersion);
|
|
44
|
-
const updateType = getUpdateType(version, latestVersion);
|
|
45
|
-
const needsUpdate = versionComparison < 0;
|
|
46
|
-
|
|
47
|
-
if (!silent && needsUpdate) {
|
|
48
|
-
logger.debug(`New update available: ${latestVersion} (${updateType})`);
|
|
49
|
-
console.log('');
|
|
50
|
-
|
|
51
|
-
const updateMessages = {
|
|
52
|
-
[UPDATE_TYPES.SECURITY]: `CRITICAL: Security update (${latestVersion}) available!`,
|
|
53
|
-
[UPDATE_TYPES.CORE]: `IMPORTANT: Core update (${latestVersion}) available!`,
|
|
54
|
-
[UPDATE_TYPES.FEATURE]: `NEW: Feature update (${latestVersion}) available!`
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
if (updateType === UPDATE_TYPES.SECURITY) {
|
|
58
|
-
logger.error(updateMessages[UPDATE_TYPES.SECURITY]); //using .error cuz im lazy to do other variations, sorry ! :)
|
|
59
|
-
} else {
|
|
60
|
-
logger.warn(updateMessages[updateType] || `A new update (${latestVersion}) is available!`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
logger.warn(`Current version: ${version}`);
|
|
64
|
-
logger.warn(`Update u2a with: ${chalk.underline(`npm install -g u2a@${latestVersion}`)}`);
|
|
65
|
-
|
|
66
|
-
if (updateType === UPDATE_TYPES.SECURITY) {
|
|
67
|
-
logger.error('This update fixes SECURITY VULNERABILITIES and should be installed immediately!');
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
current: version,
|
|
73
|
-
latest: latestVersion,
|
|
74
|
-
needsUpdate,
|
|
75
|
-
updateType,
|
|
76
|
-
updateDetails: needsUpdate ? getUpdateDetails(version, latestVersion) : null,
|
|
77
|
-
skipped: false
|
|
78
|
-
};
|
|
79
|
-
} catch (error) {
|
|
80
|
-
logger.debug(`Version check failed: ${error.message}`);
|
|
81
|
-
return {
|
|
82
|
-
current: version,
|
|
83
|
-
latest: null,
|
|
84
|
-
needsUpdate: false,
|
|
85
|
-
updateType: UPDATE_TYPES.NONE,
|
|
86
|
-
error: error.message,
|
|
87
|
-
skipped: false
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function compareVersions(v1, v2) {
|
|
93
|
-
const parts1 = v1.split('.').map(Number);
|
|
94
|
-
const parts2 = v2.split('.').map(Number);
|
|
95
|
-
|
|
96
|
-
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
97
|
-
const part1 = parts1[i] || 0;
|
|
98
|
-
const part2 = parts2[i] || 0;
|
|
99
|
-
|
|
100
|
-
if (part1 < part2) return -1;
|
|
101
|
-
if (part1 > part2) return 1;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return 0;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function getUpdateType(currentVersion, latestVersion) {
|
|
108
|
-
if (currentVersion === latestVersion) {
|
|
109
|
-
return UPDATE_TYPES.NONE;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const current = currentVersion.split('.').map(Number);
|
|
113
|
-
const latest = latestVersion.split('.').map(Number);
|
|
114
|
-
|
|
115
|
-
/*
|
|
116
|
-
a.b.c format where:
|
|
117
|
-
a: security version
|
|
118
|
-
b: core version
|
|
119
|
-
c: feature version
|
|
120
|
-
eg, 3.4.18 -> security version: 3, core version: 4, feature version: 18
|
|
121
|
-
*/
|
|
122
|
-
|
|
123
|
-
if (latest[0] > current[0]) {
|
|
124
|
-
return UPDATE_TYPES.SECURITY;
|
|
125
|
-
} else if (latest[1] > current[1]) {
|
|
126
|
-
return UPDATE_TYPES.CORE;
|
|
127
|
-
} else if (latest[2] > current[2]) {
|
|
128
|
-
return UPDATE_TYPES.FEATURE;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return UPDATE_TYPES.NONE; //current is newer or same
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function getUpdateDetails(currentVersion, latestVersion) {
|
|
135
|
-
const current = currentVersion.split('.').map(Number);
|
|
136
|
-
const latest = latestVersion.split('.').map(Number);
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
securityChanges: latest[0] - current[0],
|
|
140
|
-
coreChanges: latest[1] - current[1],
|
|
141
|
-
featureChanges: latest[2] - current[2],
|
|
142
|
-
fromVersion: currentVersion,
|
|
143
|
-
toVersion: latestVersion
|
|
144
|
-
}; //hard maths up here
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
module.exports = {
|
|
148
|
-
checkVersion,
|
|
149
|
-
UPDATE_TYPES
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const { version } = require('../../package.json');
|
|
3
|
+
const Logger = require('./logger');
|
|
4
|
+
const { getSetting } = require('./settings');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
const logger = new Logger('version-check');
|
|
8
|
+
|
|
9
|
+
// types of updates based on pattern arount lines 90 of this file
|
|
10
|
+
const UPDATE_TYPES = {
|
|
11
|
+
NONE: 'none',
|
|
12
|
+
SECURITY: 'security',
|
|
13
|
+
CORE: 'core',
|
|
14
|
+
FEATURE: 'feature'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function checkVersion(silent = false, forceCheck = false) {
|
|
18
|
+
//check if version check is enabled in settings
|
|
19
|
+
const versionCheckEnabled = getSetting('version_check');
|
|
20
|
+
|
|
21
|
+
//if version check is disabled and not forcing skip the check (btw idk why i made forcecheck)
|
|
22
|
+
if (!versionCheckEnabled && !forceCheck) {
|
|
23
|
+
logger.debug('Version check is disabled in settings');
|
|
24
|
+
return {
|
|
25
|
+
current: version,
|
|
26
|
+
latest: null,
|
|
27
|
+
needsUpdate: false,
|
|
28
|
+
updateType: UPDATE_TYPES.NONE,
|
|
29
|
+
skipped: true,
|
|
30
|
+
reason: 'version_check disabled in settings'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
logger.debug('Started version check');
|
|
36
|
+
const response = await axios.get('https://urltoapp.xyz/api/v1/getlastest', {
|
|
37
|
+
timeout: 1000
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const latestVersion = response.data.trim();
|
|
41
|
+
logger.debug(`Version retrieved: ${latestVersion}`);
|
|
42
|
+
|
|
43
|
+
const versionComparison = compareVersions(version, latestVersion);
|
|
44
|
+
const updateType = getUpdateType(version, latestVersion);
|
|
45
|
+
const needsUpdate = versionComparison < 0;
|
|
46
|
+
|
|
47
|
+
if (!silent && needsUpdate) {
|
|
48
|
+
logger.debug(`New update available: ${latestVersion} (${updateType})`);
|
|
49
|
+
console.log('');
|
|
50
|
+
|
|
51
|
+
const updateMessages = {
|
|
52
|
+
[UPDATE_TYPES.SECURITY]: `CRITICAL: Security update (${latestVersion}) available!`,
|
|
53
|
+
[UPDATE_TYPES.CORE]: `IMPORTANT: Core update (${latestVersion}) available!`,
|
|
54
|
+
[UPDATE_TYPES.FEATURE]: `NEW: Feature update (${latestVersion}) available!`
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (updateType === UPDATE_TYPES.SECURITY) {
|
|
58
|
+
logger.error(updateMessages[UPDATE_TYPES.SECURITY]); //using .error cuz im lazy to do other variations, sorry ! :)
|
|
59
|
+
} else {
|
|
60
|
+
logger.warn(updateMessages[updateType] || `A new update (${latestVersion}) is available!`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
logger.warn(`Current version: ${version}`);
|
|
64
|
+
logger.warn(`Update u2a with: ${chalk.underline(`npm install -g u2a@${latestVersion}`)}`);
|
|
65
|
+
|
|
66
|
+
if (updateType === UPDATE_TYPES.SECURITY) {
|
|
67
|
+
logger.error('This update fixes SECURITY VULNERABILITIES and should be installed immediately!');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
current: version,
|
|
73
|
+
latest: latestVersion,
|
|
74
|
+
needsUpdate,
|
|
75
|
+
updateType,
|
|
76
|
+
updateDetails: needsUpdate ? getUpdateDetails(version, latestVersion) : null,
|
|
77
|
+
skipped: false
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
logger.debug(`Version check failed: ${error.message}`);
|
|
81
|
+
return {
|
|
82
|
+
current: version,
|
|
83
|
+
latest: null,
|
|
84
|
+
needsUpdate: false,
|
|
85
|
+
updateType: UPDATE_TYPES.NONE,
|
|
86
|
+
error: error.message,
|
|
87
|
+
skipped: false
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function compareVersions(v1, v2) {
|
|
93
|
+
const parts1 = v1.split('.').map(Number);
|
|
94
|
+
const parts2 = v2.split('.').map(Number);
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
97
|
+
const part1 = parts1[i] || 0;
|
|
98
|
+
const part2 = parts2[i] || 0;
|
|
99
|
+
|
|
100
|
+
if (part1 < part2) return -1;
|
|
101
|
+
if (part1 > part2) return 1;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getUpdateType(currentVersion, latestVersion) {
|
|
108
|
+
if (currentVersion === latestVersion) {
|
|
109
|
+
return UPDATE_TYPES.NONE;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const current = currentVersion.split('.').map(Number);
|
|
113
|
+
const latest = latestVersion.split('.').map(Number);
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
a.b.c format where:
|
|
117
|
+
a: security version
|
|
118
|
+
b: core version
|
|
119
|
+
c: feature version
|
|
120
|
+
eg, 3.4.18 -> security version: 3, core version: 4, feature version: 18
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
if (latest[0] > current[0]) {
|
|
124
|
+
return UPDATE_TYPES.SECURITY;
|
|
125
|
+
} else if (latest[1] > current[1]) {
|
|
126
|
+
return UPDATE_TYPES.CORE;
|
|
127
|
+
} else if (latest[2] > current[2]) {
|
|
128
|
+
return UPDATE_TYPES.FEATURE;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return UPDATE_TYPES.NONE; //current is newer or same
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getUpdateDetails(currentVersion, latestVersion) {
|
|
135
|
+
const current = currentVersion.split('.').map(Number);
|
|
136
|
+
const latest = latestVersion.split('.').map(Number);
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
securityChanges: latest[0] - current[0],
|
|
140
|
+
coreChanges: latest[1] - current[1],
|
|
141
|
+
featureChanges: latest[2] - current[2],
|
|
142
|
+
fromVersion: currentVersion,
|
|
143
|
+
toVersion: latestVersion
|
|
144
|
+
}; //hard maths up here
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = {
|
|
148
|
+
checkVersion,
|
|
149
|
+
UPDATE_TYPES
|
|
150
150
|
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
name: Node.js Package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
paths:
|
|
6
|
-
- 'package.json'
|
|
7
|
-
branches:
|
|
8
|
-
- main
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
|
|
12
|
-
publish-npm:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v4
|
|
16
|
-
- uses: actions/setup-node@v4
|
|
17
|
-
with:
|
|
18
|
-
node-version: 20
|
|
19
|
-
registry-url: https://registry.npmjs.org/
|
|
20
|
-
- run: npm publish
|
|
21
|
-
env:
|
|
22
|
-
NODE_AUTH_TOKEN: ${{ secrets.npm_token }}
|