diff --git a/src/benchmark/suites/product/async.ts b/src/benchmark/suites/product/async.ts index 9b797147..b0172f95 100644 --- a/src/benchmark/suites/product/async.ts +++ b/src/benchmark/suites/product/async.ts @@ -9,13 +9,19 @@ type GlobImplementation = 'fast-glob' | 'fdir' | 'node-glob'; type GlobImplFunction = (...args: any[]) => Promise; class Glob { - constructor(private readonly _cwd: string, private readonly _pattern: string) {} + readonly #cwd: string; + readonly #pattern: string; + + constructor(cwd: string, pattern: string) { + this.#cwd = cwd; + this.#pattern = pattern; + } public async measureNodeGlob(): Promise { const glob = await utils.importAndMeasure(utils.importNodeGlob); - await this._measure(() => glob.glob(this._pattern, { - cwd: this._cwd, + await this.#measure(() => glob.glob(this.#pattern, { + cwd: this.#cwd, nodir: true, })); } @@ -23,8 +29,8 @@ class Glob { public async measureFastGlob(): Promise { const glob = await utils.importAndMeasure(utils.importCurrentFastGlob); - await this._measure(() => glob(this._pattern, { - cwd: this._cwd, + await this.#measure(() => glob(this.#pattern, { + cwd: this.#cwd, unique: false, followSymbolicLinks: false, concurrency: Number.POSITIVE_INFINITY, @@ -38,13 +44,13 @@ class Glob { .withBasePath() .withRelativePaths() // Other solutions do not include hidden files by default - .globWithOptions([this._pattern], { dot: false }) - .crawl(this._cwd); + .globWithOptions([this.#pattern], { dot: false }) + .crawl(this.#cwd); - await this._measure(() => fdir.withPromise()); + await this.#measure(() => fdir.withPromise()); } - private async _measure(function_: GlobImplFunction): Promise { + async #measure(function_: GlobImplFunction): Promise { const timeStart = utils.timeStart(); const matches = await function_(); diff --git a/src/benchmark/suites/product/stream.ts b/src/benchmark/suites/product/stream.ts index 0111e148..429a8764 100644 --- a/src/benchmark/suites/product/stream.ts +++ b/src/benchmark/suites/product/stream.ts @@ -9,15 +9,21 @@ type GlobImplementation = 'fast-glob' | 'node-glob'; type GlobImplFunction = (...args: any[]) => Promise; class Glob { - constructor(private readonly _cwd: string, private readonly _pattern: string) {} + readonly #cwd: string; + readonly #pattern: string; + + constructor(cwd: string, pattern: string) { + this.#cwd = cwd; + this.#pattern = pattern; + } public async measureNodeGlob(): Promise { const glob = await utils.importAndMeasure(utils.importNodeGlob); const entries: string[] = []; - const stream = glob.globStream(this._pattern, { - cwd: this._cwd, + const stream = glob.globStream(this.#pattern, { + cwd: this.#cwd, nodir: true, }); @@ -31,7 +37,7 @@ class Glob { }); }); - await this._measure(() => action); + await this.#measure(() => action); } public async measureFastGlob(): Promise { @@ -39,8 +45,8 @@ class Glob { const entries: string[] = []; - const stream = glob.stream(this._pattern, { - cwd: this._cwd, + const stream = glob.stream(this.#pattern, { + cwd: this.#cwd, unique: false, followSymbolicLinks: false, concurrency: Number.POSITIVE_INFINITY, @@ -56,10 +62,10 @@ class Glob { }); }); - await this._measure(() => action); + await this.#measure(() => action); } - private async _measure(function_: GlobImplFunction): Promise { + async #measure(function_: GlobImplFunction): Promise { const timeStart = utils.timeStart(); const matches = await function_(); diff --git a/src/benchmark/suites/product/sync.ts b/src/benchmark/suites/product/sync.ts index ef79be66..a068ac63 100644 --- a/src/benchmark/suites/product/sync.ts +++ b/src/benchmark/suites/product/sync.ts @@ -9,13 +9,19 @@ type GlobImplementation = 'fast-glob' | 'fdir' | 'node-glob'; type GlobImplFunction = (...args: any[]) => unknown[]; class Glob { - constructor(private readonly _cwd: string, private readonly _pattern: string) {} + readonly #cwd: string; + readonly #pattern: string; + + constructor(cwd: string, pattern: string) { + this.#cwd = cwd; + this.#pattern = pattern; + } public async measureNodeGlob(): Promise { const glob = await utils.importAndMeasure(utils.importNodeGlob); - this._measure(() => glob.globSync(this._pattern, { - cwd: this._cwd, + this.#measure(() => glob.globSync(this.#pattern, { + cwd: this.#cwd, nodir: true, })); } @@ -23,8 +29,8 @@ class Glob { public async measureFastGlob(): Promise { const glob = await utils.importAndMeasure(utils.importCurrentFastGlob); - this._measure(() => glob.sync(this._pattern, { - cwd: this._cwd, + this.#measure(() => glob.sync(this.#pattern, { + cwd: this.#cwd, unique: false, followSymbolicLinks: false, })); @@ -37,13 +43,13 @@ class Glob { .withBasePath() .withRelativePaths() // Other solutions do not include hidden files by default - .globWithOptions([this._pattern], { dot: false }) - .crawl(this._cwd); + .globWithOptions([this.#pattern], { dot: false }) + .crawl(this.#cwd); - this._measure(() => fdir.sync()); + this.#measure(() => fdir.sync()); } - private _measure(function_: GlobImplFunction): void { + #measure(function_: GlobImplFunction): void { const timeStart = utils.timeStart(); const matches = function_(); diff --git a/src/benchmark/suites/regression/async.ts b/src/benchmark/suites/regression/async.ts index 1f537e37..2a45f3c1 100644 --- a/src/benchmark/suites/regression/async.ts +++ b/src/benchmark/suites/regression/async.ts @@ -2,19 +2,22 @@ import * as path from 'node:path'; import * as bencho from 'bencho'; -import * as fastGlobCurrent from '../../..'; import * as utils from '../../utils'; +import type * as fastGlobCurrent from '../../..'; + type GlobImplementation = 'current' | 'previous'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type GlobImplFunction = (...args: any[]) => Promise; type GlobOptions = fastGlobCurrent.Options; class Glob { - private readonly _options: fastGlobCurrent.Options; + readonly #pattern: string; + readonly #options: GlobOptions; - constructor(private readonly _pattern: string, options: fastGlobCurrent.Options) { - this._options = { + constructor(pattern: string, options: GlobOptions) { + this.#pattern = pattern; + this.#options = { unique: false, followSymbolicLinks: false, concurrency: Number.POSITIVE_INFINITY, @@ -26,16 +29,16 @@ class Glob { const glob = await utils.importAndMeasure(utils.importPreviousFastGlob); // @ts-expect-error remove this line after the next major release. - await this._measure(() => glob(this._pattern, this._options)); + await this.#measure(() => glob(this.#pattern, this.#options)); } public async measureCurrentVersion(): Promise { const glob = await utils.importAndMeasure(utils.importCurrentFastGlob); - await this._measure(() => glob(this._pattern, this._options)); + await this.#measure(() => glob(this.#pattern, this.#options)); } - private async _measure(function_: GlobImplFunction): Promise { + async #measure(function_: GlobImplFunction): Promise { const timeStart = utils.timeStart(); const matches = await function_(); @@ -57,7 +60,7 @@ class Glob { const cwd = path.join(process.cwd(), args[0]); const pattern = args[1]; const impl = args[2] as GlobImplementation; - const options = JSON.parse(process.env.BENCHMARK_OPTIONS ?? '{}') as GlobOptions; + const options = JSON.parse(process.env['BENCHMARK_OPTIONS'] ?? '{}') as GlobOptions; const glob = new Glob(pattern, { cwd, diff --git a/src/benchmark/suites/regression/stream.ts b/src/benchmark/suites/regression/stream.ts index 36c716d7..dae2d22c 100644 --- a/src/benchmark/suites/regression/stream.ts +++ b/src/benchmark/suites/regression/stream.ts @@ -2,19 +2,22 @@ import * as path from 'node:path'; import * as bencho from 'bencho'; -import * as fastGlobCurrent from '../../..'; import * as utils from '../../utils'; +import type * as fastGlobCurrent from '../../..'; + type GlobImplementation = 'current' | 'previous'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type GlobImplFunction = (...args: any[]) => ReturnType; type GlobOptions = fastGlobCurrent.Options; class Glob { - private readonly _options: fastGlobCurrent.Options; + readonly #pattern: string; + readonly #options: GlobOptions; - constructor(private readonly _pattern: string, options: fastGlobCurrent.Options) { - this._options = { + constructor(pattern: string, options: GlobOptions) { + this.#pattern = pattern; + this.#options = { unique: false, followSymbolicLinks: false, concurrency: Number.POSITIVE_INFINITY, @@ -26,16 +29,16 @@ class Glob { const glob = await utils.importAndMeasure(utils.importPreviousFastGlob); // @ts-expect-error remove this line after the next major release. - await this._measure(() => glob.stream(this._pattern, this._options)); + await this.#measure(() => glob.stream(this.#pattern, this.#options)); } public async measureCurrentVersion(): Promise { const glob = await utils.importAndMeasure(utils.importCurrentFastGlob); - await this._measure(() => glob.stream(this._pattern, this._options)); + await this.#measure(() => glob.stream(this.#pattern, this.#options)); } - private async _measure(function_: GlobImplFunction): Promise { + async #measure(function_: GlobImplFunction): Promise { const entries: string[] = []; const timeStart = utils.timeStart(); @@ -69,7 +72,7 @@ class Glob { const cwd = path.join(process.cwd(), args[0]); const pattern = args[1]; const impl = args[2] as GlobImplementation; - const options = JSON.parse(process.env.BENCHMARK_OPTIONS ?? '{}') as GlobOptions; + const options = JSON.parse(process.env['BENCHMARK_OPTIONS'] ?? '{}') as GlobOptions; const glob = new Glob(pattern, { cwd, diff --git a/src/benchmark/suites/regression/sync.ts b/src/benchmark/suites/regression/sync.ts index e1c9021f..1353e844 100644 --- a/src/benchmark/suites/regression/sync.ts +++ b/src/benchmark/suites/regression/sync.ts @@ -2,19 +2,22 @@ import * as path from 'node:path'; import * as bencho from 'bencho'; -import * as fastGlobCurrent from '../../..'; import * as utils from '../../utils'; +import type * as fastGlobCurrent from '../../..'; + type GlobImplementation = 'current' | 'previous'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type GlobImplFunction = (...args: any[]) => unknown[]; type GlobOptions = fastGlobCurrent.Options; class Glob { - private readonly _options: fastGlobCurrent.Options; + readonly #pattern: string; + readonly #options: GlobOptions; - constructor(private readonly _pattern: string, options: fastGlobCurrent.Options) { - this._options = { + constructor(pattern: string, options: GlobOptions) { + this.#pattern = pattern; + this.#options = { unique: false, followSymbolicLinks: false, ...options, @@ -25,16 +28,16 @@ class Glob { const glob = await utils.importAndMeasure(utils.importPreviousFastGlob); // @ts-expect-error remove this line after the next major release. - this._measure(() => glob.sync(this._pattern, this._options)); + this.#measure(() => glob.sync(this.#pattern, this.#options)); } public async measureCurrentVersion(): Promise { const glob = await utils.importAndMeasure(utils.importCurrentFastGlob); - this._measure(() => glob.sync(this._pattern, this._options)); + this.#measure(() => glob.sync(this.#pattern, this.#options)); } - private _measure(function_: GlobImplFunction): void { + #measure(function_: GlobImplFunction): void { const timeStart = utils.timeStart(); const matches = function_(); @@ -56,7 +59,7 @@ class Glob { const cwd = path.join(process.cwd(), args[0]); const pattern = args[1]; const impl = args[2] as GlobImplementation; - const options = JSON.parse(process.env.BENCHMARK_OPTIONS ?? '{}') as GlobOptions; + const options = JSON.parse(process.env['BENCHMARK_OPTIONS'] ?? '{}') as GlobOptions; const glob = new Glob(pattern, { cwd, diff --git a/src/providers/async.spec.ts b/src/providers/async.spec.ts index 7424e7f1..40b3b07e 100644 --- a/src/providers/async.spec.ts +++ b/src/providers/async.spec.ts @@ -2,17 +2,18 @@ import * as assert from 'node:assert'; import * as sinon from 'sinon'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ReaderAsync from '../readers/async'; import ProviderAsync from './async'; +import type { Options } from '../settings'; import type { Entry, EntryItem, ErrnoException } from '../types'; import type ReaderStream from '../readers/stream'; import type { Task } from '../managers/tasks'; class TestProvider extends ProviderAsync { - protected _reader: ReaderAsync = sinon.createStubInstance(ReaderAsync) as unknown as ReaderAsync; + protected override _reader: ReaderAsync = sinon.createStubInstance(ReaderAsync) as unknown as ReaderAsync; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/providers/async.ts b/src/providers/async.ts index 7da8974c..b6ed637a 100644 --- a/src/providers/async.ts +++ b/src/providers/async.ts @@ -1,11 +1,18 @@ import ReaderAsync from '../readers/async'; import Provider from './provider'; +import type Settings from '../settings'; import type { Task } from '../managers/tasks'; import type { Entry, EntryItem, ReaderOptions } from '../types'; export default class ProviderAsync extends Provider> { - protected _reader: ReaderAsync = new ReaderAsync(this._settings); + protected _reader: ReaderAsync; + + constructor(settings: Settings) { + super(settings); + + this._reader = new ReaderAsync(settings); + } public async read(task: Task): Promise { const root = this._getRootDirectory(task); diff --git a/src/providers/filters/deep.ts b/src/providers/filters/deep.ts index 6fd45b32..de4b9465 100644 --- a/src/providers/filters/deep.ts +++ b/src/providers/filters/deep.ts @@ -1,60 +1,65 @@ -import { MicromatchOptions } from '../../types'; -import Settings from '../../settings'; import * as utils from '../../utils'; import PartialMatcher from '../matchers/partial'; -import type { Entry, EntryFilterFunction, Pattern, PatternRe } from '../../types'; +import type { MicromatchOptions, Entry, EntryFilterFunction, Pattern, PatternRe } from '../../types'; +import type Settings from '../../settings'; export default class DeepFilter { - constructor(private readonly _settings: Settings, private readonly _micromatchOptions: MicromatchOptions) {} + readonly #settings: Settings; + readonly #micromatchOptions: MicromatchOptions; + + constructor(settings: Settings, micromatchOptions: MicromatchOptions) { + this.#settings = settings; + this.#micromatchOptions = micromatchOptions; + } public getFilter(basePath: string, positive: Pattern[], negative: Pattern[]): EntryFilterFunction { - const matcher = this._getMatcher(positive); - const negativeRe = this._getNegativePatternsRe(negative); + const matcher = this.#getMatcher(positive); + const negativeRe = this.#getNegativePatternsRe(negative); - return (entry) => this._filter(basePath, entry, matcher, negativeRe); + return (entry) => this.#filter(basePath, entry, matcher, negativeRe); } - private _getMatcher(patterns: Pattern[]): PartialMatcher { - return new PartialMatcher(patterns, this._settings, this._micromatchOptions); + #getMatcher(patterns: Pattern[]): PartialMatcher { + return new PartialMatcher(patterns, this.#settings, this.#micromatchOptions); } - private _getNegativePatternsRe(patterns: Pattern[]): PatternRe[] { + #getNegativePatternsRe(patterns: Pattern[]): PatternRe[] { const affectDepthOfReadingPatterns = patterns.filter((pattern) => utils.pattern.isAffectDepthOfReadingPattern(pattern)); - return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); + return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this.#micromatchOptions); } - private _filter(basePath: string, entry: Entry, matcher: PartialMatcher, negativeRe: PatternRe[]): boolean { - if (this._isSkippedByDeep(basePath, entry.path)) { + #filter(basePath: string, entry: Entry, matcher: PartialMatcher, negativeRe: PatternRe[]): boolean { + if (this.#isSkippedByDeep(basePath, entry.path)) { return false; } - if (this._isSkippedSymbolicLink(entry)) { + if (this.#isSkippedSymbolicLink(entry)) { return false; } const filepath = utils.path.removeLeadingDotSegment(entry.path); - if (this._isSkippedByPositivePatterns(filepath, matcher)) { + if (this.#isSkippedByPositivePatterns(filepath, matcher)) { return false; } - return this._isSkippedByNegativePatterns(filepath, negativeRe); + return this.#isSkippedByNegativePatterns(filepath, negativeRe); } - private _isSkippedByDeep(basePath: string, entryPath: string): boolean { + #isSkippedByDeep(basePath: string, entryPath: string): boolean { /** * Avoid unnecessary depth calculations when it doesn't matter. */ - if (this._settings.deep === Number.POSITIVE_INFINITY) { + if (this.#settings.deep === Number.POSITIVE_INFINITY) { return false; } - return this._getEntryLevel(basePath, entryPath) >= this._settings.deep; + return this.#getEntryLevel(basePath, entryPath) >= this.#settings.deep; } - private _getEntryLevel(basePath: string, entryPath: string): number { + #getEntryLevel(basePath: string, entryPath: string): number { const entryPathDepth = entryPath.split('/').length; if (basePath === '') { @@ -66,15 +71,15 @@ export default class DeepFilter { return entryPathDepth - basePathDepth; } - private _isSkippedSymbolicLink(entry: Entry): boolean { - return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); + #isSkippedSymbolicLink(entry: Entry): boolean { + return !this.#settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); } - private _isSkippedByPositivePatterns(entryPath: string, matcher: PartialMatcher): boolean { - return !this._settings.baseNameMatch && !matcher.match(entryPath); + #isSkippedByPositivePatterns(entryPath: string, matcher: PartialMatcher): boolean { + return !this.#settings.baseNameMatch && !matcher.match(entryPath); } - private _isSkippedByNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean { + #isSkippedByNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean { return !utils.pattern.matchAny(entryPath, patternsRe); } } diff --git a/src/providers/filters/entry.ts b/src/providers/filters/entry.ts index cdf1922b..47ed8a91 100644 --- a/src/providers/filters/entry.ts +++ b/src/providers/filters/entry.ts @@ -1,77 +1,82 @@ -import Settings from '../../settings'; -import { MicromatchOptions } from '../../types'; import * as utils from '../../utils'; -import type { Entry, EntryFilterFunction, Pattern, PatternRe } from '../../types'; +import type Settings from '../../settings'; +import type { MicromatchOptions, Entry, EntryFilterFunction, Pattern, PatternRe } from '../../types'; export default class EntryFilter { public readonly index = new Map(); - constructor(private readonly _settings: Settings, private readonly _micromatchOptions: MicromatchOptions) {} + readonly #settings: Settings; + readonly #micromatchOptions: MicromatchOptions; + + constructor(settings: Settings, micromatchOptions: MicromatchOptions) { + this.#settings = settings; + this.#micromatchOptions = micromatchOptions; + } public getFilter(positive: Pattern[], negative: Pattern[]): EntryFilterFunction { - const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions); + const positiveRe = utils.pattern.convertPatternsToRe(positive, this.#micromatchOptions); const negativeRe = utils.pattern.convertPatternsToRe(negative, { - ...this._micromatchOptions, + ...this.#micromatchOptions, dot: true, }); - return (entry) => this._filter(entry, positiveRe, negativeRe); + return (entry) => this.#filter(entry, positiveRe, negativeRe); } - private _filter(entry: Entry, positiveRe: PatternRe[], negativeRe: PatternRe[]): boolean { + #filter(entry: Entry, positiveRe: PatternRe[], negativeRe: PatternRe[]): boolean { const filepath = utils.path.removeLeadingDotSegment(entry.path); - if (this._settings.unique && this._isDuplicateEntry(filepath)) { + if (this.#settings.unique && this.#isDuplicateEntry(filepath)) { return false; } - if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { + if (this.#onlyFileFilter(entry) || this.#onlyDirectoryFilter(entry)) { return false; } - if (this._isSkippedByAbsoluteNegativePatterns(filepath, negativeRe)) { + if (this.#isSkippedByAbsoluteNegativePatterns(filepath, negativeRe)) { return false; } const isDirectory = entry.dirent.isDirectory(); - const isMatched = this._isMatchToPatterns(filepath, positiveRe, isDirectory) && !this._isMatchToPatterns(filepath, negativeRe, isDirectory); + const isMatched = this.#isMatchToPatterns(filepath, positiveRe, isDirectory) && !this.#isMatchToPatterns(filepath, negativeRe, isDirectory); - if (this._settings.unique && isMatched) { - this._createIndexRecord(filepath); + if (this.#settings.unique && isMatched) { + this.#createIndexRecord(filepath); } return isMatched; } - private _isDuplicateEntry(filepath: string): boolean { + #isDuplicateEntry(filepath: string): boolean { return this.index.has(filepath); } - private _createIndexRecord(filepath: string): void { + #createIndexRecord(filepath: string): void { this.index.set(filepath, undefined); } - private _onlyFileFilter(entry: Entry): boolean { - return this._settings.onlyFiles && !entry.dirent.isFile(); + #onlyFileFilter(entry: Entry): boolean { + return this.#settings.onlyFiles && !entry.dirent.isFile(); } - private _onlyDirectoryFilter(entry: Entry): boolean { - return this._settings.onlyDirectories && !entry.dirent.isDirectory(); + #onlyDirectoryFilter(entry: Entry): boolean { + return this.#settings.onlyDirectories && !entry.dirent.isDirectory(); } - private _isSkippedByAbsoluteNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean { - if (!this._settings.absolute) { + #isSkippedByAbsoluteNegativePatterns(entryPath: string, patternsRe: PatternRe[]): boolean { + if (!this.#settings.absolute) { return false; } - const fullpath = utils.path.makeAbsolute(this._settings.cwd, entryPath); + const fullpath = utils.path.makeAbsolute(this.#settings.cwd, entryPath); return utils.pattern.matchAny(fullpath, patternsRe); } - private _isMatchToPatterns(filepath: string, patternsRe: PatternRe[], isDirectory: boolean): boolean { + #isMatchToPatterns(filepath: string, patternsRe: PatternRe[], isDirectory: boolean): boolean { // Trying to match files and directories by patterns. const isMatched = utils.pattern.matchAny(filepath, patternsRe); diff --git a/src/providers/filters/error.ts b/src/providers/filters/error.ts index 1c248e08..9dba5fae 100644 --- a/src/providers/filters/error.ts +++ b/src/providers/filters/error.ts @@ -1,16 +1,20 @@ -import Settings from '../../settings'; import * as utils from '../../utils'; +import type Settings from '../../settings'; import type { ErrnoException, ErrorFilterFunction } from '../../types'; export default class ErrorFilter { - constructor(private readonly _settings: Settings) {} + readonly #settings: Settings; + + constructor(settings: Settings) { + this.#settings = settings; + } public getFilter(): ErrorFilterFunction { - return (error) => this._isNonFatalError(error); + return (error) => this.#isNonFatalError(error); } - private _isNonFatalError(error: ErrnoException): boolean { - return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; + #isNonFatalError(error: ErrnoException): boolean { + return utils.errno.isEnoentCodeError(error) || this.#settings.suppressErrors; } } diff --git a/src/providers/matchers/matcher.ts b/src/providers/matchers/matcher.ts index ab1f0585..1cc975b8 100644 --- a/src/providers/matchers/matcher.ts +++ b/src/providers/matchers/matcher.ts @@ -1,8 +1,7 @@ -import { MicromatchOptions } from '../../types'; import * as utils from '../../utils'; -import Settings from '../../settings'; -import type { Pattern, PatternRe } from '../../types'; +import type { MicromatchOptions, Pattern, PatternRe } from '../../types'; +import type Settings from '../../settings'; export type PatternSegment = DynamicPatternSegment | StaticPatternSegment; @@ -32,14 +31,22 @@ export interface PatternInfo { export default abstract class Matcher { protected readonly _storage: PatternInfo[] = []; - constructor(private readonly _patterns: Pattern[], private readonly _settings: Settings, private readonly _micromatchOptions: MicromatchOptions) { - this._fillStorage(); + readonly #patterns: string[]; + readonly #settings: Settings; + readonly #micromatchOptions: MicromatchOptions; + + constructor(patterns: Pattern[], settings: Settings, micromatchOptions: MicromatchOptions) { + this.#patterns = patterns; + this.#settings = settings; + this.#micromatchOptions = micromatchOptions; + + this.#fillStorage(); } - private _fillStorage(): void { - for (const pattern of this._patterns) { - const segments = this._getPatternSegments(pattern); - const sections = this._splitSegmentsIntoSections(segments); + #fillStorage(): void { + for (const pattern of this.#patterns) { + const segments = this.#getPatternSegments(pattern); + const sections = this.#splitSegmentsIntoSections(segments); this._storage.push({ complete: sections.length <= 1, @@ -50,11 +57,11 @@ export default abstract class Matcher { } } - private _getPatternSegments(pattern: Pattern): PatternSegment[] { - const parts = utils.pattern.getPatternParts(pattern, this._micromatchOptions); + #getPatternSegments(pattern: Pattern): PatternSegment[] { + const parts = utils.pattern.getPatternParts(pattern, this.#micromatchOptions); return parts.map((part) => { - const dynamic = utils.pattern.isDynamicPattern(part, this._settings); + const dynamic = utils.pattern.isDynamicPattern(part, this.#settings); if (!dynamic) { return { @@ -66,12 +73,12 @@ export default abstract class Matcher { return { dynamic: true, pattern: part, - patternRe: utils.pattern.makeRe(part, this._micromatchOptions), + patternRe: utils.pattern.makeRe(part, this.#micromatchOptions), }; }); } - private _splitSegmentsIntoSections(segments: PatternSegment[]): PatternSection[] { + #splitSegmentsIntoSections(segments: PatternSegment[]): PatternSection[] { return utils.array.splitWhen(segments, (segment) => segment.dynamic && utils.pattern.hasGlobStar(segment.pattern)); } } diff --git a/src/providers/provider.ts b/src/providers/provider.ts index bf07949b..6e07a905 100644 --- a/src/providers/provider.ts +++ b/src/providers/provider.ts @@ -1,26 +1,37 @@ import * as path from 'node:path'; -import Settings from '../settings'; import DeepFilter from './filters/deep'; import EntryFilter from './filters/entry'; import ErrorFilter from './filters/error'; import EntryTransformer from './transformers/entry'; +import type Settings from '../settings'; import type { MicromatchOptions, ReaderOptions } from '../types'; import type { Task } from '../managers/tasks'; export default abstract class Provider { - public readonly errorFilter: ErrorFilter = new ErrorFilter(this._settings); - public readonly entryFilter: EntryFilter = new EntryFilter(this._settings, this._getMicromatchOptions()); - public readonly deepFilter: DeepFilter = new DeepFilter(this._settings, this._getMicromatchOptions()); - public readonly entryTransformer: EntryTransformer = new EntryTransformer(this._settings); + public readonly errorFilter: ErrorFilter; + public readonly entryFilter: EntryFilter; + public readonly deepFilter: DeepFilter; + public readonly entryTransformer: EntryTransformer; - constructor(protected readonly _settings: Settings) {} + readonly #settings: Settings; + + constructor(settings: Settings) { + this.#settings = settings; + + const micromatchOptions = this._getMicromatchOptions(); + + this.errorFilter = new ErrorFilter(settings); + this.entryFilter = new EntryFilter(settings, micromatchOptions); + this.deepFilter = new DeepFilter(settings, micromatchOptions); + this.entryTransformer = new EntryTransformer(settings); + } public abstract read(_task: Task): T; protected _getRootDirectory(task: Task): string { - return path.resolve(this._settings.cwd, task.base); + return path.resolve(this.#settings.cwd, task.base); } protected _getReaderOptions(task: Task): ReaderOptions { @@ -29,26 +40,26 @@ export default abstract class Provider { return { basePath, pathSegmentSeparator: '/', - concurrency: this._settings.concurrency, + concurrency: this.#settings.concurrency, deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), entryFilter: this.entryFilter.getFilter(task.positive, task.negative), errorFilter: this.errorFilter.getFilter(), - followSymbolicLinks: this._settings.followSymbolicLinks, - fs: this._settings.fs, - stats: this._settings.stats, - throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, + followSymbolicLinks: this.#settings.followSymbolicLinks, + fs: this.#settings.fs, + stats: this.#settings.stats, + throwErrorOnBrokenSymbolicLink: this.#settings.throwErrorOnBrokenSymbolicLink, transform: this.entryTransformer.getTransformer(), }; } protected _getMicromatchOptions(): MicromatchOptions { return { - dot: this._settings.dot, - matchBase: this._settings.baseNameMatch, - nobrace: !this._settings.braceExpansion, - nocase: !this._settings.caseSensitiveMatch, - noext: !this._settings.extglob, - noglobstar: !this._settings.globstar, + dot: this.#settings.dot, + matchBase: this.#settings.baseNameMatch, + nobrace: !this.#settings.braceExpansion, + nocase: !this.#settings.caseSensitiveMatch, + noext: !this.#settings.extglob, + noglobstar: !this.#settings.globstar, posix: true, strictSlashes: false, }; diff --git a/src/providers/stream.spec.ts b/src/providers/stream.spec.ts index 9f8d6f7c..f709ae57 100644 --- a/src/providers/stream.spec.ts +++ b/src/providers/stream.spec.ts @@ -4,15 +4,16 @@ import { PassThrough } from 'node:stream'; import * as sinon from 'sinon'; import ReaderStream from '../readers/stream'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ProviderStream from './stream'; +import type { Options } from '../settings'; import type { Entry, EntryItem, ErrnoException } from '../types'; import type { Task } from '../managers/tasks'; class TestProvider extends ProviderStream { - protected _reader: ReaderStream = sinon.createStubInstance(ReaderStream) as unknown as ReaderStream; + protected override _reader: ReaderStream = sinon.createStubInstance(ReaderStream) as unknown as ReaderStream; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/providers/stream.ts b/src/providers/stream.ts index 560a2e45..327abb4b 100644 --- a/src/providers/stream.ts +++ b/src/providers/stream.ts @@ -3,11 +3,18 @@ import { Readable } from 'node:stream'; import ReaderStream from '../readers/stream'; import Provider from './provider'; +import type Settings from '../settings'; import type { Task } from '../managers/tasks'; import type { Entry, ErrnoException, ReaderOptions } from '../types'; export default class ProviderStream extends Provider { - protected _reader: ReaderStream = new ReaderStream(this._settings); + protected _reader: ReaderStream; + + constructor(settings: Settings) { + super(settings); + + this._reader = new ReaderStream(settings); + } public read(task: Task): Readable { const root = this._getRootDirectory(task); diff --git a/src/providers/sync.spec.ts b/src/providers/sync.spec.ts index f56e6968..2327c20a 100644 --- a/src/providers/sync.spec.ts +++ b/src/providers/sync.spec.ts @@ -3,12 +3,14 @@ import * as assert from 'node:assert'; import * as sinon from 'sinon'; import ReaderSync from '../readers/sync'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ProviderSync from './sync'; +import type { Options } from '../settings'; + class TestProvider extends ProviderSync { - protected _reader: ReaderSync = sinon.createStubInstance(ReaderSync) as unknown as ReaderSync; + protected override _reader: ReaderSync = sinon.createStubInstance(ReaderSync) as unknown as ReaderSync; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/providers/sync.ts b/src/providers/sync.ts index 452aa6e8..d3278c1c 100644 --- a/src/providers/sync.ts +++ b/src/providers/sync.ts @@ -1,11 +1,18 @@ import ReaderSync from '../readers/sync'; import Provider from './provider'; +import type Settings from '../settings'; import type { Task } from '../managers/tasks'; import type { Entry, EntryItem, ReaderOptions } from '../types'; export default class ProviderSync extends Provider { - protected _reader: ReaderSync = new ReaderSync(this._settings); + protected _reader: ReaderSync; + + constructor(settings: Settings) { + super(settings); + + this._reader = new ReaderSync(settings); + } public read(task: Task): EntryItem[] { const root = this._getRootDirectory(task); diff --git a/src/providers/transformers/entry.ts b/src/providers/transformers/entry.ts index 66c2c6bc..bb511d52 100644 --- a/src/providers/transformers/entry.ts +++ b/src/providers/transformers/entry.ts @@ -1,28 +1,32 @@ -import Settings from '../../settings'; import * as utils from '../../utils'; +import type Settings from '../../settings'; import type { Entry, EntryItem, EntryTransformerFunction } from '../../types'; export default class EntryTransformer { - constructor(private readonly _settings: Settings) {} + readonly #settings: Settings; + + constructor(settings: Settings) { + this.#settings = settings; + } public getTransformer(): EntryTransformerFunction { - return (entry) => this._transform(entry); + return (entry) => this.#transform(entry); } - private _transform(entry: Entry): EntryItem { + #transform(entry: Entry): EntryItem { let filepath = entry.path; - if (this._settings.absolute) { - filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); + if (this.#settings.absolute) { + filepath = utils.path.makeAbsolute(this.#settings.cwd, filepath); filepath = utils.path.unixify(filepath); } - if (this._settings.markDirectories && entry.dirent.isDirectory()) { + if (this.#settings.markDirectories && entry.dirent.isDirectory()) { filepath += '/'; } - if (!this._settings.objectMode) { + if (!this.#settings.objectMode) { return filepath; } diff --git a/src/readers/async.spec.ts b/src/readers/async.spec.ts index 5c6939c5..6d6dade3 100644 --- a/src/readers/async.spec.ts +++ b/src/readers/async.spec.ts @@ -3,19 +3,20 @@ import { PassThrough } from 'node:stream'; import * as sinon from 'sinon'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ReaderAsync from './async'; import ReaderStream from './stream'; +import type { Options } from '../settings'; import type { ReaderOptions } from '../types'; import type * as fsWalk from '@nodelib/fs.walk'; type WalkSignature = typeof fsWalk.walk; class TestReader extends ReaderAsync { - protected _walkAsync: WalkSignature = sinon.stub() as unknown as WalkSignature; - protected _readerStream: ReaderStream = sinon.createStubInstance(ReaderStream) as unknown as ReaderStream; + protected override _walkAsync: WalkSignature = sinon.stub() as unknown as WalkSignature; + protected override _readerStream: ReaderStream = sinon.createStubInstance(ReaderStream) as unknown as ReaderStream; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/readers/async.ts b/src/readers/async.ts index 7a3a7d69..09270cff 100644 --- a/src/readers/async.ts +++ b/src/readers/async.ts @@ -3,11 +3,18 @@ import * as fsWalk from '@nodelib/fs.walk'; import Reader from './reader'; import ReaderStream from './stream'; +import type Settings from '../settings'; import type { Entry, ReaderOptions, Pattern } from '../types'; export default class ReaderAsync extends Reader> { protected _walkAsync: typeof fsWalk.walk = fsWalk.walk; - protected _readerStream: ReaderStream = new ReaderStream(this._settings); + protected _readerStream: ReaderStream; + + constructor(settings: Settings) { + super(settings); + + this._readerStream = new ReaderStream(settings); + } public dynamic(root: string, options: ReaderOptions): Promise { return new Promise((resolve, reject) => { diff --git a/src/readers/reader.spec.ts b/src/readers/reader.spec.ts index 4f7297be..e0d44c61 100644 --- a/src/readers/reader.spec.ts +++ b/src/readers/reader.spec.ts @@ -3,9 +3,10 @@ import * as path from 'node:path'; import { Stats, StatsMode } from '@nodelib/fs.macchiato'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import Reader from './reader'; +import type { Options } from '../settings'; import type { Entry, FsStats, Pattern } from '../types'; class TestReader extends Reader { diff --git a/src/readers/reader.ts b/src/readers/reader.ts index 484958ab..c26b8bcd 100644 --- a/src/readers/reader.ts +++ b/src/readers/reader.ts @@ -2,25 +2,31 @@ import * as path from 'node:path'; import * as fsStat from '@nodelib/fs.stat'; -import Settings from '../settings'; import * as utils from '../utils'; +import type Settings from '../settings'; import type { Entry, ErrnoException, FsStats, Pattern, ReaderOptions } from '../types'; export default abstract class Reader { - protected readonly _fsStatSettings: fsStat.Settings = new fsStat.Settings({ - followSymbolicLink: this._settings.followSymbolicLinks, - fs: this._settings.fs, - throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks, - }); + protected readonly _fsStatSettings: fsStat.Settings; - constructor(protected readonly _settings: Settings) {} + readonly #settings: Settings; + + constructor(settings: Settings) { + this.#settings = settings; + + this._fsStatSettings = new fsStat.Settings({ + followSymbolicLink: settings.followSymbolicLinks, + fs: settings.fs, + throwErrorOnBrokenSymbolicLink: settings.followSymbolicLinks, + }); + } public abstract dynamic(root: string, options: ReaderOptions): T; public abstract static(patterns: Pattern[], options: ReaderOptions): T; protected _getFullEntryPath(filepath: string): string { - return path.resolve(this._settings.cwd, filepath); + return path.resolve(this.#settings.cwd, filepath); } protected _makeEntry(stats: FsStats, pattern: Pattern): Entry { @@ -30,7 +36,7 @@ export default abstract class Reader { dirent: utils.fs.createDirentFromStats(pattern, stats), }; - if (this._settings.stats) { + if (this.#settings.stats) { entry.stats = stats; } @@ -38,6 +44,6 @@ export default abstract class Reader { } protected _isFatalError(error: ErrnoException): boolean { - return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; + return !utils.errno.isEnoentCodeError(error) && !this.#settings.suppressErrors; } } diff --git a/src/readers/stream.spec.ts b/src/readers/stream.spec.ts index 8008e05c..6611228c 100644 --- a/src/readers/stream.spec.ts +++ b/src/readers/stream.spec.ts @@ -3,10 +3,11 @@ import * as assert from 'node:assert'; import { Stats } from '@nodelib/fs.macchiato'; import * as sinon from 'sinon'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ReaderStream from './stream'; +import type { Options } from '../settings'; import type { Entry, ErrnoException, ReaderOptions } from '../types'; import type * as fsWalk from '@nodelib/fs.walk'; import type * as fsStat from '@nodelib/fs.stat'; @@ -15,8 +16,8 @@ type WalkSignature = typeof fsWalk.walkStream; type StatSignature = typeof fsStat.stat; class TestReader extends ReaderStream { - protected _walkStream: WalkSignature = sinon.stub() as unknown as WalkSignature; - protected _stat: StatSignature = sinon.stub() as unknown as StatSignature; + protected override _walkStream: WalkSignature = sinon.stub() as unknown as WalkSignature; + protected override _stat: StatSignature = sinon.stub() as unknown as StatSignature; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/readers/stream.ts b/src/readers/stream.ts index 0992d2ac..4cd01a7b 100644 --- a/src/readers/stream.ts +++ b/src/readers/stream.ts @@ -22,7 +22,7 @@ export default class ReaderStream extends Reader { const stream = new PassThrough({ objectMode: true }); stream._write = (index: number, _enc, done) => { - this._getEntry(filepaths[index], patterns[index], options) + this.#getEntry(filepaths[index], patterns[index], options) .then((entry) => { if (entry !== null && options.entryFilter(entry)) { stream.push(entry); @@ -44,8 +44,8 @@ export default class ReaderStream extends Reader { return stream; } - private _getEntry(filepath: string, pattern: Pattern, options: ReaderOptions): Promise { - return this._getStat(filepath) + #getEntry(filepath: string, pattern: Pattern, options: ReaderOptions): Promise { + return this.#getStat(filepath) .then((stats) => this._makeEntry(stats, pattern)) .catch((error: ErrnoException) => { if (options.errorFilter(error)) { @@ -56,7 +56,7 @@ export default class ReaderStream extends Reader { }); } - private _getStat(filepath: string): Promise { + #getStat(filepath: string): Promise { return new Promise((resolve, reject) => { this._stat(filepath, this._fsStatSettings, (error: NodeJS.ErrnoException | null, stats) => { if (error === null) { diff --git a/src/readers/sync.spec.ts b/src/readers/sync.spec.ts index 509c3a84..0a051b12 100644 --- a/src/readers/sync.spec.ts +++ b/src/readers/sync.spec.ts @@ -3,10 +3,11 @@ import * as assert from 'node:assert'; import { Stats } from '@nodelib/fs.macchiato'; import * as sinon from 'sinon'; -import Settings, { Options } from '../settings'; +import Settings from '../settings'; import * as tests from '../tests'; import ReaderSync from './sync'; +import type { Options } from '../settings'; import type { ReaderOptions } from '../types'; import type * as fsWalk from '@nodelib/fs.walk'; import type * as fsStat from '@nodelib/fs.stat'; @@ -15,8 +16,8 @@ type WalkSignature = typeof fsWalk.walkSync; type StatSignature = typeof fsStat.statSync; class TestReader extends ReaderSync { - protected _walkSync: WalkSignature = sinon.stub() as unknown as WalkSignature; - protected _statSync: StatSignature = sinon.stub() as unknown as StatSignature; + protected override _walkSync: WalkSignature = sinon.stub() as unknown as WalkSignature; + protected override _statSync: StatSignature = sinon.stub() as unknown as StatSignature; constructor(options?: Options) { super(new Settings(options)); diff --git a/src/readers/sync.ts b/src/readers/sync.ts index afffafbf..177523a0 100644 --- a/src/readers/sync.ts +++ b/src/readers/sync.ts @@ -18,7 +18,7 @@ export default class ReaderSync extends Reader { for (const pattern of patterns) { const filepath = this._getFullEntryPath(pattern); - const entry = this._getEntry(filepath, pattern, options); + const entry = this.#getEntry(filepath, pattern, options); if (entry === null || !options.entryFilter(entry)) { continue; @@ -30,9 +30,9 @@ export default class ReaderSync extends Reader { return entries; } - private _getEntry(filepath: string, pattern: Pattern, options: ReaderOptions): Entry | null { + #getEntry(filepath: string, pattern: Pattern, options: ReaderOptions): Entry | null { try { - const stats = this._getStat(filepath); + const stats = this.#getStat(filepath); return this._makeEntry(stats, pattern); } catch (error) { @@ -44,7 +44,7 @@ export default class ReaderSync extends Reader { } } - private _getStat(filepath: string): FsStats { + #getStat(filepath: string): FsStats { return this._statSync(filepath, this._fsStatSettings); } } diff --git a/src/settings.ts b/src/settings.ts index 03263df6..fc378784 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -155,29 +155,52 @@ export interface Options { } export default class Settings { - public readonly absolute: boolean = this._getValue(this._options.absolute, false); - public readonly baseNameMatch: boolean = this._getValue(this._options.baseNameMatch, false); - public readonly braceExpansion: boolean = this._getValue(this._options.braceExpansion, true); - public readonly caseSensitiveMatch: boolean = this._getValue(this._options.caseSensitiveMatch, true); - public readonly concurrency: number = this._getValue(this._options.concurrency, CPU_COUNT); - public readonly cwd: string = this._getValue(this._options.cwd, process.cwd()); - public readonly deep: number = this._getValue(this._options.deep, Number.POSITIVE_INFINITY); - public readonly dot: boolean = this._getValue(this._options.dot, false); - public readonly extglob: boolean = this._getValue(this._options.extglob, true); - public readonly followSymbolicLinks: boolean = this._getValue(this._options.followSymbolicLinks, true); - public readonly fs: FileSystemAdapter = this._getFileSystemMethods(this._options.fs); - public readonly globstar: boolean = this._getValue(this._options.globstar, true); - public readonly ignore: Pattern[] = this._getValue(this._options.ignore, [] as Pattern[]); - public readonly markDirectories: boolean = this._getValue(this._options.markDirectories, false); - public readonly objectMode: boolean = this._getValue(this._options.objectMode, false); - public readonly onlyDirectories: boolean = this._getValue(this._options.onlyDirectories, false); - public readonly onlyFiles: boolean = this._getValue(this._options.onlyFiles, true); - public readonly stats: boolean = this._getValue(this._options.stats, false); - public readonly suppressErrors: boolean = this._getValue(this._options.suppressErrors, false); - public readonly throwErrorOnBrokenSymbolicLink: boolean = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); - public readonly unique: boolean = this._getValue(this._options.unique, true); + public readonly absolute: boolean; + public readonly baseNameMatch: boolean; + public readonly braceExpansion: boolean; + public readonly caseSensitiveMatch: boolean; + public readonly concurrency: number; + public readonly cwd: string; + public readonly deep: number; + public readonly dot: boolean; + public readonly extglob: boolean; + public readonly followSymbolicLinks: boolean; + public readonly fs: FileSystemAdapter; + public readonly globstar: boolean; + public readonly ignore: Pattern[]; + public readonly markDirectories: boolean; + public readonly objectMode: boolean; + public readonly onlyDirectories: boolean; + public readonly onlyFiles: boolean; + public readonly stats: boolean; + public readonly suppressErrors: boolean; + public readonly throwErrorOnBrokenSymbolicLink: boolean; + public readonly unique: boolean; + + // eslint-disable-next-line complexity + constructor(options: Options = {}) { + this.absolute = options.absolute ?? false; + this.baseNameMatch = options.baseNameMatch ?? false; + this.braceExpansion = options.braceExpansion ?? true; + this.caseSensitiveMatch = options.caseSensitiveMatch ?? true; + this.concurrency = options.concurrency ?? CPU_COUNT; + this.cwd = options.cwd ?? process.cwd(); + this.deep = options.deep ?? Number.POSITIVE_INFINITY; + this.dot = options.dot ?? false; + this.extglob = options.extglob ?? true; + this.followSymbolicLinks = options.followSymbolicLinks ?? true; + this.fs = this.#getFileSystemMethods(options.fs); + this.globstar = options.globstar ?? true; + this.ignore = options.ignore ?? []; + this.markDirectories = options.markDirectories ?? false; + this.objectMode = options.objectMode ?? false; + this.onlyDirectories = options.onlyDirectories ?? false; + this.onlyFiles = options.onlyFiles ?? true; + this.stats = options.stats ?? false; + this.suppressErrors = options.suppressErrors ?? false; + this.throwErrorOnBrokenSymbolicLink = options.throwErrorOnBrokenSymbolicLink ?? false; + this.unique = options.unique ?? true; - constructor(private readonly _options: Options = {}) { if (this.onlyDirectories) { this.onlyFiles = false; } @@ -190,11 +213,7 @@ export default class Settings { this.ignore = ([] as Pattern[]).concat(this.ignore); } - private _getValue(option: T | undefined, value: T): T { - return option ?? value; - } - - private _getFileSystemMethods(methods: Partial = {}): FileSystemAdapter { + #getFileSystemMethods(methods: Partial = {}): FileSystemAdapter { return { ...DEFAULT_FILE_SYSTEM_ADAPTER, ...methods, diff --git a/src/tests/utils/entry.ts b/src/tests/utils/entry.ts index 660bb24b..095fdbeb 100644 --- a/src/tests/utils/entry.ts +++ b/src/tests/utils/entry.ts @@ -5,49 +5,49 @@ import { Dirent, DirentType, Stats } from '@nodelib/fs.macchiato'; import type { Entry } from '../../types'; class EntryBuilder { - private _entryType: DirentType = DirentType.Unknown; + #entryType: DirentType = DirentType.Unknown; - private readonly _entry: Entry = { + readonly #entry: Entry = { name: '', path: '', dirent: new Dirent(), }; public path(filepath: string): this { - this._entry.name = path.basename(filepath); - this._entry.path = filepath; + this.#entry.name = path.basename(filepath); + this.#entry.path = filepath; return this; } public file(): this { - this._entryType = DirentType.File; + this.#entryType = DirentType.File; return this; } public directory(): this { - this._entryType = DirentType.Directory; + this.#entryType = DirentType.Directory; return this; } public symlink(): this { - this._entryType = DirentType.Link; + this.#entryType = DirentType.Link; return this; } public stats(): this { - this._entry.stats = new Stats(); + this.#entry.stats = new Stats(); return this; } public build(): Entry { - this._entry.dirent = new Dirent(this._entry.name, this._entryType); + this.#entry.dirent = new Dirent(this.#entry.name, this.#entryType); - return this._entry; + return this.#entry; } } diff --git a/src/tests/utils/pattern.ts b/src/tests/utils/pattern.ts index fad3679e..5076d34b 100644 --- a/src/tests/utils/pattern.ts +++ b/src/tests/utils/pattern.ts @@ -4,37 +4,37 @@ import type { Pattern, MicromatchOptions } from '../../types'; import type { PatternSegment, PatternInfo } from '../../providers/matchers/matcher'; class PatternSegmentBuilder { - private readonly _segment: PatternSegment = { + readonly #segment: PatternSegment = { dynamic: false, pattern: '', }; public dynamic(): this { - this._segment.dynamic = true; + this.#segment.dynamic = true; return this; } public pattern(pattern: Pattern): this { - this._segment.pattern = pattern; + this.#segment.pattern = pattern; return this; } public build(options: MicromatchOptions = {}): PatternSegment { - if (!this._segment.dynamic) { - return this._segment; + if (!this.#segment.dynamic) { + return this.#segment; } return { - ...this._segment, - patternRe: utils.pattern.makeRe(this._segment.pattern, options), + ...this.#segment, + patternRe: utils.pattern.makeRe(this.#segment.pattern, options), }; } } class PatternInfoBuilder { - private readonly _section: PatternInfo = { + readonly #section: PatternInfo = { complete: true, pattern: '', segments: [], @@ -42,16 +42,16 @@ class PatternInfoBuilder { }; public section(...segments: PatternSegment[]): this { - this._section.sections.push(segments); + this.#section.sections.push(segments); - if (this._section.segments.length === 0) { - this._section.complete = true; - this._section.segments.push(...segments); + if (this.#section.segments.length === 0) { + this.#section.complete = true; + this.#section.segments.push(...segments); } else { - this._section.complete = false; + this.#section.complete = false; const globstar = segment().dynamic().pattern('**').build(); - this._section.segments.push(globstar, ...segments); + this.#section.segments.push(globstar, ...segments); } return this; @@ -59,13 +59,13 @@ class PatternInfoBuilder { public build(): PatternInfo { return { - ...this._section, - pattern: this._buildPattern(), + ...this.#section, + pattern: this.#buildPattern(), }; } - private _buildPattern(): Pattern { - return this._section.segments.map((segment) => segment.pattern).join('/'); + #buildPattern(): Pattern { + return this.#section.segments.map((segment) => segment.pattern).join('/'); } } diff --git a/src/tests/utils/task.ts b/src/tests/utils/task.ts index 0e419e1f..611599a5 100644 --- a/src/tests/utils/task.ts +++ b/src/tests/utils/task.ts @@ -2,7 +2,7 @@ import type { Task } from '../../managers/tasks'; import type { Pattern } from '../../types'; class TaskBuilder { - private readonly _task: Task = { + readonly #task: Task = { base: '', dynamic: true, patterns: [], @@ -11,33 +11,33 @@ class TaskBuilder { }; public base(base: string): this { - this._task.base = base; + this.#task.base = base; return this; } public static(): this { - this._task.dynamic = false; + this.#task.dynamic = false; return this; } public positive(pattern: Pattern): this { - this._task.patterns.push(pattern); - this._task.positive.push(pattern); + this.#task.patterns.push(pattern); + this.#task.positive.push(pattern); return this; } public negative(pattern: Pattern): this { - this._task.patterns.push(`!${pattern}`); - this._task.negative.push(pattern); + this.#task.patterns.push(`!${pattern}`); + this.#task.negative.push(pattern); return this; } public build(): Task { - return this._task; + return this.#task; } } diff --git a/src/utils/fs.ts b/src/utils/fs.ts index 8b034dd4..f3c1758b 100644 --- a/src/utils/fs.ts +++ b/src/utils/fs.ts @@ -1,8 +1,6 @@ import * as fs from 'node:fs'; -import { FsStats } from '../types'; - -import type { FsDirent } from '../types'; +import type { FsStats, FsDirent } from '../types'; const _kStats = Symbol('stats'); diff --git a/tsconfig.json b/tsconfig.json index 888e0aa1..05361181 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,36 +1,30 @@ { "compilerOptions": { - "target": "es2017", - "lib": ["es2017", "ES2021.String"], + "target": "ES2022", + "lib": ["ES2022"], "module": "commonjs", "moduleResolution": "node", + "resolveJsonModule": true, "rootDir": "src", "outDir": "out", "strict": true, - "alwaysStrict": true, - "strictFunctionTypes": true, - "strictNullChecks": true, - "strictPropertyInitialization": true, - - "forceConsistentCasingInFileNames": true, - "noImplicitAny": true, + "noImplicitOverride": true, "noImplicitReturns": true, - "noImplicitThis": true, - "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, + "noPropertyAccessFromIndexSignature": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "noFallthroughCasesInSwitch": true, + + "forceConsistentCasingInFileNames": true, + "verbatimModuleSyntax": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, "downlevelIteration": true, "declaration": true, - - "pretty": true - }, - "include": [ - "typings", - "src/**/*" - ] + "newLine": "lf", + "stripInternal": true + } }