bitburner-studio 0.1.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/README.md ADDED
@@ -0,0 +1,169 @@
1
+ Bitburner Studio
2
+
3
+ > Build, learn, and automate.
4
+
5
+ A modern development environment for Bitburner featuring workspace synchronization, TypeScript support, live compilation, extensible modules, visual scripting, and future AI-assisted learning tools.
6
+
7
+ ---
8
+
9
+ ## Vision
10
+
11
+ Bitburner Studio aims to make Bitburner feel like a real software development environment while remaining approachable for new programmers.
12
+
13
+ The project is built around a simple idea:
14
+
15
+ > Learn programming through creation, not repetition.
16
+
17
+ Users should be able to start with visual tools, inspect the generated TypeScript, understand how it works, and eventually write their own code.
18
+
19
+ ---
20
+
21
+ ## Current Features
22
+
23
+ ### Workspace Synchronization
24
+
25
+ - Download files from Bitburner
26
+ - Upload local changes automatically
27
+ - Keep local and in-game workspaces synchronized
28
+
29
+ ### TypeScript Support
30
+
31
+ - Automatic TypeScript detection
32
+ - Incremental compilation
33
+ - Watch mode support
34
+ - Generated JavaScript deployment
35
+
36
+ ### Strongly Typed Configuration
37
+
38
+ ```ts
39
+ const root = config.get('workspace.root');
40
+ const autoWatch = config.get('typescript.auto-watch');
41
+ ```
42
+
43
+ Full autocomplete and type safety.
44
+
45
+ ### Live Development Workflow
46
+
47
+ - File watching
48
+ - Incremental builds
49
+ - Automatic uploads
50
+ - Fast iteration loop
51
+
52
+ ---
53
+
54
+ ## Planned Features
55
+
56
+ ### Module System
57
+
58
+ ```json
59
+ {
60
+ "modules": {
61
+ "ui": true,
62
+ "remote": true,
63
+ "source-manager": true
64
+ }
65
+ }
66
+ ```
67
+
68
+ Modules will be able to:
69
+
70
+ - Install automatically
71
+ - Download sources
72
+ - Generate typings
73
+ - Configure dependencies
74
+ - Integrate into the workspace
75
+
76
+ ### Visual Programming
77
+
78
+ Node-based scripting for Bitburner.
79
+
80
+ ```text
81
+ Scan Network
82
+
83
+ Find Targets
84
+
85
+ Analyze
86
+
87
+ Hack
88
+ ```
89
+
90
+ Generated code remains visible and editable.
91
+
92
+ ### AI Assistant
93
+
94
+ Future AI features may include:
95
+
96
+ - Code explanation
97
+ - Error diagnosis
98
+ - Script generation
99
+ - Learning assistance
100
+ - Contract guidance
101
+
102
+ The goal is to teach programming, not hide it.
103
+
104
+ ---
105
+
106
+ ## Roadmap
107
+
108
+ ### Core
109
+
110
+ - [x] Workspace synchronization
111
+ - [x] Automatic uploads
112
+ - [x] Automatic downloads
113
+ - [x] TypeScript support
114
+ - [x] Watch mode
115
+ - [x] Typed configuration
116
+
117
+ ### Modules
118
+
119
+ - [ ] Module manager
120
+ - [ ] Module registry
121
+ - [ ] Dependency management
122
+ - [ ] Automatic typings
123
+
124
+ ### UI
125
+
126
+ - [ ] Vizui integration
127
+ - [ ] Dashboard
128
+ - [ ] Monitoring tools
129
+ - [ ] Contract utilities
130
+
131
+ ### Visual Development
132
+
133
+ - [ ] Node editor
134
+ - [ ] Flow execution
135
+ - [ ] Code generation
136
+ - [ ] Visual debugging
137
+
138
+ ### AI
139
+
140
+ - [ ] AI assistant
141
+ - [ ] Error explanations
142
+ - [ ] Learning mode
143
+ - [ ] Context-aware guidance
144
+
145
+ ---
146
+
147
+ ## Philosophy
148
+
149
+ Bitburner Studio should:
150
+
151
+ - Encourage learning
152
+ - Generate readable code
153
+ - Remain transparent
154
+ - Stay modular
155
+ - Scale from beginner to advanced users
156
+
157
+ ---
158
+
159
+ ## Status
160
+
161
+ Early development.
162
+
163
+ Expect rapid changes before the first stable release.
164
+
165
+ ---
166
+
167
+ ## License
168
+
169
+ Apache-2.0
@@ -0,0 +1,18 @@
1
+ # Build setting
2
+ **/node_modules/
3
+ **/dist/
4
+ **/dist-*/
5
+ **/.**
6
+ **/*.log
7
+ **/*.env
8
+ **/*.tsbuildinfo
9
+ !.gitignore
10
+
11
+ # Work space setting
12
+ !.vscode/
13
+
14
+ # Bitburner Workspace setting
15
+ **/.shared/
16
+ **/.backup/
17
+ !home/
18
+ !remote/
package/dist/BBApi.js ADDED
@@ -0,0 +1,65 @@
1
+ import Logger from '@netfeez/vterm';
2
+ import { API, NSInput, NSOutput } from './contract.js';
3
+ export * from './contract.js';
4
+ const logger = new Logger({ name: 'BBC' });
5
+ export class BBApi {
6
+ ws;
7
+ pending = new Map();
8
+ index = 0;
9
+ constructor(ws) {
10
+ this.ws = ws;
11
+ }
12
+ send(method, params) {
13
+ const id = this.index++;
14
+ const entry = API[method];
15
+ const processedParams = entry.input.processUnknown(params);
16
+ return new Promise((resolve, reject) => {
17
+ const success = (data) => {
18
+ try {
19
+ const parsed = entry.output.processUnknown(data);
20
+ resolve(parsed);
21
+ }
22
+ catch (error) {
23
+ throw (new Error(`Failed to parse response for method ${method}: ${error} | data: ${data}`));
24
+ }
25
+ };
26
+ this.pending.set(id, { method, success, fail: reject });
27
+ const request = NSInput.processData({ id, method, params: processedParams });
28
+ const json = JSON.stringify(request);
29
+ this.ws.send(json);
30
+ });
31
+ }
32
+ handleMessage(message) {
33
+ let json;
34
+ let data;
35
+ try {
36
+ json = JSON.parse(message);
37
+ data = NSOutput.processUnknown(json);
38
+ }
39
+ catch (error) {
40
+ logger.error('Failed to parse message', error);
41
+ if (json)
42
+ logger.error(json);
43
+ logger.error(error);
44
+ return;
45
+ }
46
+ const pending = this.pending.get(data.id);
47
+ if (!pending)
48
+ return logger.error('No pending request for id', data.id);
49
+ this.pending.delete(data.id);
50
+ try {
51
+ if ('error' in data)
52
+ throw new Error(`${typeof data.error === 'string' ? data.error : JSON.stringify(data.error)}`);
53
+ pending.success(data.result);
54
+ }
55
+ catch (error) {
56
+ pending.fail(error);
57
+ }
58
+ }
59
+ rejectAll(error) {
60
+ this.pending.forEach((entry) => { entry.fail(error); });
61
+ this.pending.clear();
62
+ }
63
+ }
64
+ export default BBApi;
65
+ //# sourceMappingURL=BBApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BBApi.js","sourceRoot":"","sources":["../src/BBApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import Logger from '@netfeez/vterm';
2
+ import BBApi, { IS_VALID_FILENAME } from './BBApi.js';
3
+ const logger = new Logger({ name: 'BBC' });
4
+ export class BBClient {
5
+ ws;
6
+ static BACKUP_FORMAT = '{DD}-{MM}-{YYYY}/{HH}-{mm}-{ss}-{ms}';
7
+ static WORKSPACE = '.workspace';
8
+ static SHARED = '.shared';
9
+ static BACKUP = '.backup';
10
+ static DEFINITION_FILE = 'NetScript.d.ts';
11
+ api;
12
+ preBind;
13
+ constructor(ws) {
14
+ this.ws = ws;
15
+ this.api = new BBApi(ws);
16
+ this.preBind = {
17
+ message: this.api.handleMessage.bind(this.api),
18
+ close: this.closeHandler.bind(this)
19
+ };
20
+ this.ws.on('close', this.preBind.close);
21
+ this.ws.on('message:text', this.preBind.message);
22
+ }
23
+ get online() { return this.ws.status === 'open'; }
24
+ disconnect() { this.ws.close(); }
25
+ /**
26
+ * Retrieves the content of a specific file on the specified server by sending a request to the client with the server name and file path, and awaiting the response, which is expected to contain the contents of the file as a string.
27
+ * The function returns a promise that resolves to the contents of the specified file on the specified server as a string.
28
+ * @param server - The name of the server where the file is located.
29
+ * @param path - The path to the file on the server for which to retrieve the content.
30
+ * @returns A promise that resolves to the contents of the specified file on the specified server as a string.
31
+ */
32
+ async getFile(server, path) {
33
+ return await this.api.send('getFile', { server, filename: path });
34
+ }
35
+ /**
36
+ * Retrieves a list of all files on the specified server by sending a request to the client and awaiting the response, which is expected to be an array of file entries containing metadata about each file.
37
+ * The function returns a promise that resolves to an array of file entries, which can be used to access the metadata for each file on the server.
38
+ * @param server - The name of the server for which to retrieve the files.
39
+ * @returns A promise that resolves to an array of file entries containing metadata about each file on the specified server.
40
+ */
41
+ async getFiles(server) {
42
+ return await this.api.send('getAllFiles', { server });
43
+ }
44
+ /**
45
+ * Retrieves a list of file names on the specified server by sending a request to the client and awaiting the response, which is expected to be an array of strings representing the file names on the server.
46
+ * The function returns a promise that resolves to an array of file names on the specified server.
47
+ * @param server - The name of the server for which to retrieve the file names.
48
+ * @returns A promise that resolves to an array of strings representing the file names on the specified server.
49
+ */
50
+ async getFileNames(server) {
51
+ return await this.api.send('getFileNames', { server });
52
+ }
53
+ /**
54
+ * Retrieves metadata for a specific file on the specified server by sending a request to the client with the server name and file path, and awaiting the response, which is expected to contain metadata about the file such as its size and last modified date.
55
+ * The function returns a promise that resolves to an object containing the file metadata, which can be used to access information about the file on the server.
56
+ * @param server - The name of the server where the file is located.
57
+ * @param path - The path to the file on the server for which to retrieve metadata.
58
+ * @returns A promise that resolves to an object containing metadata about the specified file on the specified server.
59
+ */
60
+ async getFileMetadata(server, path) {
61
+ return await this.api.send('getFileMetadata', { server, filename: path });
62
+ }
63
+ /**
64
+ * Retrieves metadata for all files on the specified server by sending a request to the client with the server name and awaiting the response, which is expected to be an array of metadata objects for each file on the server.
65
+ * The function returns a promise that resolves to an array of file metadata objects, which can be used to access information about all files on the specified server.
66
+ * @param server - The name of the server for which to retrieve metadata for all files.
67
+ * @returns A promise that resolves to an array of file metadata objects for all files on the specified server.
68
+ */
69
+ async getAllFilesMetadata(server) {
70
+ return await this.api.send('getAllFileMetadata', { server });
71
+ }
72
+ /**
73
+ * Updates a file on the specified server by sending a request to the client with the server name, file path, and new content.
74
+ * The client is expected to handle the request and update the file accordingly.
75
+ * The function returns a boolean indicating whether the update was successful.
76
+ * @param server - The name of the server where the file is located.
77
+ * @param path - The path to the file on the server.
78
+ * @param content - The new content to be written to the file.
79
+ * @returns A promise that resolves to true if the update was successful, or false if it failed.
80
+ */
81
+ async updateFile(server, path, content) {
82
+ if (!IS_VALID_FILENAME.test(path))
83
+ throw new Error(`Invalid file name: ${path}`);
84
+ const result = await this.api.send('pushFile', { server, filename: path, content });
85
+ if (result !== 'OK')
86
+ throw new Error(`Failed to update file ${path} on server ${server}. Server responded with: ${result}`);
87
+ return true;
88
+ }
89
+ async getAllServers() {
90
+ return await this.api.send('getAllServers', {});
91
+ }
92
+ /**
93
+ * Deletes a file on the specified server by sending a request to the client with the server name and file path.
94
+ * The client is expected to handle the request and delete the file accordingly.
95
+ * The function returns a boolean indicating whether the deletion was successful.
96
+ * @param server - The name of the server where the file is located.
97
+ * @param path - The path to the file on the server that should be deleted.
98
+ * @returns A promise that resolves to true if the deletion was successful, or false if it failed.
99
+ */
100
+ async deleteFile(server, path) {
101
+ const result = await this.api.send('deleteFile', { server, filename: path });
102
+ if (result !== 'OK')
103
+ throw new Error(`Failed to delete file ${path} on server ${server}. Server responded with: ${result}`);
104
+ return true;
105
+ }
106
+ /**
107
+ * Retrieves a backup of the current state of the game by sending a request to the client and awaiting the response, which is expected to contain the backup data.
108
+ * The function returns a promise that resolves to the backup data, which can be used to restore the game state at a later time.
109
+ */
110
+ async backup() {
111
+ return await this.api.send('getSaveFile', {});
112
+ }
113
+ /**
114
+ * Retrieves the definition file from the client by sending a request and awaiting the response, which is expected to contain the contents of the definition file as a string.
115
+ * If the convertInGlobal parameter is set to true, the function wraps the contents of the definition file in a declare global block and adds an export statement at the end, allowing the definitions to be used in a global context.
116
+ * The function returns a promise that resolves to the contents of the definition file as a string, either in its original form or wrapped in a global declaration depending on the value of convertInGlobal.
117
+ * @param convertInGlobal - A boolean indicating whether to wrap the definition file contents in a declare global block for use in a global context.
118
+ * @returns A promise that resolves to the contents of the definition file as a string, optionally wrapped in a declare global block if convertInGlobal is true.
119
+ */
120
+ async getDefinitionFile(convertInGlobal = false) {
121
+ const definitions = await this.api.send('getDefinitionFile', {});
122
+ if (!convertInGlobal)
123
+ return definitions;
124
+ return [
125
+ 'declare global {',
126
+ ...definitions.split(/[\r\n]/).map(line => ` ${line}`),
127
+ '}',
128
+ 'export {};',
129
+ ].join('\n');
130
+ }
131
+ /**
132
+ * Handles the WebSocket connection close event.
133
+ * Rejects all pending API requests and removes event listeners.
134
+ */
135
+ closeHandler() {
136
+ this.api.rejectAll(new Error('WebSocket connection closed'));
137
+ this.ws.off('message:text', this.preBind.message);
138
+ this.ws.off('close', this.preBind.close);
139
+ }
140
+ }
141
+ export default BBClient;
142
+ //# sourceMappingURL=BBClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BBClient.js","sourceRoot":"","sources":["../src/BBClient.ts"],"names":[],"mappings":"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"}
package/dist/Config.js ADDED
@@ -0,0 +1,139 @@
1
+ import { Flatten, Schema } from "@netfeez/common";
2
+ import { File, Path } from "@netfeez/common-node";
3
+ export const workspaceSchema = new Schema({
4
+ type: 'object',
5
+ properties: {
6
+ download: { type: 'boolean', default: true },
7
+ typescript: { type: 'boolean', default: true },
8
+ root: { type: 'string', default: '.' }
9
+ },
10
+ additionalProperties: false,
11
+ });
12
+ export const typescriptSchema = new Schema({
13
+ type: 'object',
14
+ properties: {
15
+ "auto-watch": { type: 'boolean', default: true }
16
+ },
17
+ additionalProperties: false,
18
+ });
19
+ export const schema = new Schema({
20
+ type: 'object',
21
+ properties: {
22
+ host: { type: 'string', default: 'localhost' },
23
+ port: { type: 'number', default: 3000 },
24
+ workspace: workspaceSchema.root,
25
+ typescript: typescriptSchema.root
26
+ },
27
+ additionalProperties: false,
28
+ });
29
+ export class Config {
30
+ static CONFIG_FILE = 'bb-connect.config.json';
31
+ vData;
32
+ vPlainData;
33
+ debouncedSave;
34
+ path;
35
+ constructor(data, path = Config.CONFIG_FILE) {
36
+ this.path = Path.resolve(path);
37
+ this.vData = schema.processData(data);
38
+ this.vPlainData = Flatten.object(this.vData);
39
+ this.debouncedSave = Config.debounce(this.save.bind(this), 1000);
40
+ }
41
+ /**
42
+ * Gets the configuration data.
43
+ * The data is returned in its processed form, with any transformations defined in the schema applied.
44
+ * @returns The configuration data.
45
+ */
46
+ get data() { return this.vData; }
47
+ /**
48
+ * Sets the configuration data and saves it to the file.
49
+ * The data is processed through the schema before being saved.
50
+ * @param value The configuration data to set.
51
+ * @remarks This method is debounced, so it will delay saving the configuration until after 1 second has elapsed since the last time it was called. This is to prevent excessive file writes when multiple values are set in quick succession.
52
+ */
53
+ set data(value) {
54
+ this.vData = schema.processData(value);
55
+ this.vPlainData = Flatten.object(this.vData);
56
+ this.debouncedSave();
57
+ }
58
+ /**
59
+ * Gets a value from the configuration. The value is returned in its plain form, without any processing from the schema.
60
+ * @param key The key of the value to get.
61
+ * @returns The value associated with the given key.
62
+ */
63
+ get(key) { return this.vPlainData[key]; }
64
+ /**
65
+ * Sets a value in the configuration and saves it to the file.
66
+ * The value is processed through the schema before being saved.
67
+ * @param key The key of the value to set.
68
+ * @param value The value to set.
69
+ */
70
+ set(key, value) {
71
+ const old = this.vPlainData[key];
72
+ try {
73
+ this.vPlainData[key] = value;
74
+ this.vData = schema.processData(this.vPlainData);
75
+ }
76
+ catch (error) {
77
+ this.vPlainData[key] = old;
78
+ throw error;
79
+ }
80
+ this.debouncedSave();
81
+ }
82
+ /**
83
+ * Saves the current configuration to the specified path.
84
+ * If no path is provided, it will save to the path specified in the constructor.
85
+ * @param path The path to save the configuration to.
86
+ */
87
+ async save(path = this.path) {
88
+ const processed = schema.processData(this.vData);
89
+ const json = JSON.stringify(processed, null, 4);
90
+ await File.write(path, json, 'utf-8');
91
+ }
92
+ /**
93
+ * Saves the current configuration to the specified path.
94
+ * @param data The configuration data to save.
95
+ * @param path The path to save the configuration to.
96
+ */
97
+ static async save(data, path) {
98
+ path = Path.resolve(path);
99
+ const processed = schema.processData(data);
100
+ const json = JSON.stringify(processed, null, 4);
101
+ await File.write(path, json, 'utf-8');
102
+ }
103
+ /**
104
+ * Loads the configuration from the specified path. If the file does not exist, a new configuration will be created with default values and saved to the path.
105
+ * @param path The path to load the configuration from.
106
+ * @returns The loaded configuration.
107
+ */
108
+ static async load(path) {
109
+ path = Path.resolve(path);
110
+ if (!await File.exists(path)) {
111
+ const config = new Config(schema.processData({}), path);
112
+ await config.save();
113
+ return config;
114
+ }
115
+ const json = await File.read(path, 'utf-8');
116
+ const data = JSON.parse(json);
117
+ return new Config(data, path);
118
+ }
119
+ toJSON() { return this.vData; }
120
+ /**
121
+ * Creates a debounced version of the given function that delays invoking the function until after wait milliseconds have elapsed since the last time the debounced function was invoked.
122
+ * @param func The function to debounce.
123
+ * @param wait The number of milliseconds to delay.
124
+ * @returns A debounced version of the given function.
125
+ */
126
+ static debounce(func, wait) {
127
+ let timeout = null;
128
+ return function (...args) {
129
+ if (timeout)
130
+ clearTimeout(timeout);
131
+ timeout = setTimeout(() => {
132
+ func.apply(this, args);
133
+ timeout = null;
134
+ }, wait);
135
+ };
136
+ }
137
+ }
138
+ export default Config;
139
+ //# sourceMappingURL=Config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Config.js","sourceRoot":"","sources":["../src/Config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export const TSCONFIG = {
2
+ compilerOptions: {
3
+ target: 'EsNext',
4
+ module: 'NodeNext',
5
+ moduleResolution: 'NodeNext',
6
+ outDir: './shared',
7
+ rootDir: './server',
8
+ types: [],
9
+ lib: ['DOM', 'ESNext'],
10
+ declaration: false,
11
+ sourceMap: false
12
+ },
13
+ include: ['./server/**/*.ts', 'bin/**/*.d.ts']
14
+ };
15
+ export const PACKAGE = {
16
+ name: 'bitburner-connect-workspace',
17
+ description: 'A workspace for Bitburner Connect',
18
+ version: '1.0.0',
19
+ type: 'module',
20
+ scripts: {
21
+ start: 'cd ../; node dist/server.js',
22
+ dev: 'npx tsc --watch',
23
+ build: 'npx tsc'
24
+ },
25
+ keywords: [],
26
+ author: '',
27
+ license: 'ISC',
28
+ devDependencies: {
29
+ typescript: '^6.0.3'
30
+ }
31
+ };
32
+ const Defaults = { TSCONFIG, PACKAGE };
33
+ export default Defaults;
34
+ //# sourceMappingURL=Default.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Default.js","sourceRoot":"","sources":["../../src/Workspace/Default.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,eAAe,EAAE;QACb,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,UAAU;QAClB,gBAAgB,EAAE,UAAU;QAC5B,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,UAAU;QACnB,KAAK,EAAE,EAAE;QACT,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;QACtB,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,KAAK;KACnB;IACD,OAAO,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC;CACjD,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG;IACnB,IAAI,EAAE,6BAA6B;IACnC,WAAW,EAAE,mCAAmC;IAChD,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE;QACL,KAAK,EAAE,6BAA6B;QACpC,GAAG,EAAE,iBAAiB;QACtB,KAAK,EAAE,SAAS;KACnB;IACD,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,KAAK;IACd,eAAe,EAAE;QACb,UAAU,EAAE,QAAQ;KACvB;CACJ,CAAC;AACF,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACvC,eAAe,QAAQ,CAAC"}