clidesk 0.1.1 → 0.1.3
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 +6 -6
- package/bin/clidesk.js +153 -48
- package/package.json +1 -1
- package/scripts/install.js +18 -44
- package/vendor/clidesk-launcher.exe +0 -0
- package/vendor/clidesk.exe +0 -0
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
CliDesk is a local desktop dashboard for managing terminal sessions, files, and Git repositories — built with **Tauri v2** + **React** + **TypeScript** + **Rust**.
|
|
8
8
|
|
|
9
|
-
This npm package
|
|
9
|
+
This npm package contains the CliDesk desktop app binary and a native Windows launcher.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -20,7 +20,7 @@ npm i -g clidesk
|
|
|
20
20
|
clidesk
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
The launcher
|
|
23
|
+
The launcher copies the bundled binaries into a per-version runtime cache and opens CliDesk from there.
|
|
24
24
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
@@ -30,11 +30,11 @@ The launcher will find and open the CliDesk desktop app.
|
|
|
30
30
|
|
|
31
31
|
## How it works
|
|
32
32
|
|
|
33
|
-
1. During `npm i -g clidesk`, the postinstall script checks
|
|
34
|
-
2.
|
|
35
|
-
3.
|
|
33
|
+
1. During `npm i -g clidesk`, the postinstall script checks that `vendor/clidesk.exe` and `vendor/clidesk-launcher.exe` are bundled.
|
|
34
|
+
2. When you run `clidesk`, the npm wrapper copies both binaries to `%LOCALAPPDATA%\CliDesk\npm-runtime\<version>\`.
|
|
35
|
+
3. The native launcher starts CliDesk from that runtime directory, not from `node_modules`.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
The CliDesk desktop app itself is a Tauri application built from the [source repository](https://github.com/vykelongthuong/CliDesk).
|
|
38
38
|
|
|
39
39
|
## License
|
|
40
40
|
|
package/bin/clidesk.js
CHANGED
|
@@ -1,61 +1,166 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// CliDesk npm launcher
|
|
2
|
+
// CliDesk npm launcher.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// 1. vendor/clidesk-launcher.exe (native launcher with menu)
|
|
9
|
-
// 2. vendor/clidesk.exe (direct app binary)
|
|
10
|
-
//
|
|
11
|
-
// The launcher offers interactive menu (hidden/visible terminal).
|
|
12
|
-
// If the launcher is absent, the app is spawned directly.
|
|
4
|
+
// The package stores signed binaries in vendor/, but it never runs them from
|
|
5
|
+
// node_modules. Each package version is copied to a runtime cache first so npm
|
|
6
|
+
// can update or uninstall the global package without Windows keeping vendor/
|
|
7
|
+
// locked by a running desktop process.
|
|
13
8
|
|
|
14
|
-
const { spawn } = require('child_process');
|
|
15
|
-
const path = require('path');
|
|
16
9
|
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { execFileSync, spawn } = require('child_process');
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const debug = args.includes('--debug-launch');
|
|
15
|
+
|
|
16
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
17
|
+
const pkg = require(path.join(packageRoot, 'package.json'));
|
|
18
|
+
const version = pkg.version;
|
|
19
|
+
|
|
20
|
+
const vendorDir = path.join(packageRoot, 'vendor');
|
|
21
|
+
const runtimeBase = process.env.LOCALAPPDATA || process.env.TEMP;
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const launcherPath = path.join(vendorDir, 'clidesk-launcher.exe');
|
|
21
|
-
const appPath = path.join(vendorDir, 'clidesk.exe');
|
|
22
|
-
|
|
23
|
-
let targetPath;
|
|
24
|
-
let targetName;
|
|
25
|
-
|
|
26
|
-
if (fs.existsSync(launcherPath)) {
|
|
27
|
-
targetPath = launcherPath;
|
|
28
|
-
targetName = 'clidesk-launcher.exe';
|
|
29
|
-
} else if (fs.existsSync(appPath)) {
|
|
30
|
-
targetPath = appPath;
|
|
31
|
-
targetName = 'clidesk.exe';
|
|
32
|
-
} else {
|
|
33
|
-
console.error('[CliDesk] Binary not found.');
|
|
34
|
-
console.error('[CliDesk] Try reinstalling: npm i -g clidesk');
|
|
35
|
-
console.error('[CliDesk] Or download clidesk.exe from GitHub Releases');
|
|
36
|
-
console.error('[CliDesk] and place it in: ' + vendorDir);
|
|
23
|
+
if (!runtimeBase) {
|
|
24
|
+
console.error('[CliDesk] Không thể xác định LOCALAPPDATA hoặc TEMP.');
|
|
37
25
|
process.exit(1);
|
|
38
26
|
}
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
const args = process.argv.slice(2);
|
|
28
|
+
const runtimeDir = path.join(runtimeBase, 'CliDesk', 'npm-runtime', version);
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
30
|
+
const vendorApp = path.join(vendorDir, 'clidesk.exe');
|
|
31
|
+
const vendorLauncher = path.join(vendorDir, 'clidesk-launcher.exe');
|
|
32
|
+
|
|
33
|
+
const runtimeApp = path.join(runtimeDir, 'clidesk.exe');
|
|
34
|
+
const runtimeLauncher = path.join(runtimeDir, 'clidesk-launcher.exe');
|
|
35
|
+
const latestVersion = readLatestVersion();
|
|
36
|
+
const updateAvailable = latestVersion ? isVersionNewer(latestVersion, version) : false;
|
|
37
|
+
|
|
38
|
+
function ensureFileExists(filePath, label) {
|
|
39
|
+
if (!fs.existsSync(filePath)) {
|
|
40
|
+
throw new Error(`${label} không tồn tại: ${filePath}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function copyIfMissing(src, dest) {
|
|
45
|
+
ensureFileExists(src, 'Binary nguồn');
|
|
46
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
47
|
+
|
|
48
|
+
if (fs.existsSync(dest)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const tmpDest = `${dest}.tmp-${process.pid}`;
|
|
53
|
+
try {
|
|
54
|
+
fs.copyFileSync(src, tmpDest);
|
|
55
|
+
fs.renameSync(tmpDest, dest);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
try {
|
|
58
|
+
if (fs.existsSync(tmpDest)) {
|
|
59
|
+
fs.unlinkSync(tmpDest);
|
|
60
|
+
}
|
|
61
|
+
} catch (_) {
|
|
62
|
+
// Best-effort cleanup only.
|
|
63
|
+
}
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function printDebugInfo() {
|
|
69
|
+
console.log('[CliDesk] packageRoot:', packageRoot);
|
|
70
|
+
console.log('[CliDesk] vendorDir:', vendorDir);
|
|
71
|
+
console.log('[CliDesk] runtimeDir:', runtimeDir);
|
|
72
|
+
console.log('[CliDesk] launcherPath:', runtimeLauncher);
|
|
73
|
+
console.log('[CliDesk] appPath:', runtimeApp);
|
|
74
|
+
console.log('[CliDesk] version:', version);
|
|
75
|
+
console.log('[CliDesk] latestVersion:', latestVersion || '(unknown)');
|
|
76
|
+
console.log('[CliDesk] updateAvailable:', updateAvailable ? 'true' : 'false');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function readLatestVersion() {
|
|
80
|
+
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
81
|
+
try {
|
|
82
|
+
const output = execFileSync(npmCommand, ['view', 'clidesk', 'version', '--silent'], {
|
|
83
|
+
encoding: 'utf8',
|
|
84
|
+
timeout: 5000,
|
|
85
|
+
windowsHide: true,
|
|
86
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
87
|
+
});
|
|
88
|
+
const latest = output.trim();
|
|
89
|
+
return latest || null;
|
|
90
|
+
} catch (_) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isVersionNewer(latest, current) {
|
|
96
|
+
const latestParts = parseVersion(latest);
|
|
97
|
+
const currentParts = parseVersion(current);
|
|
98
|
+
for (let index = 0; index < 3; index += 1) {
|
|
99
|
+
if (latestParts[index] > currentParts[index]) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
if (latestParts[index] < currentParts[index]) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function parseVersion(value) {
|
|
110
|
+
const parts = String(value)
|
|
111
|
+
.split(/[.+-]/)
|
|
112
|
+
.slice(0, 3)
|
|
113
|
+
.map((part) => {
|
|
114
|
+
const parsed = Number.parseInt(part, 10);
|
|
115
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
116
|
+
});
|
|
48
117
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
118
|
+
while (parts.length < 3) {
|
|
119
|
+
parts.push(0);
|
|
120
|
+
}
|
|
53
121
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
122
|
+
return parts;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function main() {
|
|
126
|
+
copyIfMissing(vendorApp, runtimeApp);
|
|
127
|
+
copyIfMissing(vendorLauncher, runtimeLauncher);
|
|
128
|
+
|
|
129
|
+
if (debug) {
|
|
130
|
+
printDebugInfo();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const child = spawn(runtimeLauncher, args, {
|
|
134
|
+
cwd: runtimeDir,
|
|
135
|
+
env: {
|
|
136
|
+
...process.env,
|
|
137
|
+
CLIDESK_VERSION: version,
|
|
138
|
+
CLIDESK_LATEST_VERSION: latestVersion || '',
|
|
139
|
+
CLIDESK_UPDATE_AVAILABLE: updateAvailable ? '1' : '0',
|
|
140
|
+
CLIDESK_UPDATE_COMMAND: 'npm i -g clidesk',
|
|
141
|
+
},
|
|
142
|
+
stdio: 'inherit',
|
|
143
|
+
windowsHide: false,
|
|
144
|
+
});
|
|
57
145
|
|
|
58
|
-
child.on('
|
|
59
|
-
|
|
146
|
+
child.on('exit', (code) => {
|
|
147
|
+
process.exit(code ?? 0);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
child.on('error', (err) => {
|
|
151
|
+
console.error('[CliDesk] Không thể chạy launcher:', err.message);
|
|
152
|
+
console.error('[CliDesk] Path:', runtimeLauncher);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
main();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.error('[CliDesk] Không thể chuẩn bị runtime CliDesk.');
|
|
161
|
+
console.error('[CliDesk] Lỗi:', err && err.message ? err.message : err);
|
|
162
|
+
if (debug) {
|
|
163
|
+
printDebugInfo();
|
|
164
|
+
}
|
|
60
165
|
process.exit(1);
|
|
61
|
-
}
|
|
166
|
+
}
|
package/package.json
CHANGED
package/scripts/install.js
CHANGED
|
@@ -1,66 +1,40 @@
|
|
|
1
|
-
// CliDesk postinstall script
|
|
1
|
+
// CliDesk postinstall script.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// 3. Check if vendor/clidesk.exe exists
|
|
7
|
-
// 4. If not, provide clear download instructions
|
|
8
|
-
//
|
|
9
|
-
// No admin required. No process spawned. No downloads.
|
|
3
|
+
// It only validates that the package contains the Windows binaries needed by
|
|
4
|
+
// bin/clidesk.js. It does not launch the app, copy runtime files, download
|
|
5
|
+
// binaries, request admin rights, or use credentials.
|
|
10
6
|
|
|
11
7
|
const fs = require('fs');
|
|
12
8
|
const path = require('path');
|
|
13
9
|
|
|
14
|
-
const
|
|
15
|
-
const
|
|
10
|
+
const vendorDir = path.join(__dirname, '..', 'vendor');
|
|
11
|
+
const requiredBinaries = [
|
|
12
|
+
path.join(vendorDir, 'clidesk.exe'),
|
|
13
|
+
path.join(vendorDir, 'clidesk-launcher.exe'),
|
|
14
|
+
];
|
|
16
15
|
|
|
17
16
|
function main() {
|
|
18
|
-
// ── Platform check ──────────────────────────────────────
|
|
19
17
|
if (process.platform !== 'win32') {
|
|
20
18
|
console.warn('[CliDesk] This package only supports Windows x64.');
|
|
21
|
-
console.warn('[CliDesk] Skipping binary setup.');
|
|
22
19
|
return;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
if (process.arch !== 'x64') {
|
|
26
23
|
console.warn('[CliDesk] This package only supports x64 architecture.');
|
|
27
|
-
console.warn('[CliDesk] Skipping binary setup.');
|
|
28
24
|
return;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
console.log('[CliDesk] Binary found in vendor/.');
|
|
40
|
-
return;
|
|
27
|
+
const missing = requiredBinaries.filter((filePath) => !fs.existsSync(filePath));
|
|
28
|
+
if (missing.length > 0) {
|
|
29
|
+
console.error('[CliDesk] Package is missing required binaries:');
|
|
30
|
+
for (const filePath of missing) {
|
|
31
|
+
console.error('[CliDesk] Missing:', filePath);
|
|
32
|
+
}
|
|
33
|
+
console.error('[CliDesk] Please reinstall with: npm i -g clidesk');
|
|
34
|
+
process.exit(1);
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
console.log('');
|
|
45
|
-
console.log('╔══════════════════════════════════════════════╗');
|
|
46
|
-
console.log('║ CliDesk Binary Setup ║');
|
|
47
|
-
console.log('╠══════════════════════════════════════════════╣');
|
|
48
|
-
console.log('║ ║');
|
|
49
|
-
console.log('║ CliDesk binary is not bundled yet. ║');
|
|
50
|
-
console.log('║ ║');
|
|
51
|
-
console.log('║ To complete setup: ║');
|
|
52
|
-
console.log('║ ║');
|
|
53
|
-
console.log('║ 1. Download clidesk.exe from: ║');
|
|
54
|
-
console.log('║ GitHub Releases ║');
|
|
55
|
-
console.log('║ https://github.com/vykelongthuong/CliDesk ║');
|
|
56
|
-
console.log('║ ║');
|
|
57
|
-
console.log('║ 2. Place it in: ║');
|
|
58
|
-
console.log('║ ' + VENDOR_DIR.padEnd(42) + '║');
|
|
59
|
-
console.log('║ ║');
|
|
60
|
-
console.log('║ 3. Run: clidesk ║');
|
|
61
|
-
console.log('║ ║');
|
|
62
|
-
console.log('╚══════════════════════════════════════════════╝');
|
|
63
|
-
console.log('');
|
|
37
|
+
console.log('[CliDesk] Vendor binaries found.');
|
|
64
38
|
}
|
|
65
39
|
|
|
66
40
|
main();
|
|
Binary file
|
package/vendor/clidesk.exe
CHANGED
|
Binary file
|