u2a 2.1.5 → 2.1.8
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 +12 -15
- package/package.json +1 -1
- package/src/commands/create.js +65 -66
- package/src/commands/remove.js +12 -13
- package/src/index.js +7 -2
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<a href="#" style="display: block; text-align: center;">
|
|
3
|
-
<img
|
|
4
|
-
alt="Image of this repo"
|
|
5
|
-
src="https://togp.xyz?owner=douxxtech&repo=urltoapp&theme=json-dark-all&cache=false"
|
|
6
|
-
type="image/svg+xml"
|
|
7
|
-
style="border-radius: 20px; overflow: hidden;"
|
|
3
|
+
<img
|
|
4
|
+
alt="Image of this repo"
|
|
5
|
+
src="https://togp.xyz?owner=douxxtech&repo=urltoapp&theme=json-dark-all&cache=false"
|
|
6
|
+
type="image/svg+xml"
|
|
7
|
+
style="border-radius: 20px; overflow: hidden;"
|
|
8
8
|
/>
|
|
9
9
|
<h1 align="center">U2A (URL to App)</h1>
|
|
10
10
|
</a>
|
|
@@ -25,6 +25,7 @@ U2A is a command-line utility that allows you to transform any web URL into a st
|
|
|
25
25
|
- 🔄 Automatic favicon retrieval for app icons
|
|
26
26
|
- 📋 Easy management of created applications
|
|
27
27
|
- 📊 Detailed logging for troubleshooting
|
|
28
|
+
- 🏷️ Customizable application names and window sizes
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
@@ -39,17 +40,17 @@ npm install -g u2a
|
|
|
39
40
|
To create a desktop application from a website:
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
|
-
u2a create <url>
|
|
43
|
+
u2a create <url> [--name <appName>] [--width <width>] [--height <height>]
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
Example:
|
|
46
47
|
```bash
|
|
47
|
-
u2a create github.com
|
|
48
|
+
u2a create github.com --name "GitHub App" --width 1200 --height 800
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
This will:
|
|
51
52
|
1. Download the website's favicon (if available)
|
|
52
|
-
2. Create an Electron wrapper application
|
|
53
|
+
2. Create an Electron wrapper application with the specified name and window size
|
|
53
54
|
3. Add the application to your system menu/launcher
|
|
54
55
|
4. Track the application in the U2A database
|
|
55
56
|
|
|
@@ -62,7 +63,7 @@ u2a list
|
|
|
62
63
|
```
|
|
63
64
|
|
|
64
65
|
This will display a list of all created applications with their details:
|
|
65
|
-
-
|
|
66
|
+
- Application name
|
|
66
67
|
- Original URL
|
|
67
68
|
- Creation date
|
|
68
69
|
- Application directory
|
|
@@ -72,12 +73,12 @@ This will display a list of all created applications with their details:
|
|
|
72
73
|
To remove an application:
|
|
73
74
|
|
|
74
75
|
```bash
|
|
75
|
-
u2a remove <
|
|
76
|
+
u2a remove <appName>
|
|
76
77
|
```
|
|
77
78
|
|
|
78
79
|
Example:
|
|
79
80
|
```bash
|
|
80
|
-
u2a remove
|
|
81
|
+
u2a remove "GitHub App"
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
This will:
|
|
@@ -127,7 +128,3 @@ This project is licensed under the GNU General Public License v3.0 - see the [LI
|
|
|
127
128
|
## Author
|
|
128
129
|
|
|
129
130
|
Created by [Douxx](https://douxx.tech)
|
|
130
|
-
|
|
131
|
-
## Disclaimer
|
|
132
|
-
|
|
133
|
-
This tool is for personal use only. Always respect the terms of service of websites you convert to desktop apps.
|
package/package.json
CHANGED
package/src/commands/create.js
CHANGED
|
@@ -11,14 +11,14 @@ const logger = new Logger('create');
|
|
|
11
11
|
|
|
12
12
|
function createWindowsShortcut(appInfo) {
|
|
13
13
|
try {
|
|
14
|
-
const {
|
|
14
|
+
const { appName, appDir, iconPath } = appInfo;
|
|
15
15
|
const startMenuPath = path.join(process.env.APPDATA, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'U2A Apps');
|
|
16
16
|
|
|
17
17
|
if (!fs.existsSync(startMenuPath)) {
|
|
18
18
|
fs.mkdirSync(startMenuPath, { recursive: true });
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const shortcutPath = path.join(startMenuPath, `${
|
|
21
|
+
const shortcutPath = path.join(startMenuPath, `${appName}.lnk`);
|
|
22
22
|
const targetPath = path.join(appDir, 'node_modules', '.bin', 'electron.cmd');
|
|
23
23
|
const workingDir = appDir;
|
|
24
24
|
|
|
@@ -29,11 +29,11 @@ function createWindowsShortcut(appInfo) {
|
|
|
29
29
|
$Shortcut.Arguments = "."
|
|
30
30
|
$Shortcut.WorkingDirectory = "${workingDir.replace(/\\/g, '\\\\')}"
|
|
31
31
|
$Shortcut.IconLocation = "${iconPath.replace(/\\/g, '\\\\')}"
|
|
32
|
-
$Shortcut.Description = "Application Web pour ${
|
|
32
|
+
$Shortcut.Description = "Application Web pour ${appName}"
|
|
33
33
|
$Shortcut.Save()
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
|
-
const tempScriptPath = path.join(os.tmpdir(), `create_shortcut_${
|
|
36
|
+
const tempScriptPath = path.join(os.tmpdir(), `create_shortcut_${appName}.ps1`);
|
|
37
37
|
fs.writeFileSync(tempScriptPath, psScript);
|
|
38
38
|
|
|
39
39
|
execSync(`powershell -ExecutionPolicy Bypass -File "${tempScriptPath}"`, {
|
|
@@ -51,10 +51,9 @@ function createWindowsShortcut(appInfo) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
|
|
55
54
|
function createLinuxDesktopEntry(appInfo) {
|
|
56
55
|
try {
|
|
57
|
-
const {
|
|
56
|
+
const { appName, url, appDir, iconPath } = appInfo;
|
|
58
57
|
const appsDir = path.join(os.homedir(), '.local', 'share', 'applications');
|
|
59
58
|
|
|
60
59
|
if (!fs.existsSync(appsDir)) {
|
|
@@ -63,7 +62,7 @@ function createLinuxDesktopEntry(appInfo) {
|
|
|
63
62
|
|
|
64
63
|
const desktopEntry = `[Desktop Entry]
|
|
65
64
|
Type=Application
|
|
66
|
-
Name=${
|
|
65
|
+
Name=${appName}
|
|
67
66
|
Exec=${path.join(appDir, 'node_modules', '.bin', 'electron')} ${path.join(appDir, 'main.js')}
|
|
68
67
|
Icon=${iconPath}
|
|
69
68
|
Comment=Application Web pour ${url}
|
|
@@ -71,7 +70,7 @@ Categories=Network;WebBrowser;
|
|
|
71
70
|
Terminal=false
|
|
72
71
|
`;
|
|
73
72
|
|
|
74
|
-
const desktopFilePath = path.join(appsDir, `u2a-${
|
|
73
|
+
const desktopFilePath = path.join(appsDir, `u2a-${appName}.desktop`);
|
|
75
74
|
fs.writeFileSync(desktopFilePath, desktopEntry);
|
|
76
75
|
|
|
77
76
|
fs.chmodSync(desktopFilePath, '755');
|
|
@@ -86,15 +85,14 @@ Terminal=false
|
|
|
86
85
|
|
|
87
86
|
function createMacOSApp(appInfo) {
|
|
88
87
|
try {
|
|
89
|
-
const {
|
|
88
|
+
const { appName, appDir, iconPath } = appInfo;
|
|
90
89
|
const appsDir = path.join(os.homedir(), 'Applications', 'U2A Apps');
|
|
91
90
|
|
|
92
91
|
if (!fs.existsSync(appsDir)) {
|
|
93
92
|
fs.mkdirSync(appsDir, { recursive: true });
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
const
|
|
97
|
-
const appPath = path.join(appsDir, appName);
|
|
95
|
+
const appPath = path.join(appsDir, `${appName}.app`);
|
|
98
96
|
const macOsPath = path.join(appPath, 'Contents', 'MacOS');
|
|
99
97
|
const resourcesPath = path.join(appPath, 'Contents', 'Resources');
|
|
100
98
|
|
|
@@ -110,11 +108,11 @@ function createMacOSApp(appInfo) {
|
|
|
110
108
|
<key>CFBundleIconFile</key>
|
|
111
109
|
<string>icon.icns</string>
|
|
112
110
|
<key>CFBundleIdentifier</key>
|
|
113
|
-
<string>com.u2a.${
|
|
111
|
+
<string>com.u2a.${appName.replace(/\s+/g, '-')}</string>
|
|
114
112
|
<key>CFBundleName</key>
|
|
115
|
-
<string>${
|
|
113
|
+
<string>${appName}</string>
|
|
116
114
|
<key>CFBundleDisplayName</key>
|
|
117
|
-
<string>${
|
|
115
|
+
<string>${appName}</string>
|
|
118
116
|
<key>CFBundlePackageType</key>
|
|
119
117
|
<string>APPL</string>
|
|
120
118
|
<key>CFBundleVersion</key>
|
|
@@ -144,8 +142,8 @@ cd "${appDir}"
|
|
|
144
142
|
}
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
function addAppToOS(
|
|
148
|
-
const appInfo = {
|
|
145
|
+
function addAppToOS(appName, url, appDir, iconPath) {
|
|
146
|
+
const appInfo = { appName, url, appDir, iconPath };
|
|
149
147
|
let desktopPath = null;
|
|
150
148
|
|
|
151
149
|
if (process.platform === 'win32') {
|
|
@@ -161,43 +159,46 @@ function addAppToOS(domain, url, appDir, iconPath) {
|
|
|
161
159
|
return desktopPath;
|
|
162
160
|
}
|
|
163
161
|
|
|
164
|
-
function removeAppFromOS(
|
|
162
|
+
function removeAppFromOS(appName) {
|
|
165
163
|
try {
|
|
166
164
|
if (process.platform === 'win32') {
|
|
167
|
-
const startMenuPath = path.join(process.env.APPDATA, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'U2A Apps', `${
|
|
165
|
+
const startMenuPath = path.join(process.env.APPDATA, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'U2A Apps', `${appName}.lnk`);
|
|
168
166
|
if (fs.existsSync(startMenuPath)) {
|
|
169
167
|
fs.unlinkSync(startMenuPath);
|
|
170
168
|
logger.success(`Shortcut removed from the Start Menu: ${startMenuPath}`);
|
|
171
169
|
}
|
|
172
170
|
} else if (process.platform === 'darwin') {
|
|
173
|
-
const appPath = path.join(os.homedir(), 'Applications', 'U2A Apps', `${
|
|
171
|
+
const appPath = path.join(os.homedir(), 'Applications', 'U2A Apps', `${appName}.app`);
|
|
174
172
|
if (fs.existsSync(appPath)) {
|
|
175
173
|
fs.rmSync(appPath, { recursive: true, force: true });
|
|
176
174
|
logger.success(`macOS application removed: ${appPath}`);
|
|
177
175
|
}
|
|
178
176
|
} else if (process.platform === 'linux') {
|
|
179
|
-
const desktopFilePath = path.join(os.homedir(), '.local', 'share', 'applications', `u2a-${
|
|
177
|
+
const desktopFilePath = path.join(os.homedir(), '.local', 'share', 'applications', `u2a-${appName}.desktop`);
|
|
180
178
|
if (fs.existsSync(desktopFilePath)) {
|
|
181
179
|
fs.unlinkSync(desktopFilePath);
|
|
182
|
-
logger.success(`Linux desktop entry removed: ${desktopFilePath}
|
|
183
|
-
|
|
184
|
-
`);
|
|
180
|
+
logger.success(`Linux desktop entry removed: ${desktopFilePath}`);
|
|
185
181
|
}
|
|
186
182
|
}
|
|
187
183
|
} catch (error) {
|
|
188
|
-
logger.error(`Error while removing desktop integration for ${
|
|
184
|
+
logger.error(`Error while removing desktop integration for ${appName}`, error);
|
|
189
185
|
}
|
|
190
186
|
}
|
|
191
187
|
|
|
192
|
-
function generateMainJs(
|
|
188
|
+
function generateMainJs(appName, url, iconPath, options = {}) {
|
|
189
|
+
const width = options.width || 1200;
|
|
190
|
+
const height = options.height || 800;
|
|
191
|
+
|
|
193
192
|
return `
|
|
194
193
|
const { app, BrowserWindow, Menu, shell } = require('electron');
|
|
195
194
|
const path = require('path');
|
|
196
195
|
const fs = require('fs');
|
|
197
196
|
|
|
198
|
-
const
|
|
197
|
+
const APP_NAME = "${appName}";
|
|
199
198
|
const APP_URL = "${url}";
|
|
200
199
|
const APP_ICON_PATH = "${iconPath.replace(/\\/g, '\\\\')}";
|
|
200
|
+
const WINDOW_WIDTH = ${width};
|
|
201
|
+
const WINDOW_HEIGHT = ${height};
|
|
201
202
|
|
|
202
203
|
let mainWindow;
|
|
203
204
|
let splashWindow;
|
|
@@ -217,7 +218,7 @@ function logAppInfo() {
|
|
|
217
218
|
console.log('\\n--------------------------------');
|
|
218
219
|
console.log(' APPLICATION INFORMATION');
|
|
219
220
|
console.log('--------------------------------');
|
|
220
|
-
console.log(\`Application: \${
|
|
221
|
+
console.log(\`Application: \${APP_NAME}\`);
|
|
221
222
|
console.log(\`URL: \${APP_URL}\`);
|
|
222
223
|
console.log(\`Started at: \${new Date().toLocaleString()}\`);
|
|
223
224
|
console.log(\`App directory: \${__dirname}\`);
|
|
@@ -240,17 +241,14 @@ function logAppInfo() {
|
|
|
240
241
|
|
|
241
242
|
function updateSplashScreen(message, isError = false) {
|
|
242
243
|
if (splashWindow && !splashWindow.isDestroyed()) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
: ''}
|
|
252
|
-
\`;
|
|
253
|
-
splashWindow.webContents.executeJavaScript(script).catch(err => console.error('Failed to update splash screen:', err));
|
|
244
|
+
splashWindow.webContents.executeJavaScript(\`
|
|
245
|
+
try {
|
|
246
|
+
document.getElementById('loading-text').innerText = "\${message.replace(/"/g, '\\"')}";
|
|
247
|
+
} catch (e) {
|
|
248
|
+
console.error('Failed to update splash screen:', e);
|
|
249
|
+
}
|
|
250
|
+
\`).catch(err => console.error('Failed to update splash screen:', err));
|
|
251
|
+
|
|
254
252
|
}
|
|
255
253
|
}
|
|
256
254
|
|
|
@@ -273,6 +271,7 @@ function createSplashScreen() {
|
|
|
273
271
|
<html>
|
|
274
272
|
<head>
|
|
275
273
|
<meta charset="UTF-8">
|
|
274
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'none';">
|
|
276
275
|
<title>Loading...</title>
|
|
277
276
|
<style>
|
|
278
277
|
body {
|
|
@@ -395,7 +394,7 @@ function createSplashScreen() {
|
|
|
395
394
|
</head>
|
|
396
395
|
<body>
|
|
397
396
|
<div class="container">
|
|
398
|
-
<div class="domain">\${
|
|
397
|
+
<div class="domain">\${APP_NAME}</div>
|
|
399
398
|
<div class="spinner"></div>
|
|
400
399
|
<div id="loading-text" class="loading-text">Loading...</div>
|
|
401
400
|
<div class="progress-bar">
|
|
@@ -418,7 +417,7 @@ function createSplashScreen() {
|
|
|
418
417
|
</html>
|
|
419
418
|
\`;
|
|
420
419
|
|
|
421
|
-
const splashPath = path.join(app.getPath('temp'), \`\${
|
|
420
|
+
const splashPath = path.join(app.getPath('temp'), \`\${APP_NAME}-splash.html\`);
|
|
422
421
|
fs.writeFileSync(splashPath, splashHtml);
|
|
423
422
|
|
|
424
423
|
splashWindow.loadFile(splashPath);
|
|
@@ -428,12 +427,12 @@ function createSplashScreen() {
|
|
|
428
427
|
function createWindow() {
|
|
429
428
|
logAppInfo();
|
|
430
429
|
|
|
431
|
-
app.setAppUserModelId(
|
|
430
|
+
app.setAppUserModelId(APP_NAME);
|
|
432
431
|
|
|
433
432
|
mainWindow = new BrowserWindow({
|
|
434
|
-
width:
|
|
435
|
-
height:
|
|
436
|
-
title:
|
|
433
|
+
width: WINDOW_WIDTH,
|
|
434
|
+
height: WINDOW_HEIGHT,
|
|
435
|
+
title: APP_NAME,
|
|
437
436
|
icon: APP_ICON_PATH,
|
|
438
437
|
show: false,
|
|
439
438
|
webPreferences: {
|
|
@@ -444,7 +443,6 @@ function createWindow() {
|
|
|
444
443
|
|
|
445
444
|
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
|
|
446
445
|
const errorMessage = \`Load error (\${errorCode}): \${errorDescription}\`;
|
|
447
|
-
console.error(errorMessage);
|
|
448
446
|
loadErrors.push(errorMessage);
|
|
449
447
|
|
|
450
448
|
updateSplashScreen(errorMessage, true);
|
|
@@ -469,7 +467,6 @@ function createWindow() {
|
|
|
469
467
|
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
|
|
470
468
|
if (level === 2) {
|
|
471
469
|
const errorMessage = \`Console: \${message} (line \${line})\`;
|
|
472
|
-
console.error(errorMessage);
|
|
473
470
|
loadErrors.push(errorMessage);
|
|
474
471
|
|
|
475
472
|
updateSplashScreen('JavaScript error detected', true);
|
|
@@ -477,7 +474,7 @@ function createWindow() {
|
|
|
477
474
|
});
|
|
478
475
|
|
|
479
476
|
mainWindow.webContents.on('did-start-loading', () => {
|
|
480
|
-
updateSplashScreen('Connecting to ' +
|
|
477
|
+
updateSplashScreen('Connecting to ' + APP_NAME + '...');
|
|
481
478
|
});
|
|
482
479
|
|
|
483
480
|
mainWindow.webContents.on('did-start-navigation', (event, url) => {
|
|
@@ -560,11 +557,9 @@ app.on('activate', () => {
|
|
|
560
557
|
`;
|
|
561
558
|
}
|
|
562
559
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
function generatePackageJson(domain, iconPath) {
|
|
560
|
+
function generatePackageJson(appName, iconPath) {
|
|
566
561
|
const u2aPackagePath = path.resolve(__dirname, '../../package.json');
|
|
567
|
-
|
|
562
|
+
|
|
568
563
|
let u2aVersion = '1.0.0';
|
|
569
564
|
try {
|
|
570
565
|
const u2aPackageContent = fs.readFileSync(u2aPackagePath, 'utf8');
|
|
@@ -573,11 +568,11 @@ function generatePackageJson(domain, iconPath) {
|
|
|
573
568
|
} catch (error) {
|
|
574
569
|
logger.error('Error while fetching u2a package.json', error)
|
|
575
570
|
}
|
|
576
|
-
|
|
571
|
+
|
|
577
572
|
return {
|
|
578
|
-
name: `u2a-${
|
|
573
|
+
name: `u2a-${appName.replace(/\s+/g, '-')}`,
|
|
579
574
|
version: u2aVersion,
|
|
580
|
-
description: `Web app for ${
|
|
575
|
+
description: `Web app for ${appName}`,
|
|
581
576
|
main: 'main.js',
|
|
582
577
|
scripts: {
|
|
583
578
|
start: 'electron .'
|
|
@@ -586,45 +581,46 @@ function generatePackageJson(domain, iconPath) {
|
|
|
586
581
|
electron: '^22.0.0'
|
|
587
582
|
},
|
|
588
583
|
build: {
|
|
589
|
-
appId: `com.u2a.${
|
|
590
|
-
productName:
|
|
584
|
+
appId: `com.u2a.${appName.replace(/\s+/g, '-')}`,
|
|
585
|
+
productName: appName,
|
|
591
586
|
icon: iconPath
|
|
592
587
|
}
|
|
593
588
|
};
|
|
594
589
|
}
|
|
595
590
|
|
|
596
|
-
async function createApp(url) {
|
|
591
|
+
async function createApp(url, options) {
|
|
597
592
|
logger.info(`Creating application for ${url}`);
|
|
598
593
|
|
|
599
594
|
try {
|
|
600
595
|
url = await normalizeUrl(url);
|
|
601
596
|
const domain = getDomainName(url);
|
|
597
|
+
const appName = options.name || domain;
|
|
602
598
|
|
|
603
599
|
const db = readDB();
|
|
604
|
-
if (db.hasOwnProperty(
|
|
605
|
-
logger.warn(`Application for ${
|
|
600
|
+
if (db.hasOwnProperty(appName)) {
|
|
601
|
+
logger.warn(`Application for ${appName} already exists`);
|
|
606
602
|
return;
|
|
607
603
|
}
|
|
608
604
|
|
|
609
605
|
const iconPath = await getFavicon(url);
|
|
610
606
|
|
|
611
|
-
const appDir = path.join(APPS_DIR,
|
|
607
|
+
const appDir = path.join(APPS_DIR, appName);
|
|
612
608
|
if (!fs.existsSync(appDir)) {
|
|
613
609
|
fs.mkdirSync(appDir, { recursive: true });
|
|
614
610
|
logger.debug(`Directory created: ${appDir}`);
|
|
615
611
|
}
|
|
616
612
|
|
|
617
613
|
const mainJsPath = path.join(appDir, 'main.js');
|
|
618
|
-
const mainJsContent = generateMainJs(
|
|
614
|
+
const mainJsContent = generateMainJs(appName, url, iconPath, options);
|
|
619
615
|
fs.writeFileSync(mainJsPath, mainJsContent);
|
|
620
616
|
logger.debug(`main.js file created`);
|
|
621
617
|
|
|
622
618
|
const packageJsonPath = path.join(appDir, 'package.json');
|
|
623
|
-
const packageJsonContent = generatePackageJson(
|
|
619
|
+
const packageJsonContent = generatePackageJson(appName, iconPath);
|
|
624
620
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
|
|
625
621
|
logger.debug(`package.json file created`);
|
|
626
622
|
|
|
627
|
-
logger.info(`Installing dependencies for ${
|
|
623
|
+
logger.info(`Installing dependencies for ${appName}`);
|
|
628
624
|
|
|
629
625
|
const installOptions = {
|
|
630
626
|
cwd: appDir,
|
|
@@ -635,17 +631,20 @@ async function createApp(url) {
|
|
|
635
631
|
const stdout = execSync('npm install --only=prod', installOptions);
|
|
636
632
|
logger.debug(`npm install completed: ${stdout.toString().trim()}`);
|
|
637
633
|
|
|
638
|
-
const desktopPath = addAppToOS(
|
|
634
|
+
const desktopPath = addAppToOS(appName, url, appDir, iconPath);
|
|
639
635
|
|
|
640
636
|
const appData = {
|
|
641
637
|
url,
|
|
642
638
|
created: new Date().toISOString(),
|
|
643
639
|
path: appDir,
|
|
644
640
|
icon: iconPath,
|
|
645
|
-
desktopPath
|
|
641
|
+
desktopPath,
|
|
642
|
+
name: options.name,
|
|
643
|
+
width: options.width,
|
|
644
|
+
height: options.height
|
|
646
645
|
};
|
|
647
646
|
|
|
648
|
-
db[
|
|
647
|
+
db[appName] = appData;
|
|
649
648
|
writeDB(db);
|
|
650
649
|
|
|
651
650
|
logger.success(`Application successfully created for ${url}`);
|
package/src/commands/remove.js
CHANGED
|
@@ -8,13 +8,12 @@ const path = require('path');
|
|
|
8
8
|
|
|
9
9
|
const logger = new Logger('remove');
|
|
10
10
|
|
|
11
|
-
async function removeApp(
|
|
11
|
+
async function removeApp(appName) {
|
|
12
12
|
try {
|
|
13
|
-
const domain = getDomainName(await normalizeUrl(url));
|
|
14
13
|
const db = readDB();
|
|
15
14
|
|
|
16
|
-
if (!db.hasOwnProperty(
|
|
17
|
-
logger.warn(`The application for ${
|
|
15
|
+
if (!db.hasOwnProperty(appName)) {
|
|
16
|
+
logger.warn(`The application for ${appName} does not exist`);
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
20
19
|
|
|
@@ -22,7 +21,7 @@ async function removeApp(url) {
|
|
|
22
21
|
{
|
|
23
22
|
type: 'confirm',
|
|
24
23
|
name: 'confirm',
|
|
25
|
-
message: `Are you sure you want to remove the application for ${
|
|
24
|
+
message: `Are you sure you want to remove the application for ${appName}?`,
|
|
26
25
|
default: false
|
|
27
26
|
}
|
|
28
27
|
]);
|
|
@@ -32,25 +31,25 @@ async function removeApp(url) {
|
|
|
32
31
|
return;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
const appInfo = db[
|
|
34
|
+
const appInfo = db[appName];
|
|
36
35
|
const appDir = appInfo.path;
|
|
37
36
|
|
|
38
|
-
removeAppFromOS(
|
|
39
|
-
logger.info(`Removing the application ${
|
|
37
|
+
removeAppFromOS(appName);
|
|
38
|
+
logger.info(`Removing the application ${appName}...`);
|
|
40
39
|
|
|
41
|
-
const iconPath = path.join(APPS_DIR, `${
|
|
40
|
+
const iconPath = path.join(APPS_DIR, `${appName}.ico`);
|
|
42
41
|
if (fs.existsSync(iconPath)) {
|
|
43
42
|
fs.unlinkSync(iconPath);
|
|
44
|
-
logger.success(`Icon for ${
|
|
43
|
+
logger.success(`Icon for ${appName} removed`);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
fs.rmSync(appDir, { recursive: true, force: true });
|
|
48
|
-
delete db[
|
|
47
|
+
delete db[appName];
|
|
49
48
|
writeDB(db);
|
|
50
49
|
|
|
51
|
-
logger.success(`The application for ${
|
|
50
|
+
logger.success(`The application for ${appName} has been successfully removed`);
|
|
52
51
|
} catch (error) {
|
|
53
|
-
logger.error(`Error removing the application ${
|
|
52
|
+
logger.error(`Error removing the application ${appName}`, error);
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
package/src/index.js
CHANGED
|
@@ -14,10 +14,15 @@ program
|
|
|
14
14
|
.description('Convert websites into desktop applications')
|
|
15
15
|
.version(version);
|
|
16
16
|
|
|
17
|
-
program
|
|
17
|
+
program
|
|
18
18
|
.command('create <url>')
|
|
19
19
|
.description('Create a new application from a URL')
|
|
20
|
-
.
|
|
20
|
+
.option('--name <name>', 'Specify the application name')
|
|
21
|
+
.option('--width <width>', 'Specify the window width', parseInt)
|
|
22
|
+
.option('--height <height>', 'Specify the window height', parseInt)
|
|
23
|
+
.action((url, options) => {
|
|
24
|
+
createApp(url, options);
|
|
25
|
+
});
|
|
21
26
|
|
|
22
27
|
program
|
|
23
28
|
.command('list')
|