@iksdev/shard-cli 0.1.18 → 0.1.20
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/bin/shard.js +76 -23
- package/package.json +1 -1
package/bin/shard.js
CHANGED
|
@@ -16,24 +16,32 @@ const STATE_FILE = '.shard-sync-state.json';
|
|
|
16
16
|
const DEFAULT_SERVER = 'https://shard-0ow4.onrender.com';
|
|
17
17
|
const IGNORED_DIRS = new Set(['.git', 'node_modules']);
|
|
18
18
|
|
|
19
|
-
function printHelp() {
|
|
20
|
-
console.log(`Shard CLI
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
shard login
|
|
24
|
-
shard whoami
|
|
25
|
-
shard sync
|
|
26
|
-
shard share
|
|
27
|
-
shard logout
|
|
28
|
-
shard config show
|
|
29
|
-
shard config set-server <url>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
function printHelp() {
|
|
20
|
+
console.log(`Shard CLI
|
|
21
|
+
|
|
22
|
+
Commandes:
|
|
23
|
+
shard login
|
|
24
|
+
shard whoami
|
|
25
|
+
shard sync
|
|
26
|
+
shard share
|
|
27
|
+
shard logout
|
|
28
|
+
shard config show
|
|
29
|
+
shard config set-server <url>
|
|
30
|
+
|
|
31
|
+
Mode interactif:
|
|
32
|
+
La CLI pose les questions (fichier, dossier, serveur, identifiants) si tu ne passes pas d'arguments.
|
|
33
|
+
|
|
34
|
+
Options avancees (optionnelles):
|
|
35
|
+
login: --username <name> --password <pass> --server <url>
|
|
36
|
+
whoami: --server <url>
|
|
37
|
+
sync: <folder> --server <url> --dry-run --force --once --interval-ms <n>
|
|
38
|
+
share: <file> --server <url> --limits <n> --temps <jours> --upload
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
shard login
|
|
42
|
+
shard sync
|
|
43
|
+
shard share
|
|
44
|
+
shard sync ./MonDossier --once
|
|
37
45
|
shard share ./MonFichier.mp4 --upload
|
|
38
46
|
`);
|
|
39
47
|
}
|
|
@@ -455,6 +463,24 @@ async function shareFile(positionals, flags) {
|
|
|
455
463
|
|
|
456
464
|
let relayClientId = '';
|
|
457
465
|
let closed = false;
|
|
466
|
+
let heartbeat = null;
|
|
467
|
+
let createdShareId = null;
|
|
468
|
+
let shareRevoked = false;
|
|
469
|
+
|
|
470
|
+
const revokeCreatedShare = async () => {
|
|
471
|
+
if (!createdShareId || shareRevoked) return;
|
|
472
|
+
shareRevoked = true;
|
|
473
|
+
try {
|
|
474
|
+
await httpJson(`${server}/api/share/${createdShareId}`, {
|
|
475
|
+
method: 'DELETE',
|
|
476
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
477
|
+
});
|
|
478
|
+
console.log('Lien relay revoque.');
|
|
479
|
+
} catch (err) {
|
|
480
|
+
console.error(`Impossible de revoquer le lien automatiquement: ${err.message}`);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
458
484
|
const closeRelay = () => {
|
|
459
485
|
if (closed) return;
|
|
460
486
|
closed = true;
|
|
@@ -462,8 +488,23 @@ async function shareFile(positionals, flags) {
|
|
|
462
488
|
};
|
|
463
489
|
|
|
464
490
|
const stopSignals = ['SIGINT', 'SIGTERM'];
|
|
491
|
+
const stopRelayShare = (signal) => {
|
|
492
|
+
if (closed) return;
|
|
493
|
+
console.log(`Arret du partage (${signal}). Revocation du lien...`);
|
|
494
|
+
Promise.resolve()
|
|
495
|
+
.then(async () => {
|
|
496
|
+
if (heartbeat) {
|
|
497
|
+
clearInterval(heartbeat);
|
|
498
|
+
heartbeat = null;
|
|
499
|
+
}
|
|
500
|
+
await revokeCreatedShare();
|
|
501
|
+
})
|
|
502
|
+
.finally(() => {
|
|
503
|
+
closeRelay();
|
|
504
|
+
});
|
|
505
|
+
};
|
|
465
506
|
for (const sig of stopSignals) {
|
|
466
|
-
process.on(sig,
|
|
507
|
+
process.on(sig, stopRelayShare);
|
|
467
508
|
}
|
|
468
509
|
|
|
469
510
|
const openPromise = new Promise((resolve, reject) => {
|
|
@@ -544,7 +585,7 @@ async function shareFile(positionals, flags) {
|
|
|
544
585
|
}
|
|
545
586
|
});
|
|
546
587
|
|
|
547
|
-
|
|
588
|
+
heartbeat = setInterval(() => {
|
|
548
589
|
if (relaySocket.readyState === WebSocket.OPEN) {
|
|
549
590
|
relaySocket.send(JSON.stringify({ type: 'heartbeat', ts: Date.now() }));
|
|
550
591
|
}
|
|
@@ -571,6 +612,10 @@ async function shareFile(positionals, flags) {
|
|
|
571
612
|
});
|
|
572
613
|
|
|
573
614
|
const share = created?.share || {};
|
|
615
|
+
if (share?.id) {
|
|
616
|
+
const n = Number(share.id);
|
|
617
|
+
if (Number.isFinite(n) && n > 0) createdShareId = n;
|
|
618
|
+
}
|
|
574
619
|
console.log(`Partage relay cree pour: ${fileName}`);
|
|
575
620
|
if (share.url) console.log(`URL Shard: ${share.url}`);
|
|
576
621
|
if (share.token) console.log(`Token: ${share.token}`);
|
|
@@ -583,14 +628,22 @@ async function shareFile(positionals, flags) {
|
|
|
583
628
|
await new Promise((resolve) => {
|
|
584
629
|
relaySocket.on('close', () => resolve());
|
|
585
630
|
});
|
|
586
|
-
|
|
631
|
+
if (heartbeat) {
|
|
632
|
+
clearInterval(heartbeat);
|
|
633
|
+
heartbeat = null;
|
|
634
|
+
}
|
|
587
635
|
for (const sig of stopSignals) {
|
|
588
|
-
process.off(sig,
|
|
636
|
+
process.off(sig, stopRelayShare);
|
|
589
637
|
}
|
|
590
638
|
return;
|
|
591
639
|
} catch (error) {
|
|
640
|
+
if (heartbeat) {
|
|
641
|
+
clearInterval(heartbeat);
|
|
642
|
+
heartbeat = null;
|
|
643
|
+
}
|
|
644
|
+
await revokeCreatedShare();
|
|
592
645
|
for (const sig of stopSignals) {
|
|
593
|
-
process.off(sig,
|
|
646
|
+
process.off(sig, stopRelayShare);
|
|
594
647
|
}
|
|
595
648
|
closeRelay();
|
|
596
649
|
throw error;
|