@peerbit/server 2.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) 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 +614 -299
  8. package/lib/esm/cli.js.map +1 -1
  9. package/lib/esm/client.d.ts +13 -1
  10. package/lib/esm/client.js +101 -31
  11. package/lib/esm/client.js.map +1 -1
  12. package/lib/esm/config.d.ts +3 -3
  13. package/lib/esm/config.js +18 -16
  14. package/lib/esm/config.js.map +1 -1
  15. package/lib/esm/docker.browser.d.ts +0 -0
  16. package/lib/esm/docker.browser.js +3 -0
  17. package/lib/esm/docker.browser.js.map +1 -0
  18. package/lib/esm/domain.js +1 -1
  19. package/lib/esm/domain.js.map +1 -1
  20. package/lib/esm/peerbit.d.ts +2 -0
  21. package/lib/esm/peerbit.js +1 -0
  22. package/lib/esm/peerbit.js.map +1 -1
  23. package/lib/esm/remotes.d.ts +15 -3
  24. package/lib/esm/remotes.js +8 -9
  25. package/lib/esm/remotes.js.map +1 -1
  26. package/lib/esm/routes.d.ts +4 -2
  27. package/lib/esm/routes.js +6 -4
  28. package/lib/esm/routes.js.map +1 -1
  29. package/lib/esm/server.d.ts +5 -7
  30. package/lib/esm/server.js +183 -185
  31. package/lib/esm/server.js.map +1 -1
  32. package/lib/esm/signes-request.d.ts +5 -0
  33. package/lib/esm/signes-request.js +54 -0
  34. package/lib/esm/signes-request.js.map +1 -0
  35. package/lib/esm/trust.browser.d.ts +0 -0
  36. package/lib/esm/trust.browser.js +3 -0
  37. package/lib/esm/trust.browser.js.map +1 -0
  38. package/lib/esm/trust.d.ts +9 -0
  39. package/lib/esm/trust.js +36 -0
  40. package/lib/esm/trust.js.map +1 -0
  41. package/lib/ui/assets/aws.browser-4ed993c7.js +1 -0
  42. package/lib/ui/assets/index-5ed0229d.js +77 -0
  43. package/lib/ui/index.html +1 -1
  44. package/package.json +13 -7
  45. package/src/aws.browser.ts +1 -0
  46. package/src/aws.ts +250 -1
  47. package/src/cli.ts +726 -348
  48. package/src/client.ts +145 -38
  49. package/src/config.ts +21 -23
  50. package/src/docker.browser.ts +1 -0
  51. package/src/domain.ts +1 -1
  52. package/src/peerbit.ts +3 -0
  53. package/src/remotes.ts +24 -12
  54. package/src/routes.ts +6 -5
  55. package/src/server.ts +238 -254
  56. package/src/signes-request.ts +84 -0
  57. package/src/trust.browser.ts +1 -0
  58. package/src/trust.ts +39 -0
  59. package/lib/ui/assets/index-73eaa3bc.js +0 -53
package/src/client.ts CHANGED
@@ -2,28 +2,69 @@ 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
+ TRUST_PATH,
13
+ REMOTE_API_PORT,
12
14
  } from "./routes.js";
13
15
  import { Address } from "@peerbit/program";
14
16
  import { multiaddr } from "@multiformats/multiaddr";
17
+ import { signRequest } from "./signes-request.js";
18
+ import {
19
+ Ed25519Keypair,
20
+ Ed25519PublicKey,
21
+ Identity,
22
+ PublicSignKey,
23
+ getPublicKeyFromPeerId,
24
+ } from "@peerbit/crypto";
25
+ import { PeerId } from "@libp2p/interface/peer-id";
26
+ import { waitForResolved } from "@peerbit/time";
27
+ import { RemoteOrigin } from "./remotes.js";
15
28
 
16
- export const client = async (
17
- password: string,
18
- endpoint: string = "http://localhost:" + LOCAL_PORT
29
+ export const createClient = async (
30
+ keypair: Identity<Ed25519PublicKey>,
31
+ remote: { address: string; origin?: RemoteOrigin } = {
32
+ address: "http://localhost:" + LOCAL_API_PORT,
33
+ }
19
34
  ) => {
20
- const isLocalHost = endpoint.startsWith("http://localhost");
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
+ }
21
44
 
22
- if (!isLocalHost && password == null) {
23
- throw new Error("Expecting password when starting the client");
45
+ // Add missing port
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
+ }
24
53
  }
25
54
 
26
55
  const { default: axios } = await import("axios");
56
+ const axiosInstance = axios.create();
57
+ axiosInstance.interceptors.request.use(async (config) => {
58
+ const url = new URL(config.url!);
59
+ await signRequest(
60
+ config.headers,
61
+ config.method!,
62
+ url.pathname + url.search,
63
+ config.data,
64
+ keypair
65
+ );
66
+ return config;
67
+ });
27
68
 
28
69
  const validateStatus = (status: number) => {
29
70
  return (status >= 200 && status < 300) || status == 404;
@@ -53,19 +94,12 @@ export const client = async (
53
94
  };
54
95
  const getId = async () =>
55
96
  throwIfNot200(
56
- await axios.get(endpoint + PEER_ID_PATH, {
97
+ await axiosInstance.get(endpoint + PEER_ID_PATH, {
57
98
  validateStatus,
58
99
  timeout: 5000,
59
100
  })
60
101
  ).data;
61
102
 
62
- const getHeaders = async () => {
63
- const headers = {
64
- authorization: "Basic admin:" + password,
65
- };
66
- return headers;
67
- };
68
-
69
103
  return {
70
104
  peer: {
71
105
  id: {
@@ -75,7 +109,7 @@ export const client = async (
75
109
  get: async () => {
76
110
  return (
77
111
  throwIfNot200(
78
- await axios.get(endpoint + ADDRESS_PATH, {
112
+ await axiosInstance.get(endpoint + ADDRESS_PATH, {
79
113
  validateStatus,
80
114
  })
81
115
  ).data as string[]
@@ -83,14 +117,54 @@ export const client = async (
83
117
  },
84
118
  },
85
119
  },
120
+
121
+ access: {
122
+ allow: async (key: PublicSignKey | PeerId | string) => {
123
+ const result = await axiosInstance.put(
124
+ endpoint +
125
+ TRUST_PATH +
126
+ "/" +
127
+ encodeURIComponent(
128
+ typeof key === "string"
129
+ ? key
130
+ : key instanceof PublicSignKey
131
+ ? key.hashcode()
132
+ : getPublicKeyFromPeerId(key).hashcode()
133
+ ),
134
+ undefined,
135
+ { validateStatus }
136
+ );
137
+ if (result.status !== 200 && result.status !== 404) {
138
+ throw new Error(result.data);
139
+ }
140
+ return result.status === 200 ? true : false;
141
+ },
142
+ deny: async (key: PublicSignKey | PeerId) => {
143
+ const result = await axiosInstance.delete(
144
+ endpoint +
145
+ TRUST_PATH +
146
+ "/" +
147
+ encodeURIComponent(
148
+ key instanceof PublicSignKey
149
+ ? key.hashcode()
150
+ : getPublicKeyFromPeerId(key).hashcode()
151
+ ),
152
+ { validateStatus }
153
+ );
154
+ if (result.status !== 200 && result.status !== 404) {
155
+ throw new Error(result.data);
156
+ }
157
+ return result.status === 200 ? true : false;
158
+ },
159
+ },
86
160
  program: {
87
161
  has: async (address: Address | string): Promise<boolean> => {
88
- const result = await axios.head(
162
+ const result = await axiosInstance.head(
89
163
  endpoint +
90
164
  PROGRAM_PATH +
91
165
  "/" +
92
166
  encodeURIComponent(address.toString()),
93
- { validateStatus, headers: await getHeaders() }
167
+ { validateStatus }
94
168
  );
95
169
  if (result.status !== 200 && result.status !== 404) {
96
170
  throw new Error(result.data);
@@ -100,24 +174,26 @@ export const client = async (
100
174
 
101
175
  open: async (program: StartProgram): Promise<Address> => {
102
176
  const resp = throwIfNot200(
103
- await axios.put(endpoint + PROGRAM_PATH, JSON.stringify(program), {
104
- validateStatus,
105
- headers: await getHeaders(),
106
- })
177
+ await axiosInstance.put(
178
+ endpoint + PROGRAM_PATH,
179
+ JSON.stringify(program),
180
+ {
181
+ validateStatus,
182
+ }
183
+ )
107
184
  );
108
185
  return resp.data as string;
109
186
  },
110
187
 
111
188
  close: async (address: string): Promise<void> => {
112
189
  throwIfNot200(
113
- await axios.delete(
190
+ await axiosInstance.delete(
114
191
  endpoint +
115
192
  PROGRAM_PATH +
116
193
  "/" +
117
194
  encodeURIComponent(address.toString()),
118
195
  {
119
196
  validateStatus,
120
- headers: await getHeaders(),
121
197
  }
122
198
  )
123
199
  );
@@ -125,7 +201,7 @@ export const client = async (
125
201
 
126
202
  drop: async (address: string): Promise<void> => {
127
203
  throwIfNot200(
128
- await axios.delete(
204
+ await axiosInstance.delete(
129
205
  endpoint +
130
206
  PROGRAM_PATH +
131
207
  "/" +
@@ -133,7 +209,6 @@ export const client = async (
133
209
  "?delete=true",
134
210
  {
135
211
  validateStatus,
136
- headers: await getHeaders(),
137
212
  }
138
213
  )
139
214
  );
@@ -141,9 +216,8 @@ export const client = async (
141
216
 
142
217
  list: async (): Promise<string[]> => {
143
218
  const resp = throwIfNot200(
144
- await axios.get(endpoint + PROGRAMS_PATH, {
219
+ await axiosInstance.get(endpoint + PROGRAMS_PATH, {
145
220
  validateStatus,
146
- headers: await getHeaders(),
147
221
  })
148
222
  );
149
223
  return resp.data as string[];
@@ -151,12 +225,11 @@ export const client = async (
151
225
  },
152
226
  dependency: {
153
227
  install: async (instruction: InstallDependency): Promise<string[]> => {
154
- const resp = await axios.put(
228
+ const resp = await axiosInstance.put(
155
229
  endpoint + INSTALL_PATH,
156
230
  JSON.stringify(instruction),
157
231
  {
158
232
  validateStatus,
159
- headers: await getHeaders(),
160
233
  }
161
234
  );
162
235
  if (resp.status !== 200) {
@@ -170,28 +243,62 @@ export const client = async (
170
243
  network: {
171
244
  bootstrap: async (): Promise<void> => {
172
245
  throwIfNot200(
173
- await axios.post(endpoint + BOOTSTRAP_PATH, undefined, {
246
+ await axiosInstance.post(endpoint + BOOTSTRAP_PATH, undefined, {
174
247
  validateStatus,
175
- headers: await getHeaders(),
176
248
  })
177
249
  );
178
250
  },
179
251
  },
252
+
180
253
  restart: async (): Promise<void> => {
181
254
  throwIfNot200(
182
- await axios.post(endpoint + RESTART_PATH, undefined, {
255
+ await axiosInstance.post(endpoint + RESTART_PATH, undefined, {
183
256
  validateStatus,
184
- headers: await getHeaders(),
185
257
  })
186
258
  );
187
259
  },
188
- terminate: async (): Promise<void> => {
260
+ stop: async (): Promise<void> => {
189
261
  throwIfNot200(
190
- await axios.post(endpoint + TERMINATE_PATH, undefined, {
262
+ await axiosInstance.post(endpoint + STOP_PATH, undefined, {
191
263
  validateStatus,
192
- headers: await getHeaders(),
193
264
  })
194
265
  );
195
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
+ },
196
276
  };
197
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
+ };
package/src/config.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import path from "path";
2
2
  import os from "os";
3
3
  import fs from "fs";
4
-
4
+ import { deserialize, serialize } from "@dao-xyz/borsh";
5
5
  import { Duplex } from "stream"; // Native Node Module
6
+ import { Ed25519Keypair, Keypair, fromBase64 } from "@peerbit/crypto";
6
7
 
7
8
  const bufferToStream = (myBuffer) => {
8
9
  const tmp = new Duplex();
@@ -16,10 +17,6 @@ export const getHomeConfigDir = (): string => {
16
17
  return configDir;
17
18
  };
18
19
 
19
- export const getCredentialsPath = (configDir: string): string => {
20
- return path.join(configDir, "credentials.json");
21
- };
22
-
23
20
  export const getServerConfigPath = (configDir: string): string => {
24
21
  return path.join(configDir, "server");
25
22
  };
@@ -32,10 +29,28 @@ export const getNodePath = (directory: string): string => {
32
29
  return path.join(directory, "node");
33
30
  };
34
31
 
35
- export const getKeysPath = async (configDir: string): Promise<string> => {
32
+ export const getTrustPath = (directory: string): string => {
33
+ return path.join(directory, "trust.json");
34
+ };
35
+
36
+ const getKeysPath = (configDir: string): string => {
36
37
  return path.join(configDir, "keys");
37
38
  };
38
39
 
40
+ export const getKeypair = async (
41
+ configDir: string
42
+ ): Promise<Ed25519Keypair> => {
43
+ const keypath = getKeysPath(configDir);
44
+ if (!fs.existsSync(keypath)) {
45
+ const keypair = await Ed25519Keypair.create();
46
+ fs.writeFileSync(keypath, serialize(keypair));
47
+ return keypair;
48
+ } else {
49
+ const keypair = deserialize(fs.readFileSync(keypath), Ed25519Keypair);
50
+ return keypair;
51
+ }
52
+ };
53
+
39
54
  export const checkExistPath = async (path: string) => {
40
55
  try {
41
56
  if (!fs.existsSync(path)) {
@@ -51,23 +66,6 @@ export const checkExistPath = async (path: string) => {
51
66
  }
52
67
  };
53
68
 
54
- export const loadPassword = async (
55
- configDirectory: string
56
- ): Promise<string> => {
57
- const configDir = configDirectory || (await getHomeConfigDir());
58
- const credentialsPath = await getCredentialsPath(configDir);
59
- if (!(await checkExistPath(credentialsPath))) {
60
- throw new NotFoundError("Credentials file does not exist");
61
- }
62
- const password = JSON.parse(
63
- fs.readFileSync(credentialsPath, "utf-8")
64
- ).password;
65
- if (!password || password.length === 0) {
66
- throw new NotFoundError("Password not found");
67
- }
68
- return password;
69
- };
70
-
71
69
  export const getPackageName = async (
72
70
  path: string | Uint8Array
73
71
  ): Promise<string> => {
@@ -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,12 +2,14 @@ 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
6
 
6
7
  export const LIBP2P_LISTEN_PORT = 8001;
7
8
  export const create = (properties: {
8
9
  directory?: string;
9
10
  domain?: string;
10
11
  listenPort?: number;
12
+ peerId: PeerId;
11
13
  }) => {
12
14
  const listenPort = properties.listenPort ?? LIBP2P_LISTEN_PORT;
13
15
  const blocksDirectory =
@@ -17,6 +19,7 @@ export const create = (properties: {
17
19
 
18
20
  return Peerbit.create({
19
21
  libp2p: {
22
+ peerId: properties.peerId,
20
23
  addresses: {
21
24
  announce: properties.domain
22
25
  ? [
package/src/remotes.ts CHANGED
@@ -1,12 +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;
6
- password: string;
16
+ group: string;
17
+ origin?: RemoteOrigin;
7
18
  }
8
19
 
9
- interface RemotesObject {
20
+ export interface RemotesObject {
10
21
  remotes: RemoteObject[];
11
22
  }
12
23
 
@@ -32,20 +43,21 @@ export class Remotes {
32
43
  getByName(name: string) {
33
44
  return this.data.remotes.find((x) => x.name === name);
34
45
  }
46
+
47
+ getByGroup(group: string) {
48
+ return this.data.remotes.filter((x) => x.group === group);
49
+ }
50
+
35
51
  getByAddress(address: string) {
36
52
  return this.data.remotes.find((x) => x.address === address);
37
53
  }
38
- add(name: string, address: string, password: string) {
39
- const obj: RemoteObject = {
40
- address,
41
- name,
42
- password,
43
- };
44
- 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);
45
57
  if (existing >= 0) {
46
- this.data.remotes[existing] = obj;
58
+ this.data.remotes[existing] = remote;
47
59
  } else {
48
- this.data.remotes.push(obj);
60
+ this.data.remotes.push(remote);
49
61
  }
50
62
  this.save();
51
63
  }
package/src/routes.ts CHANGED
@@ -1,17 +1,17 @@
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;
14
-
12
+ export const REMOTE_API_PORT = 9002;
13
+ export const LOCAL_API_PORT = 8082;
14
+ export const TRUST_PATH = "/trust";
15
15
  export const PEER_ID_PATH = "/peer/id";
16
16
  export const ADDRESS_PATH = "/peer/address";
17
17
  export const PROGRAM_PATH = "/program";
@@ -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";