u2a 3.4.19 → 3.5.0

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/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "u2a",
3
- "version": "3.4.19",
3
+ "version": "3.5.0",
4
4
  "description": "URL to App - Turn any URL into a desktop application",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "u2a": "src/index.js"
8
8
  },
9
9
  "scripts": {
10
- "start": "node src/index.js"
10
+ "start": "node src/index.js",
11
+ "postinstall": "node src/utils/postinstall.js"
11
12
  },
12
13
  "keywords": [
13
14
  "cli",
@@ -0,0 +1,63 @@
1
+ const fs = require('fs');
2
+ const { SETTINGS_PATH } = require('../utils/config');
3
+ const Logger = require('../utils/logger');
4
+ const chalk = require('chalk');
5
+
6
+ const logger = new Logger('configure');
7
+
8
+ function configureReports(action) {
9
+ try {
10
+ let settings = {};
11
+ if (fs.existsSync(SETTINGS_PATH)) {
12
+ settings = JSON.parse(fs.readFileSync(SETTINGS_PATH, 'utf8'));
13
+ }
14
+
15
+ if (action === 'status') {
16
+ const status = settings.send_anon_reports !== false;
17
+ logger.info(`Anonymous reports are currently ${status ? chalk.green('enabled') : chalk.yellow('disabled')}`);
18
+ return;
19
+ } else if (action === 'enable') {
20
+ settings.send_anon_reports = true;
21
+ logger.info(chalk.green('Anonymous reports have been enabled'));
22
+ } else if (action === 'disable') {
23
+ settings.send_anon_reports = false;
24
+ logger.info(chalk.yellow('Anonymous reports have been disabled'));
25
+ } else {
26
+ logger.error(`Invalid action: ${action}`);
27
+ logger.info('Available actions: status, enable, disable');
28
+ return;
29
+ }
30
+
31
+ fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
32
+ } catch (err) {
33
+ logger.error(`Error configuring reports`, err.message);
34
+ }
35
+ }
36
+
37
+ function configure(category, action) {
38
+ if (!category || !action) {
39
+ logger.error('Missing category or action');
40
+ logger.info('Usage: u2a configure [category] [action]');
41
+ logger.info('Available categories:');
42
+ logger.info(' reports - Configure anonymous usage reports');
43
+ logger.info('Available actions:');
44
+ logger.info(' status - Check current status');
45
+ logger.info(' enable - Enable specified category');
46
+ logger.info(' disable - Disable specified category');
47
+ return;
48
+ }
49
+
50
+ switch (category) {
51
+ case 'reports':
52
+ configureReports(action);
53
+ break;
54
+ default:
55
+ logger.error(`Unknown configuration category: ${category}`);
56
+ logger.info('Available categories: reports');
57
+ break;
58
+ }
59
+ }
60
+
61
+ module.exports = {
62
+ configure
63
+ };
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ const { program } = require('commander');
11
11
  const { createApp } = require('./commands/create');
12
12
  const { listApps } = require('./commands/list');
13
13
  const { removeApp } = require('./commands/remove');
14
+ const { configure } = require('./commands/configure');
14
15
  const { version } = require('../package.json');
15
16
  const { setupConfig } = require('./utils/config');
16
17
  const { checkNotRoot } = require('./utils/noroot');
@@ -50,6 +51,13 @@ setupConfig();
50
51
  .description('Remove an existing application')
51
52
  .action(removeApp);
52
53
 
54
+ program
55
+ .command('configure [category] [action]')
56
+ .description('Configure application settings')
57
+ .action((category, action) => {
58
+ configure(category, action);
59
+ });
60
+
53
61
  program.on('command:*', () => {
54
62
  console.error(`\nInvalid command: ${program.args.join(' ')}`);
55
63
  console.log(`\nUse --help to see the list of available commands.`);
@@ -254,7 +254,7 @@ app.on('activate', () => {
254
254
  }
255
255
  });
256
256
  `;
257
- }
257
+ } // note for one day: put this in a different file
258
258
 
259
259
  async function createPackageJson(appName, iconPath, isExecutable = false, createSetup = false) {
260
260
  const u2aPackagePath = path.resolve(__dirname, '../../package.json');
@@ -114,7 +114,8 @@ async function buildSetup(appDir, platform, arch) {
114
114
  return null;
115
115
  }
116
116
  } catch (error) {
117
- logger.error(`Error while building setup:`, error);
117
+ logger.error(`Error while building setup.`, error);
118
+ logger.warn('Try to run u2a with administrator privileges to avoid this error.');
118
119
  return null;
119
120
  }
120
121
  }
@@ -6,6 +6,7 @@ const CONFIG_DIR = path.join(os.homedir(), '.u2a');
6
6
  const APPS_DIR = path.join(CONFIG_DIR, 'apps');
7
7
  const LOGS_DIR = path.join(CONFIG_DIR, 'logs');
8
8
  const DB_PATH = path.join(CONFIG_DIR, 'db.json');
9
+ const SETTINGS_PATH = path.join(CONFIG_DIR, 'settings.json');
9
10
 
10
11
  function setupConfig() {
11
12
  if (!fs.existsSync(CONFIG_DIR)) {
@@ -20,6 +21,9 @@ function setupConfig() {
20
21
  if (!fs.existsSync(DB_PATH)) {
21
22
  fs.writeFileSync(DB_PATH, JSON.stringify({}, null, 2));
22
23
  }
24
+ if (!fs.existsSync(SETTINGS_PATH)) {
25
+ fs.writeFileSync(SETTINGS_PATH, JSON.stringify({}, null, 2));
26
+ }
23
27
  }
24
28
 
25
29
  function readDB() {
@@ -41,6 +45,8 @@ module.exports = {
41
45
  CONFIG_DIR,
42
46
  APPS_DIR,
43
47
  LOGS_DIR,
48
+ DB_PATH,
49
+ SETTINGS_PATH,
44
50
  setupConfig,
45
51
  readDB,
46
52
  writeDB,
@@ -3,6 +3,18 @@ const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const { LOGS_DIR } = require('./config');
5
5
 
6
+ /*
7
+ To use:
8
+ const Logger = require('./logger');
9
+ const logger = new Logger('name');
10
+
11
+ //then
12
+ logger.info('information');
13
+ logger.warn('warning');
14
+ logger.error('error message', 'error');
15
+ */
16
+
17
+
6
18
  class Logger {
7
19
  constructor(component) {
8
20
  this.component = component;
@@ -24,7 +36,7 @@ class Logger {
24
36
 
25
37
  info(message) {
26
38
  const formattedMessage = this._format('INFO', message);
27
- console.log(chalk.blue(formattedMessage));
39
+ console.log(chalk.blueBright(formattedMessage));
28
40
  this._writeToFile(formattedMessage);
29
41
  }
30
42
 
@@ -6,7 +6,7 @@ const logger = new Logger('noroot');
6
6
 
7
7
  async function checkNotRoot(allowRoot = false) {
8
8
  if (allowRoot) {
9
- logger.warn('Running with elevated privileges. This is not recommended.', '');
9
+ logger.warn('Running with elevated privileges. This is not recommended.');
10
10
  return;
11
11
  }
12
12
 
@@ -15,7 +15,9 @@ async function checkNotRoot(allowRoot = false) {
15
15
  switch (platform) {
16
16
  case 'win32':
17
17
  if (await isAdmin()) {
18
- logger.error('This application should not be run as an administrator.', '');
18
+ logger.error('This application should not be run as an administrator.');
19
+ logger.warn('Run with --allowroot to avoid this message.');
20
+ logger.warn('Running u2a as administrator can be dangerous.');
19
21
  process.exit(1);
20
22
  }
21
23
  break;
@@ -23,7 +25,9 @@ async function checkNotRoot(allowRoot = false) {
23
25
  case 'darwin':
24
26
  case 'linux':
25
27
  if (process.getuid() === 0) {
26
- logger.error('This application should not be run as root.', '');
28
+ logger.error('This application should not be run as root.');
29
+ logger.warn('Run with --allowroot to avoid this message.');
30
+ logger.warn('Running u2a as root can be dangerous.');
27
31
  process.exit(1);
28
32
  }
29
33
  break;
@@ -0,0 +1,126 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const axios = require('axios');
4
+ const Logger = require('./logger');
5
+ const { setupConfig, CONFIG_DIR, SETTINGS_PATH } = require('./config');
6
+
7
+ setupConfig(); // builds ~/.u2a/*
8
+
9
+ const logger = new Logger('postinstall');
10
+ const postinstallJsonPath = path.join(CONFIG_DIR, 'postinstall.json');
11
+ let isUpgrade = false;
12
+ let currentVersion = '0.0.0'; //0.0.0 for new installations
13
+ let sendAnonReports = true; // u2a configure reports disable to disable
14
+
15
+ const formatVersionLine = (label, version) => {
16
+ // calculates how many spaces we need after the version to have a correct formatting
17
+ const baseLength = `; ${label}: `.length + version.length;
18
+ const spaceCount = Math.max(0, 30 - baseLength);
19
+ const spaces = ' '.repeat(spaceCount);
20
+
21
+ return `; ${label}: ${version}${spaces};`;
22
+ };
23
+
24
+ async function run() {
25
+ //check if postinstall.json exists (exists -> update, doesnt -> new install)
26
+ if (fs.existsSync(postinstallJsonPath)) {
27
+ try {
28
+ const postinstallData = JSON.parse(fs.readFileSync(postinstallJsonPath, 'utf8'));
29
+ currentVersion = postinstallData.version || '';
30
+ isUpgrade = true;
31
+
32
+ let newVersion = '';
33
+ try {
34
+ const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
35
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
36
+ newVersion = packageJson.version || '';
37
+ } catch (err) {
38
+ logger.error(`Error reading package.json for display`, err.message);
39
+ newVersion = 'unknown';
40
+ }
41
+
42
+ logger.info(';=============================;');
43
+ logger.info('; u2a has been updated! ;');
44
+ logger.info('; Successfully migrated from ;');
45
+ logger.info(formatVersionLine('Old version', currentVersion));
46
+ logger.info(formatVersionLine('New version', newVersion));
47
+ logger.info(';=============================;');
48
+ } catch (err) {
49
+ logger.error(`Error reading postinstall.json`, err.message);
50
+ isUpgrade = false;
51
+ }
52
+ }
53
+
54
+ if (fs.existsSync(SETTINGS_PATH)) {
55
+ try {
56
+ const settingsData = JSON.parse(fs.readFileSync(SETTINGS_PATH, 'utf8'));
57
+ sendAnonReports = settingsData.send_anon_reports !== false;
58
+ } catch (err) {
59
+ logger.error(`Error reading settings.json`, err.message);
60
+ sendAnonReports = true;
61
+ }
62
+ }
63
+
64
+ // shows this cool message if it isnt an upgrade
65
+ if (!isUpgrade) {
66
+ logger.info(';=============================;');
67
+ logger.info('; Welcome to u2a ! ;');
68
+ logger.info('; Thanks for downloading this ;');
69
+ logger.info('; tool ! ;');
70
+ logger.info('; ;');
71
+ logger.info('; Create a local webapp with ;');
72
+ logger.info('; \'u2a create <url/domain>\' ;');
73
+ logger.info('; ;');
74
+ logger.info('; Check docs.urltoapp.xyz for ;');
75
+ logger.info('; more detailed usage. ;');
76
+ logger.info('; ;');
77
+ logger.info('; Note: Anonymous installs ;');
78
+ logger.info('; reports are enabled by ;');
79
+ logger.info('; default. To disable: ;');
80
+ logger.info('; \'u2a configure reports ;');
81
+ logger.info('; disable\' ;');
82
+ logger.info(';=============================;');
83
+
84
+ const settings = { send_anon_reports: true };
85
+ fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
86
+ }
87
+
88
+ const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
89
+ let newVersion = '';
90
+
91
+ try {
92
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
93
+ newVersion = packageJson.version || '';
94
+ } catch (err) {
95
+ logger.error(`Error reading package.json`, err.message);
96
+ }
97
+
98
+ if (sendAnonReports) {
99
+ try {
100
+
101
+ const params = new URLSearchParams({
102
+ previousVersion: currentVersion,
103
+ newVersion: newVersion
104
+ });
105
+
106
+ // backend here https://github.com/url2app/urltoapp.xyz/blob/main/api/v1/api/reports.php
107
+ await axios.get(`https://urltoapp.xyz/api/v1/reports?${params.toString()}`);
108
+ logger.debug('Anonymous usage report sent');
109
+ } catch (err) {
110
+ logger.debug(`Failed to send anonymous report: ${err.message}`);
111
+ }
112
+ }
113
+
114
+ try {
115
+ fs.writeFileSync(postinstallJsonPath, JSON.stringify({
116
+ version: newVersion,
117
+ installed_at: new Date().toISOString()
118
+ }, null, 2));
119
+ } catch (err) {
120
+ logger.error(`Error updating postinstall.json`, err.message);
121
+ }
122
+ }
123
+
124
+ run().catch(err => {
125
+ logger.error(`Unexpected error`, err.message);
126
+ });