Skip to content

feat: add sort support#189

Open
userquin wants to merge 6 commits intoSuperchupuDev:mainfrom
userquin:feat-add-sort-support
Open

feat: add sort support#189
userquin wants to merge 6 commits intoSuperchupuDev:mainfrom
userquin:feat-add-sort-support

Conversation

@userquin
Copy link

@userquin userquin commented Jan 27, 2026

Description

This PR adds built-in sorting support to glob and globSync to ensure predictable results. This is crucial for tools like unplugin-vue-components (and maybe at unimport, and unplugin-auto-import), where declaration overwrites and .d.ts generation need to be deterministic.

It introduces a new sort option with the following modes:

  • 'asc': Sorts results in ascending order (alphabetical).
  • 'desc': Sorts results in descending order.
  • 'pattern': Sorts results based on the order of the provided patterns (precedence).
  • 'pattern-asc': Sorts by pattern precedence, then ascending within matches of the same pattern.
  • 'pattern-desc': Sorts by pattern precedence, then descending within matches of the same pattern.
  • Function: A custom comparison function (a: string, b: string) => number.

Changes

  • Refactor: extracted getOptions from index.ts to a new options.ts module (reusing it at crawler.ts and sort.ts)
  • Refactor: extracted patterns logic at crawler.ts to buildCrawlerInfo function (reusing it at index.ts and sort.ts)
  • Feat: Added sort option to GlobOptions.
  • Feat: Added compileMatchers, sortFiles and sortFilesByPatternPrecedence exported utilities.
  • Refactor: Renamed compileGlobs to compileMatchers and moved logic to src/sort.ts from original PR feat: add new compileGlobs helper function #168.

resolves #166
supersedes #168

@userquin
Copy link
Author

We also need to add a custom sort, working on it...

@userquin
Copy link
Author

@SuperchupuDev added custom sort, PR should be ready for review

@userquin
Copy link
Author

userquin commented Jan 27, 2026

We cannot use overload signature with generators, we just use modern patterns (about update this on my review), I also need to change the signature:

TS1222: An overload signature cannot be declared as a generator.
Biome: An overload signature cannot be declared as a generator.

@userquin
Copy link
Author

I'm going to check if we can avoid regenerating the options when using sort from options, just returning the info from the buildCrawler

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 27, 2026

Open in StackBlitz

npm i https://pkg.pr.new/tinyglobby@189

commit: 46902a8

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 27, 2026

Open in StackBlitz

npm i https://pkg.pr.new/tinyglobby@189

commit: bbb93ee

Comment on lines +141 to +156
test('sort files by precedence with no options', () => {
// we need to change the cwd to the fixture path to make sure the patterns match
// since we are not passing options to sortFilesByPatternPrecedence
const originalCwd = process.cwd();
try {
process.chdir(cwd);
const files = ['common/Button.js', 'common/Card.js', 'overrides/Button.js'];
// sort without options
assert.deepEqual(
[...sortFilesByPatternPrecedence(files, patterns)],
['overrides/Button.js', 'common/Button.js', 'common/Card.js']
);
} finally {
process.chdir(originalCwd);
}
});
Copy link
Author

@userquin userquin Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc node:test doesn't support before/after inside describe/test, and so this test should be as it is since node runs the test in the same process and we're not using workers.

Since tests in node:test (and in general in JS) run sequentially within the same file (unless there is explicit concurrency, which here does not appear to have been set up at the individual test level), this is safe.

Copy link
Author

@userquin userquin Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there were concurrency, changing the global cwd would be dangerous. But for this use case and with the current structure, the try...finally block is a correct and localized way to handle the context switch needed to test the function without options.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can just use relative path using import.meta.url and relativizing the path from the fixture

@userquin
Copy link
Author

userquin commented Jan 28, 2026

I need to do some more tests, looks like there is some edge case we need to cover, we need to sort also globs when filtering by pattern-asc or pattern-desc.

For example, using pattern-desc using src/components and src/layer-components at unplugin-vue-components/examples/vite-vue3 (changing the dirs options from dirs: ['src/components', 'src/layer-components'] to [dirs: ['src/layer-components', 'src/components'] works, maybe not a problem here).

Anyway, we should fix this here or change sort function to be a factory, or just sort the dirs at unplugin-vue-components when sort is pattern-asc/pattern-desc.

wrong files sort
unplugin-vue-components:glob started with: [<project-root>/examples/vite-vue3/src/components/**/*.{vue,md,svg}, <project-root>/examples/vite-vue3/src/layer-components/**/*.{vue,md,svg}] +0ms
[
  '<project-root>/examples/vite-vue3/src/components/**/*.{vue,md,svg}',
  '<project-root>/examples/vite-vue3/src/layer-components/**/*.{vue,md,svg}'
]
[
  '<project-root>/examples/vite-vue3/src/components/ui/nested/checkbox.vue',
  '<project-root>/examples/vite-vue3/src/components/ui/button.vue',
  '<project-root>/examples/vite-vue3/src/components/sort/Component.vue',
  '<project-root>/examples/vite-vue3/src/components/sort-a/ComponentCollision.vue',
  '<project-root>/examples/vite-vue3/src/components/Recursive.vue',
  '<project-root>/examples/vite-vue3/src/components/MarkdownB.md',
  '<project-root>/examples/vite-vue3/src/components/MarkdownA.md',
  '<project-root>/examples/vite-vue3/src/components/kebab-case/KebabCaseFile.vue',
  '<project-root>/examples/vite-vue3/src/components/kebab-case/kebab-case-collapse/KebabCaseCollapseFile.vue',
  '<project-root>/examples/vite-vue3/src/components/global/avatar.vue',
  '<project-root>/examples/vite-vue3/src/components/ComponentD.vue',
  '<project-root>/examples/vite-vue3/src/components/ComponentB.vue',
  '<project-root>/examples/vite-vue3/src/components/ComponentAsync.vue',
  '<project-root>/examples/vite-vue3/src/components/ComponentA.vue',
  '<project-root>/examples/vite-vue3/src/components/component-c.vue',
  '<project-root>/examples/vite-vue3/src/components/collapse/collapseFolder/FolderAndComponentPartially.vue',
  '<project-root>/examples/vite-vue3/src/components/collapse/collapseFolder/CollapseFolderAndComponentFromRoot.vue',
  '<project-root>/examples/vite-vue3/src/components/book/index.vue',
  '<project-root>/examples/vite-vue3/src/layer-components/sort-b/ComponentCollision.vue'
]
image

@userquin
Copy link
Author

I guess it should be added in the target project, so this PR should be fine.

@userquin
Copy link
Author

userquin commented Jan 28, 2026

One last optimization: if sort is pattern, pattern-asc or pattern-desc using a single pattern, then, we can just yield the files, yield the files using sort acending or yield the files using sort descending respetivelly (will require to provide patterns in the CrawlerInfo)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

patterns being sorted

1 participant