From 2f1807812d983b65c104d3c7333ebeaa27f6082b Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 12:12:34 +1000 Subject: [PATCH 01/10] Added folder exclusion feature and .gitattributes --- .gitattributes | 26 ++++++++++++++++++++++++++ src/config.ts | 5 +++++ src/fileWatch.ts | 23 +++++++++++++++++------ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..198198d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,26 @@ +# js / ts files +*.js text +*.ts text + +# Config text files +*.jsonc text +*.json text +*.yml text +.eslintrc text +.eslintignore text +.gitignore text +.gitattributes text +.prettierignore text +.prettierrc text + +# Standard text files +*.txt text +*.md text +*.sh text eol=lf +*.bat text eol=crlf +LICENSE text + +# Binary files +*.gif binary +*.jpg binary +*.png binary diff --git a/src/config.ts b/src/config.ts index 46e9b1b..396f8a3 100644 --- a/src/config.ts +++ b/src/config.ts @@ -28,6 +28,11 @@ export const config = convict({ env: "BB_SCRIPTFOLDER", arg: "folder", }, + exclude: { + doc: "A list of folders or files to exclude from the sync.", + format: "Array", + default: [".vscode", ".idea", ".github"], + }, quiet: { doc: "Log less internal events to stdout.", format: "Boolean", diff --git a/src/fileWatch.ts b/src/fileWatch.ts index a505560..1dccca9 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -5,12 +5,7 @@ import { mkdir } from "fs/promises"; import { resolve } from "path"; import type { Signal } from "signal-js"; import type { File } from "./interfaces"; - -function fileFilter(file: File) { - if (config.get("allowedFiletypes").some((extension) => file.path.endsWith(extension))) return true; - if (file.stats.isDirectory()) return true; - return false; -} +import fs from "node:fs"; function isError(err: unknown): err is NodeJS.ErrnoException { return (err as NodeJS.ErrnoException).code !== undefined; @@ -26,6 +21,22 @@ export async function setupWatch(signaller: Signal) { } } + const excludedPaths = config.get("exclude").map((path) => resolve(path)); + const excludedFiles = new Set(); + for (const excludedPath of excludedPaths) { + for (const excludedFile of fs.readdirSync(excludedPath)) { + excludedFiles.add(excludedFile); + } + } + + const fileFilter = (file: File) => { + // If the file is excluded, skip all other checks and ignore it. + if (excludedFiles.has(file.path)) return false; + if (config.get("allowedFiletypes").some((extension) => file.path.endsWith(extension))) return true; + if (file.stats.isDirectory()) return true; + return false; + }; + const watch = new CheapWatch({ dir: config.get("scriptsFolder"), filter: fileFilter, From 5bebc2832ade947e95fbbd77854f2f57b7063197 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 12:20:06 +1000 Subject: [PATCH 02/10] Added missing type packages to eliminate build errors --- package-lock.json | 112 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 +++ 2 files changed, 118 insertions(+) diff --git a/package-lock.json b/package-lock.json index 84312c3..caa3300 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,12 @@ "@types/expect": "^24.3.0", "@types/mocha": "^10.0.0", "@types/node": "^18.7.23", + "@types/parse-json": "^4.0.0", + "@types/prop-types": "^15.7.5", + "@types/react": "^18.0.34", + "@types/react-is": "^17.0.3", + "@types/react-transition-group": "^4.4.5", + "@types/scheduler": "^0.16.3", "@types/sinon": "^10.0.13", "@types/sinon-chai": "^3.2.8", "@types/ws": "^8.5.3", @@ -944,6 +950,53 @@ "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==", "dev": true }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.0.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.34.tgz", + "integrity": "sha512-NO1UO8941541CJl1BeOXi8a9dNKFK09Gnru5ZJqkm4Q3/WoQJtHvmwt0VX0SB9YCEwe7TfSSxDuaNmx6H2BAIQ==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "dev": true + }, "node_modules/@types/sinon": { "version": "10.0.13", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", @@ -1709,6 +1762,12 @@ "node": ">= 8" } }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -5205,6 +5264,53 @@ "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==", "dev": true }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "@types/react": { + "version": "18.0.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.34.tgz", + "integrity": "sha512-NO1UO8941541CJl1BeOXi8a9dNKFK09Gnru5ZJqkm4Q3/WoQJtHvmwt0VX0SB9YCEwe7TfSSxDuaNmx6H2BAIQ==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "dev": true + }, "@types/sinon": { "version": "10.0.13", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", @@ -5746,6 +5852,12 @@ "which": "^2.0.1" } }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index cdbee67..bff8bf5 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,12 @@ "@types/ws": "^8.5.3", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", + "@types/parse-json": "^4.0.0", + "@types/react": "^18.0.34", + "@types/react-is": "^17.0.3", + "@types/react-transition-group": "^4.4.5", + "@types/prop-types": "^15.7.5", + "@types/scheduler": "^0.16.3", "chai": "^4.3.6", "eslint": "^8.25.0", "mocha": "^10.0.0", From daf7854cd01804eb4666c1cd77f8d330c14d60f0 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 14:29:05 +1000 Subject: [PATCH 03/10] Bumped dependency versions to the latest --- package-lock.json | 54 ++++++++++++++++++----------------------------- package.json | 4 ++-- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index caa3300..02592ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "Unlicense", "dependencies": { "cheap-watch": "^1.0.4", - "convict": "^6.2.3", + "convict": "^6.2.4", "signal-js": "^3.0.1", "typescript": "^4.8.4", "ws": "^8.8.1" @@ -38,7 +38,7 @@ "@typescript-eslint/parser": "^5.40.0", "chai": "^4.3.6", "eslint": "^8.25.0", - "mocha": "^10.0.0", + "mocha": "^10.1.0", "nyc": "^15.1.0", "prettier": "^2.7.1", "sinon": "^14.0.0", @@ -1282,12 +1282,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -1731,9 +1725,9 @@ "dev": true }, "node_modules/convict": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.3.tgz", - "integrity": "sha512-mTY04Qr7WrqiXifdeUYXr4/+Te4hPFWDvz6J2FVIKCLc2XBhq63VOSSYAKJ+unhZAYOAjmEdNswTOeHt7s++pQ==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", + "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", "dependencies": { "lodash.clonedeep": "^4.5.0", "yargs-parser": "^20.2.7" @@ -2972,9 +2966,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -3133,12 +3127,11 @@ } }, "node_modules/mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "dependencies": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", @@ -5495,12 +5488,6 @@ "eslint-visitor-keys": "^3.3.0" } }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, "acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -5827,9 +5814,9 @@ } }, "convict": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.3.tgz", - "integrity": "sha512-mTY04Qr7WrqiXifdeUYXr4/+Te4hPFWDvz6J2FVIKCLc2XBhq63VOSSYAKJ+unhZAYOAjmEdNswTOeHt7s++pQ==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", + "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", "requires": { "lodash.clonedeep": "^4.5.0", "yargs-parser": "^20.2.7" @@ -6754,9 +6741,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "just-extend": { @@ -6876,12 +6863,11 @@ } }, "mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "requires": { - "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", diff --git a/package.json b/package.json index bff8bf5..a36a1bb 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "homepage": "https://github.com/bitburner-official/bitburner-filesync#readme", "dependencies": { "cheap-watch": "^1.0.4", - "convict": "^6.2.3", + "convict": "^6.2.4", "signal-js": "^3.0.1", "typescript": "^4.8.4", "ws": "^8.8.1" @@ -57,7 +57,7 @@ "@types/scheduler": "^0.16.3", "chai": "^4.3.6", "eslint": "^8.25.0", - "mocha": "^10.0.0", + "mocha": "^10.1.0", "nyc": "^15.1.0", "prettier": "^2.7.1", "sinon": "^14.0.0", From fd3392fb231dcdece007e988d8de167f411da969 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 15:04:42 +1000 Subject: [PATCH 04/10] Added a prepare script to allow installing off GitHub --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index a36a1bb..c409a53 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "bin": "./dist/npx/bitburner-filesync.js", "main": "./dist/npx/bitburner-filesync.js", "scripts": { + "prepare": "npm run build", "build": "tsc --build --verbose --pretty", "clean": "tsc --build --clean", "format": "prettier -w .", From 2b40438341489cc4110f4d1a4e9fb61b72347007 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 21:48:05 +1000 Subject: [PATCH 05/10] Bug fixes --- src/fileWatch.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/fileWatch.ts b/src/fileWatch.ts index 1dccca9..07583a9 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -1,11 +1,10 @@ import CheapWatch from "cheap-watch"; import { config } from "./config"; import { EventType } from "./eventTypes"; -import { mkdir } from "fs/promises"; +import { mkdir, readdir } from "fs/promises"; import { resolve } from "path"; import type { Signal } from "signal-js"; import type { File } from "./interfaces"; -import fs from "node:fs"; function isError(err: unknown): err is NodeJS.ErrnoException { return (err as NodeJS.ErrnoException).code !== undefined; @@ -21,13 +20,13 @@ export async function setupWatch(signaller: Signal) { } } - const excludedPaths = config.get("exclude").map((path) => resolve(path)); - const excludedFiles = new Set(); - for (const excludedPath of excludedPaths) { - for (const excludedFile of fs.readdirSync(excludedPath)) { - excludedFiles.add(excludedFile); - } - } + const promises = config.get("exclude") + .map(path => readdir(resolve(path)).catch(err => { + console.log(`Failed to excluded item ${path}: ${err}`); + return []; + })); + const excludedFiles = new Set(await Promise.all(promises) + .then(lists => lists.flat())); const fileFilter = (file: File) => { // If the file is excluded, skip all other checks and ignore it. From 043a2d34b1142328b6d16452ce9af035de3f95a6 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 11 Apr 2023 21:48:05 +1000 Subject: [PATCH 06/10] Bug fixes --- npx/bitburner-filesync.ts | 2 +- src/fileWatch.ts | 19 +++++++++---------- src/index.ts | 6 +++--- src/networking/messageGenerators.ts | 4 ++-- src/networking/messageHandler.ts | 10 +++++----- src/networking/messageTracker.ts | 2 +- src/networking/webSocket.ts | 8 ++++---- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/npx/bitburner-filesync.ts b/npx/bitburner-filesync.ts index abd9301..a24f503 100755 --- a/npx/bitburner-filesync.ts +++ b/npx/bitburner-filesync.ts @@ -1,4 +1,4 @@ #!/usr/bin/env -S node --experimental-specifier-resolution=node -import { start } from "../src/index"; +import { start } from "../src/index.js"; await start(); diff --git a/src/fileWatch.ts b/src/fileWatch.ts index 1dccca9..cb74f7f 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -1,11 +1,10 @@ import CheapWatch from "cheap-watch"; import { config } from "./config"; import { EventType } from "./eventTypes"; -import { mkdir } from "fs/promises"; +import { mkdir, readdir } from "fs/promises"; import { resolve } from "path"; import type { Signal } from "signal-js"; -import type { File } from "./interfaces"; -import fs from "node:fs"; +import type { File } from "./interfaces.js"; function isError(err: unknown): err is NodeJS.ErrnoException { return (err as NodeJS.ErrnoException).code !== undefined; @@ -21,13 +20,13 @@ export async function setupWatch(signaller: Signal) { } } - const excludedPaths = config.get("exclude").map((path) => resolve(path)); - const excludedFiles = new Set(); - for (const excludedPath of excludedPaths) { - for (const excludedFile of fs.readdirSync(excludedPath)) { - excludedFiles.add(excludedFile); - } - } + const promises = config.get("exclude") + .map(path => readdir(resolve(path)).catch(err => { + console.log(`Failed to excluded item ${path}: ${err}`); + return []; + })); + const excludedFiles = new Set(await Promise.all(promises) + .then(lists => lists.flat())); const fileFilter = (file: File) => { // If the file is excluded, skip all other checks and ignore it. diff --git a/src/index.ts b/src/index.ts index c256948..50caee4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ -import { setupWatch } from "./fileWatch"; -import { config, loadConfig } from "./config"; -import { setupSocket } from "./networking/webSocket"; +import { setupWatch } from "./fileWatch.js"; +import { config, loadConfig } from "./config.js"; +import { setupSocket } from "./networking/webSocket.js"; import signal from "signal-js"; import { RawData } from "ws"; import { diff --git a/src/networking/messageGenerators.ts b/src/networking/messageGenerators.ts index e8db805..86b9d35 100644 --- a/src/networking/messageGenerators.ts +++ b/src/networking/messageGenerators.ts @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; -import { config } from "../config"; +import { config } from "../config.js"; import { join } from "path"; -import type { FileEvent, Message } from "../interfaces"; +import type { FileEvent, Message } from "../interfaces.js"; let messageCounter = 0; diff --git a/src/networking/messageHandler.ts b/src/networking/messageHandler.ts index 48d122d..819fe66 100644 --- a/src/networking/messageHandler.ts +++ b/src/networking/messageHandler.ts @@ -1,11 +1,11 @@ -import { messageTracker } from "./messageTracker"; +import { messageTracker } from "./messageTracker.js"; import { Stats, writeFile } from "fs"; import { RawData } from "ws"; -import { config } from "../config"; -import { EventType } from "../eventTypes"; -import { fileChangeEventToMsg } from "./messageGenerators"; +import { config } from "../config.js"; +import { EventType } from "../eventTypes.js"; +import { fileChangeEventToMsg } from "./messageGenerators.js"; import type { Signal } from "signal-js"; -import { Message } from "../interfaces"; +import { Message } from "../interfaces.js"; function deserialize(data: RawData): Message { const msg = JSON.parse(data.toString()); diff --git a/src/networking/messageTracker.ts b/src/networking/messageTracker.ts index 67eb528..1e48ce0 100644 --- a/src/networking/messageTracker.ts +++ b/src/networking/messageTracker.ts @@ -1,4 +1,4 @@ -import type { Message } from "../interfaces"; +import type { Message } from "../interfaces.js"; class MessageTracker { data = new Map(); diff --git a/src/networking/webSocket.ts b/src/networking/webSocket.ts index 044e3bd..9f26b17 100644 --- a/src/networking/webSocket.ts +++ b/src/networking/webSocket.ts @@ -1,9 +1,9 @@ import type { Signal } from "signal-js"; import { WebSocketServer } from "ws"; -import { config } from "../config"; -import { EventType } from "../eventTypes"; -import { Message } from "../interfaces"; -import { messageTracker } from "./messageTracker"; +import { config } from "../config.js"; +import { EventType } from "../eventTypes.js"; +import { Message } from "../interfaces.js"; +import { messageTracker } from "./messageTracker.js"; export function setupSocket(signaller: Signal) { const wss = new WebSocketServer({ port: config.get("port") }); From 544344bbb47c4d1c6b3840e324ebafb4d4644302 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 12 Apr 2023 17:40:50 +1000 Subject: [PATCH 07/10] Bug fixes --- src/fileWatch.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fileWatch.ts b/src/fileWatch.ts index cb74f7f..98d95e9 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -1,6 +1,6 @@ import CheapWatch from "cheap-watch"; -import { config } from "./config"; -import { EventType } from "./eventTypes"; +import { config } from "./config.js"; +import { EventType } from "./eventTypes.js"; import { mkdir, readdir } from "fs/promises"; import { resolve } from "path"; import type { Signal } from "signal-js"; From fbab8a375f6e77156cbb9e8e450b8321f942c372 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 12 Apr 2023 17:57:34 +1000 Subject: [PATCH 08/10] Added some documentation --- src/fileWatch.ts | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/fileWatch.ts b/src/fileWatch.ts index 98d95e9..1b65fd7 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -1,11 +1,33 @@ import CheapWatch from "cheap-watch"; import { config } from "./config.js"; import { EventType } from "./eventTypes.js"; -import { mkdir, readdir } from "fs/promises"; -import { resolve } from "path"; +import { mkdir } from "fs/promises"; +import { resolve, relative, isAbsolute } from "path"; import type { Signal } from "signal-js"; import type { File } from "./interfaces.js"; +/** + * Returns true if the given file should be watched. + * @param file The provided file. + */ +function fileFilter(file: File) { + // If the file is excluded, skip all other checks and ignore it. + if (config.get("exclude").some(x => isSubDirOf(file.path, x))) return false; + if (config.get("allowedFiletypes").some((extension) => file.path.endsWith(extension))) return true; + if (file.stats.isDirectory()) return true; + return false; +} + +/** + * Returns true if a directory is a subdirectory of a parent directory (not necessarily strict). + * @param dir The directory to perform the check on. + * @param parent The parent directory. + */ +function isSubDirOf(dir: string, parent: string) { + const relPath = relative(resolve(parent), resolve(dir)); + return !!relPath && !relPath.startsWith('..') && !isAbsolute(relPath); +} + function isError(err: unknown): err is NodeJS.ErrnoException { return (err as NodeJS.ErrnoException).code !== undefined; } @@ -20,22 +42,6 @@ export async function setupWatch(signaller: Signal) { } } - const promises = config.get("exclude") - .map(path => readdir(resolve(path)).catch(err => { - console.log(`Failed to excluded item ${path}: ${err}`); - return []; - })); - const excludedFiles = new Set(await Promise.all(promises) - .then(lists => lists.flat())); - - const fileFilter = (file: File) => { - // If the file is excluded, skip all other checks and ignore it. - if (excludedFiles.has(file.path)) return false; - if (config.get("allowedFiletypes").some((extension) => file.path.endsWith(extension))) return true; - if (file.stats.isDirectory()) return true; - return false; - }; - const watch = new CheapWatch({ dir: config.get("scriptsFolder"), filter: fileFilter, From ee7231af9c72001e3ace02973169fc349f2fa13a Mon Sep 17 00:00:00 2001 From: david Date: Thu, 13 Apr 2023 17:10:26 +1000 Subject: [PATCH 09/10] Added more documentation --- src/fileWatch.ts | 24 ++++++++++++++++-------- src/index.ts | 3 +++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/fileWatch.ts b/src/fileWatch.ts index 1b65fd7..057aed0 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -6,6 +6,16 @@ import { resolve, relative, isAbsolute } from "path"; import type { Signal } from "signal-js"; import type { File } from "./interfaces.js"; +/** + * Returns true if a directory is a subdirectory of a parent directory (not necessarily strict). + * @param dir The directory to perform the check on. + * @param parent The parent directory. + */ +function isSubDirOf(dir: string, parent: string) { + const relPath = relative(resolve(parent), resolve(dir)); + return !!relPath && !relPath.startsWith('..') && !isAbsolute(relPath); +} + /** * Returns true if the given file should be watched. * @param file The provided file. @@ -19,19 +29,17 @@ function fileFilter(file: File) { } /** - * Returns true if a directory is a subdirectory of a parent directory (not necessarily strict). - * @param dir The directory to perform the check on. - * @param parent The parent directory. + * Type guard for {@code NodeJS.ErrnoException}. + * @param err */ -function isSubDirOf(dir: string, parent: string) { - const relPath = relative(resolve(parent), resolve(dir)); - return !!relPath && !relPath.startsWith('..') && !isAbsolute(relPath); -} - function isError(err: unknown): err is NodeJS.ErrnoException { return (err as NodeJS.ErrnoException).code !== undefined; } +/** + * Sets up the file watch. + * @param signaller The signal event emitter. + */ export async function setupWatch(signaller: Signal) { try { await mkdir(resolve(config.get("scriptsFolder"))); diff --git a/src/index.ts b/src/index.ts index 14f1a1b..196b988 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,9 @@ import { EventType } from "./eventTypes.js"; import { messageHandler } from "./networking/messageHandler.js"; import { FileEvent } from "./interfaces.js"; +/** + * Starts the file watcher. + */ export async function start() { loadConfig(); const watch = await setupWatch(signal); From cc976840694e03a48f959b52d18565f41e751a7c Mon Sep 17 00:00:00 2001 From: david Date: Wed, 19 Apr 2023 07:16:40 +1000 Subject: [PATCH 10/10] Run prettier --- src/fileWatch.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fileWatch.ts b/src/fileWatch.ts index 057aed0..3a25349 100644 --- a/src/fileWatch.ts +++ b/src/fileWatch.ts @@ -13,7 +13,7 @@ import type { File } from "./interfaces.js"; */ function isSubDirOf(dir: string, parent: string) { const relPath = relative(resolve(parent), resolve(dir)); - return !!relPath && !relPath.startsWith('..') && !isAbsolute(relPath); + return !!relPath && !relPath.startsWith("..") && !isAbsolute(relPath); } /** @@ -22,7 +22,7 @@ function isSubDirOf(dir: string, parent: string) { */ function fileFilter(file: File) { // If the file is excluded, skip all other checks and ignore it. - if (config.get("exclude").some(x => isSubDirOf(file.path, x))) return false; + if (config.get("exclude").some((x) => isSubDirOf(file.path, x))) return false; if (config.get("allowedFiletypes").some((extension) => file.path.endsWith(extension))) return true; if (file.stats.isDirectory()) return true; return false;