Skip to content

Commit

Permalink
Merge pull request #413 from mrmlnc/use_native_fs_dirent
Browse files Browse the repository at this point in the history
Use native fs.Dirent
  • Loading branch information
mrmlnc committed Aug 3, 2023
2 parents 79b039a + 824170b commit 212f02e
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 33 deletions.
5 changes: 2 additions & 3 deletions src/readers/reader.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as assert from 'assert';
import * as fs from 'fs';
import * as path from 'path';

import { Stats, StatsMode } from '@nodelib/fs.macchiato';

import Settings, { Options } from '../settings';
import { Entry, Pattern } from '../types';
import { Entry, FsStats, Pattern } from '../types';
import Reader from './reader';

class TestReader extends Reader<never[]> {
Expand All @@ -25,7 +24,7 @@ class TestReader extends Reader<never[]> {
return this._getFullEntryPath(filepath);
}

public makeEntry(stats: fs.Stats, pattern: Pattern): Entry {
public makeEntry(stats: FsStats, pattern: Pattern): Entry {
return this._makeEntry(stats, pattern);
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/readers/reader.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as fs from 'fs';
import * as path from 'path';

import * as fsStat from '@nodelib/fs.stat';

import Settings from '../settings';
import { Entry, ErrnoException, Pattern, ReaderOptions } from '../types';
import { Entry, ErrnoException, FsStats, Pattern, ReaderOptions } from '../types';
import * as utils from '../utils';

export default abstract class Reader<T> {
Expand All @@ -23,7 +22,7 @@ export default abstract class Reader<T> {
return path.resolve(this._settings.cwd, filepath);
}

protected _makeEntry(stats: fs.Stats, pattern: Pattern): Entry {
protected _makeEntry(stats: FsStats, pattern: Pattern): Entry {
const entry: Entry = {
name: pattern,
path: pattern,
Expand Down
5 changes: 2 additions & 3 deletions src/readers/stream.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as fs from 'fs';
import { PassThrough, Readable } from 'stream';

import * as fsStat from '@nodelib/fs.stat';
import * as fsWalk from '@nodelib/fs.walk';

import { Entry, ErrnoException, Pattern, ReaderOptions } from '../types';
import { Entry, ErrnoException, FsStats, Pattern, ReaderOptions } from '../types';
import Reader from './reader';

export default class ReaderStream extends Reader<Readable> {
Expand Down Expand Up @@ -55,7 +54,7 @@ export default class ReaderStream extends Reader<Readable> {
});
}

private _getStat(filepath: string): Promise<fs.Stats> {
private _getStat(filepath: string): Promise<FsStats> {
return new Promise((resolve, reject) => {
this._stat(filepath, this._fsStatSettings, (error: NodeJS.ErrnoException | null, stats) => {
return error === null ? resolve(stats) : reject(error);
Expand Down
6 changes: 2 additions & 4 deletions src/readers/sync.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import * as fs from 'fs';

import * as fsStat from '@nodelib/fs.stat';
import * as fsWalk from '@nodelib/fs.walk';

import { Entry, ErrnoException, Pattern, ReaderOptions } from '../types';
import { Entry, ErrnoException, FsStats, Pattern, ReaderOptions } from '../types';
import Reader from './reader';

export default class ReaderSync extends Reader<Entry[]> {
Expand Down Expand Up @@ -45,7 +43,7 @@ export default class ReaderSync extends Reader<Entry[]> {
}
}

private _getStat(filepath: string): fs.Stats {
private _getStat(filepath: string): FsStats {
return this._statSync(filepath, this._fsStatSettings);
}
}
3 changes: 3 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import * as fs from 'fs';
import * as fsWalk from '@nodelib/fs.walk';

export type ErrnoException = NodeJS.ErrnoException;

export type FsDirent = fs.Dirent;
export type FsStats = fs.Stats;
export type Entry = fsWalk.Entry;
export type EntryItem = string | Entry;

Expand Down
50 changes: 30 additions & 20 deletions src/utils/fs.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
import * as fs from 'fs';

import { Dirent } from '@nodelib/fs.walk';

class DirentFromStats implements fs.Dirent {
public isBlockDevice: fs.Stats['isBlockDevice'];
public isCharacterDevice: fs.Stats['isCharacterDevice'];
public isDirectory: fs.Stats['isDirectory'];
public isFIFO: fs.Stats['isFIFO'];
public isFile: fs.Stats['isFile'];
public isSocket: fs.Stats['isSocket'];
public isSymbolicLink: fs.Stats['isSymbolicLink'];

constructor(public name: string, stats: fs.Stats) {
this.isBlockDevice = stats.isBlockDevice.bind(stats);
this.isCharacterDevice = stats.isCharacterDevice.bind(stats);
this.isDirectory = stats.isDirectory.bind(stats);
this.isFIFO = stats.isFIFO.bind(stats);
this.isFile = stats.isFile.bind(stats);
this.isSocket = stats.isSocket.bind(stats);
this.isSymbolicLink = stats.isSymbolicLink.bind(stats);
import type { FsDirent, FsStats } from '../types';

const _kStats = Symbol('stats');

type DirentStatsKeysIntersection = 'constructor' | keyof FsDirent & keyof FsStats;

// Adapting an internal class in Node.js to mimic the behavior of `fs.Dirent` when creating it manually from `fs.Stats`.
// https://github.com/nodejs/node/blob/a4cf6b204f0b160480153dc293ae748bf15225f9/lib/internal/fs/utils.js#L199C1-L213
export class DirentFromStats extends fs.Dirent {
private readonly [_kStats]: FsStats;

constructor(name: string, stats: FsStats) {
// @ts-expect-error The constructor has parameters, but they are not represented in types.
// https://github.com/nodejs/node/blob/a4cf6b204f0b160480153dc293ae748bf15225f9/lib/internal/fs/utils.js#L164
super(name, null);

this[_kStats] = stats;
}
}

export function createDirentFromStats(name: string, stats: fs.Stats): Dirent {
for (const key of Reflect.ownKeys(fs.Dirent.prototype)) {
const name = key as DirentStatsKeysIntersection | 'constructor';

if (name === 'constructor') {
continue;
}

DirentFromStats.prototype[name] = function () {
return this[_kStats][name]();
};
}

export function createDirentFromStats(name: string, stats: FsStats): FsDirent {
return new DirentFromStats(name, stats);
}

0 comments on commit 212f02e

Please sign in to comment.