@peerbit/server 3.0.0 → 4.0.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/lib/esm/aws.browser.d.ts +0 -0
- package/lib/esm/aws.browser.js +3 -0
- package/lib/esm/aws.browser.js.map +1 -0
- package/lib/esm/aws.d.ts +19 -0
- package/lib/esm/aws.js +185 -1
- package/lib/esm/aws.js.map +1 -1
- package/lib/esm/cli.js +592 -324
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/client.d.ts +11 -5
- package/lib/esm/client.js +64 -11
- package/lib/esm/client.js.map +1 -1
- package/lib/esm/docker.browser.d.ts +0 -0
- package/lib/esm/docker.browser.js +3 -0
- package/lib/esm/docker.browser.js.map +1 -0
- package/lib/esm/domain.js +1 -1
- package/lib/esm/domain.js.map +1 -1
- package/lib/esm/peerbit.d.ts +1 -1
- package/lib/esm/remotes.d.ts +15 -2
- package/lib/esm/remotes.js +8 -8
- package/lib/esm/remotes.js.map +1 -1
- package/lib/esm/routes.d.ts +3 -2
- package/lib/esm/routes.js +5 -4
- package/lib/esm/routes.js.map +1 -1
- package/lib/esm/server.d.ts +3 -1
- package/lib/esm/server.js +32 -19
- package/lib/esm/server.js.map +1 -1
- package/lib/esm/trust.d.ts +1 -1
- package/lib/esm/trust.js.map +1 -1
- package/lib/ui/assets/aws.browser-4ed993c7.js +1 -0
- package/lib/ui/assets/index-5ed0229d.js +77 -0
- package/lib/ui/index.html +1 -1
- package/package.json +13 -7
- package/src/aws.browser.ts +1 -0
- package/src/aws.ts +250 -1
- package/src/cli.ts +676 -354
- package/src/client.ts +76 -11
- package/src/docker.browser.ts +1 -0
- package/src/domain.ts +1 -1
- package/src/peerbit.ts +1 -1
- package/src/remotes.ts +24 -10
- package/src/routes.ts +5 -4
- package/src/server.ts +43 -23
- package/src/trust.ts +1 -1
- package/lib/ui/assets/index-cac7195d.js +0 -77
package/lib/esm/cli.js
CHANGED
|
@@ -1,22 +1,88 @@
|
|
|
1
1
|
import { createTestDomain, getDomainFromConfig, loadConfig, startCertbot, } from "./domain.js";
|
|
2
2
|
import { startServerWithNode } from "./server.js";
|
|
3
|
-
import { createRecord } from "./aws.js";
|
|
3
|
+
import { AWS_LINUX_ARM_AMIs, createRecord, launchNodes, terminateNode, } from "./aws.js";
|
|
4
4
|
import { getHomeConfigDir, getKeypair, getPackageName, getRemotesPath, } from "./config.js";
|
|
5
5
|
import chalk from "chalk";
|
|
6
|
-
import {
|
|
6
|
+
import { createClient, waitForDomain } from "./client.js";
|
|
7
7
|
import { exit } from "process";
|
|
8
8
|
import readline from "readline";
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
11
11
|
import { toBase64 } from "@peerbit/crypto";
|
|
12
|
-
import { Remotes } from "./remotes.js";
|
|
12
|
+
import { DEFAULT_REMOTE_GROUP, Remotes } from "./remotes.js";
|
|
13
13
|
import { peerIdFromString } from "@libp2p/peer-id";
|
|
14
|
-
|
|
14
|
+
import { LOCAL_API_PORT } from "./routes.js";
|
|
15
|
+
const colors = [
|
|
16
|
+
"#00FF00",
|
|
17
|
+
"#0000FF",
|
|
18
|
+
"#FF0000",
|
|
19
|
+
"#01FFFE",
|
|
20
|
+
"#FFA6FE",
|
|
21
|
+
"#FFDB66",
|
|
22
|
+
"#006401",
|
|
23
|
+
"#010067",
|
|
24
|
+
"#95003A",
|
|
25
|
+
"#007DB5",
|
|
26
|
+
"#FF00F6",
|
|
27
|
+
"#FFEEE8",
|
|
28
|
+
"#774D00",
|
|
29
|
+
"#90FB92",
|
|
30
|
+
"#0076FF",
|
|
31
|
+
"#D5FF00",
|
|
32
|
+
"#FF937E",
|
|
33
|
+
"#6A826C",
|
|
34
|
+
"#FF029D",
|
|
35
|
+
"#FE8900",
|
|
36
|
+
"#7A4782",
|
|
37
|
+
"#7E2DD2",
|
|
38
|
+
"#85A900",
|
|
39
|
+
"#FF0056",
|
|
40
|
+
"#A42400",
|
|
41
|
+
"#00AE7E",
|
|
42
|
+
"#683D3B",
|
|
43
|
+
"#BDC6FF",
|
|
44
|
+
"#263400",
|
|
45
|
+
"#BDD393",
|
|
46
|
+
"#00B917",
|
|
47
|
+
"#9E008E",
|
|
48
|
+
"#001544",
|
|
49
|
+
"#C28C9F",
|
|
50
|
+
"#FF74A3",
|
|
51
|
+
"#01D0FF",
|
|
52
|
+
"#004754",
|
|
53
|
+
"#E56FFE",
|
|
54
|
+
"#788231",
|
|
55
|
+
"#0E4CA1",
|
|
56
|
+
"#91D0CB",
|
|
57
|
+
"#BE9970",
|
|
58
|
+
"#968AE8",
|
|
59
|
+
"#BB8800",
|
|
60
|
+
"#43002C",
|
|
61
|
+
"#DEFF74",
|
|
62
|
+
"#00FFC6",
|
|
63
|
+
"#FFE502",
|
|
64
|
+
"#620E00",
|
|
65
|
+
"#008F9C",
|
|
66
|
+
"#98FF52",
|
|
67
|
+
"#7544B1",
|
|
68
|
+
"#B500FF",
|
|
69
|
+
"#00FF78",
|
|
70
|
+
"#FF6E41",
|
|
71
|
+
"#005F39",
|
|
72
|
+
"#6B6882",
|
|
73
|
+
"#5FAD4E",
|
|
74
|
+
"#A75740",
|
|
75
|
+
"#A5FFD2",
|
|
76
|
+
"#FFB167",
|
|
77
|
+
"#009BFF",
|
|
78
|
+
"#E85EBE",
|
|
79
|
+
];
|
|
80
|
+
const padString = function (string, padding, padChar = " ", stringLength = string.valueOf().length) {
|
|
15
81
|
const val = string.valueOf();
|
|
16
|
-
if (Math.abs(padding) <=
|
|
82
|
+
if (Math.abs(padding) <= stringLength) {
|
|
17
83
|
return val;
|
|
18
84
|
}
|
|
19
|
-
const m = Math.max(Math.abs(padding) -
|
|
85
|
+
const m = Math.max(Math.abs(padding) - stringLength || 0, 0);
|
|
20
86
|
const pad = Array(m + 1).join(String(padChar).charAt(0));
|
|
21
87
|
// var pad = String(c || ' ').charAt(0).repeat(Math.abs(n) - this.length);
|
|
22
88
|
return padding < 0 ? pad + val : val + pad;
|
|
@@ -46,6 +112,13 @@ export const cli = async (args) => {
|
|
|
46
112
|
describe: "Whether to connect to bootstap nodes on startup",
|
|
47
113
|
type: "boolean",
|
|
48
114
|
default: false,
|
|
115
|
+
})
|
|
116
|
+
.option("grant-access", {
|
|
117
|
+
describe: "Grant access to public keys on start",
|
|
118
|
+
defaultDescription: "The publickey of this device located in 'directory'",
|
|
119
|
+
type: "string",
|
|
120
|
+
array: true,
|
|
121
|
+
alias: "ga",
|
|
49
122
|
})
|
|
50
123
|
.option("reset", {
|
|
51
124
|
describe: "If true, then programs opened during last session will not be opened",
|
|
@@ -72,6 +145,7 @@ export const cli = async (args) => {
|
|
|
72
145
|
ports: { api: args["port-api"], node: args["port-node"] },
|
|
73
146
|
bootstrap: args.bootstrap,
|
|
74
147
|
newSession: args.reset,
|
|
148
|
+
grantAccess: args["grant-access"],
|
|
75
149
|
});
|
|
76
150
|
},
|
|
77
151
|
})
|
|
@@ -195,6 +269,156 @@ export const cli = async (args) => {
|
|
|
195
269
|
})
|
|
196
270
|
.command("remote", "Handle remote nodes", (innerYargs) => {
|
|
197
271
|
innerYargs
|
|
272
|
+
.command("spawn", "Spawn remote nodes", (spawnYargs) => {
|
|
273
|
+
spawnYargs
|
|
274
|
+
.command({
|
|
275
|
+
command: "aws",
|
|
276
|
+
describe: "Spawn remote nodes on AWS",
|
|
277
|
+
builder: (awsArgs) => {
|
|
278
|
+
awsArgs.option("count", {
|
|
279
|
+
describe: "Amount of nodes to spawn",
|
|
280
|
+
defaultDescription: "One node",
|
|
281
|
+
type: "number",
|
|
282
|
+
alias: "c",
|
|
283
|
+
default: 1,
|
|
284
|
+
});
|
|
285
|
+
awsArgs.option("region", {
|
|
286
|
+
describe: "Region",
|
|
287
|
+
type: "string",
|
|
288
|
+
defaultDescription: "Region defined in ~.aws/config",
|
|
289
|
+
choices: Object.keys(AWS_LINUX_ARM_AMIs),
|
|
290
|
+
});
|
|
291
|
+
awsArgs.option("group", {
|
|
292
|
+
describe: "Remote group to launch nodes in",
|
|
293
|
+
type: "string",
|
|
294
|
+
alias: "g",
|
|
295
|
+
default: DEFAULT_REMOTE_GROUP,
|
|
296
|
+
});
|
|
297
|
+
awsArgs.option("size", {
|
|
298
|
+
describe: "Instance size",
|
|
299
|
+
type: "string",
|
|
300
|
+
alias: "s",
|
|
301
|
+
choices: [
|
|
302
|
+
"micro",
|
|
303
|
+
"small",
|
|
304
|
+
"medium",
|
|
305
|
+
"large",
|
|
306
|
+
"xlarge",
|
|
307
|
+
"2xlarge",
|
|
308
|
+
],
|
|
309
|
+
default: "micro",
|
|
310
|
+
});
|
|
311
|
+
awsArgs.option("name", {
|
|
312
|
+
describe: "Name prefix for spawned nodes",
|
|
313
|
+
type: "string",
|
|
314
|
+
alias: "n",
|
|
315
|
+
default: "peerbit-node",
|
|
316
|
+
});
|
|
317
|
+
awsArgs.option("grant-access", {
|
|
318
|
+
describe: "Grant access to public keys on start",
|
|
319
|
+
defaultDescription: "The publickey of this device located in 'directory'",
|
|
320
|
+
type: "string",
|
|
321
|
+
array: true,
|
|
322
|
+
alias: "ga",
|
|
323
|
+
});
|
|
324
|
+
awsArgs.option("directory", {
|
|
325
|
+
describe: "Peerbit directory",
|
|
326
|
+
defaultDescription: "~.peerbit",
|
|
327
|
+
type: "string",
|
|
328
|
+
alias: "d",
|
|
329
|
+
default: getHomeConfigDir(),
|
|
330
|
+
});
|
|
331
|
+
return awsArgs;
|
|
332
|
+
},
|
|
333
|
+
handler: async (args) => {
|
|
334
|
+
const accessGrant = args.access?.length > 0
|
|
335
|
+
? args.access.map((x) => peerIdFromString(x))
|
|
336
|
+
: [
|
|
337
|
+
await (await getKeypair(args.directory)).publicKey.toPeerId(),
|
|
338
|
+
];
|
|
339
|
+
const nodes = await launchNodes({
|
|
340
|
+
email: "marcus@dao.xyz",
|
|
341
|
+
count: args.number,
|
|
342
|
+
namePrefix: args.name,
|
|
343
|
+
region: args.region,
|
|
344
|
+
grantAccess: accessGrant,
|
|
345
|
+
size: args.size,
|
|
346
|
+
});
|
|
347
|
+
console.log(`Waiting for ${args.count} ${args.count > 1 ? "nodes" : "node"} to spawn. This might take a few minutes. You can watch the progress in your AWS console.`);
|
|
348
|
+
const twirlTimer = (function () {
|
|
349
|
+
const P = ["\\", "|", "/", "-"];
|
|
350
|
+
let x = 0;
|
|
351
|
+
return setInterval(function () {
|
|
352
|
+
process.stdout.write("\r" + "Loading: " + chalk.hex(colors[x])(P[x++]));
|
|
353
|
+
x &= 3;
|
|
354
|
+
}, 250);
|
|
355
|
+
})();
|
|
356
|
+
try {
|
|
357
|
+
for (const node of nodes) {
|
|
358
|
+
const domain = await waitForDomain(node.publicIp);
|
|
359
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
360
|
+
remotes.add({
|
|
361
|
+
name: node.name,
|
|
362
|
+
address: domain,
|
|
363
|
+
group: args.group,
|
|
364
|
+
origin: {
|
|
365
|
+
type: "aws",
|
|
366
|
+
instanceId: node.instanceId,
|
|
367
|
+
region: node.region,
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
console.error("Error waiting for domains to be available: " +
|
|
374
|
+
error?.toString());
|
|
375
|
+
}
|
|
376
|
+
finally {
|
|
377
|
+
clearInterval(twirlTimer);
|
|
378
|
+
process.stdout.write("\r");
|
|
379
|
+
}
|
|
380
|
+
console.log(`New nodes available ${nodes.length}:`);
|
|
381
|
+
for (const node of nodes) {
|
|
382
|
+
console.log(chalk.green(node.name));
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
})
|
|
386
|
+
.strict()
|
|
387
|
+
.demandCommand();
|
|
388
|
+
})
|
|
389
|
+
.command({
|
|
390
|
+
command: "terminate [name...]",
|
|
391
|
+
describe: "Terminate remote instances that was previously spawned",
|
|
392
|
+
builder: (killArgs) => {
|
|
393
|
+
killArgs.option("all", {
|
|
394
|
+
describe: "Kill all nodes",
|
|
395
|
+
type: "boolean",
|
|
396
|
+
default: false,
|
|
397
|
+
});
|
|
398
|
+
killArgs.positional("name", {
|
|
399
|
+
type: "string",
|
|
400
|
+
describe: "Remote name",
|
|
401
|
+
default: "localhost",
|
|
402
|
+
demandOption: false,
|
|
403
|
+
array: true,
|
|
404
|
+
});
|
|
405
|
+
return killArgs;
|
|
406
|
+
},
|
|
407
|
+
handler: async (args) => {
|
|
408
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
409
|
+
const allRemotes = await remotes.all();
|
|
410
|
+
for (const remote of allRemotes) {
|
|
411
|
+
if (args.all || args.name.includes(remote.name)) {
|
|
412
|
+
if (remote.origin?.type === "aws") {
|
|
413
|
+
await terminateNode({
|
|
414
|
+
instanceId: remote.origin.instanceId,
|
|
415
|
+
region: remote.origin.region,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
})
|
|
198
422
|
.command({
|
|
199
423
|
command: "list",
|
|
200
424
|
aliases: "ls",
|
|
@@ -219,8 +443,9 @@ export const cli = async (args) => {
|
|
|
219
443
|
}, 0);
|
|
220
444
|
const all = await remotes.all();
|
|
221
445
|
if (all.length > 0) {
|
|
446
|
+
console.log(padString("Name", maxNameLength + 10), padString("Group" || "", 10), "Address");
|
|
222
447
|
for (const remote of all) {
|
|
223
|
-
console.log(padString(remote.name, maxNameLength + 10), remote.address);
|
|
448
|
+
console.log(padString(remote.name, maxNameLength + 10), padString(remote.group || "", 10), remote.address);
|
|
224
449
|
}
|
|
225
450
|
}
|
|
226
451
|
else {
|
|
@@ -233,15 +458,21 @@ export const cli = async (args) => {
|
|
|
233
458
|
describe: "Add remote",
|
|
234
459
|
builder: (yargs) => {
|
|
235
460
|
yargs
|
|
461
|
+
.positional("name", {
|
|
462
|
+
type: "string",
|
|
463
|
+
describe: "Remote address",
|
|
464
|
+
demandOption: true,
|
|
465
|
+
})
|
|
236
466
|
.positional("address", {
|
|
237
467
|
type: "string",
|
|
238
468
|
describe: "Remote name",
|
|
239
469
|
demandOption: true,
|
|
240
470
|
})
|
|
241
|
-
.
|
|
471
|
+
.option("group", {
|
|
472
|
+
describe: "Group name",
|
|
242
473
|
type: "string",
|
|
243
|
-
|
|
244
|
-
|
|
474
|
+
alias: "g",
|
|
475
|
+
default: DEFAULT_REMOTE_GROUP,
|
|
245
476
|
})
|
|
246
477
|
.option("directory", {
|
|
247
478
|
describe: "Peerbit directory",
|
|
@@ -256,7 +487,9 @@ export const cli = async (args) => {
|
|
|
256
487
|
if (args.name === "localhost") {
|
|
257
488
|
throw new Error("Remote can not be named 'localhost'");
|
|
258
489
|
}
|
|
259
|
-
const api = await
|
|
490
|
+
const api = await createClient(await getKeypair(args.directory), {
|
|
491
|
+
address: args.address,
|
|
492
|
+
});
|
|
260
493
|
try {
|
|
261
494
|
await api.program.list();
|
|
262
495
|
}
|
|
@@ -267,7 +500,11 @@ export const cli = async (args) => {
|
|
|
267
500
|
fs.mkdirSync(args.directory, { recursive: true });
|
|
268
501
|
}
|
|
269
502
|
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
270
|
-
remotes.add(
|
|
503
|
+
remotes.add({
|
|
504
|
+
name: args.name,
|
|
505
|
+
address: args.address,
|
|
506
|
+
group: args.group,
|
|
507
|
+
});
|
|
271
508
|
},
|
|
272
509
|
})
|
|
273
510
|
.command({
|
|
@@ -310,6 +547,18 @@ export const cli = async (args) => {
|
|
|
310
547
|
default: "localhost",
|
|
311
548
|
demandOption: false,
|
|
312
549
|
array: true,
|
|
550
|
+
})
|
|
551
|
+
.option("all", {
|
|
552
|
+
type: "boolean",
|
|
553
|
+
describe: "Connect to all nodes",
|
|
554
|
+
default: false,
|
|
555
|
+
})
|
|
556
|
+
.option("group", {
|
|
557
|
+
type: "string",
|
|
558
|
+
describe: "Remote group name",
|
|
559
|
+
alias: "g",
|
|
560
|
+
default: [],
|
|
561
|
+
array: true,
|
|
313
562
|
})
|
|
314
563
|
.option("directory", {
|
|
315
564
|
describe: "Peerbit directory",
|
|
@@ -321,19 +570,24 @@ export const cli = async (args) => {
|
|
|
321
570
|
return yargs;
|
|
322
571
|
},
|
|
323
572
|
handler: async (connectArgs) => {
|
|
324
|
-
const
|
|
573
|
+
const remotes = new Remotes(getRemotesPath(connectArgs.directory));
|
|
574
|
+
let names = connectArgs.name;
|
|
575
|
+
if (names.length === 0 ||
|
|
576
|
+
connectArgs.all ||
|
|
577
|
+
connectArgs.group.length > 0) {
|
|
578
|
+
names = (await remotes.all()).map((x) => x.name);
|
|
579
|
+
}
|
|
325
580
|
const apis = [];
|
|
326
|
-
console.log(getRemotesPath(connectArgs.directory));
|
|
327
581
|
const config = await import("./config.js");
|
|
328
582
|
const keypair = await config.getKeypair(connectArgs.directory);
|
|
583
|
+
const selectedRemotes = [];
|
|
329
584
|
if (names.length > 0) {
|
|
330
|
-
const
|
|
331
|
-
for (const name of names) {
|
|
585
|
+
for (const [ix, name] of names.entries()) {
|
|
332
586
|
if (name === "localhost") {
|
|
333
|
-
|
|
334
|
-
|
|
587
|
+
selectedRemotes.push({
|
|
588
|
+
address: "http://localhost:" + LOCAL_API_PORT,
|
|
335
589
|
name: "localhost",
|
|
336
|
-
|
|
590
|
+
group: DEFAULT_REMOTE_GROUP,
|
|
337
591
|
});
|
|
338
592
|
}
|
|
339
593
|
else {
|
|
@@ -341,351 +595,365 @@ export const cli = async (args) => {
|
|
|
341
595
|
if (!remote) {
|
|
342
596
|
throw new Error("Missing remote with name: " + name);
|
|
343
597
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
598
|
+
if (connectArgs.group.length > 0 &&
|
|
599
|
+
!connectArgs.group.includes(remote.group)) {
|
|
600
|
+
continue;
|
|
347
601
|
}
|
|
348
|
-
|
|
349
|
-
logFn = (string) => console.log(string);
|
|
350
|
-
}
|
|
351
|
-
apis.push({
|
|
352
|
-
log: logFn,
|
|
353
|
-
name,
|
|
354
|
-
api: await client(keypair, remote.address),
|
|
355
|
-
});
|
|
602
|
+
selectedRemotes.push(remote);
|
|
356
603
|
}
|
|
357
604
|
}
|
|
358
605
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
606
|
+
const maxNameLength = selectedRemotes
|
|
607
|
+
.map((x) => x.name.length)
|
|
608
|
+
.reduce((prev, c, i) => {
|
|
609
|
+
return Math.max(prev, c);
|
|
610
|
+
}, 0);
|
|
611
|
+
if (selectedRemotes.length === 0) {
|
|
612
|
+
console.log(chalk.red("No remotes matched your connection condition"));
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
console.log(`Connected to (${selectedRemotes.length}):`);
|
|
616
|
+
for (const [ix, remote] of selectedRemotes.entries()) {
|
|
617
|
+
const chalkBg = chalk.bgHex(colors[ix]);
|
|
618
|
+
console.log(chalkBg(remote.name));
|
|
619
|
+
const logFn = (string) => console.log(padString(chalkBg(remote.name), maxNameLength, " ", remote.name.length) +
|
|
620
|
+
": " +
|
|
621
|
+
string);
|
|
622
|
+
apis.push({
|
|
623
|
+
log: logFn,
|
|
624
|
+
name: remote.name,
|
|
625
|
+
api: await createClient(keypair, remote),
|
|
626
|
+
});
|
|
363
627
|
}
|
|
364
|
-
|
|
365
|
-
|
|
628
|
+
// try if authenticated
|
|
629
|
+
for (const api of apis) {
|
|
630
|
+
try {
|
|
631
|
+
await api.api.program.list();
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
throw new Error(`Failed to connect to '${api.name}': ${error?.toString()}`);
|
|
635
|
+
}
|
|
366
636
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
yargs.positional("peer-id", {
|
|
401
|
-
describe: "Peer id",
|
|
402
|
-
type: "string",
|
|
403
|
-
demandOption: true,
|
|
404
|
-
});
|
|
405
|
-
return yargs;
|
|
406
|
-
},
|
|
407
|
-
handler: async (args) => {
|
|
408
|
-
const peerId = peerIdFromString(args["peer-id"]);
|
|
409
|
-
for (const api of apis) {
|
|
410
|
-
await api.api.trust.add(peerId);
|
|
411
|
-
}
|
|
412
|
-
},
|
|
637
|
+
const rl = readline.createInterface({
|
|
638
|
+
input: process.stdin,
|
|
639
|
+
output: process.stdout,
|
|
640
|
+
terminal: true,
|
|
641
|
+
historySize: 100,
|
|
642
|
+
});
|
|
643
|
+
console.log("Write 'help' to show commands.\n");
|
|
644
|
+
rl.prompt(false);
|
|
645
|
+
const capi = () => yargs
|
|
646
|
+
.default()
|
|
647
|
+
.command("peer", "Peer info", (yargs) => {
|
|
648
|
+
yargs
|
|
649
|
+
.command({
|
|
650
|
+
command: "id",
|
|
651
|
+
describe: "Get peer id",
|
|
652
|
+
handler: async (args) => {
|
|
653
|
+
for (const api of apis) {
|
|
654
|
+
api.log((await api.api.peer.id.get()).toString());
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
})
|
|
658
|
+
.command({
|
|
659
|
+
command: "address",
|
|
660
|
+
describe: "Get addresses",
|
|
661
|
+
handler: async (args) => {
|
|
662
|
+
for (const api of apis) {
|
|
663
|
+
(await api.api.peer.addresses.get()).forEach((x) => api.log(x.toString()));
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
})
|
|
667
|
+
.strict()
|
|
668
|
+
.demandCommand();
|
|
669
|
+
return yargs;
|
|
413
670
|
})
|
|
414
|
-
.command({
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
671
|
+
.command("access", "Modify access control for this node", (yargs) => {
|
|
672
|
+
yargs
|
|
673
|
+
.command({
|
|
674
|
+
command: "grant <peer-id>",
|
|
675
|
+
describe: "Give a peer-id admin capabilities",
|
|
676
|
+
builder: (yargs) => {
|
|
677
|
+
yargs.positional("peer-id", {
|
|
678
|
+
describe: "Peer id",
|
|
679
|
+
type: "string",
|
|
680
|
+
demandOption: true,
|
|
681
|
+
});
|
|
682
|
+
return yargs;
|
|
683
|
+
},
|
|
684
|
+
handler: async (args) => {
|
|
685
|
+
const peerId = peerIdFromString(args["peer-id"]);
|
|
686
|
+
for (const api of apis) {
|
|
687
|
+
await api.api.access.allow(peerId);
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
})
|
|
691
|
+
.command({
|
|
692
|
+
command: "deny <peer-id>",
|
|
693
|
+
describe: "Remove admin capabilities from peer-id",
|
|
694
|
+
builder: (yargs) => {
|
|
695
|
+
yargs.positional("peer-id", {
|
|
696
|
+
describe: "Peer id",
|
|
697
|
+
demandOption: true,
|
|
698
|
+
});
|
|
699
|
+
return yargs;
|
|
700
|
+
},
|
|
701
|
+
handler: async (args) => {
|
|
702
|
+
const peerId = peerIdFromString(args["peer-id"]);
|
|
703
|
+
for (const api of apis) {
|
|
704
|
+
await api.api.access.deny(peerId);
|
|
705
|
+
}
|
|
706
|
+
},
|
|
707
|
+
})
|
|
708
|
+
.strict()
|
|
709
|
+
.demandCommand();
|
|
430
710
|
})
|
|
431
|
-
.
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
711
|
+
.command("network", "Manage network", (yargs) => {
|
|
712
|
+
yargs
|
|
713
|
+
.command({
|
|
714
|
+
command: "bootstrap",
|
|
715
|
+
describe: "Connect to bootstrap nodes",
|
|
716
|
+
handler: async () => {
|
|
717
|
+
for (const api of apis) {
|
|
718
|
+
await api.api.network.bootstrap();
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
})
|
|
722
|
+
.strict()
|
|
723
|
+
.demandCommand();
|
|
444
724
|
})
|
|
445
|
-
.
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
console.log(
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
725
|
+
.command("topic", "Manage topics the node is listening to", (yargs) => {
|
|
726
|
+
yargs
|
|
727
|
+
.command({
|
|
728
|
+
command: "list",
|
|
729
|
+
aliases: "ls",
|
|
730
|
+
describe: "List all topics",
|
|
731
|
+
builder: (yargs) => {
|
|
732
|
+
yargs.option("replicate", {
|
|
733
|
+
type: "boolean",
|
|
734
|
+
describe: "Replicate data on this topic",
|
|
735
|
+
aliases: "r",
|
|
736
|
+
default: false,
|
|
737
|
+
});
|
|
738
|
+
return yargs;
|
|
739
|
+
},
|
|
740
|
+
handler: async (args) => {
|
|
741
|
+
/* const c = await client();
|
|
742
|
+
const topics = await c.topics.get(args.replicate);
|
|
743
|
+
if (topics?.length > 0) {
|
|
744
|
+
console.log("Topic (" + topics.length + "):");
|
|
745
|
+
for (const t of topics) {
|
|
746
|
+
console.log(t);
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
console.log("Not subscribed to any topics");
|
|
750
|
+
} */
|
|
751
|
+
console.error("Not implemented");
|
|
752
|
+
},
|
|
753
|
+
})
|
|
754
|
+
.strict()
|
|
755
|
+
.demandCommand();
|
|
756
|
+
return yargs;
|
|
476
757
|
})
|
|
477
|
-
.
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
758
|
+
.command("program", "Manage programs", (yargs) => {
|
|
759
|
+
yargs
|
|
760
|
+
.command({
|
|
761
|
+
command: "status <address>",
|
|
762
|
+
describe: "Is a program open",
|
|
763
|
+
builder: (yargs) => {
|
|
764
|
+
yargs.positional("address", {
|
|
765
|
+
type: "string",
|
|
766
|
+
describe: "Program address",
|
|
767
|
+
demandOption: true,
|
|
768
|
+
});
|
|
769
|
+
return yargs;
|
|
770
|
+
},
|
|
771
|
+
handler: async (args) => {
|
|
772
|
+
for (const api of apis) {
|
|
773
|
+
const program = await api.api.program.has(args.address);
|
|
774
|
+
if (!program) {
|
|
775
|
+
api.log(chalk.red("Closed"));
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
api.log(chalk.green("Open"));
|
|
779
|
+
}
|
|
499
780
|
}
|
|
500
|
-
|
|
501
|
-
|
|
781
|
+
},
|
|
782
|
+
})
|
|
783
|
+
.command({
|
|
784
|
+
command: "drop <address>",
|
|
785
|
+
describe: "Drop a program",
|
|
786
|
+
builder: (yargs) => {
|
|
787
|
+
yargs.positional("address", {
|
|
788
|
+
type: "string",
|
|
789
|
+
describe: "Program address",
|
|
790
|
+
demandOption: true,
|
|
791
|
+
});
|
|
792
|
+
return yargs;
|
|
793
|
+
},
|
|
794
|
+
handler: async (args) => {
|
|
795
|
+
for (const api of apis) {
|
|
796
|
+
try {
|
|
797
|
+
await api.api.program.drop(args.address);
|
|
798
|
+
}
|
|
799
|
+
catch (error) {
|
|
800
|
+
api.log(chalk.red(`Failed to drop ${args.address}: ${error.toString()}`));
|
|
801
|
+
}
|
|
502
802
|
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
try {
|
|
520
|
-
await api.api.program.drop(args.address);
|
|
803
|
+
},
|
|
804
|
+
})
|
|
805
|
+
.command({
|
|
806
|
+
command: "close <address>",
|
|
807
|
+
describe: "Close a program",
|
|
808
|
+
builder: (yargs) => {
|
|
809
|
+
yargs.positional("address", {
|
|
810
|
+
type: "string",
|
|
811
|
+
describe: "Program address",
|
|
812
|
+
demandOption: true,
|
|
813
|
+
});
|
|
814
|
+
return yargs;
|
|
815
|
+
},
|
|
816
|
+
handler: async (args) => {
|
|
817
|
+
for (const api of apis) {
|
|
818
|
+
await api.api.program.close(args.address);
|
|
521
819
|
}
|
|
522
|
-
|
|
523
|
-
|
|
820
|
+
},
|
|
821
|
+
})
|
|
822
|
+
.command({
|
|
823
|
+
command: "list",
|
|
824
|
+
describe: "List all running programs",
|
|
825
|
+
aliases: "ls",
|
|
826
|
+
handler: async (args) => {
|
|
827
|
+
for (const api of apis) {
|
|
828
|
+
const list = await api.api.program.list();
|
|
829
|
+
api.log(`Running programs (${list.length}):`);
|
|
830
|
+
list.forEach((p) => {
|
|
831
|
+
api.log(chalk.green(p));
|
|
832
|
+
});
|
|
524
833
|
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
834
|
+
},
|
|
835
|
+
})
|
|
836
|
+
.command({
|
|
837
|
+
command: "open [program]",
|
|
838
|
+
describe: "Open program",
|
|
839
|
+
builder: (yargs) => {
|
|
840
|
+
yargs.positional("program", {
|
|
841
|
+
type: "string",
|
|
842
|
+
describe: "Identifier",
|
|
843
|
+
demandOption: true,
|
|
844
|
+
});
|
|
845
|
+
yargs.option("base64", {
|
|
846
|
+
type: "string",
|
|
847
|
+
describe: "Base64 encoded serialized",
|
|
848
|
+
aliases: "b",
|
|
849
|
+
});
|
|
850
|
+
yargs.option("variant", {
|
|
851
|
+
type: "string",
|
|
852
|
+
describe: "Variant name",
|
|
853
|
+
aliases: "v",
|
|
854
|
+
});
|
|
855
|
+
return yargs;
|
|
856
|
+
},
|
|
857
|
+
handler: async (args) => {
|
|
858
|
+
if (!args.base64 && !args.variant) {
|
|
859
|
+
throw new Error("Either base64 or variant argument needs to be provided");
|
|
860
|
+
}
|
|
861
|
+
let startArg;
|
|
862
|
+
if (args.base64) {
|
|
863
|
+
startArg = {
|
|
864
|
+
base64: args.base64,
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
startArg = {
|
|
869
|
+
variant: args.variant,
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
for (const api of apis) {
|
|
873
|
+
const address = await api.api.program.open(startArg);
|
|
874
|
+
api.log("Started program with address: ");
|
|
875
|
+
api.log(chalk.green(address.toString()));
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
})
|
|
879
|
+
.strict()
|
|
880
|
+
.demandCommand();
|
|
881
|
+
return yargs;
|
|
527
882
|
})
|
|
528
883
|
.command({
|
|
529
|
-
command: "
|
|
530
|
-
describe: "
|
|
884
|
+
command: "install <package-spec>",
|
|
885
|
+
describe: "install and import a dependency",
|
|
531
886
|
builder: (yargs) => {
|
|
532
|
-
yargs.positional("
|
|
887
|
+
yargs.positional("package-spec", {
|
|
533
888
|
type: "string",
|
|
534
|
-
describe: "
|
|
889
|
+
describe: "Installed dependency will be loaded with js import(...)",
|
|
535
890
|
demandOption: true,
|
|
536
891
|
});
|
|
537
892
|
return yargs;
|
|
538
893
|
},
|
|
539
894
|
handler: async (args) => {
|
|
895
|
+
// if ends with .tgz assume it is a file
|
|
896
|
+
let installCommand;
|
|
897
|
+
const packageName = args["package-spec"];
|
|
898
|
+
if (packageName.endsWith(".tgz")) {
|
|
899
|
+
const packagePath = path.isAbsolute(packageName)
|
|
900
|
+
? packageName
|
|
901
|
+
: path.join(process.cwd(), packageName);
|
|
902
|
+
const buffer = fs.readFileSync(packagePath);
|
|
903
|
+
const base64 = toBase64(buffer);
|
|
904
|
+
installCommand = {
|
|
905
|
+
type: "tgz",
|
|
906
|
+
name: await getPackageName(packageName),
|
|
907
|
+
base64,
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
installCommand = { type: "npm", name: packageName };
|
|
912
|
+
}
|
|
540
913
|
for (const api of apis) {
|
|
541
|
-
await api.api.
|
|
914
|
+
const newPrograms = await api.api.dependency.install(installCommand);
|
|
915
|
+
api.log(`New programs available (${newPrograms.length}):`);
|
|
916
|
+
newPrograms.forEach((p) => {
|
|
917
|
+
api.log(chalk.green(p));
|
|
918
|
+
});
|
|
542
919
|
}
|
|
543
920
|
},
|
|
544
921
|
})
|
|
545
922
|
.command({
|
|
546
|
-
command: "
|
|
547
|
-
describe: "
|
|
548
|
-
|
|
549
|
-
handler: async (args) => {
|
|
923
|
+
command: "restart",
|
|
924
|
+
describe: "Restart the server",
|
|
925
|
+
handler: async () => {
|
|
550
926
|
for (const api of apis) {
|
|
551
|
-
|
|
552
|
-
api.log(`Running programs (${list.length}):`);
|
|
553
|
-
list.forEach((p) => {
|
|
554
|
-
api.log(chalk.green(p));
|
|
555
|
-
});
|
|
927
|
+
await api.api.restart();
|
|
556
928
|
}
|
|
557
929
|
},
|
|
558
930
|
})
|
|
559
931
|
.command({
|
|
560
|
-
command: "
|
|
561
|
-
describe: "
|
|
562
|
-
|
|
563
|
-
yargs.positional("program", {
|
|
564
|
-
type: "string",
|
|
565
|
-
describe: "Identifier",
|
|
566
|
-
demandOption: true,
|
|
567
|
-
});
|
|
568
|
-
yargs.option("base64", {
|
|
569
|
-
type: "string",
|
|
570
|
-
describe: "Base64 encoded serialized",
|
|
571
|
-
aliases: "b",
|
|
572
|
-
});
|
|
573
|
-
yargs.option("variant", {
|
|
574
|
-
type: "string",
|
|
575
|
-
describe: "Variant name",
|
|
576
|
-
aliases: "v",
|
|
577
|
-
});
|
|
578
|
-
return yargs;
|
|
579
|
-
},
|
|
580
|
-
handler: async (args) => {
|
|
581
|
-
if (!args.base64 && !args.variant) {
|
|
582
|
-
throw new Error("Either base64 or variant argument needs to be provided");
|
|
583
|
-
}
|
|
584
|
-
let startArg;
|
|
585
|
-
if (args.base64) {
|
|
586
|
-
startArg = {
|
|
587
|
-
base64: args.base64,
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
else {
|
|
591
|
-
startArg = {
|
|
592
|
-
variant: args.variant,
|
|
593
|
-
};
|
|
594
|
-
}
|
|
932
|
+
command: "stop",
|
|
933
|
+
describe: "Stop the server",
|
|
934
|
+
handler: async () => {
|
|
595
935
|
for (const api of apis) {
|
|
596
|
-
|
|
597
|
-
api.log("Started program with address: ");
|
|
598
|
-
api.log(chalk.green(address.toString()));
|
|
936
|
+
await api.api.stop();
|
|
599
937
|
}
|
|
600
938
|
},
|
|
601
939
|
})
|
|
940
|
+
.help()
|
|
602
941
|
.strict()
|
|
603
|
-
.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
type: "string",
|
|
612
|
-
describe: "Installed dependency will be loaded with js import(...)",
|
|
613
|
-
demandOption: true,
|
|
614
|
-
});
|
|
615
|
-
return yargs;
|
|
616
|
-
},
|
|
617
|
-
handler: async (args) => {
|
|
618
|
-
// if ends with .tgz assume it is a file
|
|
619
|
-
let installCommand;
|
|
620
|
-
const packageName = args["package-spec"];
|
|
621
|
-
if (packageName.endsWith(".tgz")) {
|
|
622
|
-
const packagePath = path.isAbsolute(packageName)
|
|
623
|
-
? packageName
|
|
624
|
-
: path.join(process.cwd(), packageName);
|
|
625
|
-
const buffer = fs.readFileSync(packagePath);
|
|
626
|
-
const base64 = toBase64(buffer);
|
|
627
|
-
installCommand = {
|
|
628
|
-
type: "tgz",
|
|
629
|
-
name: await getPackageName(packageName),
|
|
630
|
-
base64,
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
installCommand = { type: "npm", name: packageName };
|
|
942
|
+
.scriptName("")
|
|
943
|
+
.demandCommand()
|
|
944
|
+
.showHelpOnFail(true)
|
|
945
|
+
.exitProcess(false);
|
|
946
|
+
rl.on("line", async (cargs) => {
|
|
947
|
+
const cmds = capi();
|
|
948
|
+
try {
|
|
949
|
+
await cmds.parse(cargs);
|
|
635
950
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
api.log(`New programs available (${newPrograms.length}):`);
|
|
639
|
-
newPrograms.forEach((p) => {
|
|
640
|
-
api.log(chalk.green(p));
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
})
|
|
645
|
-
.command({
|
|
646
|
-
command: "restart",
|
|
647
|
-
describe: "Restart the server",
|
|
648
|
-
handler: async () => {
|
|
649
|
-
for (const api of apis) {
|
|
650
|
-
await api.api.restart();
|
|
951
|
+
catch (error) {
|
|
952
|
+
/* console.log(chalk.red("Error parsing command: " + cargs))*/
|
|
651
953
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
command: "terminate",
|
|
656
|
-
describe: "Terminate the server",
|
|
657
|
-
handler: async () => {
|
|
658
|
-
for (const api of apis) {
|
|
659
|
-
await api.api.terminate();
|
|
660
|
-
}
|
|
661
|
-
},
|
|
662
|
-
})
|
|
663
|
-
.help()
|
|
664
|
-
.strict()
|
|
665
|
-
.scriptName("")
|
|
666
|
-
.demandCommand()
|
|
667
|
-
.showHelpOnFail(true)
|
|
668
|
-
.exitProcess(false);
|
|
669
|
-
const rl = readline.createInterface({
|
|
670
|
-
input: process.stdin,
|
|
671
|
-
output: process.stdout,
|
|
672
|
-
terminal: true,
|
|
673
|
-
historySize: 100,
|
|
674
|
-
});
|
|
675
|
-
console.log(chalk.green("Connected"));
|
|
676
|
-
console.log("Write 'help' to show commands.\n");
|
|
677
|
-
const first = true;
|
|
678
|
-
rl.prompt(false);
|
|
679
|
-
rl.on("line", async (cargs) => {
|
|
680
|
-
const cmds = capi();
|
|
681
|
-
try {
|
|
682
|
-
await cmds.parse(cargs);
|
|
683
|
-
}
|
|
684
|
-
catch (error) {
|
|
685
|
-
/* console.log(chalk.red("Error parsing command: " + cargs))*/
|
|
686
|
-
}
|
|
687
|
-
rl.prompt(true);
|
|
688
|
-
});
|
|
954
|
+
rl.prompt(true);
|
|
955
|
+
});
|
|
956
|
+
}
|
|
689
957
|
},
|
|
690
958
|
})
|
|
691
959
|
.help()
|