From e246fef883559fabfd1629ad903613588ba7470a Mon Sep 17 00:00:00 2001 From: dualfroz Date: Thu, 3 Sep 2026 14:37:27 +0200 Subject: [PATCH] fix: use the basename as the entry name for static patterns The static reader built the entry from the pattern as is, so `name` and `dirent.name` were the whole pattern, while the dynamic reader returns the basename. The same `objectMode: true` option therefore produced a different entry shape depending on whether the pattern was static: globSync('fixtures/file.md', { objectMode: true }) // name: 'fixtures/file.md', path: 'fixtures/file.md' globSync('fixtures/*.md', { objectMode: true }) // name: 'file.md', path: 'fixtures/file.md' Note that `path` already agreed between the two readers, only `name` diverged. Use the basename for the entry name and for the dirent built from the stats, which matches both the dynamic reader and the entry builder the tests already use. Fixes #487 --- src/index.spec.ts | 14 ++++++++++++++ src/readers/reader.spec.ts | 24 ++++++++++++++++++++++++ src/readers/reader.ts | 9 +++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/index.spec.ts b/src/index.spec.ts index 917e292..0882843 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -36,6 +36,20 @@ describe('Package', () => { assert.deepStrictEqual(actual, expected); }); + it('should returns entries with the same name for static and dynamic patterns in the object mode', () => { + const [staticEntry] = fg.globSync('fixtures/file.md', { objectMode: true }); + const [dynamicEntry] = fg.globSync('fixtures/*.md', { objectMode: true }); + + assert.strictEqual(staticEntry.name, 'file.md'); + assert.strictEqual(staticEntry.dirent.name, 'file.md'); + assert.strictEqual(staticEntry.path, 'fixtures/file.md'); + + assert.deepStrictEqual( + [staticEntry.name, staticEntry.path, staticEntry.dirent.name], + [dynamicEntry.name, dynamicEntry.path, dynamicEntry.dirent.name], + ); + }); + it('should returns entries (two sources)', () => { const expected: EntryItem[] = [ 'fixtures/first/file.md', diff --git a/src/readers/reader.spec.ts b/src/readers/reader.spec.ts index e0494a8..a29fb95 100644 --- a/src/readers/reader.spec.ts +++ b/src/readers/reader.spec.ts @@ -77,6 +77,30 @@ describe('Readers → Reader', () => { assert.ok(actual.dirent.isFile()); }); + it('should return created entry with the basename as name when the pattern has a directory', () => { + const reader = getReader(); + const pattern = 'directory/config.json'; + const stats = new Stats({ mode: StatsMode.File }); + + const actual = reader.makeEntry(stats, pattern); + + assert.strictEqual(actual.name, 'config.json'); + assert.strictEqual(actual.path, pattern); + assert.strictEqual(actual.dirent.name, 'config.json'); + }); + + it('should return created entry with the basename as name when the pattern has a leading dot segment', () => { + const reader = getReader(); + const pattern = './config.json'; + const stats = new Stats({ mode: StatsMode.File }); + + const actual = reader.makeEntry(stats, pattern); + + assert.strictEqual(actual.name, 'config.json'); + assert.strictEqual(actual.path, pattern); + assert.strictEqual(actual.dirent.name, 'config.json'); + }); + it('should return created entry with fs.Stats', () => { const reader = getReader({ stats: true }); const pattern = 'config.json'; diff --git a/src/readers/reader.ts b/src/readers/reader.ts index 427ca72..bdf3258 100644 --- a/src/readers/reader.ts +++ b/src/readers/reader.ts @@ -33,10 +33,15 @@ export abstract class Reader { } protected _makeEntry(stats: FsStats, pattern: Pattern): Entry { + // A static pattern is the path to the entry, so it is used as the entry path as is. + // The name, however, is the basename of that path, the same as for the entries that + // the dynamic reader produces, so that both readers return the same shape. + const name = path.basename(pattern); + const entry: Entry = { - name: pattern, + name, path: pattern, - dirent: utils.fs.createDirentFromStats(pattern, stats), + dirent: utils.fs.createDirentFromStats(name, stats), }; if (this.#settings.stats) {