u2a 3.4.20 → 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.20",
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.`);
@@ -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;
@@ -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
+ });