From cb952492b2e7421bc0e99489c7b48e728e6a3b9f Mon Sep 17 00:00:00 2001 From: Romain Lanz Date: Tue, 1 Sep 2026 20:18:26 +0000 Subject: [PATCH] perf: speed up index generation sorting --- src/virtual_file_system.ts | 4 ++-- tests/virtual_file_system.spec.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/virtual_file_system.ts b/src/virtual_file_system.ts index 9c351756..558eedf0 100644 --- a/src/virtual_file_system.ts +++ b/src/virtual_file_system.ts @@ -13,7 +13,6 @@ import { relative } from 'node:path/posix' import lodash from '@poppinss/utils/lodash' import string from '@poppinss/utils/string' import { readFile } from 'node:fs/promises' -import { naturalSort } from '@poppinss/utils' import { Lang, parse, type SgNode } from '@ast-grep/napi' import picomatch, { type PicomatchOptions, type Matcher } from 'picomatch' @@ -23,6 +22,7 @@ import { type RecursiveFileTree, type VirtualFileSystemOptions } from './types/c const BYPASS_FN = (input: T) => input const DEFAULT_GLOB = ['**/!(*.d).ts', '**/*.tsx', '**/*.js'] +const NATURAL_SORT = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare /** * Virtual file system for managing and tracking files with AST parsing capabilities. @@ -105,7 +105,7 @@ export class VirtualFileSystem { const filesList = await crawler.crawl(this.#source).withPromise() debug('scanned files %O', filesList) - const sortedFiles = filesList.sort(naturalSort) + const sortedFiles = filesList.sort(NATURAL_SORT) this.#files.clear() for (let filePath of sortedFiles) { diff --git a/tests/virtual_file_system.spec.ts b/tests/virtual_file_system.spec.ts index a75d27a7..411bfdac 100644 --- a/tests/virtual_file_system.spec.ts +++ b/tests/virtual_file_system.spec.ts @@ -44,6 +44,36 @@ test.group('Virtual file system', () => { ) }) + test('naturally sort file paths', async ({ fs, assert }) => { + await fs.create('controllers/item_10.ts', '') + await fs.create('controllers/item_2.ts', '') + await fs.create('controllers/item_01.ts', '') + await fs.create('controllers/item_1.ts', '') + await fs.create('controllers/café.ts', '') + await fs.create('controllers/cafe.ts', '') + await fs.create('controllers/alpha.ts', '') + await fs.create('controllers/Alpha.ts', '') + await fs.create('controllers/nested_10/item_2.ts', '') + await fs.create('controllers/nested_2/item_10.ts', '') + + const source = string.toUnixSlash(join(fs.basePath, 'controllers')) + const vfs = new VirtualFileSystem(source) + await vfs.scan() + + assert.deepEqual(Object.keys(vfs.asList()), [ + 'Alpha', + 'alpha', + 'cafe', + 'café', + 'item_01', + 'item_1', + 'item_2', + 'item_10', + 'nested_2/item_10', + 'nested_10/item_2', + ]) + }) + test('list files as a tree', async ({ fs, assert }) => { await setupFakeAdonisproject(fs) await createControllers()