@peerbit/server 5.5.0 → 5.6.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.
@@ -23,7 +23,7 @@
23
23
  Learn how to configure a non-root public URL by running `npm run build`.
24
24
  -->
25
25
  <title>Peerbit</title>
26
- <script type="module" crossorigin src="/assets/index-C8bxNrXj.js"></script>
26
+ <script type="module" crossorigin src="/assets/index-Dcbn6kSA.js"></script>
27
27
  <link rel="stylesheet" crossorigin href="/assets/index-CIfVvUo9.css">
28
28
  </head>
29
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peerbit/server",
3
- "version": "5.5.0",
3
+ "version": "5.6.0",
4
4
  "author": "dao.xyz",
5
5
  "repository": {
6
6
  "type": "git",
package/src/cli.ts CHANGED
@@ -1188,6 +1188,29 @@ export const cli = async (args?: string[]) => {
1188
1188
  }
1189
1189
  },
1190
1190
  })
1191
+ .command({
1192
+ command: "self-update [version]",
1193
+ describe:
1194
+ "Update @peerbit/server on the target node to [version] (default latest) and restart",
1195
+ builder: (yargs) => {
1196
+ yargs.positional("version", {
1197
+ describe:
1198
+ "Version spec for @peerbit/server (e.g. 5.4.16)",
1199
+ type: "string",
1200
+ });
1201
+ return yargs;
1202
+ },
1203
+ handler: async (args) => {
1204
+ for (const api of apis) {
1205
+ const { version } = await api.api.selfUpdate(
1206
+ args.version as string | undefined,
1207
+ );
1208
+ api.log(
1209
+ `Self-update to @peerbit/server@${version} initiated`,
1210
+ );
1211
+ }
1212
+ },
1213
+ })
1191
1214
  .command({
1192
1215
  command: "stop",
1193
1216
  describe: "Stop the server",
package/src/client.ts CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  PROGRAM_VARIANTS_PATH,
23
23
  REMOTE_API_PORT,
24
24
  RESTART_PATH,
25
+ SELF_UPDATE_PATH,
25
26
  STOP_PATH,
26
27
  TRUST_PATH,
27
28
  VERSIONS_PATH,
@@ -301,6 +302,18 @@ export const createClient = async (
301
302
  }),
302
303
  );
303
304
  },
305
+ selfUpdate: async (version?: string): Promise<{ version: string }> => {
306
+ const resp = throwIfNot200(
307
+ await axiosInstance.post(
308
+ endpoint + SELF_UPDATE_PATH,
309
+ version ? JSON.stringify({ version }) : undefined,
310
+ {
311
+ validateStatus,
312
+ },
313
+ ),
314
+ );
315
+ return resp.data as { version: string };
316
+ },
304
317
  stop: async (): Promise<void> => {
305
318
  throwIfNot200(
306
319
  await axiosInstance.post(endpoint + STOP_PATH, undefined, {
package/src/routes.ts CHANGED
@@ -24,3 +24,4 @@ export const TERMINATE_PATH = "/terminate";
24
24
  export const STOP_PATH = "/stop";
25
25
  export const LOG_PATH = "/log";
26
26
  export const VERSIONS_PATH = "/versions";
27
+ export const SELF_UPDATE_PATH = "/self/update";
package/src/server.ts CHANGED
@@ -35,6 +35,7 @@ import {
35
35
  PROGRAM_PATH,
36
36
  PROGRAM_VARIANTS_PATH,
37
37
  RESTART_PATH,
38
+ SELF_UPDATE_PATH,
38
39
  STOP_PATH,
39
40
  TRUST_PATH,
40
41
  VERSIONS_PATH,
@@ -712,6 +713,73 @@ export const startApiServer = async (
712
713
  }
713
714
 
714
715
  /* keep the remaining else-if blocks (PEER_ID_PATH, etc.) unchanged */
716
+ } else if (req.url.startsWith(SELF_UPDATE_PATH)) {
717
+ if (req.method === "POST") {
718
+ try {
719
+ // version is optional; default to latest
720
+ let versionSpec: string | undefined;
721
+ try {
722
+ const parsed = JSON.parse(body || "{}");
723
+ versionSpec = parsed?.version;
724
+ } catch (_e) {}
725
+
726
+ let resolvedVersion = "latest";
727
+ try {
728
+ const spec = `@peerbit/server${versionSpec ? "@" + versionSpec : ""}`;
729
+ const out = execSync(`npm view ${spec} version --json`, {
730
+ encoding: "utf8",
731
+ });
732
+ resolvedVersion = JSON.parse(out);
733
+ } catch (_e) {
734
+ resolvedVersion = versionSpec || "latest";
735
+ }
736
+
737
+ console.log(
738
+ "Self-updating @peerbit/server to version: " +
739
+ resolvedVersion,
740
+ );
741
+ res.setHeader("Content-Type", "application/json");
742
+ res.writeHead(200);
743
+ res.end(JSON.stringify({ version: resolvedVersion }));
744
+
745
+ process.nextTick(() => {
746
+ try {
747
+ const installDir = getInstallDir();
748
+ let permission = "";
749
+ if (installDir) {
750
+ try {
751
+ fs.accessSync(installDir, fs.constants.W_OK);
752
+ } catch (_e) {
753
+ permission = "sudo";
754
+ }
755
+ try {
756
+ execSync(
757
+ `${permission} npm install -g @peerbit/server@${resolvedVersion}`,
758
+ );
759
+ } catch (_globalErr) {
760
+ execSync(
761
+ `${permission} npm install @peerbit/server@${resolvedVersion} --prefix ${installDir} --no-save --no-package-lock`,
762
+ );
763
+ }
764
+ } else {
765
+ execSync(
766
+ `npm install -g @peerbit/server@${resolvedVersion}`,
767
+ );
768
+ }
769
+ } catch (e) {
770
+ console.error("Self-update installation failed:", e);
771
+ }
772
+ restart();
773
+ });
774
+ } catch (error: any) {
775
+ res.writeHead(500);
776
+ res.end(
777
+ "Unexpected self-update error: " + (error?.message || ""),
778
+ );
779
+ }
780
+ } else {
781
+ r404();
782
+ }
715
783
  } else if (req.url.startsWith(BOOTSTRAP_PATH)) {
716
784
  switch (req.method) {
717
785
  case "POST":