@nasriya/overwatch
Advanced tools
| import Watcher from "./watcher/Watcher"; | ||
| import { WatchOptions } from "./docs/docs"; | ||
| export type { WatchOptions, OnWatchedDataUpdateHandler, onWatchedDataRemoveHandler, onWatchedDataRenameHandler, onWatchedDataAddHandler, WatchedDataChangeEvent, onWatchedDataChangeHandler, RenameEvent, UpdateEvent, RemoveEvent, AddEvent, ChangeEvent, WatchedFile, WatchedFolder, WatchedData } from './docs/docs'; | ||
| declare class Overwatch { | ||
@@ -4,0 +5,0 @@ #private; |
| import { WatchedData, WatchedFile, WatchedFolder } from "../docs/docs"; | ||
| declare class Utils { | ||
| /** | ||
| * Converts a glob expression to a regular expression. | ||
| * @param glob The glob expression to convert. | ||
| * @param options Options to customize the conversion. | ||
| * @param options.globstar Whether or not to enable globstar matching (e.g. `** /foo`). | ||
| * @param options.flags A string containing additional flags to pass to the created RegExp. | ||
| * @returns The regular expression representation of the glob expression. | ||
| */ | ||
| globToRegExp(glob: string, options?: { | ||
| globstar?: boolean; | ||
| flags?: string; | ||
| }): RegExp; | ||
| /** | ||
| * Checks if the given pattern is a glob-like pattern, meaning it contains at least one of the | ||
| * characters `*` or `?`. | ||
| * @param pattern The pattern to check. | ||
| * @returns true if the given pattern is a glob-like pattern, false otherwise. | ||
| */ | ||
| isGlobLike(pattern: string): boolean; | ||
| /** | ||
| * Checks if the given WatchedData is a WatchedFile. | ||
@@ -35,9 +16,2 @@ * @param data The WatchedData to check. | ||
| /** | ||
| * Checks if the given object has the given property. | ||
| * @param object The object to check. | ||
| * @param property The property to check for. | ||
| * @returns true if the object has the property, false otherwise. | ||
| */ | ||
| hasOwnProperty(object: any, property: string): boolean; | ||
| /** | ||
| * Checks if the given `WatchedData` objects are of the same type (i.e. both are `WatchedFolder`, or both are `WatchedFile`). | ||
@@ -49,16 +23,4 @@ * @param a The first `WatchedData` object to compare. | ||
| areSameWatchedDataTypes(a: WatchedData, b: WatchedData): boolean; | ||
| /** | ||
| * Checks if the current platform is Windows. | ||
| * @returns true if the platform is Windows, false otherwise. | ||
| */ | ||
| isWindows(): boolean; | ||
| /** | ||
| * Normalizes the given path by resolving it to an absolute path and converting | ||
| * it to lowercase if the current platform is Windows. | ||
| * @param path_ The path to normalize. | ||
| * @returns The normalized path. | ||
| */ | ||
| normalizePath(path_: string): string; | ||
| } | ||
| declare const utils: Utils; | ||
| export default utils; |
@@ -6,8 +6,8 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const atomix_1 = __importDefault(require("@nasriya/atomix")); | ||
| const vom_1 = __importDefault(require("./vom/vom")); | ||
| const Watcher_1 = __importDefault(require("./watcher/Watcher")); | ||
| const manager_1 = __importDefault(require("./events/manager")); | ||
| const utils_1 = __importDefault(require("./utils/utils")); | ||
| const path_1 = __importDefault(require("path")); | ||
| const fs_1 = __importDefault(require("fs")); | ||
| const path_1 = __importDefault(require("path")); | ||
| class Overwatch { | ||
@@ -43,3 +43,4 @@ #_vom = new vom_1.default(); | ||
| } | ||
| if ('include' in options && utils_1.default.hasOwnProperty(options, 'include')) { | ||
| const hasOwnProperty = atomix_1.default.dataTypes.record.hasOwnProperty.bind(atomix_1.default.dataTypes.record); | ||
| if ('include' in options && hasOwnProperty(options, 'include')) { | ||
| if (!Array.isArray(options.include)) { | ||
@@ -55,3 +56,3 @@ throw new TypeError('options.include (when provided) must be an array.'); | ||
| } | ||
| if ('exclude' in options && utils_1.default.hasOwnProperty(options, 'exclude')) { | ||
| if ('exclude' in options && hasOwnProperty(options, 'exclude')) { | ||
| if (!Array.isArray(options.exclude)) { | ||
@@ -167,3 +168,3 @@ throw new TypeError('options.exclude (when provided) must be an array.'); | ||
| try { | ||
| const resolvedPath = utils_1.default.normalizePath(path_); | ||
| const resolvedPath = atomix_1.default.path.normalizePath(path_); | ||
| const isFile = fs_1.default.statSync(resolvedPath).isFile(); | ||
@@ -201,3 +202,3 @@ const directory = isFile ? path_1.default.dirname(resolvedPath) : resolvedPath; | ||
| try { | ||
| const watcher = await this.watch(path_); | ||
| const watcher = await this.watch(path_, options); | ||
| return watcher; | ||
@@ -204,0 +205,0 @@ } |
+7
-132
@@ -6,105 +6,6 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const path_1 = __importDefault(require("path")); | ||
| const atomix_1 = __importDefault(require("@nasriya/atomix")); | ||
| const hasOwnProperty = atomix_1.default.dataTypes.record.hasOwnProperty.bind(atomix_1.default.dataTypes.record); | ||
| class Utils { | ||
| /** | ||
| * Converts a glob expression to a regular expression. | ||
| * @param glob The glob expression to convert. | ||
| * @param options Options to customize the conversion. | ||
| * @param options.globstar Whether or not to enable globstar matching (e.g. `** /foo`). | ||
| * @param options.flags A string containing additional flags to pass to the created RegExp. | ||
| * @returns The regular expression representation of the glob expression. | ||
| */ | ||
| globToRegExp(glob, options) { | ||
| const globstar = options?.globstar ?? true; | ||
| const flags = options?.flags ?? ''; | ||
| let re = ''; | ||
| let inGroup = false; | ||
| let escaping = false; | ||
| for (let i = 0; i < glob.length; i++) { | ||
| const char = glob[i]; | ||
| // Handle escaped characters (e.g., \*, \?, \{, etc.) | ||
| if (escaping) { | ||
| re += '\\' + char; | ||
| escaping = false; | ||
| continue; | ||
| } | ||
| if (char === '\\') { | ||
| escaping = true; | ||
| continue; | ||
| } | ||
| switch (char) { | ||
| case '/': | ||
| re += '\\/'; | ||
| break; | ||
| case '.': | ||
| case '+': | ||
| case '^': | ||
| case '$': | ||
| case '!': | ||
| case '=': | ||
| case '|': | ||
| case '(': | ||
| case ')': | ||
| re += '\\' + char; | ||
| break; | ||
| case '*': { | ||
| const prev = glob[i - 1]; | ||
| let starCount = 1; | ||
| while (glob[i + 1] === '*') { | ||
| i++; | ||
| starCount++; | ||
| } | ||
| const next = glob[i + 1]; | ||
| const isGlobstar = globstar && | ||
| starCount > 1 && | ||
| (prev === '/' || prev === undefined) && | ||
| (next === '/' || next === undefined); | ||
| if (isGlobstar) { | ||
| re += '((?:[^\\/]*(?:\\/|$))*)'; | ||
| if (next === '/') | ||
| i++; // skip slash after globstar | ||
| } | ||
| else { | ||
| re += '[^\\/]*'; | ||
| } | ||
| break; | ||
| } | ||
| case '?': | ||
| re += '.'; | ||
| break; | ||
| case '{': | ||
| inGroup = true; | ||
| re += '('; | ||
| break; | ||
| case '}': | ||
| inGroup = false; | ||
| re += ')'; | ||
| break; | ||
| case ',': | ||
| re += inGroup ? '|' : ','; | ||
| break; | ||
| // allow valid character classes (e.g., [jt]) | ||
| case '[': | ||
| case ']': | ||
| re += char; | ||
| break; | ||
| default: | ||
| re += char; | ||
| break; | ||
| } | ||
| } | ||
| // Only anchor if not global, to behave like globs | ||
| const anchored = flags.includes('g') ? re : `^${re}$`; | ||
| return new RegExp(anchored, flags); | ||
| } | ||
| /** | ||
| * Checks if the given pattern is a glob-like pattern, meaning it contains at least one of the | ||
| * characters `*` or `?`. | ||
| * @param pattern The pattern to check. | ||
| * @returns true if the given pattern is a glob-like pattern, false otherwise. | ||
| */ | ||
| isGlobLike(pattern) { | ||
| return /[*?]/.test(pattern); | ||
| } | ||
| /** | ||
| * Checks if the given WatchedData is a WatchedFile. | ||
@@ -118,6 +19,6 @@ * @param data The WatchedData to check. | ||
| } | ||
| if (!(this.hasOwnProperty(data, 'path') && | ||
| this.hasOwnProperty(data, 'name') && | ||
| this.hasOwnProperty(data, 'size') && | ||
| this.hasOwnProperty(data, 'mTime'))) { | ||
| if (!(hasOwnProperty(data, 'path') && | ||
| hasOwnProperty(data, 'name') && | ||
| hasOwnProperty(data, 'size') && | ||
| hasOwnProperty(data, 'mTime'))) { | ||
| return false; | ||
@@ -139,14 +40,5 @@ } | ||
| isWatchedFolder(data) { | ||
| return this.isWatchedFile(data) && 'children' in data && this.hasOwnProperty(data, 'children') && data.children instanceof Map; | ||
| return this.isWatchedFile(data) && 'children' in data && hasOwnProperty(data, 'children') && data.children instanceof Map; | ||
| } | ||
| /** | ||
| * Checks if the given object has the given property. | ||
| * @param object The object to check. | ||
| * @param property The property to check for. | ||
| * @returns true if the object has the property, false otherwise. | ||
| */ | ||
| hasOwnProperty(object, property) { | ||
| return typeof object === 'object' && Object.prototype.hasOwnProperty.call(object, property); | ||
| } | ||
| /** | ||
| * Checks if the given `WatchedData` objects are of the same type (i.e. both are `WatchedFolder`, or both are `WatchedFile`). | ||
@@ -162,21 +54,4 @@ * @param a The first `WatchedData` object to compare. | ||
| } | ||
| /** | ||
| * Checks if the current platform is Windows. | ||
| * @returns true if the platform is Windows, false otherwise. | ||
| */ | ||
| isWindows() { | ||
| return process.platform === 'win32'; | ||
| } | ||
| /** | ||
| * Normalizes the given path by resolving it to an absolute path and converting | ||
| * it to lowercase if the current platform is Windows. | ||
| * @param path_ The path to normalize. | ||
| * @returns The normalized path. | ||
| */ | ||
| normalizePath(path_) { | ||
| const resolved = path_1.default.resolve(path_); | ||
| return this.isWindows() ? resolved.toLowerCase() : resolved; | ||
| } | ||
| } | ||
| const utils = new Utils(); | ||
| exports.default = utils; |
@@ -6,6 +6,6 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const atomix_1 = __importDefault(require("@nasriya/atomix")); | ||
| const snapshot_1 = __importDefault(require("./snapshot")); | ||
| const manager_1 = __importDefault(require("../events/manager")); | ||
| const path_1 = __importDefault(require("path")); | ||
| const utils_1 = __importDefault(require("../utils/utils")); | ||
| const manager_1 = __importDefault(require("../events/manager")); | ||
| class VirtualObjectManager { | ||
@@ -49,3 +49,3 @@ #_snapshots = new Map(); | ||
| getCoveringSnapshot: (path_) => { | ||
| const isWin = utils_1.default.isWindows(); | ||
| const isWin = atomix_1.default.runtime.platform.isWindows(); | ||
| let currentPath = path_; | ||
@@ -75,3 +75,3 @@ while (true) { | ||
| async snapshot(path_) { | ||
| const originalPath = utils_1.default.normalizePath(path_); | ||
| const originalPath = atomix_1.default.path.normalizePath(path_); | ||
| const snapshot = this.#_helpers.getCoveringSnapshot(originalPath); | ||
@@ -78,0 +78,0 @@ if (snapshot) { |
@@ -6,3 +6,3 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const utils_1 = __importDefault(require("../utils/utils")); | ||
| const atomix_1 = __importDefault(require("@nasriya/atomix")); | ||
| class Watcher { | ||
@@ -28,7 +28,7 @@ #_path; | ||
| if (typeof rule === 'string') { | ||
| if (utils_1.default.isGlobLike(rule)) { | ||
| return utils_1.default.globToRegExp(rule); | ||
| if (atomix_1.default.dataTypes.regex.guard.isGlobLike(rule)) { | ||
| return atomix_1.default.dataTypes.regex.globToRegExp(rule); | ||
| } | ||
| else { | ||
| return utils_1.default.normalizePath(rule); | ||
| return atomix_1.default.path.normalizePath(rule); | ||
| } | ||
@@ -48,20 +48,23 @@ } | ||
| this.#_filters.exclude = this.#_filters.exclude.map(rule => this.#_helpers.normalizeFilterRule(rule)); | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onChange')) { | ||
| this.onChange(watchOptions?.onChange); | ||
| if (atomix_1.default.dataTypes.record.guard.isRecord(watchOptions)) { | ||
| const hasOwnProperty = atomix_1.default.dataTypes.record.hasOwnProperty.bind(atomix_1.default.dataTypes.record); | ||
| if (hasOwnProperty(watchOptions, 'onChange')) { | ||
| this.onChange(watchOptions?.onChange); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onUpdate')) { | ||
| this.onUpdate(watchOptions?.onUpdate); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRemove')) { | ||
| this.onRemove(watchOptions?.onRemove); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRename')) { | ||
| this.onRename(watchOptions?.onRename); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onAdd')) { | ||
| this.onAdd(watchOptions?.onAdd); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRootRemoved')) { | ||
| this.onRootRemoved(watchOptions?.onRootRemoved); | ||
| } | ||
| } | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onUpdate')) { | ||
| this.onUpdate(watchOptions?.onUpdate); | ||
| } | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onRemove')) { | ||
| this.onRemove(watchOptions?.onRemove); | ||
| } | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onRename')) { | ||
| this.onRename(watchOptions?.onRename); | ||
| } | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onAdd')) { | ||
| this.onAdd(watchOptions?.onAdd); | ||
| } | ||
| if (utils_1.default.hasOwnProperty(watchOptions, 'onRootRemoved')) { | ||
| this.onRootRemoved(watchOptions?.onRootRemoved); | ||
| } | ||
| } | ||
@@ -68,0 +71,0 @@ /** |
@@ -0,7 +1,7 @@ | ||
| import atomix from "@nasriya/atomix"; | ||
| import VirtualObjectManager from "./vom/vom.js"; | ||
| import Watcher from "./watcher/Watcher.js"; | ||
| import eventsManager from "./events/manager.js"; | ||
| import utils from "./utils/utils.js"; | ||
| import path from "path"; | ||
| import fs from "fs"; | ||
| import path from "path"; | ||
| class Overwatch { | ||
@@ -37,3 +37,4 @@ #_vom = new VirtualObjectManager(); | ||
| } | ||
| if ('include' in options && utils.hasOwnProperty(options, 'include')) { | ||
| const hasOwnProperty = atomix.dataTypes.record.hasOwnProperty.bind(atomix.dataTypes.record); | ||
| if ('include' in options && hasOwnProperty(options, 'include')) { | ||
| if (!Array.isArray(options.include)) { | ||
@@ -49,3 +50,3 @@ throw new TypeError('options.include (when provided) must be an array.'); | ||
| } | ||
| if ('exclude' in options && utils.hasOwnProperty(options, 'exclude')) { | ||
| if ('exclude' in options && hasOwnProperty(options, 'exclude')) { | ||
| if (!Array.isArray(options.exclude)) { | ||
@@ -161,3 +162,3 @@ throw new TypeError('options.exclude (when provided) must be an array.'); | ||
| try { | ||
| const resolvedPath = utils.normalizePath(path_); | ||
| const resolvedPath = atomix.path.normalizePath(path_); | ||
| const isFile = fs.statSync(resolvedPath).isFile(); | ||
@@ -195,3 +196,3 @@ const directory = isFile ? path.dirname(resolvedPath) : resolvedPath; | ||
| try { | ||
| const watcher = await this.watch(path_); | ||
| const watcher = await this.watch(path_, options); | ||
| return watcher; | ||
@@ -198,0 +199,0 @@ } |
+7
-132
@@ -1,104 +0,5 @@ | ||
| import path from 'path'; | ||
| import atomix from "@nasriya/atomix"; | ||
| const hasOwnProperty = atomix.dataTypes.record.hasOwnProperty.bind(atomix.dataTypes.record); | ||
| class Utils { | ||
| /** | ||
| * Converts a glob expression to a regular expression. | ||
| * @param glob The glob expression to convert. | ||
| * @param options Options to customize the conversion. | ||
| * @param options.globstar Whether or not to enable globstar matching (e.g. `** /foo`). | ||
| * @param options.flags A string containing additional flags to pass to the created RegExp. | ||
| * @returns The regular expression representation of the glob expression. | ||
| */ | ||
| globToRegExp(glob, options) { | ||
| const globstar = options?.globstar ?? true; | ||
| const flags = options?.flags ?? ''; | ||
| let re = ''; | ||
| let inGroup = false; | ||
| let escaping = false; | ||
| for (let i = 0; i < glob.length; i++) { | ||
| const char = glob[i]; | ||
| // Handle escaped characters (e.g., \*, \?, \{, etc.) | ||
| if (escaping) { | ||
| re += '\\' + char; | ||
| escaping = false; | ||
| continue; | ||
| } | ||
| if (char === '\\') { | ||
| escaping = true; | ||
| continue; | ||
| } | ||
| switch (char) { | ||
| case '/': | ||
| re += '\\/'; | ||
| break; | ||
| case '.': | ||
| case '+': | ||
| case '^': | ||
| case '$': | ||
| case '!': | ||
| case '=': | ||
| case '|': | ||
| case '(': | ||
| case ')': | ||
| re += '\\' + char; | ||
| break; | ||
| case '*': { | ||
| const prev = glob[i - 1]; | ||
| let starCount = 1; | ||
| while (glob[i + 1] === '*') { | ||
| i++; | ||
| starCount++; | ||
| } | ||
| const next = glob[i + 1]; | ||
| const isGlobstar = globstar && | ||
| starCount > 1 && | ||
| (prev === '/' || prev === undefined) && | ||
| (next === '/' || next === undefined); | ||
| if (isGlobstar) { | ||
| re += '((?:[^\\/]*(?:\\/|$))*)'; | ||
| if (next === '/') | ||
| i++; // skip slash after globstar | ||
| } | ||
| else { | ||
| re += '[^\\/]*'; | ||
| } | ||
| break; | ||
| } | ||
| case '?': | ||
| re += '.'; | ||
| break; | ||
| case '{': | ||
| inGroup = true; | ||
| re += '('; | ||
| break; | ||
| case '}': | ||
| inGroup = false; | ||
| re += ')'; | ||
| break; | ||
| case ',': | ||
| re += inGroup ? '|' : ','; | ||
| break; | ||
| // allow valid character classes (e.g., [jt]) | ||
| case '[': | ||
| case ']': | ||
| re += char; | ||
| break; | ||
| default: | ||
| re += char; | ||
| break; | ||
| } | ||
| } | ||
| // Only anchor if not global, to behave like globs | ||
| const anchored = flags.includes('g') ? re : `^${re}$`; | ||
| return new RegExp(anchored, flags); | ||
| } | ||
| /** | ||
| * Checks if the given pattern is a glob-like pattern, meaning it contains at least one of the | ||
| * characters `*` or `?`. | ||
| * @param pattern The pattern to check. | ||
| * @returns true if the given pattern is a glob-like pattern, false otherwise. | ||
| */ | ||
| isGlobLike(pattern) { | ||
| return /[*?]/.test(pattern); | ||
| } | ||
| /** | ||
| * Checks if the given WatchedData is a WatchedFile. | ||
@@ -112,6 +13,6 @@ * @param data The WatchedData to check. | ||
| } | ||
| if (!(this.hasOwnProperty(data, 'path') && | ||
| this.hasOwnProperty(data, 'name') && | ||
| this.hasOwnProperty(data, 'size') && | ||
| this.hasOwnProperty(data, 'mTime'))) { | ||
| if (!(hasOwnProperty(data, 'path') && | ||
| hasOwnProperty(data, 'name') && | ||
| hasOwnProperty(data, 'size') && | ||
| hasOwnProperty(data, 'mTime'))) { | ||
| return false; | ||
@@ -133,14 +34,5 @@ } | ||
| isWatchedFolder(data) { | ||
| return this.isWatchedFile(data) && 'children' in data && this.hasOwnProperty(data, 'children') && data.children instanceof Map; | ||
| return this.isWatchedFile(data) && 'children' in data && hasOwnProperty(data, 'children') && data.children instanceof Map; | ||
| } | ||
| /** | ||
| * Checks if the given object has the given property. | ||
| * @param object The object to check. | ||
| * @param property The property to check for. | ||
| * @returns true if the object has the property, false otherwise. | ||
| */ | ||
| hasOwnProperty(object, property) { | ||
| return typeof object === 'object' && Object.prototype.hasOwnProperty.call(object, property); | ||
| } | ||
| /** | ||
| * Checks if the given `WatchedData` objects are of the same type (i.e. both are `WatchedFolder`, or both are `WatchedFile`). | ||
@@ -156,21 +48,4 @@ * @param a The first `WatchedData` object to compare. | ||
| } | ||
| /** | ||
| * Checks if the current platform is Windows. | ||
| * @returns true if the platform is Windows, false otherwise. | ||
| */ | ||
| isWindows() { | ||
| return process.platform === 'win32'; | ||
| } | ||
| /** | ||
| * Normalizes the given path by resolving it to an absolute path and converting | ||
| * it to lowercase if the current platform is Windows. | ||
| * @param path_ The path to normalize. | ||
| * @returns The normalized path. | ||
| */ | ||
| normalizePath(path_) { | ||
| const resolved = path.resolve(path_); | ||
| return this.isWindows() ? resolved.toLowerCase() : resolved; | ||
| } | ||
| } | ||
| const utils = new Utils(); | ||
| export default utils; |
@@ -0,5 +1,5 @@ | ||
| import atomix from "@nasriya/atomix"; | ||
| import Snapshot from "./snapshot.js"; | ||
| import eventsManager from "../events/manager.js"; | ||
| import path from "path"; | ||
| import utils from "../utils/utils.js"; | ||
| import eventsManager from "../events/manager.js"; | ||
| class VirtualObjectManager { | ||
@@ -43,3 +43,3 @@ #_snapshots = new Map(); | ||
| getCoveringSnapshot: (path_) => { | ||
| const isWin = utils.isWindows(); | ||
| const isWin = atomix.runtime.platform.isWindows(); | ||
| let currentPath = path_; | ||
@@ -69,3 +69,3 @@ while (true) { | ||
| async snapshot(path_) { | ||
| const originalPath = utils.normalizePath(path_); | ||
| const originalPath = atomix.path.normalizePath(path_); | ||
| const snapshot = this.#_helpers.getCoveringSnapshot(originalPath); | ||
@@ -72,0 +72,0 @@ if (snapshot) { |
@@ -1,2 +0,2 @@ | ||
| import utils from "../utils/utils.js"; | ||
| import atomix from "@nasriya/atomix"; | ||
| class Watcher { | ||
@@ -22,7 +22,7 @@ #_path; | ||
| if (typeof rule === 'string') { | ||
| if (utils.isGlobLike(rule)) { | ||
| return utils.globToRegExp(rule); | ||
| if (atomix.dataTypes.regex.guard.isGlobLike(rule)) { | ||
| return atomix.dataTypes.regex.globToRegExp(rule); | ||
| } | ||
| else { | ||
| return utils.normalizePath(rule); | ||
| return atomix.path.normalizePath(rule); | ||
| } | ||
@@ -42,20 +42,23 @@ } | ||
| this.#_filters.exclude = this.#_filters.exclude.map(rule => this.#_helpers.normalizeFilterRule(rule)); | ||
| if (utils.hasOwnProperty(watchOptions, 'onChange')) { | ||
| this.onChange(watchOptions?.onChange); | ||
| if (atomix.dataTypes.record.guard.isRecord(watchOptions)) { | ||
| const hasOwnProperty = atomix.dataTypes.record.hasOwnProperty.bind(atomix.dataTypes.record); | ||
| if (hasOwnProperty(watchOptions, 'onChange')) { | ||
| this.onChange(watchOptions?.onChange); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onUpdate')) { | ||
| this.onUpdate(watchOptions?.onUpdate); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRemove')) { | ||
| this.onRemove(watchOptions?.onRemove); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRename')) { | ||
| this.onRename(watchOptions?.onRename); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onAdd')) { | ||
| this.onAdd(watchOptions?.onAdd); | ||
| } | ||
| if (hasOwnProperty(watchOptions, 'onRootRemoved')) { | ||
| this.onRootRemoved(watchOptions?.onRootRemoved); | ||
| } | ||
| } | ||
| if (utils.hasOwnProperty(watchOptions, 'onUpdate')) { | ||
| this.onUpdate(watchOptions?.onUpdate); | ||
| } | ||
| if (utils.hasOwnProperty(watchOptions, 'onRemove')) { | ||
| this.onRemove(watchOptions?.onRemove); | ||
| } | ||
| if (utils.hasOwnProperty(watchOptions, 'onRename')) { | ||
| this.onRename(watchOptions?.onRename); | ||
| } | ||
| if (utils.hasOwnProperty(watchOptions, 'onAdd')) { | ||
| this.onAdd(watchOptions?.onAdd); | ||
| } | ||
| if (utils.hasOwnProperty(watchOptions, 'onRootRemoved')) { | ||
| this.onRootRemoved(watchOptions?.onRootRemoved); | ||
| } | ||
| } | ||
@@ -62,0 +65,0 @@ /** |
+8
-5
| { | ||
| "name": "@nasriya/overwatch", | ||
| "version": "1.0.6", | ||
| "version": "1.1.0", | ||
| "description": "A high-performance, dependency-free file system watcher that monitors file and directory changes efficiently across platforms.", | ||
@@ -40,3 +40,3 @@ "keywords": [ | ||
| "postbuild-init": "postbuild-init", | ||
| "test": "jest" | ||
| "test": "jest --detectOpenHandles" | ||
| }, | ||
@@ -60,6 +60,9 @@ "repository": { | ||
| "@types/jest": "^30.0.0", | ||
| "@types/node": "^24.0.3", | ||
| "jest": "^30.0.1", | ||
| "@types/node": "^24.0.4", | ||
| "jest": "^30.0.3", | ||
| "ts-jest": "^29.4.0" | ||
| }, | ||
| "dependencies": { | ||
| "@nasriya/atomix": "^1.0.1" | ||
| } | ||
| } | ||
| } |
+1
-1
| [](https://nasriya.net) | ||
| # Overwatch. | ||
| [](https://github.com/nasriyasoftware/Overwatch?tab=License-1-ov-file)     [](link-to-your-status-page) | ||
| [](https://github.com/nasriyasoftware/Overwatch?tab=License-1-ov-file)    [](link-to-your-status-page) | ||
@@ -6,0 +6,0 @@ ##### Visit us at [www.nasriya.net](https://nasriya.net). |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
Found 2 instances in 1 package
108659
-8.01%1
Infinity%2329
-10.66%+ Added
+ Added
+ Added