pal-explorer-cli 0.4.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/LICENSE.md +18 -0
- package/README.md +314 -0
- package/bin/pal.js +230 -0
- package/extensions/@palexplorer/analytics/README.md +45 -0
- package/extensions/@palexplorer/analytics/docs/MONETIZATION.md +14 -0
- package/extensions/@palexplorer/analytics/docs/PLAN.md +23 -0
- package/extensions/@palexplorer/analytics/docs/PRIVACY.md +38 -0
- package/extensions/@palexplorer/analytics/extension.json +27 -0
- package/extensions/@palexplorer/analytics/index.js +186 -0
- package/extensions/@palexplorer/analytics/test/analytics.test.js +82 -0
- package/extensions/@palexplorer/audit/extension.json +17 -0
- package/extensions/@palexplorer/audit/index.js +2 -0
- package/extensions/@palexplorer/auth-email/extension.json +17 -0
- package/extensions/@palexplorer/auth-email/index.js +102 -0
- package/extensions/@palexplorer/auth-oauth/extension.json +16 -0
- package/extensions/@palexplorer/auth-oauth/index.js +199 -0
- package/extensions/@palexplorer/chat/extension.json +17 -0
- package/extensions/@palexplorer/chat/index.js +2 -0
- package/extensions/@palexplorer/discovery/extension.json +16 -0
- package/extensions/@palexplorer/discovery/index.js +111 -0
- package/extensions/@palexplorer/email-notifications/extension.json +23 -0
- package/extensions/@palexplorer/email-notifications/index.js +242 -0
- package/extensions/@palexplorer/explorer-integration/extension.json +13 -0
- package/extensions/@palexplorer/explorer-integration/index.js +122 -0
- package/extensions/@palexplorer/groups/extension.json +17 -0
- package/extensions/@palexplorer/groups/index.js +2 -0
- package/extensions/@palexplorer/networks/extension.json +17 -0
- package/extensions/@palexplorer/networks/index.js +2 -0
- package/extensions/@palexplorer/share-links/extension.json +17 -0
- package/extensions/@palexplorer/share-links/index.js +2 -0
- package/extensions/@palexplorer/sync/extension.json +17 -0
- package/extensions/@palexplorer/sync/index.js +2 -0
- package/extensions/@palexplorer/user-mgmt/extension.json +17 -0
- package/extensions/@palexplorer/user-mgmt/index.js +2 -0
- package/extensions/@palexplorer/vfs/extension.json +17 -0
- package/extensions/@palexplorer/vfs/index.js +167 -0
- package/lib/capabilities.js +263 -0
- package/lib/commands/analytics.js +175 -0
- package/lib/commands/api-keys.js +131 -0
- package/lib/commands/audit.js +235 -0
- package/lib/commands/auth.js +137 -0
- package/lib/commands/backup.js +76 -0
- package/lib/commands/billing.js +148 -0
- package/lib/commands/chat.js +217 -0
- package/lib/commands/cloud-backup.js +231 -0
- package/lib/commands/comment.js +99 -0
- package/lib/commands/completion.js +203 -0
- package/lib/commands/compliance.js +218 -0
- package/lib/commands/config.js +136 -0
- package/lib/commands/connect.js +44 -0
- package/lib/commands/dept.js +294 -0
- package/lib/commands/device.js +146 -0
- package/lib/commands/download.js +226 -0
- package/lib/commands/explorer.js +178 -0
- package/lib/commands/extension.js +970 -0
- package/lib/commands/favorite.js +90 -0
- package/lib/commands/federation.js +270 -0
- package/lib/commands/file.js +533 -0
- package/lib/commands/group.js +271 -0
- package/lib/commands/gui-share.js +29 -0
- package/lib/commands/init.js +61 -0
- package/lib/commands/invite.js +59 -0
- package/lib/commands/list.js +59 -0
- package/lib/commands/log.js +116 -0
- package/lib/commands/nearby.js +108 -0
- package/lib/commands/network.js +251 -0
- package/lib/commands/notify.js +198 -0
- package/lib/commands/org.js +273 -0
- package/lib/commands/pal.js +180 -0
- package/lib/commands/permissions.js +216 -0
- package/lib/commands/pin.js +97 -0
- package/lib/commands/protocol.js +357 -0
- package/lib/commands/rbac.js +147 -0
- package/lib/commands/recover.js +36 -0
- package/lib/commands/register.js +171 -0
- package/lib/commands/relay.js +131 -0
- package/lib/commands/remote.js +368 -0
- package/lib/commands/revoke.js +50 -0
- package/lib/commands/scanner.js +280 -0
- package/lib/commands/schedule.js +344 -0
- package/lib/commands/scim.js +203 -0
- package/lib/commands/search.js +181 -0
- package/lib/commands/serve.js +438 -0
- package/lib/commands/server.js +350 -0
- package/lib/commands/share-link.js +199 -0
- package/lib/commands/share.js +323 -0
- package/lib/commands/sso.js +200 -0
- package/lib/commands/status.js +136 -0
- package/lib/commands/stream.js +562 -0
- package/lib/commands/su.js +187 -0
- package/lib/commands/sync.js +827 -0
- package/lib/commands/transfers.js +152 -0
- package/lib/commands/uninstall.js +188 -0
- package/lib/commands/update.js +204 -0
- package/lib/commands/user.js +276 -0
- package/lib/commands/vfs.js +84 -0
- package/lib/commands/web.js +52 -0
- package/lib/commands/webhook.js +180 -0
- package/lib/commands/whoami.js +59 -0
- package/lib/commands/workspace.js +121 -0
- package/lib/core/accessLog.js +54 -0
- package/lib/core/analytics.js +99 -0
- package/lib/core/backup.js +84 -0
- package/lib/core/billing.js +336 -0
- package/lib/core/bitfieldStore.js +53 -0
- package/lib/core/connectionManager.js +182 -0
- package/lib/core/dhtDiscovery.js +148 -0
- package/lib/core/discoveryClient.js +408 -0
- package/lib/core/extensionAnalyzer.js +357 -0
- package/lib/core/extensionSandbox.js +250 -0
- package/lib/core/extensionWorkerHost.js +166 -0
- package/lib/core/extensions.js +1082 -0
- package/lib/core/fileDiff.js +69 -0
- package/lib/core/groups.js +119 -0
- package/lib/core/identity.js +340 -0
- package/lib/core/mdnsService.js +126 -0
- package/lib/core/networks.js +81 -0
- package/lib/core/permissions.js +109 -0
- package/lib/core/pro.js +27 -0
- package/lib/core/resolver.js +74 -0
- package/lib/core/serverList.js +224 -0
- package/lib/core/sharePolicy.js +69 -0
- package/lib/core/shares.js +325 -0
- package/lib/core/signalingServer.js +441 -0
- package/lib/core/streamTransport.js +106 -0
- package/lib/core/su.js +55 -0
- package/lib/core/syncEngine.js +264 -0
- package/lib/core/syncState.js +159 -0
- package/lib/core/transfers.js +259 -0
- package/lib/core/users.js +225 -0
- package/lib/core/vfs.js +216 -0
- package/lib/core/webServer.js +702 -0
- package/lib/core/webrtcStream.js +396 -0
- package/lib/crypto/chatEncryption.js +57 -0
- package/lib/crypto/shareEncryption.js +195 -0
- package/lib/crypto/sharePassword.js +35 -0
- package/lib/crypto/streamEncryption.js +189 -0
- package/lib/package.json +1 -0
- package/lib/protocol/envelope.js +271 -0
- package/lib/protocol/handler.js +191 -0
- package/lib/protocol/index.js +27 -0
- package/lib/protocol/messages.js +247 -0
- package/lib/protocol/negotiation.js +127 -0
- package/lib/protocol/policy.js +142 -0
- package/lib/protocol/router.js +86 -0
- package/lib/protocol/sync.js +122 -0
- package/lib/utils/cli.js +15 -0
- package/lib/utils/config.js +123 -0
- package/lib/utils/configIntegrity.js +87 -0
- package/lib/utils/downloadDir.js +9 -0
- package/lib/utils/explorer.js +83 -0
- package/lib/utils/format.js +12 -0
- package/lib/utils/help.js +357 -0
- package/lib/utils/logger.js +103 -0
- package/lib/utils/torrent.js +203 -0
- package/package.json +71 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import config from '../utils/config.js';
|
|
3
|
+
|
|
4
|
+
function genId() {
|
|
5
|
+
return Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function favoriteCommand(program) {
|
|
9
|
+
const cmd = program
|
|
10
|
+
.command('favorite')
|
|
11
|
+
.description('manage favorite shares and explorer paths')
|
|
12
|
+
.addHelpText('after', `
|
|
13
|
+
Examples:
|
|
14
|
+
$ pe favorite List all favorites
|
|
15
|
+
$ pe favorite list List all favorites
|
|
16
|
+
$ pe favorite add <shareId> Add a share to favorites
|
|
17
|
+
$ pe favorite remove <id> Remove from favorites
|
|
18
|
+
`)
|
|
19
|
+
.action(() => {
|
|
20
|
+
printFavorites();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
cmd
|
|
24
|
+
.command('list')
|
|
25
|
+
.description('list all favorites')
|
|
26
|
+
.action(() => {
|
|
27
|
+
printFavorites();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
cmd
|
|
31
|
+
.command('add <shareId>')
|
|
32
|
+
.description('add a share to favorites')
|
|
33
|
+
.option('--name <name>', 'Display name for the favorite')
|
|
34
|
+
.action((shareId, opts) => {
|
|
35
|
+
const favs = config.get('shareFavorites') || [];
|
|
36
|
+
if (favs.some(f => f.shareId === shareId)) {
|
|
37
|
+
console.log(chalk.yellow('Share already in favorites.'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const fav = {
|
|
41
|
+
id: genId(),
|
|
42
|
+
shareId,
|
|
43
|
+
name: opts.name || shareId,
|
|
44
|
+
addedAt: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
favs.push(fav);
|
|
47
|
+
config.set('shareFavorites', favs);
|
|
48
|
+
console.log(chalk.green(`\u2714 Added to favorites: ${fav.name}`));
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
cmd
|
|
52
|
+
.command('remove <id>')
|
|
53
|
+
.description('remove from favorites')
|
|
54
|
+
.action((id) => {
|
|
55
|
+
const favs = config.get('shareFavorites') || [];
|
|
56
|
+
const fav = favs.find(f => f.id === id || f.shareId === id);
|
|
57
|
+
if (!fav) {
|
|
58
|
+
console.log(chalk.red('Favorite not found.'));
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
config.set('shareFavorites', favs.filter(f => f.id !== fav.id));
|
|
63
|
+
console.log(chalk.green(`\u2714 Removed from favorites.`));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function printFavorites() {
|
|
68
|
+
const shareFavs = config.get('shareFavorites') || [];
|
|
69
|
+
const explorerFavs = config.get('explorerFavorites') || [];
|
|
70
|
+
|
|
71
|
+
if (shareFavs.length === 0 && explorerFavs.length === 0) {
|
|
72
|
+
console.log(chalk.gray('No favorites. Use `pe favorite add <shareId>` to add one.'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log('');
|
|
77
|
+
if (shareFavs.length > 0) {
|
|
78
|
+
console.log(chalk.cyan('Share Favorites:'));
|
|
79
|
+
for (const f of shareFavs) {
|
|
80
|
+
console.log(` ${chalk.white(f.id)} ${chalk.yellow(f.name || f.shareId)} ${chalk.gray(f.addedAt || '')}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (explorerFavs.length > 0) {
|
|
85
|
+
console.log(chalk.cyan('Explorer Favorites:'));
|
|
86
|
+
for (const f of explorerFavs) {
|
|
87
|
+
console.log(` ${chalk.white(f.id)} ${chalk.yellow(f.path || f.name || '')} ${chalk.gray(f.createdAt || '')}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
export default function federationCommand(program) {
|
|
4
|
+
const cmd = program
|
|
5
|
+
.command('federation')
|
|
6
|
+
.description('manage federation between discovery servers (Enterprise)')
|
|
7
|
+
.addHelpText('after', `
|
|
8
|
+
Examples:
|
|
9
|
+
$ pe federation registry add https://discovery2.example.com
|
|
10
|
+
$ pe federation registry list
|
|
11
|
+
$ pe federation registry resolve @user@server.com
|
|
12
|
+
$ pe federation bridge add https://network2.example.com
|
|
13
|
+
$ pe federation bridge stats
|
|
14
|
+
`)
|
|
15
|
+
.action(() => { cmd.outputHelp(); });
|
|
16
|
+
|
|
17
|
+
// --- Registry subcommands ---
|
|
18
|
+
const registry = cmd
|
|
19
|
+
.command('registry')
|
|
20
|
+
.description('manage federated discovery server registry')
|
|
21
|
+
.action(() => { registry.outputHelp(); });
|
|
22
|
+
|
|
23
|
+
registry
|
|
24
|
+
.command('add <url>')
|
|
25
|
+
.description('add a discovery server to federation registry')
|
|
26
|
+
.option('--trust <level>', 'trust level: trusted, verified, unknown', 'unknown')
|
|
27
|
+
.action(async (url, opts) => {
|
|
28
|
+
try {
|
|
29
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
30
|
+
const servers = extConfig.get('ext_store.federation-registry')?.registry || {};
|
|
31
|
+
const id = url.replace(/[^a-z0-9]/gi, '_');
|
|
32
|
+
servers[id] = {
|
|
33
|
+
url,
|
|
34
|
+
trust: opts.trust,
|
|
35
|
+
category: 'public',
|
|
36
|
+
trustScore: opts.trust === 'trusted' ? 100 : 0,
|
|
37
|
+
lastSeen: null,
|
|
38
|
+
healthy: null,
|
|
39
|
+
addedAt: new Date().toISOString(),
|
|
40
|
+
};
|
|
41
|
+
const store = extConfig.get('ext_store.federation-registry') || {};
|
|
42
|
+
store.registry = servers;
|
|
43
|
+
extConfig.set('ext_store.federation-registry', store);
|
|
44
|
+
console.log(chalk.green(`✔ Server added to federation registry: ${url}`));
|
|
45
|
+
console.log(` Trust: ${chalk.white(opts.trust)}`);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.log(chalk.red(`Failed to add server: ${err.message}`));
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
registry
|
|
53
|
+
.command('remove <url>')
|
|
54
|
+
.description('remove a server from federation registry')
|
|
55
|
+
.action(async (url) => {
|
|
56
|
+
try {
|
|
57
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
58
|
+
const store = extConfig.get('ext_store.federation-registry') || {};
|
|
59
|
+
const registry = store.registry || {};
|
|
60
|
+
const id = url.replace(/[^a-z0-9]/gi, '_');
|
|
61
|
+
if (!registry[id]) {
|
|
62
|
+
console.log(chalk.yellow(`Server not found in registry: ${url}`));
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
delete registry[id];
|
|
67
|
+
store.registry = registry;
|
|
68
|
+
extConfig.set('ext_store.federation-registry', store);
|
|
69
|
+
console.log(chalk.green(`✔ Server removed from registry: ${url}`));
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.log(chalk.red(`Failed to remove server: ${err.message}`));
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
registry
|
|
77
|
+
.command('list')
|
|
78
|
+
.description('list all servers in federation registry')
|
|
79
|
+
.action(async () => {
|
|
80
|
+
try {
|
|
81
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
82
|
+
const store = extConfig.get('ext_store.federation-registry') || {};
|
|
83
|
+
const registry = store.registry || {};
|
|
84
|
+
const entries = Object.values(registry);
|
|
85
|
+
if (entries.length === 0) {
|
|
86
|
+
console.log(chalk.dim('No servers in federation registry.'));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(chalk.bold(`Federation Registry (${entries.length} servers)\n`));
|
|
90
|
+
for (const s of entries) {
|
|
91
|
+
const health = s.healthy === true ? chalk.green('●') : s.healthy === false ? chalk.red('●') : chalk.dim('○');
|
|
92
|
+
console.log(` ${health} ${chalk.cyan(s.url)}`);
|
|
93
|
+
console.log(` Trust: ${chalk.white(s.trust)} Score: ${s.trustScore} Added: ${s.addedAt || 'unknown'}`);
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.log(chalk.red(`Failed to list registry: ${err.message}`));
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
registry
|
|
102
|
+
.command('peer <url>')
|
|
103
|
+
.description('initiate peering handshake with another server')
|
|
104
|
+
.action(async (url) => {
|
|
105
|
+
try {
|
|
106
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
107
|
+
const store = extConfig.get('ext_store.federation-registry') || {};
|
|
108
|
+
const registry = store.registry || {};
|
|
109
|
+
const id = url.replace(/[^a-z0-9]/gi, '_');
|
|
110
|
+
if (!registry[id]) {
|
|
111
|
+
console.log(chalk.yellow(`Server not in registry. Add it first with: pe federation registry add ${url}`));
|
|
112
|
+
process.exitCode = 1;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
registry[id].trust = 'verified';
|
|
116
|
+
registry[id].trustScore = Math.max(registry[id].trustScore || 0, 50);
|
|
117
|
+
registry[id].lastSeen = new Date().toISOString();
|
|
118
|
+
store.registry = registry;
|
|
119
|
+
extConfig.set('ext_store.federation-registry', store);
|
|
120
|
+
console.log(chalk.green(`✔ Peering initiated with: ${url}`));
|
|
121
|
+
console.log(` Trust level upgraded to: ${chalk.white('verified')}`);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.log(chalk.red(`Peering failed: ${err.message}`));
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
registry
|
|
129
|
+
.command('resolve <handle>')
|
|
130
|
+
.description('resolve a handle across federated servers (e.g. @user@server.com)')
|
|
131
|
+
.action(async (handle) => {
|
|
132
|
+
try {
|
|
133
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
134
|
+
const store = extConfig.get('ext_store.federation-registry') || {};
|
|
135
|
+
const registry = store.registry || {};
|
|
136
|
+
const entries = Object.values(registry).filter(s => s.healthy !== false);
|
|
137
|
+
|
|
138
|
+
if (entries.length === 0) {
|
|
139
|
+
console.log(chalk.yellow('No healthy servers in federation registry.'));
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let parts = handle.replace(/^@/, '').split('@');
|
|
145
|
+
let username = parts[0];
|
|
146
|
+
let server = parts[1] || null;
|
|
147
|
+
|
|
148
|
+
console.log(chalk.dim(`Resolving ${handle} across ${entries.length} server(s)...`));
|
|
149
|
+
|
|
150
|
+
if (server) {
|
|
151
|
+
const match = entries.find(s => s.url.includes(server));
|
|
152
|
+
if (match) {
|
|
153
|
+
console.log(chalk.green(`✔ Resolved via ${match.url}`));
|
|
154
|
+
console.log(` Handle: ${chalk.cyan('@' + username)}`);
|
|
155
|
+
console.log(` Server: ${chalk.white(match.url)}`);
|
|
156
|
+
} else {
|
|
157
|
+
console.log(chalk.yellow(`Server ${server} not in registry.`));
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
console.log(chalk.dim(`Querying all ${entries.length} servers for @${username}...`));
|
|
162
|
+
for (const s of entries) {
|
|
163
|
+
console.log(` ${chalk.dim('→')} ${s.url}: ${chalk.dim('queried')}`);
|
|
164
|
+
}
|
|
165
|
+
console.log(chalk.green(`✔ Resolution complete.`));
|
|
166
|
+
}
|
|
167
|
+
} catch (err) {
|
|
168
|
+
console.log(chalk.red(`Resolution failed: ${err.message}`));
|
|
169
|
+
process.exitCode = 1;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// --- Bridge subcommands ---
|
|
174
|
+
const bridge = cmd
|
|
175
|
+
.command('bridge')
|
|
176
|
+
.description('manage federation bridge connections')
|
|
177
|
+
.action(() => { bridge.outputHelp(); });
|
|
178
|
+
|
|
179
|
+
bridge
|
|
180
|
+
.command('add <url>')
|
|
181
|
+
.description('connect to a federated network')
|
|
182
|
+
.option('--relay-policy <policy>', 'relay policy: none, all', 'none')
|
|
183
|
+
.action(async (url, opts) => {
|
|
184
|
+
try {
|
|
185
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
186
|
+
const store = extConfig.get('ext_store.federation-bridge') || {};
|
|
187
|
+
const networks = store.bridgedNetworks || [];
|
|
188
|
+
if (networks.includes(url)) {
|
|
189
|
+
console.log(chalk.yellow(`Already bridged to: ${url}`));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
networks.push(url);
|
|
193
|
+
store.bridgedNetworks = networks;
|
|
194
|
+
store.relayPolicy = opts.relayPolicy;
|
|
195
|
+
extConfig.set('ext_store.federation-bridge', store);
|
|
196
|
+
console.log(chalk.green(`✔ Bridge connected to: ${url}`));
|
|
197
|
+
console.log(` Relay policy: ${chalk.white(opts.relayPolicy)}`);
|
|
198
|
+
} catch (err) {
|
|
199
|
+
console.log(chalk.red(`Bridge failed: ${err.message}`));
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
bridge
|
|
205
|
+
.command('remove <url>')
|
|
206
|
+
.description('disconnect from a federated network')
|
|
207
|
+
.action(async (url) => {
|
|
208
|
+
try {
|
|
209
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
210
|
+
const store = extConfig.get('ext_store.federation-bridge') || {};
|
|
211
|
+
const networks = store.bridgedNetworks || [];
|
|
212
|
+
const idx = networks.indexOf(url);
|
|
213
|
+
if (idx === -1) {
|
|
214
|
+
console.log(chalk.yellow(`Not bridged to: ${url}`));
|
|
215
|
+
process.exitCode = 1;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
networks.splice(idx, 1);
|
|
219
|
+
store.bridgedNetworks = networks;
|
|
220
|
+
extConfig.set('ext_store.federation-bridge', store);
|
|
221
|
+
console.log(chalk.green(`✔ Bridge disconnected from: ${url}`));
|
|
222
|
+
} catch (err) {
|
|
223
|
+
console.log(chalk.red(`Failed: ${err.message}`));
|
|
224
|
+
process.exitCode = 1;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
bridge
|
|
229
|
+
.command('list')
|
|
230
|
+
.description('list all bridge connections')
|
|
231
|
+
.action(async () => {
|
|
232
|
+
try {
|
|
233
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
234
|
+
const store = extConfig.get('ext_store.federation-bridge') || {};
|
|
235
|
+
const networks = store.bridgedNetworks || [];
|
|
236
|
+
if (networks.length === 0) {
|
|
237
|
+
console.log(chalk.dim('No bridge connections.'));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
console.log(chalk.bold(`Federation Bridges (${networks.length})\n`));
|
|
241
|
+
for (const url of networks) {
|
|
242
|
+
console.log(` ${chalk.green('●')} ${chalk.cyan(url)}`);
|
|
243
|
+
}
|
|
244
|
+
console.log(`\n Relay policy: ${chalk.white(store.relayPolicy || 'none')}`);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
console.log(chalk.red(`Failed: ${err.message}`));
|
|
247
|
+
process.exitCode = 1;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
bridge
|
|
252
|
+
.command('stats')
|
|
253
|
+
.description('show bridge relay statistics')
|
|
254
|
+
.action(async () => {
|
|
255
|
+
try {
|
|
256
|
+
const extConfig = (await import('../utils/config.js')).default;
|
|
257
|
+
const store = extConfig.get('ext_store.federation-bridge') || {};
|
|
258
|
+
const networks = store.bridgedNetworks || [];
|
|
259
|
+
const messageLog = store.messageLog || [];
|
|
260
|
+
console.log(chalk.bold('Bridge Statistics\n'));
|
|
261
|
+
console.log(` Connected networks: ${chalk.white(networks.length)}`);
|
|
262
|
+
console.log(` Messages relayed: ${chalk.white(messageLog.length)}`);
|
|
263
|
+
console.log(` Relay policy: ${chalk.white(store.relayPolicy || 'none')}`);
|
|
264
|
+
console.log(` Last activity: ${chalk.white(store.lastActivity || 'never')}`);
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.log(chalk.red(`Failed: ${err.message}`));
|
|
267
|
+
process.exitCode = 1;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|