@bitsocial/bitsocial-cli 0.19.43 → 0.19.45
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 +30 -24
- package/bin/update-webuis.js +129 -0
- package/dist/challenge-packages/challenge-utils.js +4 -2
- package/dist/cli/commands/community/edit.d.ts +3 -0
- package/dist/cli/commands/community/edit.js +56 -10
- package/dist/cli/commands/daemon.js +0 -1
- package/dist/cli/commands/update/install.d.ts +2 -0
- package/dist/cli/commands/update/install.js +59 -0
- package/dist/cli/hooks/prerun/parse-dynamic-flags-hook.js +13 -0
- package/oclif.manifest.json +20 -8
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -344,7 +344,7 @@ EXAMPLES
|
|
|
344
344
|
$ bitsocial challenge install ./my-local-challenge
|
|
345
345
|
```
|
|
346
346
|
|
|
347
|
-
_See code: [src/cli/commands/challenge/install.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
347
|
+
_See code: [src/cli/commands/challenge/install.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/challenge/install.ts)_
|
|
348
348
|
|
|
349
349
|
## `bitsocial challenge list`
|
|
350
350
|
|
|
@@ -367,7 +367,7 @@ EXAMPLES
|
|
|
367
367
|
$ bitsocial challenge list -q
|
|
368
368
|
```
|
|
369
369
|
|
|
370
|
-
_See code: [src/cli/commands/challenge/list.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
370
|
+
_See code: [src/cli/commands/challenge/list.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/challenge/list.ts)_
|
|
371
371
|
|
|
372
372
|
## `bitsocial challenge remove NAME`
|
|
373
373
|
|
|
@@ -392,7 +392,7 @@ EXAMPLES
|
|
|
392
392
|
$ bitsocial challenge remove @scope/my-challenge
|
|
393
393
|
```
|
|
394
394
|
|
|
395
|
-
_See code: [src/cli/commands/challenge/remove.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
395
|
+
_See code: [src/cli/commands/challenge/remove.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/challenge/remove.ts)_
|
|
396
396
|
|
|
397
397
|
## `bitsocial community create`
|
|
398
398
|
|
|
@@ -417,7 +417,7 @@ EXAMPLES
|
|
|
417
417
|
$ bitsocial community create --title 'Hello Plebs' --description 'Welcome'
|
|
418
418
|
```
|
|
419
419
|
|
|
420
|
-
_See code: [src/cli/commands/community/create.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
420
|
+
_See code: [src/cli/commands/community/create.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/create.ts)_
|
|
421
421
|
|
|
422
422
|
## `bitsocial community delete ADDRESSES`
|
|
423
423
|
|
|
@@ -442,7 +442,7 @@ EXAMPLES
|
|
|
442
442
|
$ bitsocial community delete 12D3KooWG3XbzoVyAE6Y9vHZKF64Yuuu4TjdgQKedk14iYmTEPWu
|
|
443
443
|
```
|
|
444
444
|
|
|
445
|
-
_See code: [src/cli/commands/community/delete.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
445
|
+
_See code: [src/cli/commands/community/delete.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/delete.ts)_
|
|
446
446
|
|
|
447
447
|
## `bitsocial community edit ADDRESS`
|
|
448
448
|
|
|
@@ -450,13 +450,14 @@ Edit a community's properties. For a list of properties, visit https://github.co
|
|
|
450
450
|
|
|
451
451
|
```
|
|
452
452
|
USAGE
|
|
453
|
-
$ bitsocial community edit ADDRESS --pkcRpcUrl <value>
|
|
453
|
+
$ bitsocial community edit ADDRESS --pkcRpcUrl <value> [-f <value>]
|
|
454
454
|
|
|
455
455
|
ARGUMENTS
|
|
456
|
-
ADDRESS Address of the community to edit
|
|
456
|
+
ADDRESS Address of the community to edit. It could be the name domain, or a public key
|
|
457
457
|
|
|
458
458
|
FLAGS
|
|
459
|
-
--
|
|
459
|
+
-f, --jsonFile=<value> Path to a JSON file containing edit options
|
|
460
|
+
--pkcRpcUrl=<value> (required) [default: ws://localhost:9138/] URL to PKC RPC
|
|
460
461
|
|
|
461
462
|
DESCRIPTION
|
|
462
463
|
Edit a community's properties. For a list of properties, visit https://github.com/pkcprotocol/pkc-js
|
|
@@ -468,33 +469,38 @@ EXAMPLES
|
|
|
468
469
|
|
|
469
470
|
Add the author address 'esteban.bso' as an admin on the community
|
|
470
471
|
|
|
471
|
-
$ bitsocial community edit
|
|
472
|
+
$ bitsocial community edit mycommunity.bso '--roles["esteban.bso"].role' admin
|
|
472
473
|
|
|
473
474
|
Add two challenges to the community. The first challenge will be a question and answer, and the second will be an
|
|
474
475
|
image captcha
|
|
475
476
|
|
|
476
|
-
$ bitsocial community edit
|
|
477
|
+
$ bitsocial community edit mycommunity.bso --settings.challenges[0].name question \
|
|
477
478
|
--settings.challenges[0].options.question "what is the password?" --settings.challenges[0].options.answer \
|
|
478
479
|
thepassword --settings.challenges[1].name captcha-canvas-v3
|
|
479
480
|
|
|
480
481
|
Change the title and description
|
|
481
482
|
|
|
482
|
-
$ bitsocial community edit
|
|
483
|
+
$ bitsocial community edit mycommunity.bso --title "This is the new title" --description "This is the new \
|
|
484
|
+
description"
|
|
483
485
|
|
|
484
486
|
Remove a role from a moderator/admin/owner
|
|
485
487
|
|
|
486
|
-
$ bitsocial community edit
|
|
488
|
+
$ bitsocial community edit bitsocial.bso --roles['rinse12.bso'] null
|
|
487
489
|
|
|
488
490
|
Enable settings.fetchThumbnailUrls to fetch the thumbnail of url submitted by authors
|
|
489
491
|
|
|
490
|
-
$ bitsocial community edit
|
|
492
|
+
$ bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls
|
|
491
493
|
|
|
492
494
|
disable settings.fetchThumbnailUrls
|
|
493
495
|
|
|
494
|
-
$ bitsocial community edit
|
|
496
|
+
$ bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls=false
|
|
497
|
+
|
|
498
|
+
Edit a community using options from a JSON file
|
|
499
|
+
|
|
500
|
+
$ bitsocial community edit bitsocial.bso --jsonFile ./edit-options.json
|
|
495
501
|
```
|
|
496
502
|
|
|
497
|
-
_See code: [src/cli/commands/community/edit.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
503
|
+
_See code: [src/cli/commands/community/edit.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/edit.ts)_
|
|
498
504
|
|
|
499
505
|
## `bitsocial community get [ADDRESS]`
|
|
500
506
|
|
|
@@ -525,7 +531,7 @@ EXAMPLES
|
|
|
525
531
|
$ bitsocial community get --publicKey 12D3KooWG3XbzoVyAE6Y9vHZKF64Yuuu4TjdgQKedk14iYmTEPWu
|
|
526
532
|
```
|
|
527
533
|
|
|
528
|
-
_See code: [src/cli/commands/community/get.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
534
|
+
_See code: [src/cli/commands/community/get.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/get.ts)_
|
|
529
535
|
|
|
530
536
|
## `bitsocial community list`
|
|
531
537
|
|
|
@@ -548,7 +554,7 @@ EXAMPLES
|
|
|
548
554
|
$ bitsocial community list
|
|
549
555
|
```
|
|
550
556
|
|
|
551
|
-
_See code: [src/cli/commands/community/list.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
557
|
+
_See code: [src/cli/commands/community/list.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/list.ts)_
|
|
552
558
|
|
|
553
559
|
## `bitsocial community start ADDRESSES`
|
|
554
560
|
|
|
@@ -577,7 +583,7 @@ EXAMPLES
|
|
|
577
583
|
$ bitsocial community start $(bitsocial community list -q)
|
|
578
584
|
```
|
|
579
585
|
|
|
580
|
-
_See code: [src/cli/commands/community/start.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
586
|
+
_See code: [src/cli/commands/community/start.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/start.ts)_
|
|
581
587
|
|
|
582
588
|
## `bitsocial community stop ADDRESSES`
|
|
583
589
|
|
|
@@ -602,7 +608,7 @@ EXAMPLES
|
|
|
602
608
|
$ bitsocial community stop Qmb99crTbSUfKXamXwZBe829Vf6w5w5TktPkb6WstC9RFW
|
|
603
609
|
```
|
|
604
610
|
|
|
605
|
-
_See code: [src/cli/commands/community/stop.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
611
|
+
_See code: [src/cli/commands/community/stop.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/community/stop.ts)_
|
|
606
612
|
|
|
607
613
|
## `bitsocial daemon`
|
|
608
614
|
|
|
@@ -643,7 +649,7 @@ EXAMPLES
|
|
|
643
649
|
$ bitsocial daemon --chainProviderUrls https://mainnet.infura.io/v3/YOUR_KEY
|
|
644
650
|
```
|
|
645
651
|
|
|
646
|
-
_See code: [src/cli/commands/daemon.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
652
|
+
_See code: [src/cli/commands/daemon.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/daemon.ts)_
|
|
647
653
|
|
|
648
654
|
## `bitsocial help [COMMAND]`
|
|
649
655
|
|
|
@@ -700,7 +706,7 @@ EXAMPLES
|
|
|
700
706
|
$ bitsocial logs --since 1h -f
|
|
701
707
|
```
|
|
702
708
|
|
|
703
|
-
_See code: [src/cli/commands/logs.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
709
|
+
_See code: [src/cli/commands/logs.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/logs.ts)_
|
|
704
710
|
|
|
705
711
|
## `bitsocial update check`
|
|
706
712
|
|
|
@@ -717,7 +723,7 @@ EXAMPLES
|
|
|
717
723
|
$ bitsocial update check
|
|
718
724
|
```
|
|
719
725
|
|
|
720
|
-
_See code: [src/cli/commands/update/check.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
726
|
+
_See code: [src/cli/commands/update/check.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/update/check.ts)_
|
|
721
727
|
|
|
722
728
|
## `bitsocial update install [VERSION]`
|
|
723
729
|
|
|
@@ -749,7 +755,7 @@ EXAMPLES
|
|
|
749
755
|
$ bitsocial update install --no-restart-daemons
|
|
750
756
|
```
|
|
751
757
|
|
|
752
|
-
_See code: [src/cli/commands/update/install.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
758
|
+
_See code: [src/cli/commands/update/install.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/update/install.ts)_
|
|
753
759
|
|
|
754
760
|
## `bitsocial update versions`
|
|
755
761
|
|
|
@@ -771,7 +777,7 @@ EXAMPLES
|
|
|
771
777
|
$ bitsocial update versions --limit 5
|
|
772
778
|
```
|
|
773
779
|
|
|
774
|
-
_See code: [src/cli/commands/update/versions.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.
|
|
780
|
+
_See code: [src/cli/commands/update/versions.ts](https://github.com/bitsocialnet/bitsocial-cli/blob/v0.19.45/src/cli/commands/update/versions.ts)_
|
|
775
781
|
<!-- commandsstop -->
|
|
776
782
|
|
|
777
783
|
## Contribution
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { Readable } from "node:stream";
|
|
7
|
+
import { finished as streamFinished } from "node:stream/promises";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const packageRoot = path.join(__dirname, "..");
|
|
13
|
+
|
|
14
|
+
const dryRun = process.argv.includes("--dry-run");
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
const pkgPath = path.join(packageRoot, "package.json");
|
|
18
|
+
const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));
|
|
19
|
+
const webuis = pkg.webuis;
|
|
20
|
+
if (!webuis || webuis.length === 0) {
|
|
21
|
+
console.log("No webuis configured in package.json");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const githubToken = process.env["GITHUB_TOKEN"];
|
|
26
|
+
if (githubToken) console.log("Using GITHUB_TOKEN for API requests");
|
|
27
|
+
const headers = githubToken ? { authorization: `Bearer ${githubToken}` } : undefined;
|
|
28
|
+
|
|
29
|
+
let updatedCount = 0;
|
|
30
|
+
|
|
31
|
+
for (const entry of webuis) {
|
|
32
|
+
const { url, sha256OfHtmlZip } = entry;
|
|
33
|
+
|
|
34
|
+
// Parse "https://github.com/{owner}/{repo}/releases/tag/{tag}"
|
|
35
|
+
const match = url.match(/github\.com\/([^/]+\/[^/]+)\/releases\/tag\/(.+)$/);
|
|
36
|
+
if (!match) {
|
|
37
|
+
console.warn(`Warning: Could not parse GitHub release URL: ${url}. Skipping.`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const [, ownerRepo, currentTag] = match;
|
|
41
|
+
const repoName = ownerRepo.split("/")[1];
|
|
42
|
+
|
|
43
|
+
// Fetch latest release
|
|
44
|
+
const latestRes = await fetch(`https://api.github.com/repos/${ownerRepo}/releases/latest`, { headers });
|
|
45
|
+
if (!latestRes.ok) {
|
|
46
|
+
if (latestRes.status === 403) {
|
|
47
|
+
console.warn(`Warning: GitHub API rate limited for ${ownerRepo}. Set GITHUB_TOKEN to avoid this. Skipping.`);
|
|
48
|
+
} else {
|
|
49
|
+
console.warn(`Warning: Failed to fetch latest release for ${ownerRepo}, status ${latestRes.status}. Skipping.`);
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const latest = await latestRes.json();
|
|
55
|
+
const latestTag = latest.tag_name;
|
|
56
|
+
|
|
57
|
+
if (latestTag === currentTag) {
|
|
58
|
+
console.log(`${repoName}: ${currentTag} (already latest)`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Find html zip asset
|
|
63
|
+
const htmlZipAsset = latest.assets.find((asset) => asset.name.includes("html"));
|
|
64
|
+
if (!htmlZipAsset) {
|
|
65
|
+
console.warn(`Warning: No HTML zip asset found in ${ownerRepo}@${latestTag}. Skipping.`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (dryRun) {
|
|
70
|
+
console.log(`${repoName}: ${currentTag} -> ${latestTag} (would update)`);
|
|
71
|
+
updatedCount++;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Download zip to temp dir
|
|
76
|
+
const tmpPath = path.join(os.tmpdir(), htmlZipAsset.name);
|
|
77
|
+
const downloadRes = await fetch(htmlZipAsset["browser_download_url"], { headers });
|
|
78
|
+
if (!downloadRes.ok || !downloadRes.body) {
|
|
79
|
+
console.warn(`Warning: Failed to download ${htmlZipAsset.name}, status ${downloadRes.status}. Skipping.`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const writer = createWriteStream(tmpPath);
|
|
84
|
+
await streamFinished(Readable.fromWeb(downloadRes.body).pipe(writer));
|
|
85
|
+
writer.close();
|
|
86
|
+
|
|
87
|
+
// Compute SHA256
|
|
88
|
+
const fileBuffer = await fs.readFile(tmpPath);
|
|
89
|
+
const newHash = createHash("sha256").update(fileBuffer).digest("hex");
|
|
90
|
+
|
|
91
|
+
// Clean up temp file
|
|
92
|
+
await fs.rm(tmpPath);
|
|
93
|
+
|
|
94
|
+
// Update entry
|
|
95
|
+
entry.url = `https://github.com/${ownerRepo}/releases/tag/${latestTag}`;
|
|
96
|
+
entry.sha256OfHtmlZip = newHash;
|
|
97
|
+
updatedCount++;
|
|
98
|
+
console.log(`${repoName}: ${currentTag} -> ${latestTag} (updated)`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (updatedCount === 0) {
|
|
102
|
+
console.log("\nAll web UIs are already at their latest versions.");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (dryRun) {
|
|
107
|
+
console.log(`\n${updatedCount} web UI(s) would be updated (dry run, no changes made).`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Write updated package.json
|
|
112
|
+
pkg.webuis = webuis;
|
|
113
|
+
await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 4) + "\n");
|
|
114
|
+
console.log(`\nUpdated ${updatedCount} web UI(s) in package.json.`);
|
|
115
|
+
|
|
116
|
+
// Remove dist/webuis/ so postinstall re-downloads
|
|
117
|
+
const distWebuis = path.join(packageRoot, "dist", "webuis");
|
|
118
|
+
try {
|
|
119
|
+
await fs.rm(distWebuis, { recursive: true });
|
|
120
|
+
console.log("Removed dist/webuis/ — run 'npm run ci:download-web-uis' to re-download.");
|
|
121
|
+
} catch (e) {
|
|
122
|
+
if (e.code !== "ENOENT") throw e;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
main().catch((err) => {
|
|
127
|
+
console.error(err);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
});
|
|
@@ -208,9 +208,11 @@ export async function runNpmInstall(challengeDir) {
|
|
|
208
208
|
const originalContent = await fs.readFile(pkgJsonPath, "utf-8");
|
|
209
209
|
const pkg = JSON.parse(originalContent);
|
|
210
210
|
const hadDevDeps = pkg.devDependencies !== undefined;
|
|
211
|
-
|
|
211
|
+
const hadScripts = pkg.scripts !== undefined;
|
|
212
|
+
if (hadDevDeps || hadScripts) {
|
|
212
213
|
const stripped = { ...pkg };
|
|
213
214
|
delete stripped.devDependencies;
|
|
215
|
+
delete stripped.scripts;
|
|
214
216
|
await fs.writeFile(pkgJsonPath, JSON.stringify(stripped, null, 2) + "\n");
|
|
215
217
|
}
|
|
216
218
|
try {
|
|
@@ -243,7 +245,7 @@ export async function runNpmInstall(challengeDir) {
|
|
|
243
245
|
});
|
|
244
246
|
}
|
|
245
247
|
finally {
|
|
246
|
-
if (hadDevDeps) {
|
|
248
|
+
if (hadDevDeps || hadScripts) {
|
|
247
249
|
await fs.writeFile(pkgJsonPath, originalContent);
|
|
248
250
|
}
|
|
249
251
|
}
|
|
@@ -4,6 +4,9 @@ export default class Edit extends BaseCommand {
|
|
|
4
4
|
static args: {
|
|
5
5
|
address: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
6
|
};
|
|
7
|
+
static flags: {
|
|
8
|
+
jsonFile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
7
10
|
static examples: {
|
|
8
11
|
description: string;
|
|
9
12
|
command: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//@ts-expect-error
|
|
2
2
|
import DataObjectParser from "dataobject-parser";
|
|
3
|
-
import { Args } from "@oclif/core";
|
|
3
|
+
import { Args, Flags } from "@oclif/core";
|
|
4
|
+
import fs from "fs";
|
|
4
5
|
import { BaseCommand } from "../../base-command.js";
|
|
5
6
|
import { PKCLogger, mergeDeep } from "../../../util.js";
|
|
6
7
|
import * as remeda from "remeda";
|
|
@@ -10,37 +11,51 @@ export default class Edit extends BaseCommand {
|
|
|
10
11
|
address: Args.string({
|
|
11
12
|
name: "address",
|
|
12
13
|
required: true,
|
|
13
|
-
description: "Address of the community to edit"
|
|
14
|
+
description: "Address of the community to edit. It could be the name domain, or a public key"
|
|
15
|
+
})
|
|
16
|
+
};
|
|
17
|
+
static flags = {
|
|
18
|
+
jsonFile: Flags.file({
|
|
19
|
+
char: "f",
|
|
20
|
+
exists: true,
|
|
21
|
+
description: "Path to a JSON file containing edit options"
|
|
14
22
|
})
|
|
15
23
|
};
|
|
16
24
|
static examples = [
|
|
25
|
+
// TODO update this to change the name instead
|
|
26
|
+
// Also are we testing modifying name properly?
|
|
27
|
+
// in theory user should not modify address, they should modify name
|
|
17
28
|
{
|
|
18
29
|
description: "Change the address of the community to a new domain address",
|
|
19
30
|
command: "bitsocial community edit 12D3KooWG3XbzoVyAE6Y9vHZKF64Yuuu4TjdgQKedk14iYmTEPWu --address newAddress.bso"
|
|
20
31
|
},
|
|
21
32
|
{
|
|
22
33
|
description: "Add the author address 'esteban.bso' as an admin on the community",
|
|
23
|
-
command: `bitsocial community edit
|
|
34
|
+
command: `bitsocial community edit mycommunity.bso '--roles["esteban.bso"].role' admin`
|
|
24
35
|
},
|
|
25
36
|
{
|
|
26
37
|
description: "Add two challenges to the community. The first challenge will be a question and answer, and the second will be an image captcha",
|
|
27
|
-
command: `bitsocial community edit
|
|
38
|
+
command: `bitsocial community edit mycommunity.bso --settings.challenges[0].name question --settings.challenges[0].options.question "what is the password?" --settings.challenges[0].options.answer thepassword --settings.challenges[1].name captcha-canvas-v3`
|
|
28
39
|
},
|
|
29
40
|
{
|
|
30
41
|
description: "Change the title and description",
|
|
31
|
-
command: `bitsocial community edit
|
|
42
|
+
command: `bitsocial community edit mycommunity.bso --title "This is the new title" --description "This is the new description" `
|
|
32
43
|
},
|
|
33
44
|
{
|
|
34
45
|
description: "Remove a role from a moderator/admin/owner",
|
|
35
|
-
command: "bitsocial community edit
|
|
46
|
+
command: "bitsocial community edit bitsocial.bso --roles['rinse12.bso'] null"
|
|
36
47
|
},
|
|
37
48
|
{
|
|
38
49
|
description: "Enable settings.fetchThumbnailUrls to fetch the thumbnail of url submitted by authors",
|
|
39
|
-
command: "bitsocial community edit
|
|
50
|
+
command: "bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls"
|
|
40
51
|
},
|
|
41
52
|
{
|
|
42
53
|
description: "disable settings.fetchThumbnailUrls",
|
|
43
|
-
command: "bitsocial community edit
|
|
54
|
+
command: "bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls=false"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
description: "Edit a community using options from a JSON file",
|
|
58
|
+
command: "bitsocial community edit bitsocial.bso --jsonFile ./edit-options.json"
|
|
44
59
|
}
|
|
45
60
|
];
|
|
46
61
|
async run() {
|
|
@@ -48,8 +63,39 @@ export default class Edit extends BaseCommand {
|
|
|
48
63
|
const log = PKCLogger("bitsocial-cli:commands:community:edit");
|
|
49
64
|
log(`flags: `, flags);
|
|
50
65
|
const pkc = await this._connectToPkcRpc(flags.pkcRpcUrl.toString());
|
|
51
|
-
const
|
|
52
|
-
log("
|
|
66
|
+
const cliEditOptions = DataObjectParser.transpose(remeda.omit(flags, ["pkcRpcUrl", "jsonFile"]))["_data"];
|
|
67
|
+
log("CLI edit options parsed:", cliEditOptions);
|
|
68
|
+
// Parse JSON file if provided
|
|
69
|
+
let jsonFileOptions = {};
|
|
70
|
+
if (flags.jsonFile) {
|
|
71
|
+
try {
|
|
72
|
+
const fileContent = await fs.promises.readFile(flags.jsonFile, "utf-8");
|
|
73
|
+
const parsed = JSON.parse(fileContent);
|
|
74
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
75
|
+
this.error("JSON file must contain a JSON object (not an array, null, string, or number)");
|
|
76
|
+
}
|
|
77
|
+
jsonFileOptions = parsed;
|
|
78
|
+
log("JSON file options parsed:", jsonFileOptions);
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
if (e instanceof SyntaxError) {
|
|
82
|
+
this.error(`Invalid JSON in file ${flags.jsonFile}: ${e.message}`);
|
|
83
|
+
}
|
|
84
|
+
throw e;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Merge: JSON file options first, then CLI flags override
|
|
88
|
+
let editOptions;
|
|
89
|
+
if (flags.jsonFile && Object.keys(cliEditOptions).length > 0) {
|
|
90
|
+
editOptions = mergeDeep(jsonFileOptions, cliEditOptions);
|
|
91
|
+
}
|
|
92
|
+
else if (flags.jsonFile) {
|
|
93
|
+
editOptions = jsonFileOptions;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
editOptions = cliEditOptions;
|
|
97
|
+
}
|
|
98
|
+
log("Final edit options:", editOptions);
|
|
53
99
|
const localCommunities = pkc.communities;
|
|
54
100
|
if (!localCommunities.includes(args.address))
|
|
55
101
|
this.error("Can't edit a remote community, make sure you're editing a local community");
|
|
@@ -223,7 +223,6 @@ export default class Daemon extends Command {
|
|
|
223
223
|
// Create BSO name resolvers for .bso/.eth domain resolution
|
|
224
224
|
const bsoResolvers = createBsoResolvers(flags.chainProviderUrls, mergedPkcOptions.dataPath);
|
|
225
225
|
mergedPkcOptions.nameResolvers = [...(mergedPkcOptions.nameResolvers || []), ...bsoResolvers];
|
|
226
|
-
console.log(".bso name resolvers:", bsoResolvers.map((r) => r.provider).join(", "));
|
|
227
226
|
let mainProcessExited = false;
|
|
228
227
|
let pendingKuboStart;
|
|
229
228
|
// Kubo Node may fail randomly, we need to set a listener so when it exits because of an error we restart it
|
|
@@ -4,6 +4,11 @@ import tcpPortUsed from "tcp-port-used";
|
|
|
4
4
|
import { fetchLatestVersion, installGlobal } from "../../../update/npm-registry.js";
|
|
5
5
|
import { compareVersions } from "../../../update/semver.js";
|
|
6
6
|
import { getAliveDaemonStates } from "../../../common-utils/daemon-state.js";
|
|
7
|
+
import PKC from "@pkcprotocol/pkc-js";
|
|
8
|
+
const getPKCConnectOverride = () => {
|
|
9
|
+
const globalWithOverride = globalThis;
|
|
10
|
+
return globalWithOverride.__PKC_RPC_CONNECT_OVERRIDE;
|
|
11
|
+
};
|
|
7
12
|
export default class Install extends Command {
|
|
8
13
|
static description = "Install a specific version of bitsocial from npm";
|
|
9
14
|
static args = {
|
|
@@ -122,10 +127,64 @@ export default class Install extends Command {
|
|
|
122
127
|
const started = await tcpPortUsed.waitUntilUsed(port, 500, 30000).then(() => true).catch(() => false);
|
|
123
128
|
if (started) {
|
|
124
129
|
this.log(` Daemon started (port ${port}).`);
|
|
130
|
+
await this._reportCommunityStatus(d.pkcRpcUrl);
|
|
125
131
|
}
|
|
126
132
|
else {
|
|
127
133
|
this.warn(` Daemon may not have started — port ${port} not responding after 30s. Check logs with: bitsocial logs`);
|
|
128
134
|
}
|
|
129
135
|
}
|
|
130
136
|
}
|
|
137
|
+
async _connectToRpc(pkcRpcUrl) {
|
|
138
|
+
const connectOverride = getPKCConnectOverride();
|
|
139
|
+
if (connectOverride) {
|
|
140
|
+
return connectOverride(pkcRpcUrl);
|
|
141
|
+
}
|
|
142
|
+
const pkc = await PKC({ pkcRpcClientsOptions: [pkcRpcUrl] });
|
|
143
|
+
const errors = [];
|
|
144
|
+
pkc.on("error", (err) => {
|
|
145
|
+
errors.push(err);
|
|
146
|
+
});
|
|
147
|
+
await new Promise((resolve, reject) => {
|
|
148
|
+
const timeout = setTimeout(() => {
|
|
149
|
+
const lastError = errors[errors.length - 1];
|
|
150
|
+
reject(lastError ?? new Error(`Timed out waiting for RPC server at ${pkcRpcUrl} to respond`));
|
|
151
|
+
}, 20000);
|
|
152
|
+
pkc.once("communitieschange", () => {
|
|
153
|
+
clearTimeout(timeout);
|
|
154
|
+
resolve();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
return pkc;
|
|
158
|
+
}
|
|
159
|
+
async _reportCommunityStatus(pkcRpcUrl) {
|
|
160
|
+
let pkc;
|
|
161
|
+
try {
|
|
162
|
+
pkc = await this._connectToRpc(pkcRpcUrl);
|
|
163
|
+
const communities = pkc.communities;
|
|
164
|
+
if (communities.length === 0)
|
|
165
|
+
return;
|
|
166
|
+
const statuses = await Promise.all(communities.map(async (address) => {
|
|
167
|
+
const community = await pkc.createCommunity({ address });
|
|
168
|
+
return community.started;
|
|
169
|
+
}));
|
|
170
|
+
const startedCount = statuses.filter(Boolean).length;
|
|
171
|
+
const total = communities.length;
|
|
172
|
+
if (startedCount === total) {
|
|
173
|
+
this.log(` ${startedCount} ${startedCount === 1 ? "community" : "communities"} started.`);
|
|
174
|
+
}
|
|
175
|
+
else if (startedCount > 0) {
|
|
176
|
+
this.log(` ${startedCount} of ${total} communities started (remaining still loading).`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.log(` ${total} ${total === 1 ? "community" : "communities"} in data path (still loading). Check with: bitsocial community list`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
this.warn("Could not check community status.");
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
if (pkc)
|
|
187
|
+
await pkc.destroy().catch(() => { });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
131
190
|
}
|
|
@@ -60,6 +60,10 @@ const traverseObjectToSetAsFlagInOclif = (opts, flagsGrouped, path = "") => {
|
|
|
60
60
|
if (Object.keys(flagsGrouped[flagName]).length !== 0)
|
|
61
61
|
continue;
|
|
62
62
|
}
|
|
63
|
+
const fullFlagName = path + flagName;
|
|
64
|
+
// Skip flags that are already statically declared on the command
|
|
65
|
+
if (opts.Command.flags && fullFlagName in opts.Command.flags)
|
|
66
|
+
continue;
|
|
63
67
|
const flagsIndices = Object.assign({}, ...Object.keys(flagsGrouped).map((flag) => ({ [flag]: 0 })));
|
|
64
68
|
const multipleValues = Array.isArray(flagsGrouped[flagName]) && flagsGrouped[flagName].length > 1;
|
|
65
69
|
const parsedValue = flagsGrouped[flagName];
|
|
@@ -76,9 +80,18 @@ const traverseObjectToSetAsFlagInOclif = (opts, flagsGrouped, path = "") => {
|
|
|
76
80
|
});
|
|
77
81
|
}
|
|
78
82
|
};
|
|
83
|
+
// Tracks original static flags per Command class so dynamic flags can be reset across invocations (e.g. in tests)
|
|
84
|
+
const originalStaticFlags = new WeakMap();
|
|
79
85
|
const hook = async function (opts) {
|
|
80
86
|
// Need to parse flag here and add it to opts.Command._flags
|
|
81
87
|
if (opts.Command.id === "community:edit" || opts.Command.id === "community:create" || opts.Command.id === "daemon") {
|
|
88
|
+
// Snapshot static flags on first run; restore on subsequent runs (test isolation)
|
|
89
|
+
if (!originalStaticFlags.has(opts.Command)) {
|
|
90
|
+
originalStaticFlags.set(opts.Command, opts.Command.flags ? { ...opts.Command.flags } : {});
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
opts.Command.flags = { ...originalStaticFlags.get(opts.Command) };
|
|
94
|
+
}
|
|
82
95
|
// Parse the dynamic flags and add them to opts.Command.flags so that it wouldn't throw
|
|
83
96
|
if (opts.argv.length <= 1)
|
|
84
97
|
return; // if no flags are provided, then we don't need to do anything
|
package/oclif.manifest.json
CHANGED
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
"aliases": [],
|
|
351
351
|
"args": {
|
|
352
352
|
"address": {
|
|
353
|
-
"description": "Address of the community to edit",
|
|
353
|
+
"description": "Address of the community to edit. It could be the name domain, or a public key",
|
|
354
354
|
"name": "address",
|
|
355
355
|
"required": true
|
|
356
356
|
}
|
|
@@ -363,27 +363,31 @@
|
|
|
363
363
|
},
|
|
364
364
|
{
|
|
365
365
|
"description": "Add the author address 'esteban.bso' as an admin on the community",
|
|
366
|
-
"command": "bitsocial community edit
|
|
366
|
+
"command": "bitsocial community edit mycommunity.bso '--roles[\"esteban.bso\"].role' admin"
|
|
367
367
|
},
|
|
368
368
|
{
|
|
369
369
|
"description": "Add two challenges to the community. The first challenge will be a question and answer, and the second will be an image captcha",
|
|
370
|
-
"command": "bitsocial community edit
|
|
370
|
+
"command": "bitsocial community edit mycommunity.bso --settings.challenges[0].name question --settings.challenges[0].options.question \"what is the password?\" --settings.challenges[0].options.answer thepassword --settings.challenges[1].name captcha-canvas-v3"
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
373
|
"description": "Change the title and description",
|
|
374
|
-
"command": "bitsocial community edit
|
|
374
|
+
"command": "bitsocial community edit mycommunity.bso --title \"This is the new title\" --description \"This is the new description\" "
|
|
375
375
|
},
|
|
376
376
|
{
|
|
377
377
|
"description": "Remove a role from a moderator/admin/owner",
|
|
378
|
-
"command": "bitsocial community edit
|
|
378
|
+
"command": "bitsocial community edit bitsocial.bso --roles['rinse12.bso'] null"
|
|
379
379
|
},
|
|
380
380
|
{
|
|
381
381
|
"description": "Enable settings.fetchThumbnailUrls to fetch the thumbnail of url submitted by authors",
|
|
382
|
-
"command": "bitsocial community edit
|
|
382
|
+
"command": "bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls"
|
|
383
383
|
},
|
|
384
384
|
{
|
|
385
385
|
"description": "disable settings.fetchThumbnailUrls",
|
|
386
|
-
"command": "bitsocial community edit
|
|
386
|
+
"command": "bitsocial community edit bitsocial.bso --settings.fetchThumbnailUrls=false"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"description": "Edit a community using options from a JSON file",
|
|
390
|
+
"command": "bitsocial community edit bitsocial.bso --jsonFile ./edit-options.json"
|
|
387
391
|
}
|
|
388
392
|
],
|
|
389
393
|
"flags": {
|
|
@@ -395,6 +399,14 @@
|
|
|
395
399
|
"hasDynamicHelp": false,
|
|
396
400
|
"multiple": false,
|
|
397
401
|
"type": "option"
|
|
402
|
+
},
|
|
403
|
+
"jsonFile": {
|
|
404
|
+
"char": "f",
|
|
405
|
+
"description": "Path to a JSON file containing edit options",
|
|
406
|
+
"name": "jsonFile",
|
|
407
|
+
"hasDynamicHelp": false,
|
|
408
|
+
"multiple": false,
|
|
409
|
+
"type": "option"
|
|
398
410
|
}
|
|
399
411
|
},
|
|
400
412
|
"hasDynamicHelp": false,
|
|
@@ -713,5 +725,5 @@
|
|
|
713
725
|
]
|
|
714
726
|
}
|
|
715
727
|
},
|
|
716
|
-
"version": "0.19.
|
|
728
|
+
"version": "0.19.45"
|
|
717
729
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitsocial/bitsocial-cli",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.45",
|
|
4
4
|
"description": "Command line interface to Bitsocial API",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"homepage": "https://github.com/bitsocialnet/bitsocial-cli",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"postinstall": "node bin/postinstall.js",
|
|
26
26
|
"generate:readme": "oclif readme && sed -i 's@/src/commands/@/src/cli/commands/@g' README.md && sed -i 's@src/commands@src/cli/commands@g' README.md",
|
|
27
27
|
"ci:download-web-uis": "node bin/postinstall.js",
|
|
28
|
-
"ci:daemon:test-before-release": "node --loader ts-node/esm ci-bin/run-daemon-before-release.ts"
|
|
28
|
+
"ci:daemon:test-before-release": "node --loader ts-node/esm ci-bin/run-daemon-before-release.ts",
|
|
29
|
+
"update-webuis": "node bin/update-webuis.js"
|
|
29
30
|
},
|
|
30
31
|
"files": [
|
|
31
32
|
"/bin",
|
|
@@ -93,7 +94,7 @@
|
|
|
93
94
|
"@types/node": "22.19.13",
|
|
94
95
|
"@types/prettier": "2.7.1",
|
|
95
96
|
"@types/tcp-port-used": "1.0.4",
|
|
96
|
-
"@types/ws": "
|
|
97
|
+
"@types/ws": "8.18.1",
|
|
97
98
|
"commitizen": "4.2.5",
|
|
98
99
|
"cz-conventional-changelog": "3.3.0",
|
|
99
100
|
"eslint": "8.27.0",
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
"wait-on": "6.0.1"
|
|
112
113
|
},
|
|
113
114
|
"dependencies": {
|
|
114
|
-
"@bitsocial/bso-resolver": "0.0.
|
|
115
|
+
"@bitsocial/bso-resolver": "0.0.6",
|
|
115
116
|
"@multiformats/multiaddr": "13.0.1",
|
|
116
117
|
"@oclif/core": "4.8.0",
|
|
117
118
|
"@oclif/plugin-help": "6.2.36",
|
|
@@ -139,8 +140,8 @@
|
|
|
139
140
|
"sha256OfHtmlZip": "14653b19e88868fda6fef26601f477947e44251cc52bd95d7d6fec158ae67b6f"
|
|
140
141
|
},
|
|
141
142
|
{
|
|
142
|
-
"url": "https://github.com/bitsocialnet/5chan/releases/tag/v0.
|
|
143
|
-
"sha256OfHtmlZip": "
|
|
143
|
+
"url": "https://github.com/bitsocialnet/5chan/releases/tag/v0.7.4",
|
|
144
|
+
"sha256OfHtmlZip": "c768bd40a6f9e6c3889d2e57df843e667594974c6f3048357e2b6148aeec3385"
|
|
144
145
|
}
|
|
145
146
|
]
|
|
146
147
|
}
|