@peerbit/server 1.1.2 → 3.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/cli.js +518 -144
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/client.d.ts +11 -3
- package/lib/esm/client.js +61 -27
- package/lib/esm/client.js.map +1 -1
- package/lib/esm/config.d.ts +8 -5
- package/lib/esm/config.js +44 -19
- package/lib/esm/config.js.map +1 -1
- package/lib/esm/peerbit.d.ts +4 -0
- package/lib/esm/peerbit.js +15 -2
- package/lib/esm/peerbit.js.map +1 -1
- package/lib/esm/remotes.browser.d.ts +0 -0
- package/lib/esm/remotes.browser.js +3 -0
- package/lib/esm/remotes.browser.js.map +1 -0
- package/lib/esm/remotes.d.ts +16 -0
- package/lib/esm/remotes.js +51 -0
- package/lib/esm/remotes.js.map +1 -0
- package/lib/esm/routes.d.ts +3 -0
- package/lib/esm/routes.js +3 -0
- package/lib/esm/routes.js.map +1 -1
- package/lib/esm/server.d.ts +14 -4
- package/lib/esm/server.js +297 -144
- package/lib/esm/server.js.map +1 -1
- package/lib/esm/session.d.ts +19 -0
- package/lib/esm/session.js +49 -0
- package/lib/esm/session.js.map +1 -0
- package/lib/esm/signes-request.d.ts +5 -0
- package/lib/esm/signes-request.js +54 -0
- package/lib/esm/signes-request.js.map +1 -0
- package/lib/esm/trust.browser.d.ts +0 -0
- package/lib/esm/trust.browser.js +3 -0
- package/lib/esm/trust.browser.js.map +1 -0
- package/lib/esm/trust.d.ts +9 -0
- package/lib/esm/trust.js +36 -0
- package/lib/esm/trust.js.map +1 -0
- package/lib/esm/types.d.ts +10 -0
- package/lib/ui/assets/index-cac7195d.js +77 -0
- package/lib/ui/index.html +1 -1
- package/package.json +9 -5
- package/src/cli.ts +705 -271
- package/src/client.ts +105 -30
- package/src/config.ts +52 -25
- package/src/peerbit.ts +27 -3
- package/src/remotes.browser.ts +1 -0
- package/src/remotes.ts +63 -0
- package/src/routes.ts +3 -1
- package/src/server.ts +381 -190
- package/src/session.ts +69 -0
- package/src/signes-request.ts +84 -0
- package/src/trust.browser.ts +1 -0
- package/src/trust.ts +39 -0
- package/src/types.ts +13 -0
- package/lib/ui/assets/config.browser-4ed993c7.js +0 -1
- package/lib/ui/assets/index-a8188422.js +0 -53
package/src/cli.ts
CHANGED
|
@@ -6,10 +6,35 @@ import {
|
|
|
6
6
|
} from "./domain.js";
|
|
7
7
|
import { startServerWithNode } from "./server.js";
|
|
8
8
|
import { createRecord } from "./aws.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getHomeConfigDir,
|
|
11
|
+
getKeypair,
|
|
12
|
+
getPackageName,
|
|
13
|
+
getRemotesPath,
|
|
14
|
+
} from "./config.js";
|
|
10
15
|
import chalk from "chalk";
|
|
11
16
|
import { client } from "./client.js";
|
|
12
|
-
import { StartProgram } from "./types.js";
|
|
17
|
+
import { InstallDependency, StartProgram } from "./types.js";
|
|
18
|
+
import { exit } from "process";
|
|
19
|
+
import yargs from "yargs";
|
|
20
|
+
import readline from "readline";
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
import { toBase64 } from "@peerbit/crypto";
|
|
24
|
+
import { Remotes } from "./remotes.js";
|
|
25
|
+
import { peerIdFromString } from "@libp2p/peer-id";
|
|
26
|
+
|
|
27
|
+
const padString = function (string: string, padding: number, padChar = " ") {
|
|
28
|
+
const val = string.valueOf();
|
|
29
|
+
if (Math.abs(padding) <= val.length) {
|
|
30
|
+
return val;
|
|
31
|
+
}
|
|
32
|
+
const m = Math.max(Math.abs(padding) - string.length || 0, 0);
|
|
33
|
+
const pad = Array(m + 1).join(String(padChar).charAt(0));
|
|
34
|
+
// var pad = String(c || ' ').charAt(0).repeat(Math.abs(n) - this.length);
|
|
35
|
+
return padding < 0 ? pad + val : val + pad;
|
|
36
|
+
// return (n < 0) ? val + pad : pad + val;
|
|
37
|
+
};
|
|
13
38
|
|
|
14
39
|
export const cli = async (args?: string[]) => {
|
|
15
40
|
const yargs = await import("yargs");
|
|
@@ -24,19 +49,40 @@ export const cli = async (args?: string[]) => {
|
|
|
24
49
|
.command({
|
|
25
50
|
command: "start",
|
|
26
51
|
describe: "Start node",
|
|
27
|
-
builder: {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
builder: (yargs: yargs.Argv) => {
|
|
53
|
+
yargs
|
|
54
|
+
.option("directory", {
|
|
55
|
+
describe: "Peerbit directory",
|
|
56
|
+
defaultDescription: "~.peerbit",
|
|
57
|
+
type: "string",
|
|
58
|
+
alias: "d",
|
|
59
|
+
default: getHomeConfigDir(),
|
|
60
|
+
})
|
|
61
|
+
.option("bootstrap", {
|
|
62
|
+
describe: "Whether to connect to bootstap nodes on startup",
|
|
63
|
+
type: "boolean",
|
|
64
|
+
default: false,
|
|
65
|
+
})
|
|
66
|
+
.option("reset", {
|
|
67
|
+
describe:
|
|
68
|
+
"If true, then programs opened during last session will not be opened",
|
|
69
|
+
type: "boolean",
|
|
70
|
+
default: false,
|
|
71
|
+
alias: "r",
|
|
72
|
+
})
|
|
73
|
+
.option("port-api", {
|
|
74
|
+
describe:
|
|
75
|
+
"Set API server port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
76
|
+
type: "number",
|
|
77
|
+
default: undefined,
|
|
78
|
+
})
|
|
79
|
+
.option("port-node", {
|
|
80
|
+
describe:
|
|
81
|
+
"Set Libp2p listen port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
82
|
+
type: "number",
|
|
83
|
+
default: undefined,
|
|
84
|
+
});
|
|
85
|
+
return yargs;
|
|
40
86
|
},
|
|
41
87
|
handler: async (args) => {
|
|
42
88
|
await startServerWithNode({
|
|
@@ -44,306 +90,694 @@ export const cli = async (args?: string[]) => {
|
|
|
44
90
|
domain: await loadConfig().then((config) =>
|
|
45
91
|
config ? getDomainFromConfig(config) : undefined
|
|
46
92
|
),
|
|
93
|
+
ports: { api: args["port-api"], node: args["port-node"] },
|
|
47
94
|
bootstrap: args.bootstrap,
|
|
95
|
+
newSession: args.reset,
|
|
48
96
|
});
|
|
49
97
|
},
|
|
50
98
|
})
|
|
51
|
-
.command(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
alias: "hz",
|
|
96
|
-
type: "string",
|
|
97
|
-
require: true,
|
|
98
|
-
},
|
|
99
|
-
accessKeyId: {
|
|
100
|
-
describe: "Access key id of the AWS user",
|
|
101
|
-
alias: "ak",
|
|
102
|
-
type: "string",
|
|
103
|
-
},
|
|
104
|
-
region: {
|
|
105
|
-
describe: "AWS region",
|
|
106
|
-
alias: "r",
|
|
107
|
-
type: "string",
|
|
108
|
-
},
|
|
109
|
-
secretAccessKey: {
|
|
110
|
-
describe: "Secret key id of the AWS user",
|
|
111
|
-
alias: "sk",
|
|
112
|
-
type: "string",
|
|
113
|
-
},
|
|
114
|
-
email: {
|
|
115
|
-
describe: "Email for Lets encrypt auto-renewal messages",
|
|
116
|
-
type: "string",
|
|
117
|
-
demandOption: true,
|
|
99
|
+
.command({
|
|
100
|
+
command: "id",
|
|
101
|
+
describe: "Get peer id",
|
|
102
|
+
builder: (yargs: yargs.Argv) => {
|
|
103
|
+
yargs.option("directory", {
|
|
104
|
+
describe: "Peerbit directory",
|
|
105
|
+
defaultDescription: "~.peerbit",
|
|
106
|
+
type: "string",
|
|
107
|
+
alias: "d",
|
|
108
|
+
default: getHomeConfigDir(),
|
|
109
|
+
});
|
|
110
|
+
return yargs;
|
|
111
|
+
},
|
|
112
|
+
handler: async (args) => {
|
|
113
|
+
const kp = await getKeypair(args.directory);
|
|
114
|
+
console.log((await kp.toPeerId()).toString());
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
.command(
|
|
118
|
+
"domain",
|
|
119
|
+
"Setup a domain and certificate for this node",
|
|
120
|
+
(yargs) => {
|
|
121
|
+
yargs
|
|
122
|
+
.command({
|
|
123
|
+
command: "test",
|
|
124
|
+
describe:
|
|
125
|
+
"Setup a testing domain with SSL (no guarantess on how long the domain will be available)",
|
|
126
|
+
builder: {
|
|
127
|
+
email: {
|
|
128
|
+
describe: "Email for Lets encrypt autorenewal messages",
|
|
129
|
+
type: "string",
|
|
130
|
+
demandOption: true,
|
|
131
|
+
},
|
|
132
|
+
outdir: {
|
|
133
|
+
describe: "Output path for Nginx config",
|
|
134
|
+
type: "string",
|
|
135
|
+
alias: "o",
|
|
136
|
+
},
|
|
137
|
+
wait: {
|
|
138
|
+
alias: "w",
|
|
139
|
+
describe: "Wait for setup to succeed (or fail)",
|
|
140
|
+
type: "boolean",
|
|
141
|
+
default: false,
|
|
142
|
+
},
|
|
118
143
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
handler: async (args) => {
|
|
145
|
+
const domain = await createTestDomain();
|
|
146
|
+
await startCertbot(domain, args.email, args.outdir, args.wait);
|
|
147
|
+
exit();
|
|
123
148
|
},
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
149
|
+
})
|
|
150
|
+
.command({
|
|
151
|
+
command: "aws",
|
|
152
|
+
describe:
|
|
153
|
+
"Setup a domain with an AWS account. You either have to setup you AWS credentials in the .aws folder, or pass the credentials in the cli",
|
|
154
|
+
builder: {
|
|
155
|
+
domain: {
|
|
156
|
+
describe: "domain, e.g. abc.example.com, example.com",
|
|
157
|
+
alias: "d",
|
|
158
|
+
type: "string",
|
|
159
|
+
demandOption: true,
|
|
160
|
+
},
|
|
161
|
+
hostedZoneId: {
|
|
162
|
+
describe: 'The id of the hosted zone "HostedZoneId"',
|
|
163
|
+
alias: "hz",
|
|
164
|
+
type: "string",
|
|
165
|
+
require: true,
|
|
166
|
+
},
|
|
167
|
+
accessKeyId: {
|
|
168
|
+
describe: "Access key id of the AWS user",
|
|
169
|
+
alias: "ak",
|
|
170
|
+
type: "string",
|
|
171
|
+
},
|
|
172
|
+
region: {
|
|
173
|
+
describe: "AWS region",
|
|
174
|
+
alias: "r",
|
|
175
|
+
type: "string",
|
|
176
|
+
},
|
|
177
|
+
secretAccessKey: {
|
|
178
|
+
describe: "Secret key id of the AWS user",
|
|
179
|
+
alias: "sk",
|
|
180
|
+
type: "string",
|
|
181
|
+
},
|
|
182
|
+
email: {
|
|
183
|
+
describe: "Email for Lets encrypt auto-renewal messages",
|
|
184
|
+
type: "string",
|
|
185
|
+
demandOption: true,
|
|
186
|
+
},
|
|
187
|
+
outdir: {
|
|
188
|
+
describe: "Output path for Nginx config",
|
|
189
|
+
type: "string",
|
|
190
|
+
alias: "o",
|
|
191
|
+
},
|
|
192
|
+
wait: {
|
|
193
|
+
alias: "w",
|
|
194
|
+
describe: "Wait for setup to succeed (or fail)",
|
|
195
|
+
type: "boolean",
|
|
196
|
+
default: false,
|
|
197
|
+
},
|
|
129
198
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
199
|
+
handler: async (args) => {
|
|
200
|
+
if (
|
|
201
|
+
!!args.accessKeyId !== !!args.secretAccessKey ||
|
|
202
|
+
!!args.region !== !!args.secretAccessKey
|
|
203
|
+
) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
"Expecting either all 'accessKeyId', 'region' and 'secretAccessKey' to be provided or none"
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
await createRecord({
|
|
209
|
+
domain: args.domain,
|
|
210
|
+
hostedZoneId: args.hostedZoneId,
|
|
211
|
+
region: args.region,
|
|
212
|
+
credentials: args.accessKeyId
|
|
213
|
+
? {
|
|
214
|
+
accessKeyId: args.accessKeyId,
|
|
215
|
+
secretAccessKey: args.secretAccessKey,
|
|
216
|
+
}
|
|
217
|
+
: undefined,
|
|
218
|
+
});
|
|
219
|
+
await startCertbot(
|
|
220
|
+
args.domain,
|
|
221
|
+
args.email,
|
|
222
|
+
args.outdir,
|
|
223
|
+
args.wait
|
|
138
224
|
);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
: undefined,
|
|
150
|
-
});
|
|
151
|
-
await startCertbot(args.domain, args.email, args.outdir, args.wait);
|
|
152
|
-
const { exit } = await import("process");
|
|
153
|
-
exit();
|
|
154
|
-
},
|
|
155
|
-
})
|
|
156
|
-
.strict()
|
|
157
|
-
.demandCommand();
|
|
158
|
-
})
|
|
159
|
-
.command("network", "Manage network", (yargs) => {
|
|
160
|
-
yargs
|
|
161
|
-
.command({
|
|
162
|
-
command: "bootstrap",
|
|
163
|
-
describe: "Connect to bootstrap nodes",
|
|
164
|
-
handler: async () => {
|
|
165
|
-
const c = await client();
|
|
166
|
-
await c.network.bootstrap();
|
|
167
|
-
},
|
|
168
|
-
})
|
|
169
|
-
.strict()
|
|
170
|
-
.demandCommand();
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
.command("topic", "Manage topics the node is listening to", (yargs) => {
|
|
174
|
-
yargs
|
|
225
|
+
exit();
|
|
226
|
+
},
|
|
227
|
+
})
|
|
228
|
+
.strict()
|
|
229
|
+
.demandCommand();
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
.command("remote", "Handle remote nodes", (innerYargs) => {
|
|
233
|
+
innerYargs
|
|
175
234
|
.command({
|
|
176
235
|
command: "list",
|
|
177
236
|
aliases: "ls",
|
|
178
|
-
describe: "List
|
|
179
|
-
builder: (yargs:
|
|
180
|
-
yargs.option("
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
237
|
+
describe: "List remotes",
|
|
238
|
+
builder: (yargs: yargs.Argv) => {
|
|
239
|
+
yargs.option("directory", {
|
|
240
|
+
describe: "Peerbit directory",
|
|
241
|
+
defaultDescription: "~.peerbit",
|
|
242
|
+
type: "string",
|
|
243
|
+
alias: "d",
|
|
244
|
+
default: getHomeConfigDir(),
|
|
185
245
|
});
|
|
246
|
+
|
|
186
247
|
return yargs;
|
|
187
248
|
},
|
|
188
249
|
handler: async (args) => {
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
250
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
251
|
+
const allRemotes = await remotes.all();
|
|
252
|
+
const maxNameLength = allRemotes
|
|
253
|
+
.map((x) => x.name.length)
|
|
254
|
+
.reduce((prev, c, i) => {
|
|
255
|
+
return Math.max(prev, c);
|
|
256
|
+
}, 0);
|
|
257
|
+
const all = await remotes.all();
|
|
258
|
+
if (all.length > 0) {
|
|
259
|
+
for (const remote of all) {
|
|
260
|
+
console.log(
|
|
261
|
+
padString(remote.name, maxNameLength + 10),
|
|
262
|
+
remote.address
|
|
263
|
+
);
|
|
195
264
|
}
|
|
196
265
|
} else {
|
|
197
|
-
console.log("
|
|
198
|
-
}
|
|
199
|
-
console.error("Not implemented");
|
|
266
|
+
console.log("No remotes found!");
|
|
267
|
+
}
|
|
200
268
|
},
|
|
201
269
|
})
|
|
202
|
-
.strict()
|
|
203
|
-
.demandCommand();
|
|
204
|
-
return yargs;
|
|
205
|
-
})
|
|
206
|
-
.command("program", "Manage programs", (yargs) => {
|
|
207
|
-
yargs
|
|
208
270
|
.command({
|
|
209
|
-
command: "
|
|
210
|
-
describe: "
|
|
211
|
-
builder: (yargs:
|
|
212
|
-
yargs
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
271
|
+
command: "add <name> <address>",
|
|
272
|
+
describe: "Add remote",
|
|
273
|
+
builder: (yargs: yargs.Argv) => {
|
|
274
|
+
yargs
|
|
275
|
+
.positional("address", {
|
|
276
|
+
type: "string",
|
|
277
|
+
describe: "Remote name",
|
|
278
|
+
demandOption: true,
|
|
279
|
+
})
|
|
280
|
+
.positional("name", {
|
|
281
|
+
type: "string",
|
|
282
|
+
describe: "Remote address",
|
|
283
|
+
demandOption: true,
|
|
284
|
+
})
|
|
285
|
+
.option("directory", {
|
|
286
|
+
describe: "Peerbit directory",
|
|
287
|
+
defaultDescription: "~.peerbit",
|
|
288
|
+
type: "string",
|
|
289
|
+
alias: "d",
|
|
290
|
+
default: getHomeConfigDir(),
|
|
291
|
+
});
|
|
292
|
+
|
|
217
293
|
return yargs;
|
|
218
294
|
},
|
|
219
|
-
|
|
220
295
|
handler: async (args) => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
296
|
+
if (args.name === "localhost") {
|
|
297
|
+
throw new Error("Remote can not be named 'localhost'");
|
|
298
|
+
}
|
|
299
|
+
const api = await client(
|
|
300
|
+
await getKeypair(args.directory),
|
|
301
|
+
args.address
|
|
302
|
+
);
|
|
303
|
+
try {
|
|
304
|
+
await api.program.list();
|
|
305
|
+
} catch (error) {
|
|
306
|
+
throw new Error("Failed to add remote: " + error?.toString());
|
|
227
307
|
}
|
|
308
|
+
if (!fs.existsSync(args.directory)) {
|
|
309
|
+
fs.mkdirSync(args.directory, { recursive: true });
|
|
310
|
+
}
|
|
311
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
312
|
+
remotes.add(args.name, args.address);
|
|
228
313
|
},
|
|
229
314
|
})
|
|
230
315
|
.command({
|
|
231
|
-
command: "
|
|
232
|
-
describe: "
|
|
233
|
-
builder: (yargs:
|
|
234
|
-
yargs
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
316
|
+
command: "remove <name>",
|
|
317
|
+
describe: "Remove a remote",
|
|
318
|
+
builder: (yargs: yargs.Argv) => {
|
|
319
|
+
yargs
|
|
320
|
+
|
|
321
|
+
.positional("name", {
|
|
322
|
+
type: "string",
|
|
323
|
+
describe: "Remote address",
|
|
324
|
+
demandOption: true,
|
|
325
|
+
})
|
|
326
|
+
.option("directory", {
|
|
327
|
+
describe: "Peerbit directory",
|
|
328
|
+
defaultDescription: "~.peerbit",
|
|
329
|
+
type: "string",
|
|
330
|
+
alias: "d",
|
|
331
|
+
default: getHomeConfigDir(),
|
|
332
|
+
});
|
|
333
|
+
|
|
239
334
|
return yargs;
|
|
240
335
|
},
|
|
241
|
-
|
|
242
336
|
handler: async (args) => {
|
|
243
|
-
const
|
|
244
|
-
|
|
337
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
338
|
+
if (remotes.remove(args.name)) {
|
|
339
|
+
console.log(
|
|
340
|
+
chalk.green("Removed remote with name: " + args.name)
|
|
341
|
+
);
|
|
342
|
+
} else {
|
|
343
|
+
console.log(
|
|
344
|
+
chalk.red("Did not find any remote with name: " + args.name)
|
|
345
|
+
);
|
|
346
|
+
}
|
|
245
347
|
},
|
|
246
348
|
})
|
|
247
349
|
.command({
|
|
248
|
-
command: "
|
|
249
|
-
describe: "
|
|
250
|
-
builder: (yargs:
|
|
251
|
-
yargs
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
350
|
+
command: "connect [name...]",
|
|
351
|
+
describe: "Connect to remote(s)",
|
|
352
|
+
builder: (yargs: yargs.Argv) => {
|
|
353
|
+
yargs
|
|
354
|
+
.positional("name", {
|
|
355
|
+
type: "string",
|
|
356
|
+
describe: "Remote name",
|
|
357
|
+
default: "localhost",
|
|
358
|
+
demandOption: false,
|
|
359
|
+
array: true,
|
|
360
|
+
})
|
|
361
|
+
.option("directory", {
|
|
362
|
+
describe: "Peerbit directory",
|
|
363
|
+
defaultDescription: "~.peerbit",
|
|
364
|
+
type: "string",
|
|
365
|
+
alias: "d",
|
|
366
|
+
default: getHomeConfigDir(),
|
|
367
|
+
});
|
|
256
368
|
return yargs;
|
|
257
369
|
},
|
|
370
|
+
handler: async (connectArgs) => {
|
|
371
|
+
const names = connectArgs.name;
|
|
372
|
+
const apis: {
|
|
373
|
+
log: (string: string) => void;
|
|
374
|
+
name: string;
|
|
375
|
+
api: Awaited<ReturnType<typeof client>>;
|
|
376
|
+
}[] = [];
|
|
377
|
+
console.log(getRemotesPath(connectArgs.directory));
|
|
378
|
+
const config = await import("./config.js");
|
|
379
|
+
const keypair = await config.getKeypair(connectArgs.directory);
|
|
258
380
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
381
|
+
if (names.length > 0) {
|
|
382
|
+
const remotes = new Remotes(
|
|
383
|
+
getRemotesPath(connectArgs.directory)
|
|
384
|
+
);
|
|
385
|
+
for (const name of names) {
|
|
386
|
+
if (name === "localhost") {
|
|
387
|
+
apis.push({
|
|
388
|
+
log: (string) => console.log("localhost: " + string),
|
|
389
|
+
name: "localhost",
|
|
390
|
+
api: await client(keypair),
|
|
391
|
+
});
|
|
392
|
+
} else {
|
|
393
|
+
const remote = remotes.getByName(name);
|
|
394
|
+
if (!remote) {
|
|
395
|
+
throw new Error("Missing remote with name: " + name);
|
|
396
|
+
}
|
|
397
|
+
let logFn: (name: string) => void;
|
|
398
|
+
if (names.length > 0) {
|
|
399
|
+
logFn = (string) => console.log(name + ": " + string);
|
|
400
|
+
} else {
|
|
401
|
+
logFn = (string) => console.log(string);
|
|
402
|
+
}
|
|
271
403
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
404
|
+
apis.push({
|
|
405
|
+
log: logFn,
|
|
406
|
+
name,
|
|
407
|
+
api: await client(keypair, remote.address),
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
278
412
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
413
|
+
// try if authenticated
|
|
414
|
+
for (const api of apis) {
|
|
415
|
+
try {
|
|
416
|
+
await api.api.program.list();
|
|
417
|
+
} catch (error) {
|
|
418
|
+
throw new Error(
|
|
419
|
+
`Failed to connect to '${api.name}': ${error?.toString()}`
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const capi = () =>
|
|
424
|
+
yargs
|
|
425
|
+
.default()
|
|
426
|
+
.command("peer", "Peer info", (yargs) => {
|
|
427
|
+
yargs
|
|
428
|
+
.command({
|
|
429
|
+
command: "id",
|
|
430
|
+
describe: "Get peer id",
|
|
431
|
+
handler: async (args) => {
|
|
432
|
+
for (const api of apis) {
|
|
433
|
+
api.log((await api.api.peer.id.get()).toString());
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
})
|
|
437
|
+
.command({
|
|
438
|
+
command: "address",
|
|
439
|
+
describe: "Get addresses",
|
|
440
|
+
handler: async (args) => {
|
|
441
|
+
for (const api of apis) {
|
|
442
|
+
(await api.api.peer.addresses.get()).forEach((x) =>
|
|
443
|
+
api.log(x.toString())
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
})
|
|
448
|
+
.strict()
|
|
449
|
+
.demandCommand();
|
|
450
|
+
return yargs;
|
|
451
|
+
})
|
|
452
|
+
.command(
|
|
453
|
+
"access",
|
|
454
|
+
"Modify access control for this node",
|
|
455
|
+
(yargs) => {
|
|
456
|
+
yargs
|
|
457
|
+
.command({
|
|
458
|
+
command: "grant <peer-id>",
|
|
459
|
+
describe: "Give a peer-id admin capabilities",
|
|
460
|
+
builder: (yargs: yargs.Argv) => {
|
|
461
|
+
yargs.positional("peer-id", {
|
|
462
|
+
describe: "Peer id",
|
|
463
|
+
type: "string",
|
|
464
|
+
demandOption: true,
|
|
465
|
+
});
|
|
466
|
+
return yargs;
|
|
467
|
+
},
|
|
468
|
+
handler: async (args) => {
|
|
469
|
+
const peerId = peerIdFromString(args["peer-id"]);
|
|
470
|
+
for (const api of apis) {
|
|
471
|
+
await api.api.trust.add(peerId);
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
})
|
|
475
|
+
.command({
|
|
476
|
+
command: "deny <peer-id>",
|
|
477
|
+
describe: "Remove admin capabilities from peer-id",
|
|
478
|
+
builder: (yargs: yargs.Argv) => {
|
|
479
|
+
yargs.positional("peer-id", {
|
|
480
|
+
describe: "Peer id",
|
|
481
|
+
demandOption: true,
|
|
482
|
+
});
|
|
483
|
+
return yargs;
|
|
484
|
+
},
|
|
485
|
+
handler: async (args) => {
|
|
486
|
+
const peerId = peerIdFromString(args["peer-id"]);
|
|
487
|
+
for (const api of apis) {
|
|
488
|
+
await api.api.trust.remove(peerId);
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
})
|
|
492
|
+
.strict()
|
|
493
|
+
.demandCommand();
|
|
494
|
+
}
|
|
495
|
+
)
|
|
496
|
+
.command("network", "Manage network", (yargs) => {
|
|
497
|
+
yargs
|
|
498
|
+
.command({
|
|
499
|
+
command: "bootstrap",
|
|
500
|
+
describe: "Connect to bootstrap nodes",
|
|
501
|
+
handler: async () => {
|
|
502
|
+
for (const api of apis) {
|
|
503
|
+
await api.api.network.bootstrap();
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
})
|
|
507
|
+
.strict()
|
|
508
|
+
.demandCommand();
|
|
509
|
+
})
|
|
510
|
+
|
|
511
|
+
.command(
|
|
512
|
+
"topic",
|
|
513
|
+
"Manage topics the node is listening to",
|
|
514
|
+
(yargs) => {
|
|
515
|
+
yargs
|
|
516
|
+
.command({
|
|
517
|
+
command: "list",
|
|
518
|
+
aliases: "ls",
|
|
519
|
+
describe: "List all topics",
|
|
520
|
+
builder: (yargs: any) => {
|
|
521
|
+
yargs.option("replicate", {
|
|
522
|
+
type: "boolean",
|
|
523
|
+
describe: "Replicate data on this topic",
|
|
524
|
+
aliases: "r",
|
|
525
|
+
default: false,
|
|
526
|
+
});
|
|
527
|
+
return yargs;
|
|
528
|
+
},
|
|
529
|
+
handler: async (args) => {
|
|
530
|
+
/* const c = await client();
|
|
531
|
+
const topics = await c.topics.get(args.replicate);
|
|
532
|
+
if (topics?.length > 0) {
|
|
533
|
+
console.log("Topic (" + topics.length + "):");
|
|
534
|
+
for (const t of topics) {
|
|
535
|
+
console.log(t);
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
console.log("Not subscribed to any topics");
|
|
539
|
+
} */
|
|
540
|
+
console.error("Not implemented");
|
|
541
|
+
},
|
|
542
|
+
})
|
|
543
|
+
.strict()
|
|
544
|
+
.demandCommand();
|
|
545
|
+
return yargs;
|
|
546
|
+
}
|
|
547
|
+
)
|
|
548
|
+
.command("program", "Manage programs", (yargs) => {
|
|
549
|
+
yargs
|
|
550
|
+
.command({
|
|
551
|
+
command: "status <address>",
|
|
552
|
+
describe: "Is a program open",
|
|
553
|
+
builder: (yargs: any) => {
|
|
554
|
+
yargs.positional("address", {
|
|
555
|
+
type: "string",
|
|
556
|
+
describe: "Program address",
|
|
557
|
+
demandOption: true,
|
|
558
|
+
});
|
|
559
|
+
return yargs;
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
handler: async (args) => {
|
|
563
|
+
for (const api of apis) {
|
|
564
|
+
const program = await api.api.program.has(
|
|
565
|
+
args.address
|
|
566
|
+
);
|
|
567
|
+
if (!program) {
|
|
568
|
+
api.log(chalk.red("Closed"));
|
|
569
|
+
} else {
|
|
570
|
+
api.log(chalk.green("Open"));
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
})
|
|
575
|
+
.command({
|
|
576
|
+
command: "drop <address>",
|
|
577
|
+
describe: "Drop a program",
|
|
578
|
+
builder: (yargs: any) => {
|
|
579
|
+
yargs.positional("address", {
|
|
580
|
+
type: "string",
|
|
581
|
+
describe: "Program address",
|
|
582
|
+
demandOption: true,
|
|
583
|
+
});
|
|
584
|
+
return yargs;
|
|
585
|
+
},
|
|
586
|
+
|
|
587
|
+
handler: async (args) => {
|
|
588
|
+
for (const api of apis) {
|
|
589
|
+
try {
|
|
590
|
+
await api.api.program.drop(args.address);
|
|
591
|
+
} catch (error: any) {
|
|
592
|
+
api.log(
|
|
593
|
+
chalk.red(
|
|
594
|
+
`Failed to drop ${
|
|
595
|
+
args.address
|
|
596
|
+
}: ${error.toString()}`
|
|
597
|
+
)
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
})
|
|
603
|
+
.command({
|
|
604
|
+
command: "close <address>",
|
|
605
|
+
describe: "Close a program",
|
|
606
|
+
builder: (yargs: any) => {
|
|
607
|
+
yargs.positional("address", {
|
|
608
|
+
type: "string",
|
|
609
|
+
describe: "Program address",
|
|
610
|
+
demandOption: true,
|
|
611
|
+
});
|
|
612
|
+
return yargs;
|
|
613
|
+
},
|
|
614
|
+
|
|
615
|
+
handler: async (args) => {
|
|
616
|
+
for (const api of apis) {
|
|
617
|
+
await api.api.program.close(args.address);
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
})
|
|
621
|
+
.command({
|
|
622
|
+
command: "list",
|
|
623
|
+
describe: "List all running programs",
|
|
624
|
+
aliases: "ls",
|
|
625
|
+
handler: async (args) => {
|
|
626
|
+
for (const api of apis) {
|
|
627
|
+
const list = await api.api.program.list();
|
|
628
|
+
api.log(`Running programs (${list.length}):`);
|
|
629
|
+
list.forEach((p) => {
|
|
630
|
+
api.log(chalk.green(p));
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
.command({
|
|
637
|
+
command: "open [program]",
|
|
638
|
+
describe: "Open program",
|
|
639
|
+
builder: (yargs: any) => {
|
|
640
|
+
yargs.positional("program", {
|
|
641
|
+
type: "string",
|
|
642
|
+
describe: "Identifier",
|
|
643
|
+
demandOption: true,
|
|
644
|
+
});
|
|
645
|
+
yargs.option("base64", {
|
|
646
|
+
type: "string",
|
|
647
|
+
describe: "Base64 encoded serialized",
|
|
648
|
+
aliases: "b",
|
|
649
|
+
});
|
|
650
|
+
yargs.option("variant", {
|
|
651
|
+
type: "string",
|
|
652
|
+
describe: "Variant name",
|
|
653
|
+
aliases: "v",
|
|
654
|
+
});
|
|
655
|
+
return yargs;
|
|
656
|
+
},
|
|
657
|
+
handler: async (args) => {
|
|
658
|
+
if (!args.base64 && !args.variant) {
|
|
659
|
+
throw new Error(
|
|
660
|
+
"Either base64 or variant argument needs to be provided"
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
let startArg: StartProgram;
|
|
664
|
+
if (args.base64) {
|
|
665
|
+
startArg = {
|
|
666
|
+
base64: args.base64,
|
|
667
|
+
};
|
|
668
|
+
} else {
|
|
669
|
+
startArg = {
|
|
670
|
+
variant: args.variant,
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
for (const api of apis) {
|
|
674
|
+
const address = await api.api.program.open(startArg);
|
|
675
|
+
api.log("Started program with address: ");
|
|
676
|
+
api.log(chalk.green(address.toString()));
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
})
|
|
680
|
+
.strict()
|
|
681
|
+
.demandCommand();
|
|
682
|
+
return yargs;
|
|
683
|
+
})
|
|
684
|
+
.command({
|
|
685
|
+
command: "install <package-spec>",
|
|
686
|
+
describe: "install and import a dependency",
|
|
687
|
+
builder: (yargs: any) => {
|
|
688
|
+
yargs.positional("package-spec", {
|
|
689
|
+
type: "string",
|
|
690
|
+
describe:
|
|
691
|
+
"Installed dependency will be loaded with js import(...)",
|
|
692
|
+
demandOption: true,
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
return yargs;
|
|
696
|
+
},
|
|
697
|
+
handler: async (args) => {
|
|
698
|
+
// if ends with .tgz assume it is a file
|
|
699
|
+
|
|
700
|
+
let installCommand: InstallDependency;
|
|
701
|
+
const packageName: string = args["package-spec"];
|
|
702
|
+
if (packageName.endsWith(".tgz")) {
|
|
703
|
+
const packagePath = path.isAbsolute(packageName)
|
|
704
|
+
? packageName
|
|
705
|
+
: path.join(process.cwd(), packageName);
|
|
706
|
+
|
|
707
|
+
const buffer = fs.readFileSync(packagePath);
|
|
708
|
+
const base64 = toBase64(buffer);
|
|
709
|
+
installCommand = {
|
|
710
|
+
type: "tgz",
|
|
711
|
+
name: await getPackageName(packageName),
|
|
712
|
+
base64,
|
|
713
|
+
};
|
|
714
|
+
} else {
|
|
715
|
+
installCommand = { type: "npm", name: packageName };
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
for (const api of apis) {
|
|
719
|
+
const newPrograms = await api.api.dependency.install(
|
|
720
|
+
installCommand
|
|
721
|
+
);
|
|
722
|
+
api.log(
|
|
723
|
+
`New programs available (${newPrograms.length}):`
|
|
724
|
+
);
|
|
725
|
+
newPrograms.forEach((p) => {
|
|
726
|
+
api.log(chalk.green(p));
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
})
|
|
731
|
+
.command({
|
|
732
|
+
command: "restart",
|
|
733
|
+
describe: "Restart the server",
|
|
734
|
+
handler: async () => {
|
|
735
|
+
for (const api of apis) {
|
|
736
|
+
await api.api.restart();
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
})
|
|
740
|
+
.command({
|
|
741
|
+
command: "terminate",
|
|
742
|
+
describe: "Terminate the server",
|
|
743
|
+
handler: async () => {
|
|
744
|
+
for (const api of apis) {
|
|
745
|
+
await api.api.terminate();
|
|
746
|
+
}
|
|
747
|
+
},
|
|
748
|
+
})
|
|
749
|
+
.help()
|
|
750
|
+
.strict()
|
|
751
|
+
.scriptName("")
|
|
752
|
+
.demandCommand()
|
|
753
|
+
.showHelpOnFail(true)
|
|
754
|
+
.exitProcess(false);
|
|
755
|
+
const rl = readline.createInterface({
|
|
756
|
+
input: process.stdin,
|
|
757
|
+
output: process.stdout,
|
|
758
|
+
terminal: true,
|
|
759
|
+
historySize: 100,
|
|
292
760
|
});
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
761
|
+
console.log(chalk.green("Connected"));
|
|
762
|
+
console.log("Write 'help' to show commands.\n");
|
|
763
|
+
const first = true;
|
|
764
|
+
rl.prompt(false);
|
|
765
|
+
rl.on("line", async (cargs) => {
|
|
766
|
+
const cmds = capi();
|
|
767
|
+
try {
|
|
768
|
+
await cmds.parse(cargs);
|
|
769
|
+
} catch (error: any) {
|
|
770
|
+
/* console.log(chalk.red("Error parsing command: " + cargs))*/
|
|
771
|
+
}
|
|
772
|
+
rl.prompt(true);
|
|
297
773
|
});
|
|
298
|
-
return yargs;
|
|
299
|
-
},
|
|
300
|
-
handler: async (args) => {
|
|
301
|
-
const c = await client();
|
|
302
|
-
if (!args.base64 && !args.variant) {
|
|
303
|
-
throw new Error(
|
|
304
|
-
"Either base64 or variant argument needs to be provided"
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
let startArg: StartProgram;
|
|
308
|
-
if (args.base64) {
|
|
309
|
-
startArg = {
|
|
310
|
-
base64: args.base64,
|
|
311
|
-
};
|
|
312
|
-
} else {
|
|
313
|
-
startArg = {
|
|
314
|
-
variant: args.variant,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
const address = await c.program.open(startArg);
|
|
318
|
-
console.log("Started program with address: ");
|
|
319
|
-
console.log(chalk.green(address.toString()));
|
|
320
774
|
},
|
|
321
775
|
})
|
|
776
|
+
|
|
777
|
+
.help()
|
|
322
778
|
.strict()
|
|
323
779
|
.demandCommand();
|
|
324
|
-
return
|
|
325
|
-
})
|
|
326
|
-
.command({
|
|
327
|
-
command: "install <package-spec>",
|
|
328
|
-
describe: "install and import a dependency",
|
|
329
|
-
builder: (yargs: any) => {
|
|
330
|
-
yargs.positional("package-spec", {
|
|
331
|
-
type: "string",
|
|
332
|
-
describe: "Installed dependency will be loaded with js import(...)",
|
|
333
|
-
demandOption: true,
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
return yargs;
|
|
337
|
-
},
|
|
338
|
-
handler: async (args) => {
|
|
339
|
-
const c = await client();
|
|
340
|
-
const newPrograms = await c.dependency.install(args["package-spec"]);
|
|
341
|
-
|
|
342
|
-
console.log(`New programs available (${newPrograms.length}):`);
|
|
343
|
-
newPrograms.forEach((p) => {
|
|
344
|
-
console.log(chalk.green(p));
|
|
345
|
-
});
|
|
346
|
-
},
|
|
780
|
+
return innerYargs;
|
|
347
781
|
})
|
|
348
782
|
.help()
|
|
349
783
|
.strict()
|