@peerbit/server 3.0.0 → 4.0.1

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.
Files changed (44) hide show
  1. package/lib/esm/aws.browser.d.ts +0 -0
  2. package/lib/esm/aws.browser.js +3 -0
  3. package/lib/esm/aws.browser.js.map +1 -0
  4. package/lib/esm/aws.d.ts +19 -0
  5. package/lib/esm/aws.js +185 -1
  6. package/lib/esm/aws.js.map +1 -1
  7. package/lib/esm/cli.js +590 -324
  8. package/lib/esm/cli.js.map +1 -1
  9. package/lib/esm/client.d.ts +11 -5
  10. package/lib/esm/client.js +64 -11
  11. package/lib/esm/client.js.map +1 -1
  12. package/lib/esm/docker.browser.d.ts +0 -0
  13. package/lib/esm/docker.browser.js +3 -0
  14. package/lib/esm/docker.browser.js.map +1 -0
  15. package/lib/esm/domain.js +1 -1
  16. package/lib/esm/domain.js.map +1 -1
  17. package/lib/esm/peerbit.d.ts +1 -1
  18. package/lib/esm/remotes.d.ts +15 -2
  19. package/lib/esm/remotes.js +8 -8
  20. package/lib/esm/remotes.js.map +1 -1
  21. package/lib/esm/routes.d.ts +3 -2
  22. package/lib/esm/routes.js +5 -4
  23. package/lib/esm/routes.js.map +1 -1
  24. package/lib/esm/server.d.ts +3 -1
  25. package/lib/esm/server.js +32 -19
  26. package/lib/esm/server.js.map +1 -1
  27. package/lib/esm/trust.d.ts +1 -1
  28. package/lib/esm/trust.js.map +1 -1
  29. package/lib/ui/assets/aws.browser-4ed993c7.js +1 -0
  30. package/lib/ui/assets/index-5ed0229d.js +77 -0
  31. package/lib/ui/index.html +1 -1
  32. package/package.json +13 -7
  33. package/src/aws.browser.ts +1 -0
  34. package/src/aws.ts +250 -1
  35. package/src/cli.ts +677 -354
  36. package/src/client.ts +76 -11
  37. package/src/docker.browser.ts +1 -0
  38. package/src/domain.ts +1 -1
  39. package/src/peerbit.ts +1 -1
  40. package/src/remotes.ts +24 -10
  41. package/src/routes.ts +5 -4
  42. package/src/server.ts +43 -23
  43. package/src/trust.ts +1 -1
  44. package/lib/ui/assets/index-cac7195d.js +0 -77
package/src/client.ts CHANGED
@@ -2,31 +2,56 @@ import { InstallDependency, StartProgram } from "./types.js";
2
2
  import {
3
3
  ADDRESS_PATH,
4
4
  BOOTSTRAP_PATH,
5
- TERMINATE_PATH,
5
+ STOP_PATH,
6
6
  INSTALL_PATH,
7
- LOCAL_PORT,
7
+ LOCAL_API_PORT,
8
8
  PEER_ID_PATH,
9
9
  PROGRAMS_PATH,
10
10
  PROGRAM_PATH,
11
11
  RESTART_PATH,
12
12
  TRUST_PATH,
13
+ REMOTE_API_PORT,
13
14
  } from "./routes.js";
14
15
  import { Address } from "@peerbit/program";
15
16
  import { multiaddr } from "@multiformats/multiaddr";
16
17
  import { signRequest } from "./signes-request.js";
17
18
  import {
19
+ Ed25519Keypair,
18
20
  Ed25519PublicKey,
19
21
  Identity,
20
22
  PublicSignKey,
21
23
  getPublicKeyFromPeerId,
22
24
  } from "@peerbit/crypto";
23
- import { PeerId } from "@libp2p/interface-peer-id";
25
+ import { PeerId } from "@libp2p/interface/peer-id";
26
+ import { waitForResolved } from "@peerbit/time";
27
+ import { RemoteOrigin } from "./remotes.js";
24
28
 
25
- export const client = async (
29
+ export const createClient = async (
26
30
  keypair: Identity<Ed25519PublicKey>,
27
- endpoint: string = "http://localhost:" + LOCAL_PORT
31
+ remote: { address: string; origin?: RemoteOrigin } = {
32
+ address: "http://localhost:" + LOCAL_API_PORT,
33
+ }
28
34
  ) => {
35
+ // Add missing protocol
36
+ let endpoint = remote.address;
37
+ if (!endpoint.startsWith("http://") && !endpoint.startsWith("https://")) {
38
+ if (endpoint.endsWith("localhost:") || endpoint.endsWith("localhost")) {
39
+ endpoint = "http://" + endpoint;
40
+ } else {
41
+ endpoint = "https://" + endpoint;
42
+ }
43
+ }
44
+
45
+ // Add missing port
29
46
  const isLocalHost = endpoint.startsWith("http://localhost");
47
+ if (new URL(endpoint).port === "" && !endpoint.endsWith(":80")) {
48
+ if (isLocalHost) {
49
+ endpoint = endpoint + ":" + LOCAL_API_PORT;
50
+ } else {
51
+ endpoint = endpoint + ":" + REMOTE_API_PORT;
52
+ }
53
+ }
54
+
30
55
  const { default: axios } = await import("axios");
31
56
  const axiosInstance = axios.create();
32
57
  axiosInstance.interceptors.request.use(async (config) => {
@@ -92,14 +117,17 @@ export const client = async (
92
117
  },
93
118
  },
94
119
  },
95
- trust: {
96
- add: async (key: PublicSignKey | PeerId) => {
120
+
121
+ access: {
122
+ allow: async (key: PublicSignKey | PeerId | string) => {
97
123
  const result = await axiosInstance.put(
98
124
  endpoint +
99
125
  TRUST_PATH +
100
126
  "/" +
101
127
  encodeURIComponent(
102
- key instanceof PublicSignKey
128
+ typeof key === "string"
129
+ ? key
130
+ : key instanceof PublicSignKey
103
131
  ? key.hashcode()
104
132
  : getPublicKeyFromPeerId(key).hashcode()
105
133
  ),
@@ -111,7 +139,7 @@ export const client = async (
111
139
  }
112
140
  return result.status === 200 ? true : false;
113
141
  },
114
- remove: async (key: PublicSignKey | PeerId) => {
142
+ deny: async (key: PublicSignKey | PeerId) => {
115
143
  const result = await axiosInstance.delete(
116
144
  endpoint +
117
145
  TRUST_PATH +
@@ -221,6 +249,7 @@ export const client = async (
221
249
  );
222
250
  },
223
251
  },
252
+
224
253
  restart: async (): Promise<void> => {
225
254
  throwIfNot200(
226
255
  await axiosInstance.post(endpoint + RESTART_PATH, undefined, {
@@ -228,12 +257,48 @@ export const client = async (
228
257
  })
229
258
  );
230
259
  },
231
- terminate: async (): Promise<void> => {
260
+ stop: async (): Promise<void> => {
232
261
  throwIfNot200(
233
- await axiosInstance.post(endpoint + TERMINATE_PATH, undefined, {
262
+ await axiosInstance.post(endpoint + STOP_PATH, undefined, {
234
263
  validateStatus,
235
264
  })
236
265
  );
237
266
  },
267
+ terminate: async () => {
268
+ const { terminateNode } = await import("./aws.js");
269
+ if (remote.origin?.type === "aws") {
270
+ await terminateNode({
271
+ instanceId: remote.origin.instanceId,
272
+ region: remote.origin.region,
273
+ });
274
+ }
275
+ },
238
276
  };
239
277
  };
278
+
279
+ export const waitForDomain = async (
280
+ ip: string,
281
+ timeout: number = 5 * 60 * 1000
282
+ ): Promise<string> => {
283
+ const c = await createClient(await Ed25519Keypair.create(), {
284
+ address: "http://" + ip + ":" + LOCAL_API_PORT,
285
+ });
286
+ const result = await waitForResolved(
287
+ async () => {
288
+ const addresses = await c.peer.addresses.get();
289
+ const domain = multiaddr(addresses[0]).nodeAddress().address;
290
+ if (!domain) {
291
+ throw new Error("Not ready");
292
+ }
293
+ return domain;
294
+ },
295
+ {
296
+ delayInterval: 5000,
297
+ timeout,
298
+ }
299
+ );
300
+ if (!result) {
301
+ throw new Error("Failed to resolve domain");
302
+ }
303
+ return result;
304
+ };
@@ -0,0 +1 @@
1
+ // Unsupported
package/src/domain.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { waitFor, waitForAsync } from "@peerbit/time";
2
- import { installDocker, startContainer } from "./docker.js";
3
2
 
4
3
  const isNode = typeof window === undefined || typeof window === "undefined";
5
4
 
@@ -146,6 +145,7 @@ export const startCertbot = async (
146
145
  if (!validateEmail(email)) {
147
146
  throw new Error("Email for SSL renenewal is invalid");
148
147
  }
148
+ const { installDocker, startContainer } = await import("./docker.js");
149
149
 
150
150
  const nginxConfigPath = await getNginxFolderPath();
151
151
  await createConfig(nginxConfigPath, domain);
package/src/peerbit.ts CHANGED
@@ -2,7 +2,7 @@ import { DirectBlock } from "@peerbit/blocks";
2
2
  import { DirectSub } from "@peerbit/pubsub";
3
3
  import { Peerbit } from "peerbit";
4
4
  import path from "path";
5
- import { PeerId } from "@libp2p/interface-peer-id";
5
+ import { PeerId } from "@libp2p/interface/peer-id";
6
6
 
7
7
  export const LIBP2P_LISTEN_PORT = 8001;
8
8
  export const create = (properties: {
package/src/remotes.ts CHANGED
@@ -1,11 +1,23 @@
1
1
  import fs from "fs";
2
2
 
3
- interface RemoteObject {
3
+ interface AWSOrigin {
4
+ type: "aws";
5
+ region: string;
6
+ instanceId: string;
7
+ }
8
+
9
+ export type RemoteOrigin = AWSOrigin;
10
+
11
+ export const DEFAULT_REMOTE_GROUP = "default";
12
+
13
+ export interface RemoteObject {
4
14
  address: string;
5
15
  name: string;
16
+ group: string;
17
+ origin?: RemoteOrigin;
6
18
  }
7
19
 
8
- interface RemotesObject {
20
+ export interface RemotesObject {
9
21
  remotes: RemoteObject[];
10
22
  }
11
23
 
@@ -31,19 +43,21 @@ export class Remotes {
31
43
  getByName(name: string) {
32
44
  return this.data.remotes.find((x) => x.name === name);
33
45
  }
46
+
47
+ getByGroup(group: string) {
48
+ return this.data.remotes.filter((x) => x.group === group);
49
+ }
50
+
34
51
  getByAddress(address: string) {
35
52
  return this.data.remotes.find((x) => x.address === address);
36
53
  }
37
- add(name: string, address: string) {
38
- const obj: RemoteObject = {
39
- address,
40
- name,
41
- };
42
- const existing = this.data.remotes.findIndex((x) => x.name === name);
54
+
55
+ add(remote: RemoteObject) {
56
+ const existing = this.data.remotes.findIndex((x) => x.name === remote.name);
43
57
  if (existing >= 0) {
44
- this.data.remotes[existing] = obj;
58
+ this.data.remotes[existing] = remote;
45
59
  } else {
46
- this.data.remotes.push(obj);
60
+ this.data.remotes.push(remote);
47
61
  }
48
62
  this.save();
49
63
  }
package/src/routes.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  export const getPort = (protocol: string) => {
2
2
  if (protocol === "https:") {
3
- return SSL_PORT;
3
+ return REMOTE_API_PORT;
4
4
  }
5
5
 
6
6
  if (protocol === "http:") {
7
- return LOCAL_PORT;
7
+ return LOCAL_API_PORT;
8
8
  }
9
9
 
10
10
  throw new Error("Unsupported protocol: " + protocol);
11
11
  };
12
- export const SSL_PORT = 9002;
13
- export const LOCAL_PORT = 8082;
12
+ export const REMOTE_API_PORT = 9002;
13
+ export const LOCAL_API_PORT = 8082;
14
14
  export const TRUST_PATH = "/trust";
15
15
  export const PEER_ID_PATH = "/peer/id";
16
16
  export const ADDRESS_PATH = "/peer/address";
@@ -20,3 +20,4 @@ export const INSTALL_PATH = "/install";
20
20
  export const BOOTSTRAP_PATH = "/network/bootstrap";
21
21
  export const RESTART_PATH = "/restart";
22
22
  export const TERMINATE_PATH = "/terminate";
23
+ export const STOP_PATH = "/path";
package/src/server.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import http from "http";
2
- import { Ed25519Keypair, fromBase64, sha256Base64Sync } from "@peerbit/crypto";
2
+ import {
3
+ fromBase64,
4
+ getKeypairFromPeerId,
5
+ getPublicKeyFromPeerId,
6
+ } from "@peerbit/crypto";
3
7
  import { deserialize } from "@dao-xyz/borsh";
4
8
  import {
5
9
  Program,
@@ -28,14 +32,14 @@ import {
28
32
  import {
29
33
  ADDRESS_PATH,
30
34
  BOOTSTRAP_PATH,
31
- TERMINATE_PATH,
32
35
  INSTALL_PATH,
33
- LOCAL_PORT,
36
+ LOCAL_API_PORT,
34
37
  PEER_ID_PATH,
35
38
  PROGRAMS_PATH,
36
39
  PROGRAM_PATH,
37
40
  RESTART_PATH,
38
41
  TRUST_PATH,
42
+ STOP_PATH,
39
43
  } from "./routes.js";
40
44
  import { Session } from "./session.js";
41
45
  import fs from "fs";
@@ -51,6 +55,7 @@ import { MemoryLevel } from "memory-level";
51
55
  import { Trust } from "./trust.js";
52
56
  import { getBody, verifyRequest } from "./signes-request.js";
53
57
  import { cli } from "./cli.js";
58
+ import { peerIdFromString } from "@libp2p/peer-id";
54
59
 
55
60
  const __dirname = dirname(fileURLToPath(import.meta.url));
56
61
 
@@ -68,6 +73,7 @@ export const startServerWithNode = async (properties: {
68
73
  domain?: string;
69
74
  bootstrap?: boolean;
70
75
  newSession?: boolean;
76
+ grantAccess?: string[];
71
77
  ports?: {
72
78
  node: number;
73
79
  api: number;
@@ -77,12 +83,16 @@ export const startServerWithNode = async (properties: {
77
83
  if (!fs.existsSync(properties.directory)) {
78
84
  fs.mkdirSync(properties.directory, { recursive: true });
79
85
  }
86
+
87
+ const trustPeerIds =
88
+ properties.grantAccess && properties.grantAccess.length > 0
89
+ ? properties.grantAccess.map((x) => peerIdFromString(x))
90
+ : [];
91
+
80
92
  const keypair = await getKeypair(properties.directory);
93
+
81
94
  const peer = await create({
82
- directory:
83
- properties.directory != null
84
- ? getNodePath(properties.directory)
85
- : undefined,
95
+ directory: getNodePath(properties.directory),
86
96
  domain: properties.domain,
87
97
  listenPort: properties.ports?.node,
88
98
  peerId: await keypair.toPeerId(),
@@ -120,12 +130,10 @@ export const startServerWithNode = async (properties: {
120
130
  await session.clear();
121
131
  }
122
132
 
133
+ const trust = new Trust(getTrustPath(properties.directory));
123
134
  const server = await startApiServer(peer, {
124
135
  port: properties.ports?.api,
125
- configDirectory:
126
- properties.directory != null
127
- ? path.join(properties.directory, "server")
128
- : undefined || getHomeConfigDir(),
136
+ trust,
129
137
  session,
130
138
  });
131
139
  const printNodeInfo = async () => {
@@ -164,6 +172,12 @@ export const startServerWithNode = async (properties: {
164
172
  });
165
173
  };
166
174
  await shutDownHook(peer, server);
175
+
176
+ if (trustPeerIds.length > 0) {
177
+ for (const id of trustPeerIds) {
178
+ trust.add(getPublicKeyFromPeerId(id).hashcode());
179
+ }
180
+ }
167
181
  return { server, node: peer };
168
182
  };
169
183
 
@@ -212,17 +226,12 @@ function findPeerbitProgramFolder(inputDirectory: string): string | null {
212
226
  export const startApiServer = async (
213
227
  client: ProgramClient,
214
228
  properties: {
215
- configDirectory: string;
229
+ trust: Trust;
216
230
  session?: Session;
217
231
  port?: number;
218
232
  }
219
233
  ): Promise<http.Server> => {
220
- const port = properties?.port ?? LOCAL_PORT;
221
- if (!fs.existsSync(properties.configDirectory)) {
222
- fs.mkdirSync(properties.configDirectory, { recursive: true });
223
- }
224
-
225
- const trust = new Trust(getTrustPath(properties.configDirectory));
234
+ const port = properties?.port ?? LOCAL_API_PORT;
226
235
 
227
236
  const restart = async () => {
228
237
  await client.stop();
@@ -259,7 +268,7 @@ export const startApiServer = async (
259
268
  if (result.equals(client.identity.publicKey)) {
260
269
  return body;
261
270
  }
262
- if (trust.isTrusted(result.hashcode())) {
271
+ if (properties.trust.isTrusted(result.hashcode())) {
263
272
  return body;
264
273
  }
265
274
  throw new Error("Not trusted");
@@ -547,13 +556,13 @@ export const startApiServer = async (
547
556
  } else if (req.url.startsWith(TRUST_PATH)) {
548
557
  switch (req.method) {
549
558
  case "PUT": {
550
- trust.add(getPathValue(req, 1));
559
+ properties.trust.add(getPathValue(req, 1));
551
560
  res.writeHead(200);
552
561
  res.end();
553
562
  break;
554
563
  }
555
564
  case "DELETE": {
556
- const removed = trust.remove(getPathValue(req, 1));
565
+ const removed = properties.trust.remove(getPathValue(req, 1));
557
566
  res.writeHead(200);
558
567
  res.end(removed);
559
568
  break;
@@ -574,7 +583,7 @@ export const startApiServer = async (
574
583
  r404();
575
584
  break;
576
585
  }
577
- } else if (req.url.startsWith(TERMINATE_PATH)) {
586
+ } else if (req.url.startsWith(STOP_PATH)) {
578
587
  switch (req.method) {
579
588
  case "POST":
580
589
  res.writeHead(200);
@@ -586,7 +595,18 @@ export const startApiServer = async (
586
595
  r404();
587
596
  break;
588
597
  }
589
- } else if (req.url.startsWith(PEER_ID_PATH)) {
598
+ } /* else if (req.url.startsWith(TERMINATE_PATH)) {
599
+ switch (req.method) {
600
+ case "POST":
601
+ execSync("shutdown -h now")
602
+ process.exit(0);
603
+ break;
604
+
605
+ default:
606
+ r404();
607
+ break;
608
+ }
609
+ } */ else if (req.url.startsWith(PEER_ID_PATH)) {
590
610
  res.writeHead(200);
591
611
  res.end(client.peerId.toString());
592
612
  } else if (req.url.startsWith(ADDRESS_PATH)) {
package/src/trust.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import fs from "fs";
2
2
 
3
3
  export class Trust {
4
- private trusted: string[];
4
+ trusted: string[];
5
5
  constructor(readonly path: string) {
6
6
  if (fs.existsSync(path)) {
7
7
  this.trusted = JSON.parse(