From cfa8f596026d8f305918294d98b8c97d5df83627 Mon Sep 17 00:00:00 2001
From: catloversg <152669316+catloversg@users.noreply.github.com>
Date: Thu, 24 Jul 2025 04:16:24 +0700
Subject: [PATCH] DOCUMENTATION: Update Remote API docs (#2258)
---
.../doc/en/programming/remote_api.md | 213 +++++++++++++++---
.../remote-file-api-sequence-diagram.svg | 3 +
src/Documentation/pages.ts | 5 +
tools/bundle-doc/index.js | 27 +--
4 files changed, 197 insertions(+), 51 deletions(-)
create mode 100644 src/Documentation/images/remote-file-api-sequence-diagram.svg
diff --git a/src/Documentation/doc/en/programming/remote_api.md b/src/Documentation/doc/en/programming/remote_api.md
index d775fd277..deb155ab0 100644
--- a/src/Documentation/doc/en/programming/remote_api.md
+++ b/src/Documentation/doc/en/programming/remote_api.md
@@ -1,14 +1,41 @@
# Remote API
-All versions of Bitburner can use websockets to connect to a server.
-That server can then perform a number of actions.
-Most commonly this is used in conjunction with an external text editor or API
-in order to make writing scripts easier, or even use typescript.
+Bitburner can connect to a WebSocket server, and then that server can read and write Bitburner data via some APIs. The most common usage of this feature is to synchronize files between Bitburner and an external system. With a Remote API tool, you can write your scripts in any text editor and synchronize your scripts with Bitburner.
-To make use of this Remote API through the official server, look [here](https://github.com/bitburner-official/typescript-template).
-If you want to make your own server, see below for API details.
+You only need to do 2 things:
-This API uses the JSON RPC 2.0 protocol. Inputs are in the following form:
+- Start the Remote API tool.
+- In Bitburner, Options -> Remote API. Set "hostname" and "port", then press "Connect".
+
+## Community tools
+
+All these tools support synchronizing scripts to Bitburner and transpiling TypeScript/JSX to JavaScript. Note that Bitburner has native support for TypeScript/JSX.
+
+Links:
+
+- https://github.com/bitburner-official/typescript-template
+- https://github.com/Tanimodori/viteburner
+- https://github.com/shyguy1412/bb-external-editor
+
+`typescript-template` has a small set of options and features. Its simplicity is by design. `viteburner` and `bb-external-editor` have more fancy features.
+
+## Troubleshooting tips
+
+- Try to update the tool and restart it. Check error messages printed in the terminal to see what went wrong.
+- When you turn off your machine or put it in sleep mode, the connection between Bitburner and the tool is closed. You have to connect again.
+- Some external programs or browser extensions may interfere with the connection. For example, some antivirus programs and ad-blocker extensions may block the WebSocket connection.
+- Some tools support a feature that is usually called "mirroring". You must read the instructions carefully before using it. This feature allows 2-way sync, but it may overwrite your scripts or other files _on your machine_ if you set it up wrong.
+- If you need further help, please ask us on the [external-editors](https://discord.com/channels/415207508303544321/923428435618058311) channel.
+
+## How it works
+
+
+
+## API specification
+
+All APIs use an input/output format similar to the JSON RPC 2.0 protocol.
+
+Input:
{
"jsonrpc": "2.0",
@@ -17,7 +44,7 @@ This API uses the JSON RPC 2.0 protocol. Inputs are in the following form:
"params": any
}
-Outputs:
+Output:
{
"jsonrpc": "2.0",
@@ -26,23 +53,24 @@ Outputs:
"error": any
}
-## Methods
-
-## `pushFile`
+### pushFile
Create or update a file.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "pushFile",
"params": {
- filename: string;
- content: string;
- server: string;
+ "filename": string,
+ "content": string,
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
@@ -50,20 +78,23 @@ Create or update a file.
"result": "OK"
}
-## `getFile`
+### getFile
Read a file and its content.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "getFile",
"params": {
- filename: string;
- server: string;
+ "filename": string,
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
@@ -71,20 +102,52 @@ Read a file and its content.
"result": string
}
-## `deleteFile`
+### getFileMetadata
+
+Read metadata of a file.
+
+Input:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "method": "getFileMetadata",
+ "params": {
+ "filename": string,
+ "server": string
+ }
+ }
+
+Output:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "result": {
+ "filename": string,
+ "atime": string,
+ "btime": string,
+ "mtime": string
+ }
+ }
+
+### deleteFile
Delete a file.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "deleteFile",
"params": {
- filename: string;
- server: string;
+ "filename": string,
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
@@ -92,19 +155,22 @@ Delete a file.
"result": "OK"
}
-## `getFileNames`
+### getFileNames
List all file names on a server.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "getFileNames",
"params": {
- server: string;
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
@@ -112,43 +178,77 @@ List all file names on a server.
"result": string[]
}
-## `getAllFiles`
+### getAllFiles
Get the content of all files on a server.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "getAllFiles",
"params": {
- server: string;
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
"id": number,
"result": {
- filename: string,
- content: string
+ "filename": string,
+ "content": string
}[]
}
-## `calculateRam`
+### getAllFileMetadata
+
+Input:
+
+Get the content of all files on a server.
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "method": "getAllFileMetadata",
+ "params": {
+ "server": string
+ }
+ }
+
+Output:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "result": {
+ "filename": string,
+ "atime": string
+ "btime": string,
+ "mtime": string,
+ }[]
+ }
+
+### calculateRam
Calculate the in-game ram cost of a script.
+Input:
+
{
"jsonrpc": "2.0",
"id": number,
"method": "calculateRam",
"params": {
- filename: string;
- server: string;
+ "filename": string,
+ "server": string
}
}
+Output:
{
"jsonrpc": "2.0",
@@ -156,9 +256,11 @@ Calculate the in-game ram cost of a script.
"result": number
}
-## `getDefinitionFile`
+### getDefinitionFile
-Get the definition file of the API.
+Get the definition file of NS APIs.
+
+Input:
{
"jsonrpc": "2.0",
@@ -166,9 +268,58 @@ Get the definition file of the API.
"method": "getDefinitionFile"
}
+Output:
{
"jsonrpc": "2.0",
"id": number,
"result": string
}
+
+### getSaveFile
+
+Get save data.
+
+Input:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "method": "getSaveFile"
+ }
+
+Output:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "result": {
+ "identifier": string,
+ "binary": boolean,
+ "save": string
+ }
+ }
+
+### getAllServers
+
+Get all servers.
+
+Input:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "method": "getAllServers"
+ }
+
+Output:
+
+ {
+ "jsonrpc": "2.0",
+ "id": number,
+ "result": {
+ "hostname": string,
+ "hasAdminRights": boolean,
+ "purchasedByPlayer": boolean
+ }[]
+ }
diff --git a/src/Documentation/images/remote-file-api-sequence-diagram.svg b/src/Documentation/images/remote-file-api-sequence-diagram.svg
new file mode 100644
index 000000000..a08351bc1
--- /dev/null
+++ b/src/Documentation/images/remote-file-api-sequence-diagram.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/src/Documentation/pages.ts b/src/Documentation/pages.ts
index becb426a4..985d24842 100644
--- a/src/Documentation/pages.ts
+++ b/src/Documentation/pages.ts
@@ -63,6 +63,7 @@ import file60 from "./doc/en/programming/hackingalgorithms.md?raw";
import file61 from "./doc/en/programming/learn.md?raw";
import file62 from "./doc/en/programming/remote_api.md?raw";
import file63 from "./doc/en/programming/typescript_react.md?raw";
+
import nsDoc_bitburner__valueof_md from "../../markdown/bitburner._valueof.md?raw";
import nsDoc_bitburner_activefragment_highestcharge_md from "../../markdown/bitburner.activefragment.highestcharge.md?raw";
import nsDoc_bitburner_activefragment_id_md from "../../markdown/bitburner.activefragment.id.md?raw";
@@ -1497,6 +1498,8 @@ import nsDoc_bitburner_workstats_reputation_md from "../../markdown/bitburner.wo
import nsDoc_bitburner_workstats_strexp_md from "../../markdown/bitburner.workstats.strexp.md?raw";
import nsDoc_index_md from "../../markdown/index.md?raw";
+import docImages_remote_file_api_sequence_diagram_svg from "./images/remote-file-api-sequence-diagram.svg";
+
export const AllPages: Record = {};
AllPages["en/advanced/bitnode_recommendation_comprehensive_guide.md"] = file0;
AllPages["en/advanced/bitnode_recommendation_short_guide.md"] = file1;
@@ -1562,6 +1565,7 @@ AllPages["en/programming/hackingalgorithms.md"] = file60;
AllPages["en/programming/learn.md"] = file61;
AllPages["en/programming/remote_api.md"] = file62;
AllPages["en/programming/typescript_react.md"] = file63;
+
AllPages["nsDoc/bitburner._valueof.md"] = nsDoc_bitburner__valueof_md;
AllPages["nsDoc/bitburner.activefragment.highestcharge.md"] = nsDoc_bitburner_activefragment_highestcharge_md;
AllPages["nsDoc/bitburner.activefragment.id.md"] = nsDoc_bitburner_activefragment_id_md;
@@ -3001,3 +3005,4 @@ export const nsApiPages = Object.keys(AllPages)
.map((page) => page.replace("nsDoc/", ""));
export const DocImages: Record = {};
+DocImages["remote-file-api-sequence-diagram.svg"] = docImages_remote_file_api_sequence_diagram_svg;
diff --git a/tools/bundle-doc/index.js b/tools/bundle-doc/index.js
index 6ef94984a..926c649da 100644
--- a/tools/bundle-doc/index.js
+++ b/tools/bundle-doc/index.js
@@ -54,32 +54,19 @@ processDir(docImagesRoot);
* in src\Documentation\doc, but we rarely add or remove files in it, so it's not a big deal. Checking ~60 lines is also
* much easier than checking ~1400 lines.
*/
-let autogeneratedContent = `// THIS FILE IS AUTOGENERATED. DO NOT EDIT IT MANUALLY.
-${docFiles.map((f, i) => `import file${i} from "./doc/${f}?raw";`).join("\n")}
-${nsDocFiles.map((f, i) => `import nsDoc_${f.replaceAll(".", "_")} from "../../markdown/${f}?raw";`).join("\n")}
-`;
-if (docImagesFiles.length > 0) {
- autogeneratedContent += `${docImagesFiles
- .map((f) => `import docImages_${f.replaceAll(".", "_")} from "./images/${f}";`)
- .join("\n")}
-`;
-}
-autogeneratedContent += `
+const autogeneratedContent = `// THIS FILE IS AUTOGENERATED. DO NOT EDIT IT MANUALLY.
+${docFiles.map((f, i) => `import file${i} from "./doc/${f}?raw";\n`).join("")}
+${nsDocFiles.map((f) => `import nsDoc_${f.replaceAll(".", "_")} from "../../markdown/${f}?raw";\n`).join("")}
+${docImagesFiles.map((f) => `import docImages_${f.replaceAll(/\.|-/g, "_")} from "./images/${f}";\n`).join("")}
export const AllPages: Record = {};
-${docFiles.map((f, i) => `AllPages["${f}"] = file${i};`).join("\n")}
-${nsDocFiles.map((f, i) => `AllPages["nsDoc/${f}"] = nsDoc_${f.replaceAll(".", "_")};`).join("\n")}
-
+${docFiles.map((f, i) => `AllPages["${f}"] = file${i};\n`).join("")}
+${nsDocFiles.map((f) => `AllPages["nsDoc/${f}"] = nsDoc_${f.replaceAll(".", "_")};\n`).join("")}
export const nsApiPages = Object.keys(AllPages)
.filter((page) => page.startsWith("nsDoc"))
.map((page) => page.replace("nsDoc/", ""));
export const DocImages: Record = {};
-`;
-if (docImagesFiles.length > 0) {
- autogeneratedContent += `
-${docImagesFiles.map((f, i) => `DocImages["${f}"] = docImages_${f.replaceAll(".", "_")};`).join("\n")}
-`;
-}
+${docImagesFiles.map((f) => `DocImages["${f}"] = docImages_${f.replaceAll(/\.|-/g, "_")};\n`).join("")}`;
fs.writeFile(path.resolve(__dirname, "../../src/Documentation/pages.ts"), autogeneratedContent, (err) => {
if (err) {