pal-explorer-cli 0.4.12 → 0.4.13
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 +149 -149
- package/bin/pal.js +63 -2
- package/extensions/@palexplorer/analytics/extension.json +20 -1
- package/extensions/@palexplorer/analytics/index.js +19 -9
- package/extensions/@palexplorer/audit/extension.json +14 -0
- package/extensions/@palexplorer/auth-email/extension.json +15 -0
- package/extensions/@palexplorer/auth-oauth/extension.json +15 -0
- package/extensions/@palexplorer/chat/extension.json +14 -0
- package/extensions/@palexplorer/discovery/extension.json +17 -0
- package/extensions/@palexplorer/discovery/index.js +1 -1
- package/extensions/@palexplorer/email-notifications/extension.json +23 -0
- package/extensions/@palexplorer/groups/extension.json +15 -0
- package/extensions/@palexplorer/share-links/extension.json +15 -0
- package/extensions/@palexplorer/sync/extension.json +16 -0
- package/extensions/@palexplorer/user-mgmt/extension.json +15 -0
- package/lib/capabilities.js +24 -24
- package/lib/commands/analytics.js +175 -175
- package/lib/commands/api-keys.js +131 -131
- package/lib/commands/audit.js +235 -235
- package/lib/commands/auth.js +137 -137
- package/lib/commands/backup.js +76 -76
- package/lib/commands/billing.js +148 -148
- package/lib/commands/chat.js +217 -217
- package/lib/commands/cloud-backup.js +231 -231
- package/lib/commands/comment.js +99 -99
- package/lib/commands/completion.js +203 -203
- package/lib/commands/compliance.js +218 -218
- package/lib/commands/config.js +136 -136
- package/lib/commands/connect.js +44 -44
- package/lib/commands/dept.js +294 -294
- package/lib/commands/device.js +146 -146
- package/lib/commands/download.js +240 -226
- package/lib/commands/explorer.js +178 -178
- package/lib/commands/extension.js +1060 -970
- package/lib/commands/favorite.js +90 -90
- package/lib/commands/federation.js +270 -270
- package/lib/commands/file.js +533 -533
- package/lib/commands/group.js +271 -271
- package/lib/commands/gui-share.js +29 -29
- package/lib/commands/init.js +61 -61
- package/lib/commands/invite.js +59 -59
- package/lib/commands/list.js +58 -58
- package/lib/commands/log.js +116 -116
- package/lib/commands/nearby.js +108 -108
- package/lib/commands/network.js +251 -251
- package/lib/commands/notify.js +198 -198
- package/lib/commands/org.js +273 -273
- package/lib/commands/pal.js +403 -180
- package/lib/commands/permissions.js +216 -216
- package/lib/commands/pin.js +97 -97
- package/lib/commands/protocol.js +357 -357
- package/lib/commands/rbac.js +147 -147
- package/lib/commands/recover.js +36 -36
- package/lib/commands/register.js +171 -171
- package/lib/commands/relay.js +131 -131
- package/lib/commands/remote.js +368 -368
- package/lib/commands/revoke.js +50 -50
- package/lib/commands/scanner.js +280 -280
- package/lib/commands/schedule.js +344 -344
- package/lib/commands/scim.js +203 -203
- package/lib/commands/search.js +181 -181
- package/lib/commands/serve.js +438 -438
- package/lib/commands/server.js +350 -350
- package/lib/commands/share-link.js +199 -199
- package/lib/commands/share.js +336 -323
- package/lib/commands/sso.js +200 -200
- package/lib/commands/status.js +145 -145
- package/lib/commands/stream.js +562 -562
- package/lib/commands/su.js +187 -187
- package/lib/commands/sync.js +979 -979
- package/lib/commands/transfers.js +152 -152
- package/lib/commands/uninstall.js +188 -188
- package/lib/commands/update.js +204 -204
- package/lib/commands/user.js +276 -276
- package/lib/commands/vfs.js +84 -84
- package/lib/commands/web-login.js +79 -79
- package/lib/commands/web.js +52 -52
- package/lib/commands/webhook.js +180 -180
- package/lib/commands/whoami.js +59 -59
- package/lib/commands/workspace.js +121 -121
- package/lib/core/billing.js +16 -5
- package/lib/core/dhtDiscovery.js +9 -2
- package/lib/core/discoveryClient.js +13 -7
- package/lib/core/extensions.js +142 -1
- package/lib/core/identity.js +33 -2
- package/lib/core/imageProcessor.js +109 -0
- package/lib/core/imageTorrent.js +167 -0
- package/lib/core/permissions.js +1 -1
- package/lib/core/pro.js +11 -4
- package/lib/core/serverList.js +4 -1
- package/lib/core/shares.js +12 -1
- package/lib/core/signalingServer.js +14 -2
- package/lib/core/su.js +1 -1
- package/lib/core/users.js +1 -1
- package/lib/protocol/messages.js +12 -3
- package/lib/utils/explorer.js +1 -1
- package/lib/utils/help.js +357 -357
- package/lib/utils/torrent.js +1 -0
- package/package.json +4 -3
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
import config from '../utils/config.js';
|
|
6
|
-
|
|
7
|
-
const DATA_PATHS = {
|
|
8
|
-
config: () => config.path,
|
|
9
|
-
configDir: () => path.dirname(config.path),
|
|
10
|
-
logs: () => path.join(os.homedir(), '.pal', 'logs'),
|
|
11
|
-
palDir: () => path.join(os.homedir(), '.pal'),
|
|
12
|
-
keysFile: () => path.join(os.homedir(), '.palexplorer', '.keys.json'),
|
|
13
|
-
keysDir: () => path.join(os.homedir(), '.palexplorer'),
|
|
14
|
-
pidFile: () => path.join(path.dirname(config.path), 'serve.pid'),
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
function rmSafe(p) {
|
|
18
|
-
try {
|
|
19
|
-
if (!fs.existsSync(p)) return false;
|
|
20
|
-
const stat = fs.statSync(p);
|
|
21
|
-
if (stat.isDirectory()) {
|
|
22
|
-
fs.rmSync(p, { recursive: true, force: true });
|
|
23
|
-
} else {
|
|
24
|
-
fs.unlinkSync(p);
|
|
25
|
-
}
|
|
26
|
-
return true;
|
|
27
|
-
} catch { return false; }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function clearKeytar() {
|
|
31
|
-
if (process.platform !== 'win32' && process.platform !== 'darwin') return [];
|
|
32
|
-
const removed = [];
|
|
33
|
-
try {
|
|
34
|
-
const keytar = (await import('keytar')).default;
|
|
35
|
-
// Config encryption key
|
|
36
|
-
const configKey = await keytar.getPassword('pal-explorer-config', 'encryption-key');
|
|
37
|
-
if (configKey) {
|
|
38
|
-
await keytar.deletePassword('pal-explorer-config', 'encryption-key');
|
|
39
|
-
removed.push('pal-explorer-config/encryption-key');
|
|
40
|
-
}
|
|
41
|
-
// Identity private keys
|
|
42
|
-
const creds = await keytar.findCredentials('pal-explorer');
|
|
43
|
-
for (const c of creds) {
|
|
44
|
-
await keytar.deletePassword('pal-explorer', c.account);
|
|
45
|
-
removed.push(`pal-explorer/${c.account.slice(0, 16)}...`);
|
|
46
|
-
}
|
|
47
|
-
} catch {}
|
|
48
|
-
return removed;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default function uninstallCommand(program) {
|
|
52
|
-
program
|
|
53
|
-
.command('uninstall')
|
|
54
|
-
.description('remove Palexplorer app data from this machine')
|
|
55
|
-
.option('--purge', 'Also remove identity, private keys, and OS credential store entries')
|
|
56
|
-
.option('--dry-run', 'Show what would be removed without deleting')
|
|
57
|
-
.addHelpText('after', `
|
|
58
|
-
Examples:
|
|
59
|
-
$
|
|
60
|
-
$
|
|
61
|
-
$
|
|
62
|
-
`)
|
|
63
|
-
.action(async (opts) => {
|
|
64
|
-
const dryRun = opts.dryRun;
|
|
65
|
-
const purge = opts.purge;
|
|
66
|
-
|
|
67
|
-
console.log('');
|
|
68
|
-
if (dryRun) console.log(chalk.yellow('DRY RUN — nothing will be deleted\n'));
|
|
69
|
-
|
|
70
|
-
const items = [];
|
|
71
|
-
|
|
72
|
-
// Always removed
|
|
73
|
-
const configPath = DATA_PATHS.config();
|
|
74
|
-
if (fs.existsSync(configPath)) items.push({ path: configPath, label: 'Config file (shares, settings, friends)', category: 'data' });
|
|
75
|
-
|
|
76
|
-
const pidPath = DATA_PATHS.pidFile();
|
|
77
|
-
if (fs.existsSync(pidPath)) items.push({ path: pidPath, label: 'Daemon PID file', category: 'data' });
|
|
78
|
-
|
|
79
|
-
const logDir = DATA_PATHS.logs();
|
|
80
|
-
if (fs.existsSync(logDir)) items.push({ path: logDir, label: 'Log files', category: 'data' });
|
|
81
|
-
|
|
82
|
-
// Purge-only
|
|
83
|
-
if (purge) {
|
|
84
|
-
const keysFile = DATA_PATHS.keysFile();
|
|
85
|
-
if (fs.existsSync(keysFile)) items.push({ path: keysFile, label: 'Private keys file (.keys.json)', category: 'keys' });
|
|
86
|
-
|
|
87
|
-
const keysDir = DATA_PATHS.keysDir();
|
|
88
|
-
if (fs.existsSync(keysDir)) items.push({ path: keysDir, label: '~/.palexplorer directory', category: 'keys' });
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Show what will be removed
|
|
92
|
-
if (items.length === 0 && !purge) {
|
|
93
|
-
console.log(chalk.gray('No app data found to remove.'));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
console.log(chalk.cyan('Files to remove:'));
|
|
98
|
-
for (const item of items) {
|
|
99
|
-
const icon = item.category === 'keys' ? chalk.red('🔑') : chalk.yellow('📁');
|
|
100
|
-
console.log(` ${icon} ${chalk.white(item.label)}`);
|
|
101
|
-
console.log(` ${chalk.gray(item.path)}`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (purge) {
|
|
105
|
-
const keytarEntries = await clearKeytarDryRun();
|
|
106
|
-
if (keytarEntries.length > 0) {
|
|
107
|
-
console.log(` ${chalk.red('🔑')} ${chalk.white('OS credential store entries')}`);
|
|
108
|
-
for (const entry of keytarEntries) {
|
|
109
|
-
console.log(` ${chalk.gray(entry)}`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.log('');
|
|
115
|
-
|
|
116
|
-
if (!purge) {
|
|
117
|
-
console.log(chalk.gray('Identity and private keys will be kept.'));
|
|
118
|
-
console.log(chalk.gray('Use --purge to also remove identity and keys.\n'));
|
|
119
|
-
} else {
|
|
120
|
-
console.log(chalk.red('⚠ This will permanently delete your identity and private keys.'));
|
|
121
|
-
console.log(chalk.red(' Make sure you have your 24-word recovery phrase backed up!\n'));
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (dryRun) {
|
|
125
|
-
console.log(chalk.yellow('No changes made (dry run).'));
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Perform deletion
|
|
130
|
-
let removed = 0;
|
|
131
|
-
for (const item of items) {
|
|
132
|
-
if (rmSafe(item.path)) {
|
|
133
|
-
console.log(chalk.green(` ✔ Removed: ${item.label}`));
|
|
134
|
-
removed++;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Clean up empty parent dirs
|
|
139
|
-
const configDir = DATA_PATHS.configDir();
|
|
140
|
-
if (fs.existsSync(configDir)) {
|
|
141
|
-
try {
|
|
142
|
-
const remaining = fs.readdirSync(configDir);
|
|
143
|
-
if (remaining.length === 0) rmSafe(configDir);
|
|
144
|
-
} catch {}
|
|
145
|
-
}
|
|
146
|
-
const palDir = DATA_PATHS.palDir();
|
|
147
|
-
if (fs.existsSync(palDir)) {
|
|
148
|
-
try {
|
|
149
|
-
const remaining = fs.readdirSync(palDir);
|
|
150
|
-
if (remaining.length === 0) rmSafe(palDir);
|
|
151
|
-
} catch {}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (purge) {
|
|
155
|
-
const keytarRemoved = await clearKeytar();
|
|
156
|
-
for (const entry of keytarRemoved) {
|
|
157
|
-
console.log(chalk.green(` ✔ Removed credential: ${entry}`));
|
|
158
|
-
removed++;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
console.log('');
|
|
163
|
-
if (removed > 0) {
|
|
164
|
-
console.log(chalk.green(`✔ Removed ${removed} item(s).`));
|
|
165
|
-
} else {
|
|
166
|
-
console.log(chalk.gray('Nothing to remove.'));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (!purge) {
|
|
170
|
-
console.log(chalk.gray('\nTo also remove identity and keys:
|
|
171
|
-
} else {
|
|
172
|
-
console.log(chalk.gray('\nTo fully uninstall the CLI: npm rm -g pal-explorer-cli'));
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function clearKeytarDryRun() {
|
|
178
|
-
if (process.platform !== 'win32' && process.platform !== 'darwin') return [];
|
|
179
|
-
const entries = [];
|
|
180
|
-
try {
|
|
181
|
-
const keytar = (await import('keytar')).default;
|
|
182
|
-
const configKey = await keytar.getPassword('pal-explorer-config', 'encryption-key');
|
|
183
|
-
if (configKey) entries.push('pal-explorer-config/encryption-key');
|
|
184
|
-
const creds = await keytar.findCredentials('pal-explorer');
|
|
185
|
-
for (const c of creds) entries.push(`pal-explorer/${c.account.slice(0, 16)}...`);
|
|
186
|
-
} catch {}
|
|
187
|
-
return entries;
|
|
188
|
-
}
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import config from '../utils/config.js';
|
|
6
|
+
|
|
7
|
+
const DATA_PATHS = {
|
|
8
|
+
config: () => config.path,
|
|
9
|
+
configDir: () => path.dirname(config.path),
|
|
10
|
+
logs: () => path.join(os.homedir(), '.pal', 'logs'),
|
|
11
|
+
palDir: () => path.join(os.homedir(), '.pal'),
|
|
12
|
+
keysFile: () => path.join(os.homedir(), '.palexplorer', '.keys.json'),
|
|
13
|
+
keysDir: () => path.join(os.homedir(), '.palexplorer'),
|
|
14
|
+
pidFile: () => path.join(path.dirname(config.path), 'serve.pid'),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function rmSafe(p) {
|
|
18
|
+
try {
|
|
19
|
+
if (!fs.existsSync(p)) return false;
|
|
20
|
+
const stat = fs.statSync(p);
|
|
21
|
+
if (stat.isDirectory()) {
|
|
22
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
23
|
+
} else {
|
|
24
|
+
fs.unlinkSync(p);
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
} catch { return false; }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function clearKeytar() {
|
|
31
|
+
if (process.platform !== 'win32' && process.platform !== 'darwin') return [];
|
|
32
|
+
const removed = [];
|
|
33
|
+
try {
|
|
34
|
+
const keytar = (await import('keytar')).default;
|
|
35
|
+
// Config encryption key
|
|
36
|
+
const configKey = await keytar.getPassword('pal-explorer-config', 'encryption-key');
|
|
37
|
+
if (configKey) {
|
|
38
|
+
await keytar.deletePassword('pal-explorer-config', 'encryption-key');
|
|
39
|
+
removed.push('pal-explorer-config/encryption-key');
|
|
40
|
+
}
|
|
41
|
+
// Identity private keys
|
|
42
|
+
const creds = await keytar.findCredentials('pal-explorer');
|
|
43
|
+
for (const c of creds) {
|
|
44
|
+
await keytar.deletePassword('pal-explorer', c.account);
|
|
45
|
+
removed.push(`pal-explorer/${c.account.slice(0, 16)}...`);
|
|
46
|
+
}
|
|
47
|
+
} catch {}
|
|
48
|
+
return removed;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default function uninstallCommand(program) {
|
|
52
|
+
program
|
|
53
|
+
.command('uninstall')
|
|
54
|
+
.description('remove Palexplorer app data from this machine')
|
|
55
|
+
.option('--purge', 'Also remove identity, private keys, and OS credential store entries')
|
|
56
|
+
.option('--dry-run', 'Show what would be removed without deleting')
|
|
57
|
+
.addHelpText('after', `
|
|
58
|
+
Examples:
|
|
59
|
+
$ pal uninstall Remove app data (keeps identity & keys)
|
|
60
|
+
$ pal uninstall --purge Remove everything including identity & keys
|
|
61
|
+
$ pal uninstall --dry-run Preview what would be removed
|
|
62
|
+
`)
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const dryRun = opts.dryRun;
|
|
65
|
+
const purge = opts.purge;
|
|
66
|
+
|
|
67
|
+
console.log('');
|
|
68
|
+
if (dryRun) console.log(chalk.yellow('DRY RUN — nothing will be deleted\n'));
|
|
69
|
+
|
|
70
|
+
const items = [];
|
|
71
|
+
|
|
72
|
+
// Always removed
|
|
73
|
+
const configPath = DATA_PATHS.config();
|
|
74
|
+
if (fs.existsSync(configPath)) items.push({ path: configPath, label: 'Config file (shares, settings, friends)', category: 'data' });
|
|
75
|
+
|
|
76
|
+
const pidPath = DATA_PATHS.pidFile();
|
|
77
|
+
if (fs.existsSync(pidPath)) items.push({ path: pidPath, label: 'Daemon PID file', category: 'data' });
|
|
78
|
+
|
|
79
|
+
const logDir = DATA_PATHS.logs();
|
|
80
|
+
if (fs.existsSync(logDir)) items.push({ path: logDir, label: 'Log files', category: 'data' });
|
|
81
|
+
|
|
82
|
+
// Purge-only
|
|
83
|
+
if (purge) {
|
|
84
|
+
const keysFile = DATA_PATHS.keysFile();
|
|
85
|
+
if (fs.existsSync(keysFile)) items.push({ path: keysFile, label: 'Private keys file (.keys.json)', category: 'keys' });
|
|
86
|
+
|
|
87
|
+
const keysDir = DATA_PATHS.keysDir();
|
|
88
|
+
if (fs.existsSync(keysDir)) items.push({ path: keysDir, label: '~/.palexplorer directory', category: 'keys' });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Show what will be removed
|
|
92
|
+
if (items.length === 0 && !purge) {
|
|
93
|
+
console.log(chalk.gray('No app data found to remove.'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log(chalk.cyan('Files to remove:'));
|
|
98
|
+
for (const item of items) {
|
|
99
|
+
const icon = item.category === 'keys' ? chalk.red('🔑') : chalk.yellow('📁');
|
|
100
|
+
console.log(` ${icon} ${chalk.white(item.label)}`);
|
|
101
|
+
console.log(` ${chalk.gray(item.path)}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (purge) {
|
|
105
|
+
const keytarEntries = await clearKeytarDryRun();
|
|
106
|
+
if (keytarEntries.length > 0) {
|
|
107
|
+
console.log(` ${chalk.red('🔑')} ${chalk.white('OS credential store entries')}`);
|
|
108
|
+
for (const entry of keytarEntries) {
|
|
109
|
+
console.log(` ${chalk.gray(entry)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log('');
|
|
115
|
+
|
|
116
|
+
if (!purge) {
|
|
117
|
+
console.log(chalk.gray('Identity and private keys will be kept.'));
|
|
118
|
+
console.log(chalk.gray('Use --purge to also remove identity and keys.\n'));
|
|
119
|
+
} else {
|
|
120
|
+
console.log(chalk.red('⚠ This will permanently delete your identity and private keys.'));
|
|
121
|
+
console.log(chalk.red(' Make sure you have your 24-word recovery phrase backed up!\n'));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (dryRun) {
|
|
125
|
+
console.log(chalk.yellow('No changes made (dry run).'));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Perform deletion
|
|
130
|
+
let removed = 0;
|
|
131
|
+
for (const item of items) {
|
|
132
|
+
if (rmSafe(item.path)) {
|
|
133
|
+
console.log(chalk.green(` ✔ Removed: ${item.label}`));
|
|
134
|
+
removed++;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Clean up empty parent dirs
|
|
139
|
+
const configDir = DATA_PATHS.configDir();
|
|
140
|
+
if (fs.existsSync(configDir)) {
|
|
141
|
+
try {
|
|
142
|
+
const remaining = fs.readdirSync(configDir);
|
|
143
|
+
if (remaining.length === 0) rmSafe(configDir);
|
|
144
|
+
} catch {}
|
|
145
|
+
}
|
|
146
|
+
const palDir = DATA_PATHS.palDir();
|
|
147
|
+
if (fs.existsSync(palDir)) {
|
|
148
|
+
try {
|
|
149
|
+
const remaining = fs.readdirSync(palDir);
|
|
150
|
+
if (remaining.length === 0) rmSafe(palDir);
|
|
151
|
+
} catch {}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (purge) {
|
|
155
|
+
const keytarRemoved = await clearKeytar();
|
|
156
|
+
for (const entry of keytarRemoved) {
|
|
157
|
+
console.log(chalk.green(` ✔ Removed credential: ${entry}`));
|
|
158
|
+
removed++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log('');
|
|
163
|
+
if (removed > 0) {
|
|
164
|
+
console.log(chalk.green(`✔ Removed ${removed} item(s).`));
|
|
165
|
+
} else {
|
|
166
|
+
console.log(chalk.gray('Nothing to remove.'));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!purge) {
|
|
170
|
+
console.log(chalk.gray('\nTo also remove identity and keys: pal uninstall --purge'));
|
|
171
|
+
} else {
|
|
172
|
+
console.log(chalk.gray('\nTo fully uninstall the CLI: npm rm -g pal-explorer-cli'));
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function clearKeytarDryRun() {
|
|
178
|
+
if (process.platform !== 'win32' && process.platform !== 'darwin') return [];
|
|
179
|
+
const entries = [];
|
|
180
|
+
try {
|
|
181
|
+
const keytar = (await import('keytar')).default;
|
|
182
|
+
const configKey = await keytar.getPassword('pal-explorer-config', 'encryption-key');
|
|
183
|
+
if (configKey) entries.push('pal-explorer-config/encryption-key');
|
|
184
|
+
const creds = await keytar.findCredentials('pal-explorer');
|
|
185
|
+
for (const c of creds) entries.push(`pal-explorer/${c.account.slice(0, 16)}...`);
|
|
186
|
+
} catch {}
|
|
187
|
+
return entries;
|
|
188
|
+
}
|