Converts JS files to TS
Closes bitburner-official/bitburner-filesync#12
This commit is contained in:
parent
bef0628e79
commit
778b8d492a
10 changed files with 83 additions and 48 deletions
|
@ -1,9 +1,11 @@
|
||||||
import CheapWatch from "cheap-watch";
|
import CheapWatch from "cheap-watch";
|
||||||
import { config } from "./config.js";
|
import { config } from "./config";
|
||||||
import { EventType } from "./eventTypes.js";
|
import { EventType } from "./eventTypes";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
import type { Signal } from 'signal-js';
|
||||||
|
import type { File } from './interfaces';
|
||||||
|
|
||||||
function fileFilter(file) {
|
function fileFilter(file: File) {
|
||||||
if (config.get("allowedFiletypes").some(extension => file.path.endsWith(extension)))
|
if (config.get("allowedFiletypes").some(extension => file.path.endsWith(extension)))
|
||||||
return true;
|
return true;
|
||||||
if (file.stats.isDirectory())
|
if (file.stats.isDirectory())
|
||||||
|
@ -11,7 +13,7 @@ function fileFilter(file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setupWatch(signaller) {
|
export async function setupWatch(signaller: Signal) {
|
||||||
const watch = new CheapWatch({
|
const watch = new CheapWatch({
|
||||||
dir: config.get("scriptsFolder"),
|
dir: config.get("scriptsFolder"),
|
||||||
filter: fileFilter,
|
filter: fileFilter,
|
||||||
|
@ -32,4 +34,4 @@ export async function setupWatch(signaller) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return watch;
|
return watch;
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
"use strict"
|
import { setupWatch } from "./fileWatch";
|
||||||
import { setupWatch } from "./fileWatch.js";
|
import { config, loadConfig } from "./config";
|
||||||
import { config, loadConfig } from "./config.js";
|
import { setupSocket } from "./networking/webSocket";
|
||||||
import { setupSocket } from "./networking/webSocket.js";
|
|
||||||
import signal from "signal-js";
|
import signal from "signal-js";
|
||||||
import { fileChangeEventToMsg, fileRemovalEventToMsg, requestFilenames, requestDefinitionFile } from "./networking/messageGenerators.js";
|
import { fileChangeEventToMsg, fileRemovalEventToMsg, requestFilenames, requestDefinitionFile } from "./networking/messageGenerators";
|
||||||
import { EventType } from "./eventTypes.js";
|
import { EventType } from "./eventTypes";
|
||||||
import { messageHandler } from "./networking/messageHandler.js";
|
import { messageHandler } from "./networking/messageHandler";
|
||||||
|
import { FileEvent, Message } from './interfaces';
|
||||||
|
|
||||||
export async function start() {
|
export async function start() {
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
@ -13,7 +13,7 @@ export async function start() {
|
||||||
const socket = setupSocket(signal);
|
const socket = setupSocket(signal);
|
||||||
|
|
||||||
// Add a handler for received messages.
|
// Add a handler for received messages.
|
||||||
signal.on(EventType.MessageReceived, msg => messageHandler(signal, msg, watch.paths));
|
signal.on(EventType.MessageReceived, (msg: Message) => messageHandler(signal, msg, watch.paths));
|
||||||
|
|
||||||
// Add a handler for when a connection to a game is made.
|
// Add a handler for when a connection to a game is made.
|
||||||
signal.on(EventType.ConnectionMade, () => {
|
signal.on(EventType.ConnectionMade, () => {
|
||||||
|
@ -27,7 +27,7 @@ export async function start() {
|
||||||
const extensions = config.get("allowedFiletypes");
|
const extensions = config.get("allowedFiletypes");
|
||||||
for (const path of watch.paths.keys()) {
|
for (const path of watch.paths.keys()) {
|
||||||
if (extensions.some(extension => path.endsWith(extension)))
|
if (extensions.some(extension => path.endsWith(extension)))
|
||||||
signal.emit(EventType.MessageSend, fileChangeEventToMsg({ path: path }))
|
signal.emit(EventType.MessageSend, fileChangeEventToMsg({ path }))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Upload missing files to the game.
|
// Upload missing files to the game.
|
||||||
|
@ -36,14 +36,14 @@ export async function start() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add a handler for changed files.
|
// Add a handler for changed files.
|
||||||
signal.on(EventType.FileChanged, fileEvent => {
|
signal.on(EventType.FileChanged, (fileEvent: FileEvent) => {
|
||||||
if (!config.get("quiet")) console.log(fileEvent.path + " changed");
|
if (!config.get("quiet")) console.log(fileEvent.path + " changed");
|
||||||
signal.emit(EventType.MessageSend, fileChangeEventToMsg(fileEvent))
|
signal.emit(EventType.MessageSend, fileChangeEventToMsg(fileEvent))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a handler for removed files, if allowed.
|
// Add a handler for removed files, if allowed.
|
||||||
if (config.get("allowDeletingFiles"))
|
if (config.get("allowDeletingFiles"))
|
||||||
signal.on(EventType.FileDeleted, fileEvent =>
|
signal.on(EventType.FileDeleted, (fileEvent: FileEvent) =>
|
||||||
signal.emit(EventType.MessageSend, fileRemovalEventToMsg(fileEvent)));
|
signal.emit(EventType.MessageSend, fileRemovalEventToMsg(fileEvent)));
|
||||||
|
|
||||||
console.log(`Server is ready, running on ${config.get("port")}!`)
|
console.log(`Server is ready, running on ${config.get("port")}!`)
|
16
src/interfaces.ts
Normal file
16
src/interfaces.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import type { Stats } from 'fs';
|
||||||
|
|
||||||
|
export interface Message {
|
||||||
|
id: string;
|
||||||
|
method?: string;
|
||||||
|
jsonrpc: string;
|
||||||
|
params?: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileEvent {
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface File extends FileEvent {
|
||||||
|
stats: Stats
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { config } from "../config.js";
|
import { config } from "../config";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
|
import type { FileEvent, Message } from '../interfaces';
|
||||||
|
|
||||||
let messageCounter = 0;
|
let messageCounter = 0;
|
||||||
|
|
||||||
export function fileChangeEventToMsg({ path }) {
|
export function fileChangeEventToMsg({ path }: FileEvent): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "pushFile",
|
"method": "pushFile",
|
||||||
|
@ -13,11 +14,11 @@ export function fileChangeEventToMsg({ path }) {
|
||||||
"filename": addLeadingSlash(path),
|
"filename": addLeadingSlash(path),
|
||||||
"content": readFileSync(join(config.get("scriptsFolder"), path)).toString()
|
"content": readFileSync(join(config.get("scriptsFolder"), path)).toString()
|
||||||
},
|
},
|
||||||
"id": messageCounter++
|
"id": (messageCounter++).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fileRemovalEventToMsg({ path }) {
|
export function fileRemovalEventToMsg({ path }: FileEvent): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "deleteFile",
|
"method": "deleteFile",
|
||||||
|
@ -25,30 +26,30 @@ export function fileRemovalEventToMsg({ path }) {
|
||||||
"server": "home",
|
"server": "home",
|
||||||
"filename": addLeadingSlash(path),
|
"filename": addLeadingSlash(path),
|
||||||
},
|
},
|
||||||
"id": messageCounter++
|
"id": (messageCounter++).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requestDefinitionFile() {
|
export function requestDefinitionFile(): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "getDefinitionFile",
|
"method": "getDefinitionFile",
|
||||||
"id": messageCounter++
|
"id": (messageCounter++).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requestFilenames() {
|
export function requestFilenames(): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "getFileNames",
|
"method": "getFileNames",
|
||||||
"params": {
|
"params": {
|
||||||
"server": "home",
|
"server": "home",
|
||||||
},
|
},
|
||||||
"id": messageCounter++
|
"id": (messageCounter++).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLeadingSlash(path){
|
function addLeadingSlash(path: string): string {
|
||||||
const slashes = path.match('/');
|
const slashes = path.match('/');
|
||||||
if (slashes)
|
if (slashes)
|
||||||
return `/${path}`
|
return `/${path}`
|
|
@ -1,10 +1,12 @@
|
||||||
import { messageTracker } from "./messageTracker.js";
|
import { messageTracker } from "./messageTracker";
|
||||||
import { writeFile } from "fs";
|
import { Stats, writeFile } from "fs";
|
||||||
import { config } from "../config.js";
|
import { config } from "../config";
|
||||||
import { EventType } from "../eventTypes.js";
|
import { EventType } from "../eventTypes";
|
||||||
import { fileChangeEventToMsg } from "./messageGenerators.js";
|
import { fileChangeEventToMsg } from "./messageGenerators";
|
||||||
|
import type { Signal } from 'signal-js';
|
||||||
|
import { Message } from '../interfaces';
|
||||||
|
|
||||||
export function messageHandler(signaller, msg, paths) {
|
export function messageHandler(signaller: Signal, msg: Message, paths: Map<string, Stats>) {
|
||||||
let incoming;
|
let incoming;
|
||||||
|
|
||||||
try { incoming = JSON.parse(msg.toString()); }
|
try { incoming = JSON.parse(msg.toString()); }
|
||||||
|
@ -25,7 +27,7 @@ export function messageHandler(signaller, msg, paths) {
|
||||||
if (request?.method &&
|
if (request?.method &&
|
||||||
request.method == "getFileNames"
|
request.method == "getFileNames"
|
||||||
&& incoming.result) {
|
&& incoming.result) {
|
||||||
const gameFiles = incoming.result.map(file => removeLeadingSlash(file));
|
const gameFiles = incoming.result.map((file: string) => removeLeadingSlash(file));
|
||||||
|
|
||||||
paths.forEach((stats, fileName) => {
|
paths.forEach((stats, fileName) => {
|
||||||
if (!stats.isDirectory() && !gameFiles.includes(fileName))
|
if (!stats.isDirectory() && !gameFiles.includes(fileName))
|
||||||
|
@ -35,7 +37,7 @@ export function messageHandler(signaller, msg, paths) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeLeadingSlash(path) {
|
function removeLeadingSlash(path: string) {
|
||||||
const reg = /^\//;
|
const reg = /^\//;
|
||||||
return path.replace(reg, "")
|
return path.replace(reg, "")
|
||||||
}
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
class MessageTracker {
|
import type { Message } from '../interfaces';
|
||||||
data = new Map()
|
|
||||||
#maxLength = 200
|
|
||||||
|
|
||||||
push(msg) {
|
class MessageTracker {
|
||||||
|
data = new Map<string, Message>();
|
||||||
|
#maxLength = 200;
|
||||||
|
|
||||||
|
push(msg: Message) {
|
||||||
this.data.set(msg.id, msg);
|
this.data.set(msg.id, msg);
|
||||||
|
|
||||||
if (this.data.size > this.#maxLength) {
|
if (this.data.size > this.#maxLength) {
|
||||||
|
@ -11,9 +13,9 @@ class MessageTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(index) {
|
get(index: string) {
|
||||||
return this.data.get(index);
|
return this.data.get(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const messageTracker = new MessageTracker();
|
export const messageTracker = new MessageTracker();
|
|
@ -1,16 +1,18 @@
|
||||||
|
import type { Signal } from 'signal-js';
|
||||||
import { WebSocketServer } from 'ws';
|
import { WebSocketServer } from 'ws';
|
||||||
import { config } from "../config.js";
|
import { config } from "../config";
|
||||||
import { EventType } from "../eventTypes.js"
|
import { EventType } from "../eventTypes"
|
||||||
import { requestDefinitionFile } from './messageGenerators.js';
|
import { Message } from '../interfaces';
|
||||||
import { messageTracker } from "./messageTracker.js"
|
import { requestDefinitionFile } from './messageGenerators';
|
||||||
|
import { messageTracker } from "./messageTracker"
|
||||||
|
|
||||||
export function setupSocket(signaller) {
|
export function setupSocket(signaller: Signal) {
|
||||||
|
|
||||||
const wss = new WebSocketServer({ port: config.get("port") });
|
const wss = new WebSocketServer({ port: config.get("port") });
|
||||||
|
|
||||||
wss.on('connection', function connection(ws) {
|
wss.on('connection', function connection(ws) {
|
||||||
|
|
||||||
function sendMessage(msg) {
|
function sendMessage(msg: Message) {
|
||||||
messageTracker.push(msg);
|
messageTracker.push(msg);
|
||||||
ws.send(JSON.stringify(msg));
|
ws.send(JSON.stringify(msg));
|
||||||
}
|
}
|
||||||
|
@ -19,7 +21,7 @@ export function setupSocket(signaller) {
|
||||||
signaller.emit(EventType.MessageReceived, msg);
|
signaller.emit(EventType.MessageReceived, msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
signaller.on(EventType.MessageSend, msg => {
|
signaller.on(EventType.MessageSend, (msg: Message) => {
|
||||||
sendMessage(msg);
|
sendMessage(msg);
|
||||||
});
|
});
|
||||||
|
|
10
src/signals.d.ts
vendored
Normal file
10
src/signals.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
declare module 'signal-js' {
|
||||||
|
|
||||||
|
export type Signal = typeof signal;
|
||||||
|
export default class signal {
|
||||||
|
static on<T>(event: string, callback: (data: T) => void): void
|
||||||
|
static emit<T>(event: string, data: T): void
|
||||||
|
static trigger(event: string): void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue