diff --git a/package-lock.json b/package-lock.json index cd08280bf..015e3a66b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9275,6 +9275,93 @@ "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==", "dev": true }, + "tslint": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz", + "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "builtin-modules": "1.1.1", + "chalk": "2.4.1", + "commander": "2.14.1", + "diff": "3.5.0", + "glob": "7.1.2", + "js-yaml": "3.12.0", + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.5.0", + "tslib": "1.9.2", + "tsutils": "2.27.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + } + } + }, + "tsutils": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz", + "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==", + "dev": true, + "requires": { + "tslib": "1.9.2" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", diff --git a/package.json b/package.json index 809f755f9..4f537354d 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "source-map": "^0.7.3", "style-loader": "^0.21.0", "ts-loader": "^4.4.1", + "tslint": "^5.10.0", "typescript": "^2.9.2", "url-loader": "^1.0.1", "watchpack": "^1.6.0", @@ -86,6 +87,7 @@ "start:dev": "webpack-dev-server", "build": "webpack --mode production", "build:dev": "webpack --mode development", + "lint:typescript": "tslint --project . --exclude **/*.d.ts --format stylish src/**/*.ts utils/**/*.ts", "watch": "webpack --watch --mode production", "watch:dev": "webpack --watch --mode development" }, diff --git a/src/HelpText.ts b/src/HelpText.ts index 3472c9975..ff88a21ce 100644 --- a/src/HelpText.ts +++ b/src/HelpText.ts @@ -1,39 +1,43 @@ -export const TerminalHelpText = - "Type 'help name' to learn more about the command 'name'

" + - 'alias [-g] [name="value"] Create or display Terminal aliases
' + - "analyze Get information about the current machine
" + - "buy [-l/program] Purchase a program through the Dark Web
" + - "cat [file] Display a .msg, .lit, or .txt file
" + - "check [script] [args...] Print a script's logs to Terminal
" + - "clear Clear all text on the terminal
" + - "cls See 'clear' command
" + - "connect [ip/hostname] Connects to a remote server
" + - "download [script/text file] Downloads scripts or text files to your computer
" + - "free Check the machine's memory (RAM) usage
" + - "hack Hack the current machine
" + - "help [command] Display this help text, or the help text for a command
" + - "home Connect to home computer
" + - "hostname Displays the hostname of the machine
" + - "ifconfig Displays the IP address of the machine
" + - "kill [script] [args...] Stops the specified script on the current server
" + - "killall Stops all running scripts on the current machine
" + - "ls [| grep pattern] Displays all files on the machine
" + - "lscpu Displays the number of CPU cores on the machine
" + - "mem [script] [-t] [n] Displays the amount of RAM required to run the script
" + - "nano [file] Text editor - Open up and edit a script or text file
" + - "ps Display all scripts that are currently running
" + - "rm [file] Delete a file from the server
" + - "run [name] [-t] [n] [args...] Execute a program or script
" + - "scan Prints all immediately-available network connections
" + - "scan-analyze [d] [-a] Prints info for all servers up to d nodes away
" + - "scp [file] [server] Copies a file to a destination server
" + - "sudov Shows whether you have root access on this computer
" + - "tail [script] [args...] Displays dynamic logs for the specified script
" + - "theme [preset] | bg txt hlgt Change the color scheme of the UI
" + - "top Displays all running scripts and their RAM usage
" + - 'unalias "[alias name]" Deletes the specified alias
'; +/* tslint:disable:max-line-length completed-docs variable-name*/ +export const TerminalHelpText: string = + "Type 'help name' to learn more about the command 'name'

" + + 'alias [-g] [name="value"] Create or display Terminal aliases
' + + "analyze Get information about the current machine
" + + "buy [-l/program] Purchase a program through the Dark Web
" + + "cat [file] Display a .msg, .lit, or .txt file
" + + "check [script] [args...] Print a script's logs to Terminal
" + + "clear Clear all text on the terminal
" + + "cls See 'clear' command
" + + "connect [ip/hostname] Connects to a remote server
" + + "download [script/text file] Downloads scripts or text files to your computer
" + + "free Check the machine's memory (RAM) usage
" + + "hack Hack the current machine
" + + "help [command] Display this help text, or the help text for a command
" + + "home Connect to home computer
" + + "hostname Displays the hostname of the machine
" + + "ifconfig Displays the IP address of the machine
" + + "kill [script] [args...] Stops the specified script on the current server
" + + "killall Stops all running scripts on the current machine
" + + "ls [| grep pattern] Displays all files on the machine
" + + "lscpu Displays the number of CPU cores on the machine
" + + "mem [script] [-t] [n] Displays the amount of RAM required to run the script
" + + "nano [file] Text editor - Open up and edit a script or text file
" + + "ps Display all scripts that are currently running
" + + "rm [file] Delete a file from the server
" + + "run [name] [-t] [n] [args...] Execute a program or script
" + + "scan Prints all immediately-available network connections
" + + "scan-analyze [d] [-a] Prints info for all servers up to d nodes away
" + + "scp [file] [server] Copies a file to a destination server
" + + "sudov Shows whether you have root access on this computer
" + + "tail [script] [args...] Displays dynamic logs for the specified script
" + + "theme [preset] | bg txt hlgt Change the color scheme of the UI
" + + "top Displays all running scripts and their RAM usage
" + + 'unalias "[alias name]" Deletes the specified alias
'; -export const HelpTexts = { +interface IMap { + [key: string]: T; +} +export const HelpTexts: IMap = { alias: 'alias [-g] [name="value"]
' + "Create or display aliases. An alias enables a replacement of a word with another string. " + "It can be used to abbreviate a commonly used command, or commonly used parts of a command. The NAME " + @@ -211,4 +215,4 @@ export const HelpTexts = { 'unalias "r"

' + "It is not necessary to differentiate between global and non-global aliases when using 'unalias'", -} +}; diff --git a/src/TextFile.ts b/src/TextFile.ts index 8405aded7..99b685c93 100644 --- a/src/TextFile.ts +++ b/src/TextFile.ts @@ -1,71 +1,109 @@ -import {dialogBoxCreate} from "../utils/DialogBox"; -import {Reviver, Generic_toJSON, Generic_fromJSON} from "../utils/JSONReviver"; +import { dialogBoxCreate } from "../utils/DialogBox"; +import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"; +/** + * Represents a plain text file that is typically stored on a server. + */ export class TextFile { + /** + * Initiatizes a TextFile from a JSON save state. + */ + static fromJSON(value: any): TextFile { + return Generic_fromJSON(TextFile, value.data); + } + + /** + * The full file name. + */ fn: string; + + /** + * The content of the file. + */ text: string; - constructor(fn = "", txt = "") { - this.fn = (fn.endsWith(".txt") ? fn : `${fn}.txt`).replace(/\s+/g, ''); + constructor(fn: string = "", txt: string = "") { + this.fn = (fn.endsWith(".txt") ? fn : `${fn}.txt`).replace(/\s+/g, ""); this.text = txt; } - append(txt: string) { + /** + * Concatenates the raw values to the end of current content. + */ + append(txt: string): void { this.text += txt; } - write(txt: string) { - this.text = txt; - } - - read() { - return this.text; - } - - show() { - dialogBoxCreate(`${this.fn}

${this.text}`, true); - } - - download() { - const filename = this.fn; - const file = new Blob([ this.text ], { type: 'text/plain' }); + /** + * Serves the file to the user as a downloadable resource through the browser. + */ + download(): void { + const filename: string = this.fn; + const file: Blob = new Blob([ this.text ], { type: "text/plain" }); + /* tslint:disable-next-line:strict-boolean-expressions */ if (window.navigator.msSaveOrOpenBlob) { // IE10+ window.navigator.msSaveOrOpenBlob(file, filename); } else { // Others - const a = document.createElement("a"); - const url = URL.createObjectURL(file); + const a: HTMLAnchorElement = document.createElement("a"); + const url: string = URL.createObjectURL(file); a.href = url; a.download = this.fn; document.body.appendChild(a); a.click(); - setTimeout(() => { - document.body.removeChild(a); - window.URL.revokeObjectURL(url); - }, 0); + setTimeout( + () => { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, + 0); } } - toJSON() { + /** + * Retrieve the content of the file. + */ + read(): string { + return this.text; + } + + /** + * Shows the content to the user via the game's dialog box. + */ + show(): void { + dialogBoxCreate(`${this.fn}

${this.text}`, true); + } + + /** + * Serialize the current file to a JSON save state. + */ + toJSON(): any { return Generic_toJSON("TextFile", this); } - static fromJSON(value: any) { - return Generic_fromJSON(TextFile, value.data); + /** + * Replaces the current content with the text provided. + */ + write(txt: string): void { + this.text = txt; } } Reviver.constructors.TextFile = TextFile; -export function getTextFile(fn: string, server: any): string | null { - if (!fn.endsWith(".txt")) { - fn += ".txt"; - } +/** + * Retrieve the file object for the filename on the specified server. + * @param fn The file name to look for + * @param server The server object to look in + * @returns The file object, or null if it couldn't find it. + */ +export function getTextFile(fn: string, server: any): TextFile | null { + const filename: string = !fn.endsWith(".txt") ? `${fn}.txt` : fn; - for (let i = 0; i < server.textFiles.length; i++) { - if (server.textFiles[i].fn === fn) { - return server.textFiles[i]; + for (const file of (server.textFiles as TextFile[])) { + if (file.fn === filename) { + return file; } } @@ -74,30 +112,36 @@ export function getTextFile(fn: string, server: any): string | null { /** * Creates a TextFile on the target server. - * @param {string} fn The file name to create. - * @param {string} txt The contents of the file. - * @param {*} server The server that the file should be created on. - * @returns {TextFile} The instance of the file. + * @param fn The file name to create. + * @param txt The contents of the file. + * @param server The server that the file should be created on. + * @returns The instance of the file. */ -export function createTextFile(fn: string, txt: string, server: any): TextFile { +export function createTextFile(fn: string, txt: string, server: any): TextFile | undefined { if (getTextFile(fn, server) !== null) { + // This should probably be a `throw`... + /* tslint:disable-next-line:no-console */ console.error(`A file named "${fn}" already exists on server ${server.hostname}.`); - return; + + return undefined; } - const file = new TextFile(fn, txt); + const file: TextFile = new TextFile(fn, txt); server.textFiles.push(file); + return file; } -function deleteTextFile(fn, server) { - if (!fn.endsWith(".txt")) { - fn += ".txt"; - } - for (var i = 0; i < server.textFiles.length; ++i) { - if (server.textFiles[i].fn === fn) { +/* tslint:disable-next-line:no-unused-variable */ +function deleteTextFile(fn: string, server: any): boolean { + const filename: string = !fn.endsWith(".txt") ? `${fn}.txt` : fn; + /* tslint:disable-next-line:typedef */ + for (let i = 0; i < server.textFiles.length; ++i) { + if (server.textFiles[i].fn === filename) { server.textFiles.splice(i, 1); + return true; } } + return false; } diff --git a/tsconfig.json b/tsconfig.json index 26bb34a1a..b5ff056a6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "module": "commonjs", "target": "es6", - "sourceMap": true + "sourceMap": true, + "strict": true }, "exclude": [ "node_modules" diff --git a/tslint.json b/tslint.json new file mode 100644 index 000000000..4ef866e6b --- /dev/null +++ b/tslint.json @@ -0,0 +1,76 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:all" + ], + "jsRules": {}, + "linterOptions": { + "exclude": [ + "node_modules/" + ] + }, + "rules": { + "completed-docs": [ + true, + { + "classes": true, + "enums": true, + "enum-members": true, + "functions": { + "visibilities": [ + "exported" + ] + }, + "interfaces": true, + "methods": { + "privacies": [ + "public" + ] + }, + "namespaces": true, + "properties": true, + "types": true, + "variables": { + "visibilities": [ + "exported" + ] + } + } + ], + "linebreak-style": false, + "member-access": [ + true, + "no-public" + ], + "no-any": false, + "no-inferrable-types": [ + true, + "ignore-params", + "ignore-properties" + ], + "no-null-keyword": false, + "no-unsafe-any": false, + "object-literal-key-quotes": [ + true, + "as-needed" + ], + "only-arrow-functions": [ + true, + "allow-declarations", + "allow-named-functions" + ], + "typedef": [ + true, + "call-signatures", + "arrow-call-signatures", + "parameter", + "arrow-parameter", + "property-declaration", + "variable-declaration", + "member-variable-declaration", + "object-destructuring", + "array-destructuring" + ] + }, + "rulesDirectory": [] +} \ No newline at end of file diff --git a/utils/DialogBox.d.ts b/utils/DialogBox.d.ts new file mode 100644 index 000000000..67b8e43f4 --- /dev/null +++ b/utils/DialogBox.d.ts @@ -0,0 +1,2 @@ +export function dialogBoxCreate(txt: string, preformatted: boolean): void; +export var dialogBoxOpened: boolean; \ No newline at end of file diff --git a/utils/JSONReviver.d.ts b/utils/JSONReviver.d.ts new file mode 100644 index 000000000..08ff98bd4 --- /dev/null +++ b/utils/JSONReviver.d.ts @@ -0,0 +1,10 @@ +interface IReviverValue { + ctor: string; + data: object +} +export function Generic_fromJSON(ctor: new () => T, data: any): T; +export function Generic_toJSON(ctorName: string, obj: object, keys?: string[]): string; +export function Reviver(key, value: IReviverValue); +export namespace Reviver { + export var constructors: any; +} \ No newline at end of file