From 31761fd58baa226551e1b1ecf4c4f2d0b25210f1 Mon Sep 17 00:00:00 2001 From: Miguelangel Cabrera Date: Wed, 18 Mar 2026 16:38:17 -0300 Subject: [PATCH 1/6] feat: add find as an alias for filter Export find from core and main index with identical signature and behavior. Rename the lazy-iterator find to lazyFind in the main index to avoid conflict. Update docs (README, API reference, quick-start, changelog) to document the new alias. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 15 +++++++++++++-- __test__/filter.test.ts | 24 +++++++++++++++++++++++- __test__/test-d/filter.test-d.ts | 8 +++++++- docs/api/reference.md | 26 ++++++++++++++++++++++++++ docs/guide/quick-start.md | 11 +++++++++-- docs/project/changelog.md | 9 +++++++++ src/core/filter/filter.ts | 2 ++ src/core/filter/index.ts | 2 +- src/core/index.ts | 2 +- src/index.ts | 3 ++- 10 files changed, 93 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b7ac547..2ce92de 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,8 @@ - [Browser Support](#browser-support) - [Migration from v3.x](#migration-from-v3x) - [Changelog](#changelog) - - [v5.8.2 (Current)](#v582-current) + - [v5.9.0 (Current)](#v590-current) + - [v5.8.2](#v582) - [v5.8.0](#v580) - [v5.7.0](#v570) - [v5.6.0](#v560) @@ -166,6 +167,12 @@ const startsWithAl = filter(users, 'Al%'); // โ†’ [{ name: 'Alice', ... }] ``` +> **`find` is an alias for `filter`** โ€” use whichever name feels more natural: +> ```typescript +> import { find } from '@mcabreradev/filter'; +> const result = find(users, { active: true }); // identical to filter() +> ``` + **๐ŸŽฎ [Try it in the Playground โ†’](https://mcabreradev-filter.vercel.app/playground/)** --- @@ -728,7 +735,11 @@ filter(data, expression, { enableCache: true, limit: 50 }); ## Changelog -### v5.8.2 (Current) +### v5.9.0 (Current) + +- โœจ **New**: `find` โ€” an alias for `filter` with identical signature and behavior. Use whichever name reads better in your codebase: `import { find } from '@mcabreradev/filter'` + +### v5.8.2 - ๐Ÿ› **Bug Fix**: Wildcard regex now correctly escapes all special characters (`.`, `+`, `*`, `?`, `(`, `[`, `^`, etc.) โ€” patterns like `%.txt` or `a.b%` no longer silently break - ๐Ÿ› **Bug Fix**: `$timeOfDay` with `start > end` (e.g. `{ start: 22, end: 5 }`) now correctly fails validation instead of silently never matching diff --git a/__test__/filter.test.ts b/__test__/filter.test.ts index f7b3293..60fd24e 100644 --- a/__test__/filter.test.ts +++ b/__test__/filter.test.ts @@ -1,4 +1,4 @@ -import filter from '../src/index'; +import filter, { find } from '../src/index'; import data from './data.json'; @@ -300,3 +300,25 @@ describe('Array values with OR logic (syntactic sugar for $in)', () => { expect(result.map((u) => u.city).sort()).toEqual(['Berlin', 'Berlin', 'London']); }); }); + +describe('find alias', () => { + it('returns same results as filter', () => { + expect(find(data, 'Berlin')).toEqual(filter(data, 'Berlin')); + }); + + it('works with object expression', () => { + const city = 'Berlin'; + expect(find(data, { city })).toEqual(filter(data, { city })); + }); + + it('works with predicate function', () => { + const pred = (item: (typeof data)[0]) => item.city === 'Berlin'; + expect(find(data, pred)).toEqual(filter(data, pred)); + }); + + it('works with options', () => { + expect(find(data, 'berlin', { caseSensitive: false })).toEqual( + filter(data, 'berlin', { caseSensitive: false }), + ); + }); +}); diff --git a/__test__/test-d/filter.test-d.ts b/__test__/test-d/filter.test-d.ts index 81d1ce9..912f35c 100644 --- a/__test__/test-d/filter.test-d.ts +++ b/__test__/test-d/filter.test-d.ts @@ -1,5 +1,5 @@ import { expectType, expectError } from 'tsd'; -import { filter } from '../../src/core/filter'; +import { filter, find } from '../../src/core/filter'; import type { FilterOptions } from '../../src/types'; interface User { @@ -114,3 +114,9 @@ const mixedArray: (string | number)[] = ['a', 1, 'b', 2]; expectType<(string | number)[]>(filter(mixedArray, 'a')); expectType<(string | number)[]>(filter(mixedArray, (item) => typeof item === 'string')); + +expectType(find(users, 'John')); +expectType(find(users, { name: 'John' })); +expectType(find(users, (user) => user.age > 18)); +expectType(find(users, { name: 'John' }, options)); +expectError(find('not-an-array', 'test')); diff --git a/docs/api/reference.md b/docs/api/reference.md index 2de049b..e287bb3 100644 --- a/docs/api/reference.md +++ b/docs/api/reference.md @@ -34,6 +34,32 @@ const users = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]; const result = filter(users, { age: { $gte: 25 } }); ``` +### find + +Alias for `filter` โ€” identical signature and behavior. Use whichever name fits your style. + +```typescript +function find( + array: T[], + expression: Expression, + options?: FilterOptions +): T[] +``` + +**Example:** +```typescript +import { find } from '@mcabreradev/filter'; + +const users = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]; + +// Exactly the same as calling filter() +const result = find(users, { age: { $gte: 25 } }); +``` + +::: tip +`find` and `filter` are the same function. Pick the one that reads most naturally in your codebase. +::: + ### filterLazy Returns a lazy iterator for on-demand filtering. diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md index a78f540..4b64c2d 100644 --- a/docs/guide/quick-start.md +++ b/docs/guide/quick-start.md @@ -23,13 +23,20 @@ Choose between two import styles: ```typescript // Classic import (all features) -import { filter, useFilter } from '@mcabreradev/filter'; +import { filter, find, useFilter } from '@mcabreradev/filter'; // Modular import (smaller bundle, recommended for production) -import { filter } from '@mcabreradev/filter/core'; +import { filter, find } from '@mcabreradev/filter/core'; import { useFilter } from '@mcabreradev/filter/react'; ``` +::: tip `find` is an alias for `filter` +Both functions are identical โ€” same signature, same results. Use whichever reads more naturally in your codebase. +```typescript +find(users, { active: true }); // same as filter(users, { active: true }) +``` +::: + ::: tip Bundle Size Modular imports reduce bundle size by **50-70%**! See [Modular Imports](/guide/modular-imports) for details. ::: diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 2368bc1..da7d7ff 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -5,6 +5,15 @@ All notable changes to @mcabreradev/filter are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.9.0] - 2026-03-18 + +### Added +- **`find` alias**: `find` is now exported as an alias for `filter` with the identical signature and behavior. Import from `@mcabreradev/filter` or `@mcabreradev/filter/core`. Use whichever name reads more naturally in your codebase. + ```typescript + import { find } from '@mcabreradev/filter'; + const result = find(users, { active: true }); // same as filter() + ``` + ## [5.8.2] - 2025-11-17 ### Documentation diff --git a/src/core/filter/filter.ts b/src/core/filter/filter.ts index 70b3485..a31f3e5 100644 --- a/src/core/filter/filter.ts +++ b/src/core/filter/filter.ts @@ -102,6 +102,8 @@ export function filter(array: T[], expression: Expression, options?: Filte } } +export const find = filter; + export function clearFilterCache(): void { globalFilterCache.clear(); memoization.clearAll(); diff --git a/src/core/filter/index.ts b/src/core/filter/index.ts index c3354b8..b2f0c0e 100644 --- a/src/core/filter/index.ts +++ b/src/core/filter/index.ts @@ -1 +1 @@ -export { filter, clearFilterCache, getFilterCacheStats } from './filter.js'; +export { filter, find, clearFilterCache, getFilterCacheStats } from './filter.js'; diff --git a/src/core/index.ts b/src/core/index.ts index ae95aad..4c64528 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,4 +1,4 @@ -export { filter, clearFilterCache, getFilterCacheStats } from './filter/filter.js'; +export { filter, find, clearFilterCache, getFilterCacheStats } from './filter/filter.js'; export { filterLazy, filterLazyAsync, diff --git a/src/index.ts b/src/index.ts index 0167025..40183a0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { filter } from './core/index.js'; export { filter }; +export { find } from './core/index.js'; export { clearFilterCache, getFilterCacheStats } from './core/index.js'; @@ -26,7 +27,7 @@ export { forEach, every, some, - find, + find as lazyFind, chunk, flatten, asyncMap, From 0c53925286a6bd9be5c6a3afa129867f1932393d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=C3=A1ngel=20Cabrera?= Date: Wed, 18 Mar 2026 16:48:38 -0300 Subject: [PATCH 2/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/project/changelog.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/project/changelog.md b/docs/project/changelog.md index da7d7ff..4805c7f 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -14,6 +14,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 const result = find(users, { active: true }); // same as filter() ``` +### Changed / Breaking +- **`find` lazy helper renamed to `lazyFind`**: Previously, the `find` export from the main entry point was a lazy-iterator helper with a different signature and behavior. That helper has been renamed to `lazyFind`, and `find` now aliases `filter` instead. + - If you relied on the old lazy `find`, update your imports and calls: + ```typescript + // Before 5.9.0 (lazy iterator helper) + import { find } from '@mcabreradev/filter'; + const iterator = find(users, { active: true }); // lazy iterator + + // From 5.9.0 onwards + import { lazyFind } from '@mcabreradev/filter'; + const iterator = lazyFind(users, { active: true }); // same lazy behavior as old find + ``` + - The new `find` export matches `filter`โ€™s eager, array-returning behavior and signature. Use `lazyFind` when you need lazy iteration, and `find`/`filter` for eager filtering. + ## [5.8.2] - 2025-11-17 ### Documentation From a75924727c9146815f1fe7c0bd494bb48deb2cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=C3=A1ngel=20Cabrera?= Date: Wed, 18 Mar 2026 16:49:06 -0300 Subject: [PATCH 3/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/api/reference.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/api/reference.md b/docs/api/reference.md index e287bb3..94901bc 100644 --- a/docs/api/reference.md +++ b/docs/api/reference.md @@ -57,7 +57,11 @@ const result = find(users, { age: { $gte: 25 } }); ``` ::: tip -`find` and `filter` are the same function. Pick the one that reads most naturally in your codebase. +`find` and `filter` are the same array-returning function. Pick the one that reads most naturally in your codebase. If you're looking for the lazy-iterator helper that was previously named `find` (with signature `Iterable โ†’ T | undefined`), it is now exported as `lazyFind`: + +```ts +import { lazyFind } from '@mcabreradev/filter'; +``` ::: ### filterLazy From 783d394ed4f96b62b57ffee207f9642de38814d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=C3=A1ngel=20Cabrera?= Date: Wed, 18 Mar 2026 16:49:46 -0300 Subject: [PATCH 4/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ce92de..a9ff491 100644 --- a/README.md +++ b/README.md @@ -738,6 +738,7 @@ filter(data, expression, { enableCache: true, limit: 50 }); ### v5.9.0 (Current) - โœจ **New**: `find` โ€” an alias for `filter` with identical signature and behavior. Use whichever name reads better in your codebase: `import { find } from '@mcabreradev/filter'` +- โš ๏ธ **Migration**: Lazy iterator `find` is now `lazyFind` โ€” update imports from `find` to `lazyFind` if you relied on the lazy iterator helper. ### v5.8.2 From e84929a615879b9441d1408c39a1fadcea41d143 Mon Sep 17 00:00:00 2001 From: Miguelangel Cabrera Date: Wed, 18 Mar 2026 16:50:50 -0300 Subject: [PATCH 5/6] docs: explicitly document find/lazyFind breaking change with migration path The rename of the lazy-iterator find export to lazyFind is a breaking public API change. Add explicit breaking change notices, migration snippets, and full lazyFind API docs to README, changelog, and API reference so consumers know exactly what changed and how to update. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 11 +++++++++-- docs/api/reference.md | 40 +++++++++++++++++++++++++++++++++++++++ docs/project/changelog.md | 27 +++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a9ff491..df92ac3 100644 --- a/README.md +++ b/README.md @@ -737,8 +737,15 @@ filter(data, expression, { enableCache: true, limit: 50 }); ### v5.9.0 (Current) -- โœจ **New**: `find` โ€” an alias for `filter` with identical signature and behavior. Use whichever name reads better in your codebase: `import { find } from '@mcabreradev/filter'` -- โš ๏ธ **Migration**: Lazy iterator `find` is now `lazyFind` โ€” update imports from `find` to `lazyFind` if you relied on the lazy iterator helper. +- โœจ **New**: `find` โ€” an alias for `filter` with identical signature and behavior. `import { find } from '@mcabreradev/filter'` returns `T[]` just like `filter`. +- โœจ **New**: `lazyFind` โ€” the lazy-iterator helper (previously exported as `find`) is now exported as `lazyFind`. Returns `T | undefined`, exits on first match. +- โš ๏ธ **Breaking**: `find` exported from `@mcabreradev/filter` root **changed meaning**. Previously it was the lazy-iterator helper (`T | undefined`); it is now an alias for `filter` (`T[]`). Rename usages to `lazyFind`. + + ```typescript + // Migrate: rename find โ†’ lazyFind for the iterable helper + import { lazyFind } from '@mcabreradev/filter'; + const item = lazyFind(iterable, (x) => x.active); // T | undefined + ``` ### v5.8.2 diff --git a/docs/api/reference.md b/docs/api/reference.md index 94901bc..06779a8 100644 --- a/docs/api/reference.md +++ b/docs/api/reference.md @@ -64,6 +64,46 @@ import { lazyFind } from '@mcabreradev/filter'; ``` ::: +### lazyFind + +Finds the first item in an **iterable** that satisfies a predicate. Returns `T | undefined` and exits immediately on the first match โ€” no array is allocated. + +> **Migration note (v5.9.0):** This function was previously exported as `find` from the root package. It has been renamed to `lazyFind` to make room for the new `find` alias for `filter`. Update your imports accordingly. + +```typescript +function lazyFind( + iterable: Iterable, + predicate: (item: T, index: number) => boolean +): T | undefined +``` + +**Parameters:** +- `iterable` - Any iterable (array, generator, Set, Map values, โ€ฆ) +- `predicate` - Function that returns `true` for the desired item + +**Returns:** The first matching item, or `undefined` if none found + +**Example:** +```typescript +import { lazyFind } from '@mcabreradev/filter'; + +const users = [{ name: 'Alice', active: false }, { name: 'Bob', active: true }]; + +const first = lazyFind(users, (u) => u.active); +// โ†’ { name: 'Bob', active: true } (stops after finding Bob) + +// Works with generators too +function* infiniteStream() { let i = 0; while (true) yield i++; } +const found = lazyFind(infiniteStream(), (n) => n > 100); +// โ†’ 101 (exits immediately without consuming the rest) +``` + +::: warning Difference from `find` +`lazyFind(iterable, predicate)` accepts **any iterable** and a plain **predicate function**, returning the **first match** as `T | undefined`. + +`find(array, expression, options?)` accepts an **array** and any **filter expression**, returning **all matches** as `T[]`. +::: + ### filterLazy Returns a lazy iterator for on-demand filtering. diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 4805c7f..59f44a5 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -11,8 +11,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **`find` alias**: `find` is now exported as an alias for `filter` with the identical signature and behavior. Import from `@mcabreradev/filter` or `@mcabreradev/filter/core`. Use whichever name reads more naturally in your codebase. ```typescript import { find } from '@mcabreradev/filter'; - const result = find(users, { active: true }); // same as filter() + const result = find(users, { active: true }); // identical to filter() โ€” returns T[] ``` +- **`lazyFind`**: The lazy-iterator helper (previously exported as `find` from the root package) is now exported as `lazyFind`. It finds the first matching item in an iterable and returns `T | undefined`. + ```typescript + import { lazyFind } from '@mcabreradev/filter'; + const first = lazyFind(iterable, (item, i) => item.active); // returns T | undefined + ``` + +### Breaking Changes +- **`find` renamed to `lazyFind` in the main package export** (`@mcabreradev/filter`). + + Previously `import { find } from '@mcabreradev/filter'` gave you the lazy-iterator helper with signature `find(iterable: Iterable, predicate: (item: T, index: number) => boolean): T | undefined`. + + It is now exported as **`lazyFind`** with the same signature. The name `find` now refers to the array-filter alias (signature `find(array: T[], expression: Expression, options?: FilterOptions): T[]`). + + **Migration:** + ```typescript + // Before (v5.8.x) + import { find } from '@mcabreradev/filter'; + const item = find(iterable, (x) => x.active); // T | undefined + + // After (v5.9.0+) + import { lazyFind } from '@mcabreradev/filter'; + const item = lazyFind(iterable, (x) => x.active); // T | undefined + ``` + + > **Note:** This change only affects consumers who imported the `find` lazy-iterator helper from the root `@mcabreradev/filter` package. Imports from sub-packages (`@mcabreradev/filter/core`, etc.) are not affected. ### Changed / Breaking - **`find` lazy helper renamed to `lazyFind`**: Previously, the `find` export from the main entry point was a lazy-iterator helper with a different signature and behavior. That helper has been renamed to `lazyFind`, and `find` now aliases `filter` instead. From 2a7d7adefb77cbe3dd973363f28eaf0bae188e82 Mon Sep 17 00:00:00 2001 From: Miguelangel Cabrera Date: Wed, 18 Mar 2026 17:03:32 -0300 Subject: [PATCH 6/6] refactor: replace find alias with findAll to avoid breaking change find (lazy-iterator helper, returns T | undefined) is kept unchanged. findAll is introduced as the zero-breaking-change alias for filter. Update all tests, type tests, and docs accordingly. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 16 +++------- __test__/filter.test.ts | 12 +++---- __test__/test-d/filter.test-d.ts | 12 +++---- docs/api/reference.md | 54 +++++--------------------------- docs/guide/quick-start.md | 8 ++--- docs/project/changelog.md | 45 ++------------------------ src/core/filter/filter.ts | 2 +- src/core/filter/index.ts | 2 +- src/core/index.ts | 2 +- src/index.ts | 4 +-- 10 files changed, 35 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index df92ac3..139c2e0 100644 --- a/README.md +++ b/README.md @@ -167,10 +167,10 @@ const startsWithAl = filter(users, 'Al%'); // โ†’ [{ name: 'Alice', ... }] ``` -> **`find` is an alias for `filter`** โ€” use whichever name feels more natural: +> **`findAll` is an alias for `filter`** โ€” use whichever name feels more natural: > ```typescript -> import { find } from '@mcabreradev/filter'; -> const result = find(users, { active: true }); // identical to filter() +> import { findAll } from '@mcabreradev/filter'; +> const result = findAll(users, { active: true }); // identical to filter() > ``` **๐ŸŽฎ [Try it in the Playground โ†’](https://mcabreradev-filter.vercel.app/playground/)** @@ -737,15 +737,7 @@ filter(data, expression, { enableCache: true, limit: 50 }); ### v5.9.0 (Current) -- โœจ **New**: `find` โ€” an alias for `filter` with identical signature and behavior. `import { find } from '@mcabreradev/filter'` returns `T[]` just like `filter`. -- โœจ **New**: `lazyFind` โ€” the lazy-iterator helper (previously exported as `find`) is now exported as `lazyFind`. Returns `T | undefined`, exits on first match. -- โš ๏ธ **Breaking**: `find` exported from `@mcabreradev/filter` root **changed meaning**. Previously it was the lazy-iterator helper (`T | undefined`); it is now an alias for `filter` (`T[]`). Rename usages to `lazyFind`. - - ```typescript - // Migrate: rename find โ†’ lazyFind for the iterable helper - import { lazyFind } from '@mcabreradev/filter'; - const item = lazyFind(iterable, (x) => x.active); // T | undefined - ``` +- โœจ **New**: `findAll` โ€” a zero-breaking-change alias for `filter` with identical signature and behavior. `import { findAll } from '@mcabreradev/filter'` returns `T[]` just like `filter`. The existing `find` lazy-iterator helper is unchanged. ### v5.8.2 diff --git a/__test__/filter.test.ts b/__test__/filter.test.ts index 60fd24e..556b236 100644 --- a/__test__/filter.test.ts +++ b/__test__/filter.test.ts @@ -1,4 +1,4 @@ -import filter, { find } from '../src/index'; +import filter, { findAll } from '../src/index'; import data from './data.json'; @@ -301,23 +301,23 @@ describe('Array values with OR logic (syntactic sugar for $in)', () => { }); }); -describe('find alias', () => { +describe('findAll alias', () => { it('returns same results as filter', () => { - expect(find(data, 'Berlin')).toEqual(filter(data, 'Berlin')); + expect(findAll(data, 'Berlin')).toEqual(filter(data, 'Berlin')); }); it('works with object expression', () => { const city = 'Berlin'; - expect(find(data, { city })).toEqual(filter(data, { city })); + expect(findAll(data, { city })).toEqual(filter(data, { city })); }); it('works with predicate function', () => { const pred = (item: (typeof data)[0]) => item.city === 'Berlin'; - expect(find(data, pred)).toEqual(filter(data, pred)); + expect(findAll(data, pred)).toEqual(filter(data, pred)); }); it('works with options', () => { - expect(find(data, 'berlin', { caseSensitive: false })).toEqual( + expect(findAll(data, 'berlin', { caseSensitive: false })).toEqual( filter(data, 'berlin', { caseSensitive: false }), ); }); diff --git a/__test__/test-d/filter.test-d.ts b/__test__/test-d/filter.test-d.ts index 912f35c..a2ff4b4 100644 --- a/__test__/test-d/filter.test-d.ts +++ b/__test__/test-d/filter.test-d.ts @@ -1,5 +1,5 @@ import { expectType, expectError } from 'tsd'; -import { filter, find } from '../../src/core/filter'; +import { filter, findAll } from '../../src/core/filter'; import type { FilterOptions } from '../../src/types'; interface User { @@ -115,8 +115,8 @@ expectType<(string | number)[]>(filter(mixedArray, 'a')); expectType<(string | number)[]>(filter(mixedArray, (item) => typeof item === 'string')); -expectType(find(users, 'John')); -expectType(find(users, { name: 'John' })); -expectType(find(users, (user) => user.age > 18)); -expectType(find(users, { name: 'John' }, options)); -expectError(find('not-an-array', 'test')); +expectType(findAll(users, 'John')); +expectType(findAll(users, { name: 'John' })); +expectType(findAll(users, (user) => user.age > 18)); +expectType(findAll(users, { name: 'John' }, options)); +expectError(findAll('not-an-array', 'test')); diff --git a/docs/api/reference.md b/docs/api/reference.md index 06779a8..6b0ae30 100644 --- a/docs/api/reference.md +++ b/docs/api/reference.md @@ -34,12 +34,12 @@ const users = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]; const result = filter(users, { age: { $gte: 25 } }); ``` -### find +### findAll Alias for `filter` โ€” identical signature and behavior. Use whichever name fits your style. ```typescript -function find( +function findAll( array: T[], expression: Expression, options?: FilterOptions @@ -48,60 +48,20 @@ function find( **Example:** ```typescript -import { find } from '@mcabreradev/filter'; +import { findAll } from '@mcabreradev/filter'; const users = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]; // Exactly the same as calling filter() -const result = find(users, { age: { $gte: 25 } }); +const result = findAll(users, { age: { $gte: 25 } }); ``` ::: tip -`find` and `filter` are the same array-returning function. Pick the one that reads most naturally in your codebase. If you're looking for the lazy-iterator helper that was previously named `find` (with signature `Iterable โ†’ T | undefined`), it is now exported as `lazyFind`: - -```ts -import { lazyFind } from '@mcabreradev/filter'; -``` +`findAll` and `filter` are the same function. Pick whichever reads most naturally in your codebase. ::: -### lazyFind - -Finds the first item in an **iterable** that satisfies a predicate. Returns `T | undefined` and exits immediately on the first match โ€” no array is allocated. - -> **Migration note (v5.9.0):** This function was previously exported as `find` from the root package. It has been renamed to `lazyFind` to make room for the new `find` alias for `filter`. Update your imports accordingly. - -```typescript -function lazyFind( - iterable: Iterable, - predicate: (item: T, index: number) => boolean -): T | undefined -``` - -**Parameters:** -- `iterable` - Any iterable (array, generator, Set, Map values, โ€ฆ) -- `predicate` - Function that returns `true` for the desired item - -**Returns:** The first matching item, or `undefined` if none found - -**Example:** -```typescript -import { lazyFind } from '@mcabreradev/filter'; - -const users = [{ name: 'Alice', active: false }, { name: 'Bob', active: true }]; - -const first = lazyFind(users, (u) => u.active); -// โ†’ { name: 'Bob', active: true } (stops after finding Bob) - -// Works with generators too -function* infiniteStream() { let i = 0; while (true) yield i++; } -const found = lazyFind(infiniteStream(), (n) => n > 100); -// โ†’ 101 (exits immediately without consuming the rest) -``` - -::: warning Difference from `find` -`lazyFind(iterable, predicate)` accepts **any iterable** and a plain **predicate function**, returning the **first match** as `T | undefined`. - -`find(array, expression, options?)` accepts an **array** and any **filter expression**, returning **all matches** as `T[]`. +::: info Looking for `find`? +The `find` export is the **lazy-iterator helper** โ€” it finds the **first** matching item in an iterable and returns `T | undefined`. See [`filterFirst`](#filterfirst) for an eager equivalent, or use the built-in `Array.prototype.find` for simple cases. ::: ### filterLazy diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md index 4b64c2d..da727f5 100644 --- a/docs/guide/quick-start.md +++ b/docs/guide/quick-start.md @@ -23,17 +23,17 @@ Choose between two import styles: ```typescript // Classic import (all features) -import { filter, find, useFilter } from '@mcabreradev/filter'; +import { filter, findAll, useFilter } from '@mcabreradev/filter'; // Modular import (smaller bundle, recommended for production) -import { filter, find } from '@mcabreradev/filter/core'; +import { filter, findAll } from '@mcabreradev/filter/core'; import { useFilter } from '@mcabreradev/filter/react'; ``` -::: tip `find` is an alias for `filter` +::: tip `findAll` is an alias for `filter` Both functions are identical โ€” same signature, same results. Use whichever reads more naturally in your codebase. ```typescript -find(users, { active: true }); // same as filter(users, { active: true }) +findAll(users, { active: true }); // same as filter(users, { active: true }) ``` ::: diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 59f44a5..687410e 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -8,50 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [5.9.0] - 2026-03-18 ### Added -- **`find` alias**: `find` is now exported as an alias for `filter` with the identical signature and behavior. Import from `@mcabreradev/filter` or `@mcabreradev/filter/core`. Use whichever name reads more naturally in your codebase. +- **`findAll`**: Zero-breaking-change alias for `filter` โ€” identical signature and behavior. The existing `find` lazy-iterator helper (returns `T | undefined`) is untouched. ```typescript - import { find } from '@mcabreradev/filter'; - const result = find(users, { active: true }); // identical to filter() โ€” returns T[] + import { findAll } from โ€˜@mcabreradev/filterโ€™; + const result = findAll(users, { active: true }); // identical to filter() โ€” returns T[] ``` -- **`lazyFind`**: The lazy-iterator helper (previously exported as `find` from the root package) is now exported as `lazyFind`. It finds the first matching item in an iterable and returns `T | undefined`. - ```typescript - import { lazyFind } from '@mcabreradev/filter'; - const first = lazyFind(iterable, (item, i) => item.active); // returns T | undefined - ``` - -### Breaking Changes -- **`find` renamed to `lazyFind` in the main package export** (`@mcabreradev/filter`). - - Previously `import { find } from '@mcabreradev/filter'` gave you the lazy-iterator helper with signature `find(iterable: Iterable, predicate: (item: T, index: number) => boolean): T | undefined`. - - It is now exported as **`lazyFind`** with the same signature. The name `find` now refers to the array-filter alias (signature `find(array: T[], expression: Expression, options?: FilterOptions): T[]`). - - **Migration:** - ```typescript - // Before (v5.8.x) - import { find } from '@mcabreradev/filter'; - const item = find(iterable, (x) => x.active); // T | undefined - - // After (v5.9.0+) - import { lazyFind } from '@mcabreradev/filter'; - const item = lazyFind(iterable, (x) => x.active); // T | undefined - ``` - - > **Note:** This change only affects consumers who imported the `find` lazy-iterator helper from the root `@mcabreradev/filter` package. Imports from sub-packages (`@mcabreradev/filter/core`, etc.) are not affected. - -### Changed / Breaking -- **`find` lazy helper renamed to `lazyFind`**: Previously, the `find` export from the main entry point was a lazy-iterator helper with a different signature and behavior. That helper has been renamed to `lazyFind`, and `find` now aliases `filter` instead. - - If you relied on the old lazy `find`, update your imports and calls: - ```typescript - // Before 5.9.0 (lazy iterator helper) - import { find } from '@mcabreradev/filter'; - const iterator = find(users, { active: true }); // lazy iterator - - // From 5.9.0 onwards - import { lazyFind } from '@mcabreradev/filter'; - const iterator = lazyFind(users, { active: true }); // same lazy behavior as old find - ``` - - The new `find` export matches `filter`โ€™s eager, array-returning behavior and signature. Use `lazyFind` when you need lazy iteration, and `find`/`filter` for eager filtering. ## [5.8.2] - 2025-11-17 diff --git a/src/core/filter/filter.ts b/src/core/filter/filter.ts index a31f3e5..f23670e 100644 --- a/src/core/filter/filter.ts +++ b/src/core/filter/filter.ts @@ -102,7 +102,7 @@ export function filter(array: T[], expression: Expression, options?: Filte } } -export const find = filter; +export const findAll = filter; export function clearFilterCache(): void { globalFilterCache.clear(); diff --git a/src/core/filter/index.ts b/src/core/filter/index.ts index b2f0c0e..88177c8 100644 --- a/src/core/filter/index.ts +++ b/src/core/filter/index.ts @@ -1 +1 @@ -export { filter, find, clearFilterCache, getFilterCacheStats } from './filter.js'; +export { filter, findAll, clearFilterCache, getFilterCacheStats } from './filter.js'; diff --git a/src/core/index.ts b/src/core/index.ts index 4c64528..ec8ca66 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,4 +1,4 @@ -export { filter, find, clearFilterCache, getFilterCacheStats } from './filter/filter.js'; +export { filter, findAll, clearFilterCache, getFilterCacheStats } from './filter/filter.js'; export { filterLazy, filterLazyAsync, diff --git a/src/index.ts b/src/index.ts index 40183a0..c07330e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { filter } from './core/index.js'; export { filter }; -export { find } from './core/index.js'; +export { findAll } from './core/index.js'; export { clearFilterCache, getFilterCacheStats } from './core/index.js'; @@ -27,7 +27,7 @@ export { forEach, every, some, - find as lazyFind, + find, chunk, flatten, asyncMap,