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.
Files changed (156) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +314 -0
  3. package/bin/pal.js +230 -0
  4. package/extensions/@palexplorer/analytics/README.md +45 -0
  5. package/extensions/@palexplorer/analytics/docs/MONETIZATION.md +14 -0
  6. package/extensions/@palexplorer/analytics/docs/PLAN.md +23 -0
  7. package/extensions/@palexplorer/analytics/docs/PRIVACY.md +38 -0
  8. package/extensions/@palexplorer/analytics/extension.json +27 -0
  9. package/extensions/@palexplorer/analytics/index.js +186 -0
  10. package/extensions/@palexplorer/analytics/test/analytics.test.js +82 -0
  11. package/extensions/@palexplorer/audit/extension.json +17 -0
  12. package/extensions/@palexplorer/audit/index.js +2 -0
  13. package/extensions/@palexplorer/auth-email/extension.json +17 -0
  14. package/extensions/@palexplorer/auth-email/index.js +102 -0
  15. package/extensions/@palexplorer/auth-oauth/extension.json +16 -0
  16. package/extensions/@palexplorer/auth-oauth/index.js +199 -0
  17. package/extensions/@palexplorer/chat/extension.json +17 -0
  18. package/extensions/@palexplorer/chat/index.js +2 -0
  19. package/extensions/@palexplorer/discovery/extension.json +16 -0
  20. package/extensions/@palexplorer/discovery/index.js +111 -0
  21. package/extensions/@palexplorer/email-notifications/extension.json +23 -0
  22. package/extensions/@palexplorer/email-notifications/index.js +242 -0
  23. package/extensions/@palexplorer/explorer-integration/extension.json +13 -0
  24. package/extensions/@palexplorer/explorer-integration/index.js +122 -0
  25. package/extensions/@palexplorer/groups/extension.json +17 -0
  26. package/extensions/@palexplorer/groups/index.js +2 -0
  27. package/extensions/@palexplorer/networks/extension.json +17 -0
  28. package/extensions/@palexplorer/networks/index.js +2 -0
  29. package/extensions/@palexplorer/share-links/extension.json +17 -0
  30. package/extensions/@palexplorer/share-links/index.js +2 -0
  31. package/extensions/@palexplorer/sync/extension.json +17 -0
  32. package/extensions/@palexplorer/sync/index.js +2 -0
  33. package/extensions/@palexplorer/user-mgmt/extension.json +17 -0
  34. package/extensions/@palexplorer/user-mgmt/index.js +2 -0
  35. package/extensions/@palexplorer/vfs/extension.json +17 -0
  36. package/extensions/@palexplorer/vfs/index.js +167 -0
  37. package/lib/capabilities.js +263 -0
  38. package/lib/commands/analytics.js +175 -0
  39. package/lib/commands/api-keys.js +131 -0
  40. package/lib/commands/audit.js +235 -0
  41. package/lib/commands/auth.js +137 -0
  42. package/lib/commands/backup.js +76 -0
  43. package/lib/commands/billing.js +148 -0
  44. package/lib/commands/chat.js +217 -0
  45. package/lib/commands/cloud-backup.js +231 -0
  46. package/lib/commands/comment.js +99 -0
  47. package/lib/commands/completion.js +203 -0
  48. package/lib/commands/compliance.js +218 -0
  49. package/lib/commands/config.js +136 -0
  50. package/lib/commands/connect.js +44 -0
  51. package/lib/commands/dept.js +294 -0
  52. package/lib/commands/device.js +146 -0
  53. package/lib/commands/download.js +226 -0
  54. package/lib/commands/explorer.js +178 -0
  55. package/lib/commands/extension.js +970 -0
  56. package/lib/commands/favorite.js +90 -0
  57. package/lib/commands/federation.js +270 -0
  58. package/lib/commands/file.js +533 -0
  59. package/lib/commands/group.js +271 -0
  60. package/lib/commands/gui-share.js +29 -0
  61. package/lib/commands/init.js +61 -0
  62. package/lib/commands/invite.js +59 -0
  63. package/lib/commands/list.js +59 -0
  64. package/lib/commands/log.js +116 -0
  65. package/lib/commands/nearby.js +108 -0
  66. package/lib/commands/network.js +251 -0
  67. package/lib/commands/notify.js +198 -0
  68. package/lib/commands/org.js +273 -0
  69. package/lib/commands/pal.js +180 -0
  70. package/lib/commands/permissions.js +216 -0
  71. package/lib/commands/pin.js +97 -0
  72. package/lib/commands/protocol.js +357 -0
  73. package/lib/commands/rbac.js +147 -0
  74. package/lib/commands/recover.js +36 -0
  75. package/lib/commands/register.js +171 -0
  76. package/lib/commands/relay.js +131 -0
  77. package/lib/commands/remote.js +368 -0
  78. package/lib/commands/revoke.js +50 -0
  79. package/lib/commands/scanner.js +280 -0
  80. package/lib/commands/schedule.js +344 -0
  81. package/lib/commands/scim.js +203 -0
  82. package/lib/commands/search.js +181 -0
  83. package/lib/commands/serve.js +438 -0
  84. package/lib/commands/server.js +350 -0
  85. package/lib/commands/share-link.js +199 -0
  86. package/lib/commands/share.js +323 -0
  87. package/lib/commands/sso.js +200 -0
  88. package/lib/commands/status.js +136 -0
  89. package/lib/commands/stream.js +562 -0
  90. package/lib/commands/su.js +187 -0
  91. package/lib/commands/sync.js +827 -0
  92. package/lib/commands/transfers.js +152 -0
  93. package/lib/commands/uninstall.js +188 -0
  94. package/lib/commands/update.js +204 -0
  95. package/lib/commands/user.js +276 -0
  96. package/lib/commands/vfs.js +84 -0
  97. package/lib/commands/web.js +52 -0
  98. package/lib/commands/webhook.js +180 -0
  99. package/lib/commands/whoami.js +59 -0
  100. package/lib/commands/workspace.js +121 -0
  101. package/lib/core/accessLog.js +54 -0
  102. package/lib/core/analytics.js +99 -0
  103. package/lib/core/backup.js +84 -0
  104. package/lib/core/billing.js +336 -0
  105. package/lib/core/bitfieldStore.js +53 -0
  106. package/lib/core/connectionManager.js +182 -0
  107. package/lib/core/dhtDiscovery.js +148 -0
  108. package/lib/core/discoveryClient.js +408 -0
  109. package/lib/core/extensionAnalyzer.js +357 -0
  110. package/lib/core/extensionSandbox.js +250 -0
  111. package/lib/core/extensionWorkerHost.js +166 -0
  112. package/lib/core/extensions.js +1082 -0
  113. package/lib/core/fileDiff.js +69 -0
  114. package/lib/core/groups.js +119 -0
  115. package/lib/core/identity.js +340 -0
  116. package/lib/core/mdnsService.js +126 -0
  117. package/lib/core/networks.js +81 -0
  118. package/lib/core/permissions.js +109 -0
  119. package/lib/core/pro.js +27 -0
  120. package/lib/core/resolver.js +74 -0
  121. package/lib/core/serverList.js +224 -0
  122. package/lib/core/sharePolicy.js +69 -0
  123. package/lib/core/shares.js +325 -0
  124. package/lib/core/signalingServer.js +441 -0
  125. package/lib/core/streamTransport.js +106 -0
  126. package/lib/core/su.js +55 -0
  127. package/lib/core/syncEngine.js +264 -0
  128. package/lib/core/syncState.js +159 -0
  129. package/lib/core/transfers.js +259 -0
  130. package/lib/core/users.js +225 -0
  131. package/lib/core/vfs.js +216 -0
  132. package/lib/core/webServer.js +702 -0
  133. package/lib/core/webrtcStream.js +396 -0
  134. package/lib/crypto/chatEncryption.js +57 -0
  135. package/lib/crypto/shareEncryption.js +195 -0
  136. package/lib/crypto/sharePassword.js +35 -0
  137. package/lib/crypto/streamEncryption.js +189 -0
  138. package/lib/package.json +1 -0
  139. package/lib/protocol/envelope.js +271 -0
  140. package/lib/protocol/handler.js +191 -0
  141. package/lib/protocol/index.js +27 -0
  142. package/lib/protocol/messages.js +247 -0
  143. package/lib/protocol/negotiation.js +127 -0
  144. package/lib/protocol/policy.js +142 -0
  145. package/lib/protocol/router.js +86 -0
  146. package/lib/protocol/sync.js +122 -0
  147. package/lib/utils/cli.js +15 -0
  148. package/lib/utils/config.js +123 -0
  149. package/lib/utils/configIntegrity.js +87 -0
  150. package/lib/utils/downloadDir.js +9 -0
  151. package/lib/utils/explorer.js +83 -0
  152. package/lib/utils/format.js +12 -0
  153. package/lib/utils/help.js +357 -0
  154. package/lib/utils/logger.js +103 -0
  155. package/lib/utils/torrent.js +203 -0
  156. 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
+ }