@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/lib/esm/cli.js
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import { createTestDomain, getDomainFromConfig, loadConfig, startCertbot, } from "./domain.js";
|
|
2
2
|
import { startServerWithNode } from "./server.js";
|
|
3
3
|
import { createRecord } from "./aws.js";
|
|
4
|
-
import { getHomeConfigDir } from "./config.js";
|
|
4
|
+
import { getHomeConfigDir, getKeypair, getPackageName, getRemotesPath, } from "./config.js";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { client } from "./client.js";
|
|
7
|
+
import { exit } from "process";
|
|
8
|
+
import readline from "readline";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { toBase64 } from "@peerbit/crypto";
|
|
12
|
+
import { Remotes } from "./remotes.js";
|
|
13
|
+
import { peerIdFromString } from "@libp2p/peer-id";
|
|
14
|
+
const padString = function (string, padding, padChar = " ") {
|
|
15
|
+
const val = string.valueOf();
|
|
16
|
+
if (Math.abs(padding) <= val.length) {
|
|
17
|
+
return val;
|
|
18
|
+
}
|
|
19
|
+
const m = Math.max(Math.abs(padding) - string.length || 0, 0);
|
|
20
|
+
const pad = Array(m + 1).join(String(padChar).charAt(0));
|
|
21
|
+
// var pad = String(c || ' ').charAt(0).repeat(Math.abs(n) - this.length);
|
|
22
|
+
return padding < 0 ? pad + val : val + pad;
|
|
23
|
+
// return (n < 0) ? val + pad : pad + val;
|
|
24
|
+
};
|
|
7
25
|
export const cli = async (args) => {
|
|
8
26
|
const yargs = await import("yargs");
|
|
9
27
|
if (!args) {
|
|
@@ -15,28 +33,67 @@ export const cli = async (args) => {
|
|
|
15
33
|
.command({
|
|
16
34
|
command: "start",
|
|
17
35
|
describe: "Start node",
|
|
18
|
-
builder: {
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
builder: (yargs) => {
|
|
37
|
+
yargs
|
|
38
|
+
.option("directory", {
|
|
39
|
+
describe: "Peerbit directory",
|
|
21
40
|
defaultDescription: "~.peerbit",
|
|
22
41
|
type: "string",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
42
|
+
alias: "d",
|
|
43
|
+
default: getHomeConfigDir(),
|
|
44
|
+
})
|
|
45
|
+
.option("bootstrap", {
|
|
26
46
|
describe: "Whether to connect to bootstap nodes on startup",
|
|
27
47
|
type: "boolean",
|
|
28
48
|
default: false,
|
|
29
|
-
}
|
|
49
|
+
})
|
|
50
|
+
.option("reset", {
|
|
51
|
+
describe: "If true, then programs opened during last session will not be opened",
|
|
52
|
+
type: "boolean",
|
|
53
|
+
default: false,
|
|
54
|
+
alias: "r",
|
|
55
|
+
})
|
|
56
|
+
.option("port-api", {
|
|
57
|
+
describe: "Set API server port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
58
|
+
type: "number",
|
|
59
|
+
default: undefined,
|
|
60
|
+
})
|
|
61
|
+
.option("port-node", {
|
|
62
|
+
describe: "Set Libp2p listen port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
63
|
+
type: "number",
|
|
64
|
+
default: undefined,
|
|
65
|
+
});
|
|
66
|
+
return yargs;
|
|
30
67
|
},
|
|
31
68
|
handler: async (args) => {
|
|
32
69
|
await startServerWithNode({
|
|
33
70
|
directory: args.directory,
|
|
34
71
|
domain: await loadConfig().then((config) => config ? getDomainFromConfig(config) : undefined),
|
|
72
|
+
ports: { api: args["port-api"], node: args["port-node"] },
|
|
35
73
|
bootstrap: args.bootstrap,
|
|
74
|
+
newSession: args.reset,
|
|
36
75
|
});
|
|
37
76
|
},
|
|
38
77
|
})
|
|
39
|
-
.command(
|
|
78
|
+
.command({
|
|
79
|
+
command: "id",
|
|
80
|
+
describe: "Get peer id",
|
|
81
|
+
builder: (yargs) => {
|
|
82
|
+
yargs.option("directory", {
|
|
83
|
+
describe: "Peerbit directory",
|
|
84
|
+
defaultDescription: "~.peerbit",
|
|
85
|
+
type: "string",
|
|
86
|
+
alias: "d",
|
|
87
|
+
default: getHomeConfigDir(),
|
|
88
|
+
});
|
|
89
|
+
return yargs;
|
|
90
|
+
},
|
|
91
|
+
handler: async (args) => {
|
|
92
|
+
const kp = await getKeypair(args.directory);
|
|
93
|
+
console.log((await kp.toPeerId()).toString());
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
.command("domain", "Setup a domain and certificate for this node", (yargs) => {
|
|
40
97
|
yargs
|
|
41
98
|
.command({
|
|
42
99
|
command: "test",
|
|
@@ -62,7 +119,6 @@ export const cli = async (args) => {
|
|
|
62
119
|
handler: async (args) => {
|
|
63
120
|
const domain = await createTestDomain();
|
|
64
121
|
await startCertbot(domain, args.email, args.outdir, args.wait);
|
|
65
|
-
const { exit } = await import("process");
|
|
66
122
|
exit();
|
|
67
123
|
},
|
|
68
124
|
})
|
|
@@ -131,193 +187,511 @@ export const cli = async (args) => {
|
|
|
131
187
|
: undefined,
|
|
132
188
|
});
|
|
133
189
|
await startCertbot(args.domain, args.email, args.outdir, args.wait);
|
|
134
|
-
const { exit } = await import("process");
|
|
135
190
|
exit();
|
|
136
191
|
},
|
|
137
192
|
})
|
|
138
193
|
.strict()
|
|
139
194
|
.demandCommand();
|
|
140
195
|
})
|
|
141
|
-
.command("
|
|
142
|
-
|
|
143
|
-
.command({
|
|
144
|
-
command: "bootstrap",
|
|
145
|
-
describe: "Connect to bootstrap nodes",
|
|
146
|
-
handler: async () => {
|
|
147
|
-
const c = await client();
|
|
148
|
-
await c.network.bootstrap();
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
.strict()
|
|
152
|
-
.demandCommand();
|
|
153
|
-
})
|
|
154
|
-
.command("topic", "Manage topics the node is listening to", (yargs) => {
|
|
155
|
-
yargs
|
|
196
|
+
.command("remote", "Handle remote nodes", (innerYargs) => {
|
|
197
|
+
innerYargs
|
|
156
198
|
.command({
|
|
157
199
|
command: "list",
|
|
158
200
|
aliases: "ls",
|
|
159
|
-
describe: "List
|
|
160
|
-
builder: (yargs) => {
|
|
161
|
-
yargs.option("replicate", {
|
|
162
|
-
type: "boolean",
|
|
163
|
-
describe: "Replicate data on this topic",
|
|
164
|
-
alias: "r",
|
|
165
|
-
default: false,
|
|
166
|
-
});
|
|
167
|
-
return yargs;
|
|
168
|
-
},
|
|
169
|
-
handler: async (args) => {
|
|
170
|
-
/* const c = await client();
|
|
171
|
-
const topics = await c.topics.get(args.replicate);
|
|
172
|
-
if (topics?.length > 0) {
|
|
173
|
-
console.log("Topic (" + topics.length + "):");
|
|
174
|
-
for (const t of topics) {
|
|
175
|
-
console.log(t);
|
|
176
|
-
}
|
|
177
|
-
} else {
|
|
178
|
-
console.log("Not subscribed to any topics");
|
|
179
|
-
} */
|
|
180
|
-
console.error("Not implemented");
|
|
181
|
-
},
|
|
182
|
-
})
|
|
183
|
-
.strict()
|
|
184
|
-
.demandCommand();
|
|
185
|
-
return yargs;
|
|
186
|
-
})
|
|
187
|
-
.command("program", "Manage programs", (yargs) => {
|
|
188
|
-
yargs
|
|
189
|
-
.command({
|
|
190
|
-
command: "status <address>",
|
|
191
|
-
describe: "Is a program open",
|
|
201
|
+
describe: "List remotes",
|
|
192
202
|
builder: (yargs) => {
|
|
193
|
-
yargs.
|
|
203
|
+
yargs.option("directory", {
|
|
204
|
+
describe: "Peerbit directory",
|
|
205
|
+
defaultDescription: "~.peerbit",
|
|
194
206
|
type: "string",
|
|
195
|
-
|
|
196
|
-
|
|
207
|
+
alias: "d",
|
|
208
|
+
default: getHomeConfigDir(),
|
|
197
209
|
});
|
|
198
210
|
return yargs;
|
|
199
211
|
},
|
|
200
212
|
handler: async (args) => {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
213
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
214
|
+
const allRemotes = await remotes.all();
|
|
215
|
+
const maxNameLength = allRemotes
|
|
216
|
+
.map((x) => x.name.length)
|
|
217
|
+
.reduce((prev, c, i) => {
|
|
218
|
+
return Math.max(prev, c);
|
|
219
|
+
}, 0);
|
|
220
|
+
const all = await remotes.all();
|
|
221
|
+
if (all.length > 0) {
|
|
222
|
+
for (const remote of all) {
|
|
223
|
+
console.log(padString(remote.name, maxNameLength + 10), remote.address);
|
|
224
|
+
}
|
|
205
225
|
}
|
|
206
226
|
else {
|
|
207
|
-
console.log(
|
|
227
|
+
console.log("No remotes found!");
|
|
208
228
|
}
|
|
209
229
|
},
|
|
210
230
|
})
|
|
211
231
|
.command({
|
|
212
|
-
command: "
|
|
213
|
-
describe: "
|
|
232
|
+
command: "add <name> <address>",
|
|
233
|
+
describe: "Add remote",
|
|
214
234
|
builder: (yargs) => {
|
|
215
|
-
yargs
|
|
235
|
+
yargs
|
|
236
|
+
.positional("address", {
|
|
216
237
|
type: "string",
|
|
217
|
-
describe: "
|
|
238
|
+
describe: "Remote name",
|
|
218
239
|
demandOption: true,
|
|
240
|
+
})
|
|
241
|
+
.positional("name", {
|
|
242
|
+
type: "string",
|
|
243
|
+
describe: "Remote address",
|
|
244
|
+
demandOption: true,
|
|
245
|
+
})
|
|
246
|
+
.option("directory", {
|
|
247
|
+
describe: "Peerbit directory",
|
|
248
|
+
defaultDescription: "~.peerbit",
|
|
249
|
+
type: "string",
|
|
250
|
+
alias: "d",
|
|
251
|
+
default: getHomeConfigDir(),
|
|
219
252
|
});
|
|
220
253
|
return yargs;
|
|
221
254
|
},
|
|
222
255
|
handler: async (args) => {
|
|
223
|
-
|
|
224
|
-
|
|
256
|
+
if (args.name === "localhost") {
|
|
257
|
+
throw new Error("Remote can not be named 'localhost'");
|
|
258
|
+
}
|
|
259
|
+
const api = await client(await getKeypair(args.directory), args.address);
|
|
260
|
+
try {
|
|
261
|
+
await api.program.list();
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
throw new Error("Failed to add remote: " + error?.toString());
|
|
265
|
+
}
|
|
266
|
+
if (!fs.existsSync(args.directory)) {
|
|
267
|
+
fs.mkdirSync(args.directory, { recursive: true });
|
|
268
|
+
}
|
|
269
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
270
|
+
remotes.add(args.name, args.address);
|
|
225
271
|
},
|
|
226
272
|
})
|
|
227
273
|
.command({
|
|
228
|
-
command: "
|
|
229
|
-
describe: "
|
|
274
|
+
command: "remove <name>",
|
|
275
|
+
describe: "Remove a remote",
|
|
230
276
|
builder: (yargs) => {
|
|
231
|
-
yargs
|
|
277
|
+
yargs
|
|
278
|
+
.positional("name", {
|
|
232
279
|
type: "string",
|
|
233
|
-
describe: "
|
|
280
|
+
describe: "Remote address",
|
|
234
281
|
demandOption: true,
|
|
282
|
+
})
|
|
283
|
+
.option("directory", {
|
|
284
|
+
describe: "Peerbit directory",
|
|
285
|
+
defaultDescription: "~.peerbit",
|
|
286
|
+
type: "string",
|
|
287
|
+
alias: "d",
|
|
288
|
+
default: getHomeConfigDir(),
|
|
235
289
|
});
|
|
236
290
|
return yargs;
|
|
237
291
|
},
|
|
238
292
|
handler: async (args) => {
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
aliases: "ls",
|
|
247
|
-
handler: async (args) => {
|
|
248
|
-
const c = await client();
|
|
249
|
-
const list = await c.program.list();
|
|
250
|
-
console.log(`Running programs (${list.length}):`);
|
|
251
|
-
list.forEach((p) => {
|
|
252
|
-
console.log(chalk.green(p));
|
|
253
|
-
});
|
|
293
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
294
|
+
if (remotes.remove(args.name)) {
|
|
295
|
+
console.log(chalk.green("Removed remote with name: " + args.name));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
console.log(chalk.red("Did not find any remote with name: " + args.name));
|
|
299
|
+
}
|
|
254
300
|
},
|
|
255
301
|
})
|
|
256
302
|
.command({
|
|
257
|
-
command: "
|
|
258
|
-
describe: "
|
|
303
|
+
command: "connect [name...]",
|
|
304
|
+
describe: "Connect to remote(s)",
|
|
259
305
|
builder: (yargs) => {
|
|
260
|
-
yargs
|
|
306
|
+
yargs
|
|
307
|
+
.positional("name", {
|
|
261
308
|
type: "string",
|
|
262
|
-
describe: "
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
309
|
+
describe: "Remote name",
|
|
310
|
+
default: "localhost",
|
|
311
|
+
demandOption: false,
|
|
312
|
+
array: true,
|
|
313
|
+
})
|
|
314
|
+
.option("directory", {
|
|
315
|
+
describe: "Peerbit directory",
|
|
316
|
+
defaultDescription: "~.peerbit",
|
|
266
317
|
type: "string",
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
});
|
|
270
|
-
yargs.option("variant", {
|
|
271
|
-
type: "string",
|
|
272
|
-
describe: "Variant name",
|
|
273
|
-
alias: "v",
|
|
318
|
+
alias: "d",
|
|
319
|
+
default: getHomeConfigDir(),
|
|
274
320
|
});
|
|
275
321
|
return yargs;
|
|
276
322
|
},
|
|
277
|
-
handler: async (
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
323
|
+
handler: async (connectArgs) => {
|
|
324
|
+
const names = connectArgs.name;
|
|
325
|
+
const apis = [];
|
|
326
|
+
console.log(getRemotesPath(connectArgs.directory));
|
|
327
|
+
const config = await import("./config.js");
|
|
328
|
+
const keypair = await config.getKeypair(connectArgs.directory);
|
|
329
|
+
if (names.length > 0) {
|
|
330
|
+
const remotes = new Remotes(getRemotesPath(connectArgs.directory));
|
|
331
|
+
for (const name of names) {
|
|
332
|
+
if (name === "localhost") {
|
|
333
|
+
apis.push({
|
|
334
|
+
log: (string) => console.log("localhost: " + string),
|
|
335
|
+
name: "localhost",
|
|
336
|
+
api: await client(keypair),
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
const remote = remotes.getByName(name);
|
|
341
|
+
if (!remote) {
|
|
342
|
+
throw new Error("Missing remote with name: " + name);
|
|
343
|
+
}
|
|
344
|
+
let logFn;
|
|
345
|
+
if (names.length > 0) {
|
|
346
|
+
logFn = (string) => console.log(name + ": " + string);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
logFn = (string) => console.log(string);
|
|
350
|
+
}
|
|
351
|
+
apis.push({
|
|
352
|
+
log: logFn,
|
|
353
|
+
name,
|
|
354
|
+
api: await client(keypair, remote.address),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
287
358
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
359
|
+
// try if authenticated
|
|
360
|
+
for (const api of apis) {
|
|
361
|
+
try {
|
|
362
|
+
await api.api.program.list();
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
throw new Error(`Failed to connect to '${api.name}': ${error?.toString()}`);
|
|
366
|
+
}
|
|
292
367
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
368
|
+
const capi = () => yargs
|
|
369
|
+
.default()
|
|
370
|
+
.command("peer", "Peer info", (yargs) => {
|
|
371
|
+
yargs
|
|
372
|
+
.command({
|
|
373
|
+
command: "id",
|
|
374
|
+
describe: "Get peer id",
|
|
375
|
+
handler: async (args) => {
|
|
376
|
+
for (const api of apis) {
|
|
377
|
+
api.log((await api.api.peer.id.get()).toString());
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
})
|
|
381
|
+
.command({
|
|
382
|
+
command: "address",
|
|
383
|
+
describe: "Get addresses",
|
|
384
|
+
handler: async (args) => {
|
|
385
|
+
for (const api of apis) {
|
|
386
|
+
(await api.api.peer.addresses.get()).forEach((x) => api.log(x.toString()));
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
})
|
|
390
|
+
.strict()
|
|
391
|
+
.demandCommand();
|
|
392
|
+
return yargs;
|
|
393
|
+
})
|
|
394
|
+
.command("access", "Modify access control for this node", (yargs) => {
|
|
395
|
+
yargs
|
|
396
|
+
.command({
|
|
397
|
+
command: "grant <peer-id>",
|
|
398
|
+
describe: "Give a peer-id admin capabilities",
|
|
399
|
+
builder: (yargs) => {
|
|
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
|
+
},
|
|
413
|
+
})
|
|
414
|
+
.command({
|
|
415
|
+
command: "deny <peer-id>",
|
|
416
|
+
describe: "Remove admin capabilities from peer-id",
|
|
417
|
+
builder: (yargs) => {
|
|
418
|
+
yargs.positional("peer-id", {
|
|
419
|
+
describe: "Peer id",
|
|
420
|
+
demandOption: true,
|
|
421
|
+
});
|
|
422
|
+
return yargs;
|
|
423
|
+
},
|
|
424
|
+
handler: async (args) => {
|
|
425
|
+
const peerId = peerIdFromString(args["peer-id"]);
|
|
426
|
+
for (const api of apis) {
|
|
427
|
+
await api.api.trust.remove(peerId);
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
})
|
|
431
|
+
.strict()
|
|
432
|
+
.demandCommand();
|
|
433
|
+
})
|
|
434
|
+
.command("network", "Manage network", (yargs) => {
|
|
435
|
+
yargs
|
|
436
|
+
.command({
|
|
437
|
+
command: "bootstrap",
|
|
438
|
+
describe: "Connect to bootstrap nodes",
|
|
439
|
+
handler: async () => {
|
|
440
|
+
for (const api of apis) {
|
|
441
|
+
await api.api.network.bootstrap();
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
})
|
|
445
|
+
.strict()
|
|
446
|
+
.demandCommand();
|
|
447
|
+
})
|
|
448
|
+
.command("topic", "Manage topics the node is listening to", (yargs) => {
|
|
449
|
+
yargs
|
|
450
|
+
.command({
|
|
451
|
+
command: "list",
|
|
452
|
+
aliases: "ls",
|
|
453
|
+
describe: "List all topics",
|
|
454
|
+
builder: (yargs) => {
|
|
455
|
+
yargs.option("replicate", {
|
|
456
|
+
type: "boolean",
|
|
457
|
+
describe: "Replicate data on this topic",
|
|
458
|
+
aliases: "r",
|
|
459
|
+
default: false,
|
|
460
|
+
});
|
|
461
|
+
return yargs;
|
|
462
|
+
},
|
|
463
|
+
handler: async (args) => {
|
|
464
|
+
/* const c = await client();
|
|
465
|
+
const topics = await c.topics.get(args.replicate);
|
|
466
|
+
if (topics?.length > 0) {
|
|
467
|
+
console.log("Topic (" + topics.length + "):");
|
|
468
|
+
for (const t of topics) {
|
|
469
|
+
console.log(t);
|
|
470
|
+
}
|
|
471
|
+
} else {
|
|
472
|
+
console.log("Not subscribed to any topics");
|
|
473
|
+
} */
|
|
474
|
+
console.error("Not implemented");
|
|
475
|
+
},
|
|
476
|
+
})
|
|
477
|
+
.strict()
|
|
478
|
+
.demandCommand();
|
|
479
|
+
return yargs;
|
|
480
|
+
})
|
|
481
|
+
.command("program", "Manage programs", (yargs) => {
|
|
482
|
+
yargs
|
|
483
|
+
.command({
|
|
484
|
+
command: "status <address>",
|
|
485
|
+
describe: "Is a program open",
|
|
486
|
+
builder: (yargs) => {
|
|
487
|
+
yargs.positional("address", {
|
|
488
|
+
type: "string",
|
|
489
|
+
describe: "Program address",
|
|
490
|
+
demandOption: true,
|
|
491
|
+
});
|
|
492
|
+
return yargs;
|
|
493
|
+
},
|
|
494
|
+
handler: async (args) => {
|
|
495
|
+
for (const api of apis) {
|
|
496
|
+
const program = await api.api.program.has(args.address);
|
|
497
|
+
if (!program) {
|
|
498
|
+
api.log(chalk.red("Closed"));
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
api.log(chalk.green("Open"));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
})
|
|
506
|
+
.command({
|
|
507
|
+
command: "drop <address>",
|
|
508
|
+
describe: "Drop a program",
|
|
509
|
+
builder: (yargs) => {
|
|
510
|
+
yargs.positional("address", {
|
|
511
|
+
type: "string",
|
|
512
|
+
describe: "Program address",
|
|
513
|
+
demandOption: true,
|
|
514
|
+
});
|
|
515
|
+
return yargs;
|
|
516
|
+
},
|
|
517
|
+
handler: async (args) => {
|
|
518
|
+
for (const api of apis) {
|
|
519
|
+
try {
|
|
520
|
+
await api.api.program.drop(args.address);
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
api.log(chalk.red(`Failed to drop ${args.address}: ${error.toString()}`));
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
})
|
|
528
|
+
.command({
|
|
529
|
+
command: "close <address>",
|
|
530
|
+
describe: "Close a program",
|
|
531
|
+
builder: (yargs) => {
|
|
532
|
+
yargs.positional("address", {
|
|
533
|
+
type: "string",
|
|
534
|
+
describe: "Program address",
|
|
535
|
+
demandOption: true,
|
|
536
|
+
});
|
|
537
|
+
return yargs;
|
|
538
|
+
},
|
|
539
|
+
handler: async (args) => {
|
|
540
|
+
for (const api of apis) {
|
|
541
|
+
await api.api.program.close(args.address);
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
})
|
|
545
|
+
.command({
|
|
546
|
+
command: "list",
|
|
547
|
+
describe: "List all running programs",
|
|
548
|
+
aliases: "ls",
|
|
549
|
+
handler: async (args) => {
|
|
550
|
+
for (const api of apis) {
|
|
551
|
+
const list = await api.api.program.list();
|
|
552
|
+
api.log(`Running programs (${list.length}):`);
|
|
553
|
+
list.forEach((p) => {
|
|
554
|
+
api.log(chalk.green(p));
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
})
|
|
559
|
+
.command({
|
|
560
|
+
command: "open [program]",
|
|
561
|
+
describe: "Open program",
|
|
562
|
+
builder: (yargs) => {
|
|
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
|
+
}
|
|
595
|
+
for (const api of apis) {
|
|
596
|
+
const address = await api.api.program.open(startArg);
|
|
597
|
+
api.log("Started program with address: ");
|
|
598
|
+
api.log(chalk.green(address.toString()));
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
})
|
|
602
|
+
.strict()
|
|
603
|
+
.demandCommand();
|
|
604
|
+
return yargs;
|
|
605
|
+
})
|
|
606
|
+
.command({
|
|
607
|
+
command: "install <package-spec>",
|
|
608
|
+
describe: "install and import a dependency",
|
|
609
|
+
builder: (yargs) => {
|
|
610
|
+
yargs.positional("package-spec", {
|
|
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 };
|
|
635
|
+
}
|
|
636
|
+
for (const api of apis) {
|
|
637
|
+
const newPrograms = await api.api.dependency.install(installCommand);
|
|
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();
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
})
|
|
654
|
+
.command({
|
|
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
|
+
});
|
|
296
689
|
},
|
|
297
690
|
})
|
|
691
|
+
.help()
|
|
298
692
|
.strict()
|
|
299
693
|
.demandCommand();
|
|
300
|
-
return
|
|
301
|
-
})
|
|
302
|
-
.command({
|
|
303
|
-
command: "install <package-spec>",
|
|
304
|
-
describe: "install and import a dependency",
|
|
305
|
-
builder: (yargs) => {
|
|
306
|
-
yargs.positional("package-spec", {
|
|
307
|
-
type: "string",
|
|
308
|
-
describe: "Installed dependency will be loaded with js import(...)",
|
|
309
|
-
demandOption: true,
|
|
310
|
-
});
|
|
311
|
-
return yargs;
|
|
312
|
-
},
|
|
313
|
-
handler: async (args) => {
|
|
314
|
-
const c = await client();
|
|
315
|
-
const newPrograms = await c.dependency.install(args["package-spec"]);
|
|
316
|
-
console.log(`New programs available (${newPrograms.length}):`);
|
|
317
|
-
newPrograms.forEach((p) => {
|
|
318
|
-
console.log(chalk.green(p));
|
|
319
|
-
});
|
|
320
|
-
},
|
|
694
|
+
return innerYargs;
|
|
321
695
|
})
|
|
322
696
|
.help()
|
|
323
697
|
.strict()
|