Merge pull request #20 from HeinousTugboat/htugboat/update-configs-and-format
Updates prettier and friends
This commit is contained in:
commit
7ae2f836d7
24 changed files with 345 additions and 336 deletions
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
|
@ -24,20 +24,20 @@ jobs:
|
||||||
# run: npm ci
|
# run: npm ci
|
||||||
# - name: Run linter
|
# - name: Run linter
|
||||||
# run: npm run lint:report
|
# run: npm run lint:report
|
||||||
# prettier:
|
prettier:
|
||||||
# name: Prettier
|
name: Prettier
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# steps:
|
steps:
|
||||||
# - uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
# - name: Use Node.js 16.13.1
|
- name: Use Node.js 16.13.1
|
||||||
# uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
# with:
|
with:
|
||||||
# node-version: 16.13.1
|
node-version: 16.13.1
|
||||||
# cache: "npm"
|
cache: "npm"
|
||||||
# - name: Install npm dependencies
|
- name: Install npm dependencies
|
||||||
# run: npm ci
|
run: npm ci
|
||||||
# - name: Run prettier check
|
- name: Run prettier check
|
||||||
# run: npm run format:report
|
run: npm run format:report
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
15
.mocharc.jsonc
Normal file
15
.mocharc.jsonc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"bail": false,
|
||||||
|
"delay": false,
|
||||||
|
"diff": true,
|
||||||
|
"extension": ["ts"],
|
||||||
|
"node-option": "loader=ts-node/esm",
|
||||||
|
"parallel": true,
|
||||||
|
"reporter": "spec",
|
||||||
|
"require": ["./test/setup-tests.ts"],
|
||||||
|
"slow": "75",
|
||||||
|
"timeout": "2000",
|
||||||
|
"ui": "bdd",
|
||||||
|
"watch-files": ["test/**/*.ts"],
|
||||||
|
"watch-ignore": []
|
||||||
|
}
|
2
.prettierignore
Normal file
2
.prettierignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
dist
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[jsonc]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,9 @@ A file synchronisation utility for Bitburner, using the Remote File API.
|
||||||
It allows players to synchronize scripts and text files from their computer's disk to the game in both the Electron build and website.
|
It allows players to synchronize scripts and text files from their computer's disk to the game in both the Electron build and website.
|
||||||
|
|
||||||
## How to use (for users)
|
## How to use (for users)
|
||||||
|
|
||||||
You must have a recent version of `npm` installed after which you can run
|
You must have a recent version of `npm` installed after which you can run
|
||||||
|
|
||||||
```
|
```
|
||||||
npx bitburner-filesync
|
npx bitburner-filesync
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env ts-node
|
#!/usr/bin/env ts-node
|
||||||
import { start } from "../src/index"
|
import { start } from "../src/index";
|
||||||
|
|
||||||
await start();
|
await start();
|
||||||
|
|
22
package.json
22
package.json
|
@ -7,6 +7,7 @@
|
||||||
"main": "./npx/bitburner-filesync.ts",
|
"main": "./npx/bitburner-filesync.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "prettier -w .",
|
"format": "prettier -w .",
|
||||||
|
"format:report": "prettier -c .",
|
||||||
"test:all": "mocha --recursive test",
|
"test:all": "mocha --recursive test",
|
||||||
"test:single": "mocha",
|
"test:single": "mocha",
|
||||||
"start": "npx/bitburner-filesync.ts"
|
"start": "npx/bitburner-filesync.ts"
|
||||||
|
@ -48,26 +49,5 @@
|
||||||
"mocha": "^10.0.0",
|
"mocha": "^10.0.0",
|
||||||
"sinon": "^14.0.0",
|
"sinon": "^14.0.0",
|
||||||
"sinon-chai": "^3.7.0"
|
"sinon-chai": "^3.7.0"
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"bail": false,
|
|
||||||
"delay": false,
|
|
||||||
"diff": true,
|
|
||||||
"extension": [
|
|
||||||
"ts"
|
|
||||||
],
|
|
||||||
"node-option": "loader=ts-node/esm",
|
|
||||||
"parallel": true,
|
|
||||||
"reporter": "spec",
|
|
||||||
"require": [
|
|
||||||
"./test/setup-tests.ts"
|
|
||||||
],
|
|
||||||
"slow": "75",
|
|
||||||
"timeout": "2000",
|
|
||||||
"ui": "bdd",
|
|
||||||
"watch-files": [
|
|
||||||
"test/**/*.ts"
|
|
||||||
],
|
|
||||||
"watch-ignore": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,65 +4,65 @@ import { existsSync } from "fs";
|
||||||
// Define a schema
|
// Define a schema
|
||||||
export let config = convict({
|
export let config = convict({
|
||||||
allowedFiletypes: {
|
allowedFiletypes: {
|
||||||
doc: 'Filetypes that are synchronized to the game.',
|
doc: "Filetypes that are synchronized to the game.",
|
||||||
format: 'Array',
|
format: "Array",
|
||||||
default: [".js", ".script", ".txt"]
|
default: [".js", ".script", ".txt"],
|
||||||
},
|
},
|
||||||
allowDeletingFiles: {
|
allowDeletingFiles: {
|
||||||
doc: 'Allow deleting files in game if they get deleted off disk.',
|
doc: "Allow deleting files in game if they get deleted off disk.",
|
||||||
format: 'Boolean',
|
format: "Boolean",
|
||||||
default: false,
|
default: false,
|
||||||
arg: 'allowDeletingFiles',
|
arg: "allowDeletingFiles",
|
||||||
},
|
},
|
||||||
port: {
|
port: {
|
||||||
doc: 'The port to bind to.',
|
doc: "The port to bind to.",
|
||||||
format: 'Number',
|
format: "Number",
|
||||||
default: 12525,
|
default: 12525,
|
||||||
env: 'BB_PORT',
|
env: "BB_PORT",
|
||||||
arg: 'port'
|
arg: "port",
|
||||||
},
|
},
|
||||||
scriptsFolder: {
|
scriptsFolder: {
|
||||||
doc: 'The to be synchronized folder.',
|
doc: "The to be synchronized folder.",
|
||||||
format: 'String',
|
format: "String",
|
||||||
default: '.',
|
default: ".",
|
||||||
env: 'BB_SCRIPTFOLDER',
|
env: "BB_SCRIPTFOLDER",
|
||||||
arg: 'folder'
|
arg: "folder",
|
||||||
},
|
},
|
||||||
quiet: {
|
quiet: {
|
||||||
doc: 'Log less internal events to stdout.',
|
doc: "Log less internal events to stdout.",
|
||||||
format: 'Boolean',
|
format: "Boolean",
|
||||||
env: 'BB_VERBOSE',
|
env: "BB_VERBOSE",
|
||||||
default: false,
|
default: false,
|
||||||
arg: 'quiet'
|
arg: "quiet",
|
||||||
},
|
},
|
||||||
dry: {
|
dry: {
|
||||||
doc: 'Only print the files to be synchronised.',
|
doc: "Only print the files to be synchronised.",
|
||||||
format: 'Boolean',
|
format: "Boolean",
|
||||||
env: 'BB_DRY',
|
env: "BB_DRY",
|
||||||
default: false,
|
default: false,
|
||||||
arg: 'dry'
|
arg: "dry",
|
||||||
},
|
},
|
||||||
definitionFile: {
|
definitionFile: {
|
||||||
update: {
|
update: {
|
||||||
doc: 'Automatically pull the definition file from the game.',
|
doc: "Automatically pull the definition file from the game.",
|
||||||
format: 'Boolean',
|
format: "Boolean",
|
||||||
env: 'BB_UPDATE_DEF',
|
env: "BB_UPDATE_DEF",
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
location: {
|
location: {
|
||||||
doc: 'Location/name of where the definition file gets placed.',
|
doc: "Location/name of where the definition file gets placed.",
|
||||||
format: 'String',
|
format: "String",
|
||||||
env: 'BB_LOCATION_DEF',
|
env: "BB_LOCATION_DEF",
|
||||||
default: "./NetScriptDefinitions.d.ts"
|
default: "./NetScriptDefinitions.d.ts",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
pushAllOnConnection: {
|
pushAllOnConnection: {
|
||||||
doc: 'Push all files when initial connection is made.',
|
doc: "Push all files when initial connection is made.",
|
||||||
format: 'Boolean',
|
format: "Boolean",
|
||||||
env: 'BB_CON_PUSH',
|
env: "BB_CON_PUSH",
|
||||||
default: false,
|
default: false,
|
||||||
arg: 'pushAllOnConnection'
|
arg: "pushAllOnConnection",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function loadConfig() {
|
export function loadConfig() {
|
||||||
|
@ -74,11 +74,9 @@ export function loadConfig() {
|
||||||
throw new Error(`Unable to load configuration file at ${configFile}: ${e}`);
|
throw new Error(`Unable to load configuration file at ${configFile}: ${e}`);
|
||||||
}
|
}
|
||||||
} else if (!config.get("quiet")) {
|
} else if (!config.get("quiet")) {
|
||||||
console.log("No configuration file found.")
|
console.log("No configuration file found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform validation
|
// Perform validation
|
||||||
config.validate({ allowed: 'strict' });
|
config.validate({ allowed: "strict" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,12 @@ import CheapWatch from "cheap-watch";
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
import { EventType } from "./eventTypes";
|
import { EventType } from "./eventTypes";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
import type { Signal } from 'signal-js';
|
import type { Signal } from "signal-js";
|
||||||
import type { File } from './interfaces';
|
import type { File } from "./interfaces";
|
||||||
|
|
||||||
function fileFilter(file: 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()) return true;
|
||||||
if (file.stats.isDirectory())
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,19 +15,23 @@ 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,
|
||||||
watch: !config.get("dry")
|
watch: !config.get("dry"),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!config.get("quiet")) console.log("Watching folder", resolve(config.get("scriptsFolder")))
|
if (!config.get("quiet")) console.log("Watching folder", resolve(config.get("scriptsFolder")));
|
||||||
|
|
||||||
watch.on('+', fileEvent => { if (fileEvent.stats.isFile()) signaller.emit(EventType.FileChanged, fileEvent) });
|
watch.on("+", (fileEvent) => {
|
||||||
watch.on('-', fileEvent => { if (fileEvent.stats.isFile()) signaller.emit(EventType.FileDeleted, fileEvent) });
|
if (fileEvent.stats.isFile()) signaller.emit(EventType.FileChanged, fileEvent);
|
||||||
|
});
|
||||||
|
watch.on("-", (fileEvent) => {
|
||||||
|
if (fileEvent.stats.isFile()) signaller.emit(EventType.FileDeleted, fileEvent);
|
||||||
|
});
|
||||||
|
|
||||||
// Wait 'till filewatcher is ready to go
|
// Wait 'till filewatcher is ready to go
|
||||||
await watch.init();
|
await watch.init();
|
||||||
|
|
||||||
if (config.get("dry")) {
|
if (config.get("dry")) {
|
||||||
console.log("Watch would've synchronised:\n", watch.paths)
|
console.log("Watch would've synchronised:\n", watch.paths);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/index.ts
24
src/index.ts
|
@ -2,10 +2,15 @@ import { setupWatch } from "./fileWatch";
|
||||||
import { config, loadConfig } from "./config";
|
import { config, loadConfig } from "./config";
|
||||||
import { setupSocket } from "./networking/webSocket";
|
import { setupSocket } from "./networking/webSocket";
|
||||||
import signal from "signal-js";
|
import signal from "signal-js";
|
||||||
import { fileChangeEventToMsg, fileRemovalEventToMsg, requestFilenames, requestDefinitionFile } from "./networking/messageGenerators";
|
import {
|
||||||
|
fileChangeEventToMsg,
|
||||||
|
fileRemovalEventToMsg,
|
||||||
|
requestFilenames,
|
||||||
|
requestDefinitionFile,
|
||||||
|
} from "./networking/messageGenerators";
|
||||||
import { EventType } from "./eventTypes";
|
import { EventType } from "./eventTypes";
|
||||||
import { messageHandler } from "./networking/messageHandler";
|
import { messageHandler } from "./networking/messageHandler";
|
||||||
import { FileEvent, Message } from './interfaces';
|
import { FileEvent, Message } from "./interfaces";
|
||||||
|
|
||||||
export async function start() {
|
export async function start() {
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
@ -26,29 +31,30 @@ export async function start() {
|
||||||
if (config.get("pushAllOnConnection")) {
|
if (config.get("pushAllOnConnection")) {
|
||||||
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 }))
|
signal.emit(EventType.MessageSend, fileChangeEventToMsg({ path }));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Upload missing files to the game.
|
// Upload missing files to the game.
|
||||||
signal.emit(EventType.MessageSend, requestFilenames());
|
signal.emit(EventType.MessageSend, requestFilenames());
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// Add a handler for changed files.
|
// Add a handler for changed files.
|
||||||
signal.on(EventType.FileChanged, (fileEvent: 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: 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")}!`);
|
||||||
|
|
||||||
process.on('SIGINT', function () {
|
process.on("SIGINT", function () {
|
||||||
console.log("Shutting down!");
|
console.log("Shutting down!");
|
||||||
|
|
||||||
watch.close();
|
watch.close();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Stats } from 'fs';
|
import type { Stats } from "fs";
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -12,5 +12,5 @@ export interface FileEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface File extends FileEvent {
|
export interface File extends FileEvent {
|
||||||
stats: Stats
|
stats: Stats;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,56 @@
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import type { FileEvent, Message } from '../interfaces';
|
import type { FileEvent, Message } from "../interfaces";
|
||||||
|
|
||||||
let messageCounter = 0;
|
let messageCounter = 0;
|
||||||
|
|
||||||
export function fileChangeEventToMsg({ path }: FileEvent): Message {
|
export function fileChangeEventToMsg({ path }: FileEvent): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
jsonrpc: "2.0",
|
||||||
"method": "pushFile",
|
method: "pushFile",
|
||||||
"params": {
|
params: {
|
||||||
"server": "home",
|
server: "home",
|
||||||
"filename": addLeadingSlash(path),
|
filename: addLeadingSlash(path),
|
||||||
"content": readFileSync(join(config.get("scriptsFolder"), path)).toString()
|
content: readFileSync(join(config.get("scriptsFolder"), path)).toString(),
|
||||||
},
|
},
|
||||||
"id": (messageCounter++).toString()
|
id: (messageCounter++).toString(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fileRemovalEventToMsg({ path }: FileEvent): Message {
|
export function fileRemovalEventToMsg({ path }: FileEvent): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
jsonrpc: "2.0",
|
||||||
"method": "deleteFile",
|
method: "deleteFile",
|
||||||
"params": {
|
params: {
|
||||||
"server": "home",
|
server: "home",
|
||||||
"filename": addLeadingSlash(path),
|
filename: addLeadingSlash(path),
|
||||||
},
|
},
|
||||||
"id": (messageCounter++).toString()
|
id: (messageCounter++).toString(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requestDefinitionFile(): Message {
|
export function requestDefinitionFile(): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
jsonrpc: "2.0",
|
||||||
"method": "getDefinitionFile",
|
method: "getDefinitionFile",
|
||||||
"id": (messageCounter++).toString()
|
id: (messageCounter++).toString(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requestFilenames(): Message {
|
export function requestFilenames(): Message {
|
||||||
return {
|
return {
|
||||||
"jsonrpc": "2.0",
|
jsonrpc: "2.0",
|
||||||
"method": "getFileNames",
|
method: "getFileNames",
|
||||||
"params": {
|
params: {
|
||||||
"server": "home",
|
server: "home",
|
||||||
},
|
},
|
||||||
"id": (messageCounter++).toString()
|
id: (messageCounter++).toString(),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLeadingSlash(path: string): string {
|
function addLeadingSlash(path: string): string {
|
||||||
const slashes = path.match('/');
|
const slashes = path.match("/");
|
||||||
if (slashes)
|
if (slashes) return `/${path}`;
|
||||||
return `/${path}`
|
else return path;
|
||||||
else
|
|
||||||
return path
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,41 +3,40 @@ import { Stats, writeFile } from "fs";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
import { EventType } from "../eventTypes";
|
import { EventType } from "../eventTypes";
|
||||||
import { fileChangeEventToMsg } from "./messageGenerators";
|
import { fileChangeEventToMsg } from "./messageGenerators";
|
||||||
import type { Signal } from 'signal-js';
|
import type { Signal } from "signal-js";
|
||||||
import { Message } from '../interfaces';
|
import { Message } from "../interfaces";
|
||||||
|
|
||||||
export function messageHandler(signaller: Signal, msg: Message, paths: Map<string, Stats>) {
|
export function messageHandler(signaller: Signal, msg: Message, paths: Map<string, Stats>) {
|
||||||
let incoming;
|
let incoming;
|
||||||
|
|
||||||
try { incoming = JSON.parse(msg.toString()); }
|
try {
|
||||||
catch (err) { return console.log(err); }
|
incoming = JSON.parse(msg.toString());
|
||||||
console.log(incoming)
|
} catch (err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
console.log(incoming);
|
||||||
if (incoming.id == undefined) return;
|
if (incoming.id == undefined) return;
|
||||||
|
|
||||||
if (incoming.result) {
|
if (incoming.result) {
|
||||||
const request = messageTracker.get(incoming.id);
|
const request = messageTracker.get(incoming.id);
|
||||||
if (request?.method &&
|
if (request?.method && request.method == "getDefinitionFile" && incoming.result) {
|
||||||
request.method == "getDefinitionFile"
|
|
||||||
&& incoming.result) {
|
|
||||||
writeFile(config.get("definitionFile").location, incoming.result, (err) => {
|
writeFile(config.get("definitionFile").location, incoming.result, (err) => {
|
||||||
if (err) return console.log(err);
|
if (err) return console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request?.method &&
|
if (request?.method && request.method == "getFileNames" && incoming.result) {
|
||||||
request.method == "getFileNames"
|
|
||||||
&& incoming.result) {
|
|
||||||
const gameFiles = incoming.result.map((file: string) => 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))
|
||||||
signaller.emit(EventType.MessageSend, fileChangeEventToMsg({ path: fileName }));
|
signaller.emit(EventType.MessageSend, fileChangeEventToMsg({ path: fileName }));
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeLeadingSlash(path: string) {
|
function removeLeadingSlash(path: string) {
|
||||||
const reg = /^\//;
|
const reg = /^\//;
|
||||||
return path.replace(reg, "")
|
return path.replace(reg, "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Message } from '../interfaces';
|
import type { Message } from "../interfaces";
|
||||||
|
|
||||||
class MessageTracker {
|
class MessageTracker {
|
||||||
data = new Map<string, Message>();
|
data = new Map<string, Message>();
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
import type { Signal } from 'signal-js';
|
import type { Signal } from "signal-js";
|
||||||
import { WebSocketServer } from 'ws';
|
import { WebSocketServer } from "ws";
|
||||||
import { config } from "../config";
|
import { config } from "../config";
|
||||||
import { EventType } from "../eventTypes"
|
import { EventType } from "../eventTypes";
|
||||||
import { Message } from '../interfaces';
|
import { Message } from "../interfaces";
|
||||||
import { requestDefinitionFile } from './messageGenerators';
|
import { requestDefinitionFile } from "./messageGenerators";
|
||||||
import { messageTracker } from "./messageTracker"
|
import { messageTracker } from "./messageTracker";
|
||||||
|
|
||||||
export function setupSocket(signaller: Signal) {
|
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: Message) {
|
function sendMessage(msg: Message) {
|
||||||
messageTracker.push(msg);
|
messageTracker.push(msg);
|
||||||
ws.send(JSON.stringify(msg));
|
ws.send(JSON.stringify(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.on('message', (msg) => {
|
ws.on("message", (msg) => {
|
||||||
signaller.emit(EventType.MessageReceived, msg);
|
signaller.emit(EventType.MessageReceived, msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
10
src/signals.d.ts
vendored
10
src/signals.d.ts
vendored
|
@ -1,10 +1,8 @@
|
||||||
declare module 'signal-js' {
|
declare module "signal-js" {
|
||||||
|
|
||||||
export type Signal = typeof signal;
|
export type Signal = typeof signal;
|
||||||
export default class signal {
|
export default class signal {
|
||||||
static on<T>(event: string, callback: (data: T) => void): void
|
static on<T>(event: string, callback: (data: T) => void): void;
|
||||||
static emit<T>(event: string, data: T): void
|
static emit<T>(event: string, data: T): void;
|
||||||
static trigger(event: string): void
|
static trigger(event: string): void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import { setupWatch } from '../src/fileWatch';
|
import { setupWatch } from "../src/fileWatch";
|
||||||
import { expect } from 'chai';
|
import { expect } from "chai";
|
||||||
import { stub, createStubInstance } from 'sinon';
|
import { stub, createStubInstance } from "sinon";
|
||||||
import CheapWatch from 'cheap-watch';
|
import CheapWatch from "cheap-watch";
|
||||||
import signal from 'signal-js';
|
import signal from "signal-js";
|
||||||
|
|
||||||
describe('fileWatch', () => {
|
describe("fileWatch", () => {
|
||||||
describe('setupWatch', () => {
|
describe("setupWatch", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(setupWatch).to.exist;
|
expect(setupWatch).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should instantiate and initialize CheapWatch', async () => {
|
it("should instantiate and initialize CheapWatch", async () => {
|
||||||
const consoleStub = stub(console, 'log');
|
const consoleStub = stub(console, "log");
|
||||||
const watchInstance = createStubInstance(CheapWatch);
|
const watchInstance = createStubInstance(CheapWatch);
|
||||||
const watchConstructorStub = stub().returns(watchInstance);
|
const watchConstructorStub = stub().returns(watchInstance);
|
||||||
Object.setPrototypeOf(CheapWatch, watchConstructorStub);
|
Object.setPrototypeOf(CheapWatch, watchConstructorStub);
|
||||||
|
|
|
@ -1,27 +1,32 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from "chai";
|
||||||
import { fileChangeEventToMsg, fileRemovalEventToMsg, requestDefinitionFile, requestFilenames } from '../../src/networking/messageGenerators';
|
import {
|
||||||
|
fileChangeEventToMsg,
|
||||||
|
fileRemovalEventToMsg,
|
||||||
|
requestDefinitionFile,
|
||||||
|
requestFilenames,
|
||||||
|
} from "../../src/networking/messageGenerators";
|
||||||
|
|
||||||
describe('messageGenerators', () => {
|
describe("messageGenerators", () => {
|
||||||
describe('fileChangeEventToMsg', () => {
|
describe("fileChangeEventToMsg", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(fileChangeEventToMsg).to.exist;
|
expect(fileChangeEventToMsg).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('fileRemovalEventToMsg', () => {
|
describe("fileRemovalEventToMsg", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(fileRemovalEventToMsg).to.exist;
|
expect(fileRemovalEventToMsg).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('requestDefinitionFile', () => {
|
describe("requestDefinitionFile", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(requestDefinitionFile).to.exist;
|
expect(requestDefinitionFile).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('requestFilenames', () => {
|
describe("requestFilenames", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(requestFilenames).to.exist;
|
expect(requestFilenames).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from "chai";
|
||||||
import { messageHandler } from '../../src/networking/messageHandler';
|
import { messageHandler } from "../../src/networking/messageHandler";
|
||||||
|
|
||||||
describe('messageHandler', () => {
|
describe("messageHandler", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(messageHandler).to.exist;
|
expect(messageHandler).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from "chai";
|
||||||
import { messageTracker } from '../../src/networking/messageTracker';
|
import { messageTracker } from "../../src/networking/messageTracker";
|
||||||
|
|
||||||
describe('messageTracker', () => {
|
describe("messageTracker", () => {
|
||||||
it('should exist', () => {
|
it("should exist", () => {
|
||||||
expect(messageTracker).to.exist;
|
expect(messageTracker).to.exist;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from "chai";
|
||||||
|
|
||||||
describe('webSocket', () => {
|
describe("webSocket", () => {
|
||||||
it('should run test', () => {
|
it("should run test", () => {
|
||||||
expect(true).to.eq(true)
|
expect(true).to.eq(true);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import chai from 'chai';
|
import chai from "chai";
|
||||||
import { createSandbox, stub } from 'sinon';
|
import { createSandbox, stub } from "sinon";
|
||||||
import sinonChai from 'sinon-chai';
|
import sinonChai from "sinon-chai";
|
||||||
|
|
||||||
export async function mochaGlobalSetup() {
|
export async function mochaGlobalSetup() {
|
||||||
// initial global setup
|
// initial global setup
|
||||||
|
@ -27,5 +27,5 @@ export const mochaHooks: Mocha.RootHookObject = {
|
||||||
afterEach(done: () => void) {
|
afterEach(done: () => void) {
|
||||||
this.sandbox.restore();
|
this.sandbox.restore();
|
||||||
done();
|
done();
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
|
@ -4,16 +4,12 @@
|
||||||
"esm": true,
|
"esm": true,
|
||||||
"experimentalSpecifierResolution": "node"
|
"experimentalSpecifierResolution": "node"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/signals.d.ts", "src/**/*", "test/**/*"],
|
||||||
"src/signals.d.ts",
|
|
||||||
"src/**/*",
|
|
||||||
"test/**/*"
|
|
||||||
],
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
"target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||||
"module": "esnext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
@ -22,7 +18,7 @@
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
"outDir": "./dist" /* Redirect output structure to the directory. */,
|
||||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
// "composite": true, /* Enable project compilation */
|
// "composite": true, /* Enable project compilation */
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
@ -32,7 +28,7 @@
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
/* Strict Type-Checking Options */
|
/* Strict Type-Checking Options */
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
@ -46,14 +42,14 @@
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
/* Source Map Options */
|
/* Source Map Options */
|
||||||
|
|
Loading…
Add table
Reference in a new issue