@peerbit/server 1.1.2 → 2.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 +471 -144
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/client.d.ts +5 -3
- package/lib/esm/client.js +25 -8
- package/lib/esm/client.js.map +1 -1
- package/lib/esm/config.d.ts +7 -4
- package/lib/esm/config.js +31 -8
- package/lib/esm/config.js.map +1 -1
- package/lib/esm/peerbit.d.ts +2 -0
- package/lib/esm/peerbit.js +14 -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 +17 -0
- package/lib/esm/remotes.js +52 -0
- package/lib/esm/remotes.js.map +1 -0
- package/lib/esm/routes.d.ts +2 -0
- package/lib/esm/routes.js +2 -0
- package/lib/esm/routes.js.map +1 -1
- package/lib/esm/server.d.ts +17 -3
- package/lib/esm/server.js +213 -45
- 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/types.d.ts +10 -0
- package/lib/ui/assets/{index-a8188422.js → index-73eaa3bc.js} +10 -10
- package/lib/ui/index.html +1 -1
- package/package.json +7 -3
- package/src/cli.ts +649 -271
- package/src/client.ts +43 -10
- package/src/config.ts +40 -11
- package/src/peerbit.ts +24 -3
- package/src/remotes.browser.ts +1 -0
- package/src/remotes.ts +65 -0
- package/src/routes.ts +2 -0
- package/src/server.ts +278 -51
- package/src/session.ts +69 -0
- package/src/types.ts +13 -0
- package/lib/ui/assets/config.browser-4ed993c7.js +0 -1
package/lib/esm/cli.js
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
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, 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
|
+
const padString = function (string, padding, padChar = " ") {
|
|
14
|
+
const val = string.valueOf();
|
|
15
|
+
if (Math.abs(padding) <= val.length) {
|
|
16
|
+
return val;
|
|
17
|
+
}
|
|
18
|
+
const m = Math.max(Math.abs(padding) - string.length || 0, 0);
|
|
19
|
+
const pad = Array(m + 1).join(String(padChar).charAt(0));
|
|
20
|
+
// var pad = String(c || ' ').charAt(0).repeat(Math.abs(n) - this.length);
|
|
21
|
+
return padding < 0 ? pad + val : val + pad;
|
|
22
|
+
// return (n < 0) ? val + pad : pad + val;
|
|
23
|
+
};
|
|
7
24
|
export const cli = async (args) => {
|
|
8
25
|
const yargs = await import("yargs");
|
|
9
26
|
if (!args) {
|
|
@@ -15,28 +32,56 @@ export const cli = async (args) => {
|
|
|
15
32
|
.command({
|
|
16
33
|
command: "start",
|
|
17
34
|
describe: "Start node",
|
|
18
|
-
builder: {
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
builder: (yargs) => {
|
|
36
|
+
yargs
|
|
37
|
+
.option("directory", {
|
|
38
|
+
describe: "Peerbit directory",
|
|
21
39
|
defaultDescription: "~.peerbit",
|
|
22
40
|
type: "string",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
41
|
+
alias: "d",
|
|
42
|
+
default: getHomeConfigDir(),
|
|
43
|
+
})
|
|
44
|
+
.option("bootstrap", {
|
|
26
45
|
describe: "Whether to connect to bootstap nodes on startup",
|
|
27
46
|
type: "boolean",
|
|
28
47
|
default: false,
|
|
29
|
-
}
|
|
48
|
+
})
|
|
49
|
+
.option("reset", {
|
|
50
|
+
describe: "If true, then programs opened during last session will not be opened",
|
|
51
|
+
type: "boolean",
|
|
52
|
+
default: false,
|
|
53
|
+
alias: "r",
|
|
54
|
+
})
|
|
55
|
+
.option("password", {
|
|
56
|
+
describe: "Setup password so you can interact with the node remotely",
|
|
57
|
+
type: "string",
|
|
58
|
+
defaultDescription: "The password from the last session will be used or a password will be generated",
|
|
59
|
+
default: undefined,
|
|
60
|
+
})
|
|
61
|
+
.option("port-api", {
|
|
62
|
+
describe: "Set API server port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
63
|
+
type: "number",
|
|
64
|
+
default: undefined,
|
|
65
|
+
})
|
|
66
|
+
.option("port-node", {
|
|
67
|
+
describe: "Set Libp2p listen port. Only modify this when testing locally, since NGINX config depends on the default value",
|
|
68
|
+
type: "number",
|
|
69
|
+
default: undefined,
|
|
70
|
+
});
|
|
71
|
+
return yargs;
|
|
30
72
|
},
|
|
31
73
|
handler: async (args) => {
|
|
32
74
|
await startServerWithNode({
|
|
33
75
|
directory: args.directory,
|
|
34
76
|
domain: await loadConfig().then((config) => config ? getDomainFromConfig(config) : undefined),
|
|
77
|
+
ports: { api: args["port-api"], node: args["port-node"] },
|
|
35
78
|
bootstrap: args.bootstrap,
|
|
79
|
+
password: args.password,
|
|
80
|
+
newSession: args.reset,
|
|
36
81
|
});
|
|
37
82
|
},
|
|
38
83
|
})
|
|
39
|
-
.command("domain", "Setup a domain and certificate", (yargs) => {
|
|
84
|
+
.command("domain", "Setup a domain and certificate for this node", (yargs) => {
|
|
40
85
|
yargs
|
|
41
86
|
.command({
|
|
42
87
|
command: "test",
|
|
@@ -62,7 +107,6 @@ export const cli = async (args) => {
|
|
|
62
107
|
handler: async (args) => {
|
|
63
108
|
const domain = await createTestDomain();
|
|
64
109
|
await startCertbot(domain, args.email, args.outdir, args.wait);
|
|
65
|
-
const { exit } = await import("process");
|
|
66
110
|
exit();
|
|
67
111
|
},
|
|
68
112
|
})
|
|
@@ -131,193 +175,476 @@ export const cli = async (args) => {
|
|
|
131
175
|
: undefined,
|
|
132
176
|
});
|
|
133
177
|
await startCertbot(args.domain, args.email, args.outdir, args.wait);
|
|
134
|
-
const { exit } = await import("process");
|
|
135
178
|
exit();
|
|
136
179
|
},
|
|
137
180
|
})
|
|
138
181
|
.strict()
|
|
139
182
|
.demandCommand();
|
|
140
183
|
})
|
|
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
|
|
184
|
+
.command("remote", "Handle remote nodes", (innerYargs) => {
|
|
185
|
+
innerYargs
|
|
156
186
|
.command({
|
|
157
187
|
command: "list",
|
|
158
188
|
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",
|
|
189
|
+
describe: "List remotes",
|
|
192
190
|
builder: (yargs) => {
|
|
193
|
-
yargs.
|
|
191
|
+
yargs.option("directory", {
|
|
192
|
+
describe: "Peerbit directory",
|
|
193
|
+
defaultDescription: "~.peerbit",
|
|
194
194
|
type: "string",
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
alias: "d",
|
|
196
|
+
default: getHomeConfigDir(),
|
|
197
197
|
});
|
|
198
198
|
return yargs;
|
|
199
199
|
},
|
|
200
200
|
handler: async (args) => {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
202
|
+
const allRemotes = await remotes.all();
|
|
203
|
+
const maxNameLength = allRemotes
|
|
204
|
+
.map((x) => x.name.length)
|
|
205
|
+
.reduce((prev, c, i) => {
|
|
206
|
+
return Math.max(prev, c);
|
|
207
|
+
}, 0);
|
|
208
|
+
const all = await remotes.all();
|
|
209
|
+
if (all.length > 0) {
|
|
210
|
+
for (const remote of all) {
|
|
211
|
+
console.log(padString(remote.name, maxNameLength + 10), remote.address);
|
|
212
|
+
}
|
|
205
213
|
}
|
|
206
214
|
else {
|
|
207
|
-
console.log(
|
|
215
|
+
console.log("No remotes found!");
|
|
208
216
|
}
|
|
209
217
|
},
|
|
210
218
|
})
|
|
211
219
|
.command({
|
|
212
|
-
command: "
|
|
213
|
-
describe: "
|
|
220
|
+
command: "add <name> <address> <password>",
|
|
221
|
+
describe: "Add remote",
|
|
214
222
|
builder: (yargs) => {
|
|
215
|
-
yargs
|
|
223
|
+
yargs
|
|
224
|
+
.positional("address", {
|
|
216
225
|
type: "string",
|
|
217
|
-
describe: "
|
|
226
|
+
describe: "Remote name",
|
|
218
227
|
demandOption: true,
|
|
228
|
+
})
|
|
229
|
+
.positional("name", {
|
|
230
|
+
type: "string",
|
|
231
|
+
describe: "Remote address",
|
|
232
|
+
demandOption: true,
|
|
233
|
+
})
|
|
234
|
+
.positional("password", {
|
|
235
|
+
type: "string",
|
|
236
|
+
describe: "Password",
|
|
237
|
+
demandOption: true,
|
|
238
|
+
})
|
|
239
|
+
.option("directory", {
|
|
240
|
+
describe: "Peerbit directory",
|
|
241
|
+
defaultDescription: "~.peerbit",
|
|
242
|
+
type: "string",
|
|
243
|
+
alias: "d",
|
|
244
|
+
default: getHomeConfigDir(),
|
|
219
245
|
});
|
|
220
246
|
return yargs;
|
|
221
247
|
},
|
|
222
248
|
handler: async (args) => {
|
|
223
|
-
|
|
224
|
-
|
|
249
|
+
if (args.name === "localhost") {
|
|
250
|
+
throw new Error("Remote can not be named 'localhost'");
|
|
251
|
+
}
|
|
252
|
+
const api = await client(args.password, args.address);
|
|
253
|
+
try {
|
|
254
|
+
await api.program.list();
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
throw new Error("Failed to add remote: " + error?.toString());
|
|
258
|
+
}
|
|
259
|
+
if (!fs.existsSync(args.directory)) {
|
|
260
|
+
fs.mkdirSync(args.directory, { recursive: true });
|
|
261
|
+
}
|
|
262
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
263
|
+
remotes.add(args.name, args.address, args.password);
|
|
225
264
|
},
|
|
226
265
|
})
|
|
227
266
|
.command({
|
|
228
|
-
command: "
|
|
229
|
-
describe: "
|
|
267
|
+
command: "remove <name>",
|
|
268
|
+
describe: "Remove a remote",
|
|
230
269
|
builder: (yargs) => {
|
|
231
|
-
yargs
|
|
270
|
+
yargs
|
|
271
|
+
.positional("name", {
|
|
232
272
|
type: "string",
|
|
233
|
-
describe: "
|
|
273
|
+
describe: "Remote address",
|
|
234
274
|
demandOption: true,
|
|
275
|
+
})
|
|
276
|
+
.option("directory", {
|
|
277
|
+
describe: "Peerbit directory",
|
|
278
|
+
defaultDescription: "~.peerbit",
|
|
279
|
+
type: "string",
|
|
280
|
+
alias: "d",
|
|
281
|
+
default: getHomeConfigDir(),
|
|
235
282
|
});
|
|
236
283
|
return yargs;
|
|
237
284
|
},
|
|
238
285
|
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
|
-
});
|
|
286
|
+
const remotes = new Remotes(getRemotesPath(args.directory));
|
|
287
|
+
if (remotes.remove(args.name)) {
|
|
288
|
+
console.log(chalk.green("Removed remote with name: " + args.name));
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
console.log(chalk.red("Did not find any remote with name: " + args.name));
|
|
292
|
+
}
|
|
254
293
|
},
|
|
255
294
|
})
|
|
256
295
|
.command({
|
|
257
|
-
command: "
|
|
258
|
-
describe: "
|
|
296
|
+
command: "connect [name...]",
|
|
297
|
+
describe: "Connect to remote(s)",
|
|
259
298
|
builder: (yargs) => {
|
|
260
|
-
yargs
|
|
299
|
+
yargs
|
|
300
|
+
.positional("name", {
|
|
261
301
|
type: "string",
|
|
262
|
-
describe: "
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
yargs.option("variant", {
|
|
302
|
+
describe: "Remote name",
|
|
303
|
+
default: "localhost",
|
|
304
|
+
demandOption: false,
|
|
305
|
+
array: true,
|
|
306
|
+
})
|
|
307
|
+
.option("directory", {
|
|
308
|
+
describe: "Peerbit directory",
|
|
309
|
+
defaultDescription: "~.peerbit",
|
|
271
310
|
type: "string",
|
|
272
|
-
|
|
273
|
-
|
|
311
|
+
alias: "d",
|
|
312
|
+
default: getHomeConfigDir(),
|
|
274
313
|
});
|
|
275
314
|
return yargs;
|
|
276
315
|
},
|
|
277
|
-
handler: async (
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
316
|
+
handler: async (connectArgs) => {
|
|
317
|
+
const names = connectArgs.name;
|
|
318
|
+
const apis = [];
|
|
319
|
+
console.log(getRemotesPath(connectArgs.directory));
|
|
320
|
+
if (names.length > 0) {
|
|
321
|
+
const remotes = new Remotes(getRemotesPath(connectArgs.directory));
|
|
322
|
+
for (const name of names) {
|
|
323
|
+
if (name === "localhost") {
|
|
324
|
+
const config = await import("./config.js");
|
|
325
|
+
const adminPassword = await config.loadPassword(config.getServerConfigPath(connectArgs.directory));
|
|
326
|
+
apis.push({
|
|
327
|
+
log: (string) => console.log("localhost: " + string),
|
|
328
|
+
name: "localhost",
|
|
329
|
+
api: await client(adminPassword),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
const remote = remotes.getByName(name);
|
|
334
|
+
if (!remote) {
|
|
335
|
+
throw new Error("Missing remote with name: " + name);
|
|
336
|
+
}
|
|
337
|
+
let logFn;
|
|
338
|
+
if (names.length > 0) {
|
|
339
|
+
logFn = (string) => console.log(name + ": " + string);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
logFn = (string) => console.log(string);
|
|
343
|
+
}
|
|
344
|
+
apis.push({
|
|
345
|
+
log: logFn,
|
|
346
|
+
name,
|
|
347
|
+
api: await client(remote.password, remote.address),
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
287
351
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
352
|
+
// try if authenticated
|
|
353
|
+
for (const api of apis) {
|
|
354
|
+
try {
|
|
355
|
+
await api.api.program.list();
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
throw new Error(`Failed to connect to '${api.name}': ${error?.toString()}`);
|
|
359
|
+
}
|
|
292
360
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
361
|
+
const capi = () => yargs
|
|
362
|
+
.default()
|
|
363
|
+
.command("peer", "Peer info", (yargs) => {
|
|
364
|
+
yargs
|
|
365
|
+
.command({
|
|
366
|
+
command: "id",
|
|
367
|
+
describe: "Get peer id",
|
|
368
|
+
handler: async (args) => {
|
|
369
|
+
for (const api of apis) {
|
|
370
|
+
api.log((await api.api.peer.id.get()).toString());
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
})
|
|
374
|
+
.command({
|
|
375
|
+
command: "address",
|
|
376
|
+
describe: "Get addresses",
|
|
377
|
+
handler: async (args) => {
|
|
378
|
+
for (const api of apis) {
|
|
379
|
+
(await api.api.peer.addresses.get()).forEach((x) => api.log(x.toString()));
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
})
|
|
383
|
+
.strict()
|
|
384
|
+
.demandCommand();
|
|
385
|
+
return yargs;
|
|
386
|
+
})
|
|
387
|
+
.command("network", "Manage network", (yargs) => {
|
|
388
|
+
yargs
|
|
389
|
+
.command({
|
|
390
|
+
command: "bootstrap",
|
|
391
|
+
describe: "Connect to bootstrap nodes",
|
|
392
|
+
handler: async () => {
|
|
393
|
+
for (const api of apis) {
|
|
394
|
+
await api.api.network.bootstrap();
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
})
|
|
398
|
+
.strict()
|
|
399
|
+
.demandCommand();
|
|
400
|
+
})
|
|
401
|
+
.command("topic", "Manage topics the node is listening to", (yargs) => {
|
|
402
|
+
yargs
|
|
403
|
+
.command({
|
|
404
|
+
command: "list",
|
|
405
|
+
aliases: "ls",
|
|
406
|
+
describe: "List all topics",
|
|
407
|
+
builder: (yargs) => {
|
|
408
|
+
yargs.option("replicate", {
|
|
409
|
+
type: "boolean",
|
|
410
|
+
describe: "Replicate data on this topic",
|
|
411
|
+
aliases: "r",
|
|
412
|
+
default: false,
|
|
413
|
+
});
|
|
414
|
+
return yargs;
|
|
415
|
+
},
|
|
416
|
+
handler: async (args) => {
|
|
417
|
+
/* const c = await client();
|
|
418
|
+
const topics = await c.topics.get(args.replicate);
|
|
419
|
+
if (topics?.length > 0) {
|
|
420
|
+
console.log("Topic (" + topics.length + "):");
|
|
421
|
+
for (const t of topics) {
|
|
422
|
+
console.log(t);
|
|
423
|
+
}
|
|
424
|
+
} else {
|
|
425
|
+
console.log("Not subscribed to any topics");
|
|
426
|
+
} */
|
|
427
|
+
console.error("Not implemented");
|
|
428
|
+
},
|
|
429
|
+
})
|
|
430
|
+
.strict()
|
|
431
|
+
.demandCommand();
|
|
432
|
+
return yargs;
|
|
433
|
+
})
|
|
434
|
+
.command("program", "Manage programs", (yargs) => {
|
|
435
|
+
yargs
|
|
436
|
+
.command({
|
|
437
|
+
command: "status <address>",
|
|
438
|
+
describe: "Is a program open",
|
|
439
|
+
builder: (yargs) => {
|
|
440
|
+
yargs.positional("address", {
|
|
441
|
+
type: "string",
|
|
442
|
+
describe: "Program address",
|
|
443
|
+
demandOption: true,
|
|
444
|
+
});
|
|
445
|
+
return yargs;
|
|
446
|
+
},
|
|
447
|
+
handler: async (args) => {
|
|
448
|
+
for (const api of apis) {
|
|
449
|
+
const program = await api.api.program.has(args.address);
|
|
450
|
+
if (!program) {
|
|
451
|
+
api.log(chalk.red("Closed"));
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
api.log(chalk.green("Open"));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
})
|
|
459
|
+
.command({
|
|
460
|
+
command: "drop <address>",
|
|
461
|
+
describe: "Drop a program",
|
|
462
|
+
builder: (yargs) => {
|
|
463
|
+
yargs.positional("address", {
|
|
464
|
+
type: "string",
|
|
465
|
+
describe: "Program address",
|
|
466
|
+
demandOption: true,
|
|
467
|
+
});
|
|
468
|
+
return yargs;
|
|
469
|
+
},
|
|
470
|
+
handler: async (args) => {
|
|
471
|
+
for (const api of apis) {
|
|
472
|
+
try {
|
|
473
|
+
await api.api.program.drop(args.address);
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
api.log(chalk.red(`Failed to drop ${args.address}: ${error.toString()}`));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
})
|
|
481
|
+
.command({
|
|
482
|
+
command: "close <address>",
|
|
483
|
+
describe: "Close a program",
|
|
484
|
+
builder: (yargs) => {
|
|
485
|
+
yargs.positional("address", {
|
|
486
|
+
type: "string",
|
|
487
|
+
describe: "Program address",
|
|
488
|
+
demandOption: true,
|
|
489
|
+
});
|
|
490
|
+
return yargs;
|
|
491
|
+
},
|
|
492
|
+
handler: async (args) => {
|
|
493
|
+
for (const api of apis) {
|
|
494
|
+
await api.api.program.close(args.address);
|
|
495
|
+
}
|
|
496
|
+
},
|
|
497
|
+
})
|
|
498
|
+
.command({
|
|
499
|
+
command: "list",
|
|
500
|
+
describe: "List all running programs",
|
|
501
|
+
aliases: "ls",
|
|
502
|
+
handler: async (args) => {
|
|
503
|
+
for (const api of apis) {
|
|
504
|
+
const list = await api.api.program.list();
|
|
505
|
+
api.log(`Running programs (${list.length}):`);
|
|
506
|
+
list.forEach((p) => {
|
|
507
|
+
api.log(chalk.green(p));
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
})
|
|
512
|
+
.command({
|
|
513
|
+
command: "open [program]",
|
|
514
|
+
describe: "Open program",
|
|
515
|
+
builder: (yargs) => {
|
|
516
|
+
yargs.positional("program", {
|
|
517
|
+
type: "string",
|
|
518
|
+
describe: "Identifier",
|
|
519
|
+
demandOption: true,
|
|
520
|
+
});
|
|
521
|
+
yargs.option("base64", {
|
|
522
|
+
type: "string",
|
|
523
|
+
describe: "Base64 encoded serialized",
|
|
524
|
+
aliases: "b",
|
|
525
|
+
});
|
|
526
|
+
yargs.option("variant", {
|
|
527
|
+
type: "string",
|
|
528
|
+
describe: "Variant name",
|
|
529
|
+
aliases: "v",
|
|
530
|
+
});
|
|
531
|
+
return yargs;
|
|
532
|
+
},
|
|
533
|
+
handler: async (args) => {
|
|
534
|
+
if (!args.base64 && !args.variant) {
|
|
535
|
+
throw new Error("Either base64 or variant argument needs to be provided");
|
|
536
|
+
}
|
|
537
|
+
let startArg;
|
|
538
|
+
if (args.base64) {
|
|
539
|
+
startArg = {
|
|
540
|
+
base64: args.base64,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
startArg = {
|
|
545
|
+
variant: args.variant,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
for (const api of apis) {
|
|
549
|
+
const address = await api.api.program.open(startArg);
|
|
550
|
+
api.log("Started program with address: ");
|
|
551
|
+
api.log(chalk.green(address.toString()));
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
})
|
|
555
|
+
.strict()
|
|
556
|
+
.demandCommand();
|
|
557
|
+
return yargs;
|
|
558
|
+
})
|
|
559
|
+
.command({
|
|
560
|
+
command: "install <package-spec>",
|
|
561
|
+
describe: "install and import a dependency",
|
|
562
|
+
builder: (yargs) => {
|
|
563
|
+
yargs.positional("package-spec", {
|
|
564
|
+
type: "string",
|
|
565
|
+
describe: "Installed dependency will be loaded with js import(...)",
|
|
566
|
+
demandOption: true,
|
|
567
|
+
});
|
|
568
|
+
return yargs;
|
|
569
|
+
},
|
|
570
|
+
handler: async (args) => {
|
|
571
|
+
// if ends with .tgz assume it is a file
|
|
572
|
+
let installCommand;
|
|
573
|
+
const packageName = args["package-spec"];
|
|
574
|
+
if (packageName.endsWith(".tgz")) {
|
|
575
|
+
const packagePath = path.isAbsolute(packageName)
|
|
576
|
+
? packageName
|
|
577
|
+
: path.join(process.cwd(), packageName);
|
|
578
|
+
const buffer = fs.readFileSync(packagePath);
|
|
579
|
+
const base64 = toBase64(buffer);
|
|
580
|
+
installCommand = {
|
|
581
|
+
type: "tgz",
|
|
582
|
+
name: await getPackageName(packageName),
|
|
583
|
+
base64,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
installCommand = { type: "npm", name: packageName };
|
|
588
|
+
}
|
|
589
|
+
for (const api of apis) {
|
|
590
|
+
const newPrograms = await api.api.dependency.install(installCommand);
|
|
591
|
+
api.log(`New programs available (${newPrograms.length}):`);
|
|
592
|
+
newPrograms.forEach((p) => {
|
|
593
|
+
api.log(chalk.green(p));
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
})
|
|
598
|
+
.command({
|
|
599
|
+
command: "restart",
|
|
600
|
+
describe: "Restart the server",
|
|
601
|
+
handler: async () => {
|
|
602
|
+
for (const api of apis) {
|
|
603
|
+
await api.api.restart();
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
})
|
|
607
|
+
.command({
|
|
608
|
+
command: "terminate",
|
|
609
|
+
describe: "Terminate the server",
|
|
610
|
+
handler: async () => {
|
|
611
|
+
for (const api of apis) {
|
|
612
|
+
await api.api.terminate();
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
})
|
|
616
|
+
.help()
|
|
617
|
+
.strict()
|
|
618
|
+
.scriptName("")
|
|
619
|
+
.demandCommand()
|
|
620
|
+
.showHelpOnFail(true)
|
|
621
|
+
.exitProcess(false);
|
|
622
|
+
const rl = readline.createInterface({
|
|
623
|
+
input: process.stdin,
|
|
624
|
+
output: process.stdout,
|
|
625
|
+
terminal: true,
|
|
626
|
+
historySize: 100,
|
|
627
|
+
});
|
|
628
|
+
console.log(chalk.green("Connected"));
|
|
629
|
+
console.log("Write 'help' to show commands.\n");
|
|
630
|
+
const first = true;
|
|
631
|
+
rl.prompt(false);
|
|
632
|
+
rl.on("line", async (cargs) => {
|
|
633
|
+
const cmds = capi();
|
|
634
|
+
try {
|
|
635
|
+
await cmds.parse(cargs);
|
|
636
|
+
}
|
|
637
|
+
catch (error) {
|
|
638
|
+
/* console.log(chalk.red("Error parsing command: " + cargs))*/
|
|
639
|
+
}
|
|
640
|
+
rl.prompt(true);
|
|
641
|
+
});
|
|
296
642
|
},
|
|
297
643
|
})
|
|
644
|
+
.help()
|
|
298
645
|
.strict()
|
|
299
646
|
.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
|
-
},
|
|
647
|
+
return innerYargs;
|
|
321
648
|
})
|
|
322
649
|
.help()
|
|
323
650
|
.strict()
|