{"_id":"@anil-labs/collection-js","_rev":"2-1bbc37d5ef98c4a090685646d1150535","name":"@anil-labs/collection-js","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@anil-labs/collection-js","version":"0.1.0","keywords":["collection","data-structure","typescript","javascript","library","laravel","laravel-collections","collection-js","collection-ts","array","fluent","chainable","functional","manipulation"],"license":"MIT","_id":"@anil-labs/collection-js@0.1.0","maintainers":[{"name":"anilkumarthakur","email":"anilkumarthakur60@gmail.com"}],"homepage":"https://github.com/anilkumarthakur60/collection-js#readme","bugs":{"url":"https://github.com/anilkumarthakur60/collection-js/issues"},"dist":{"shasum":"8df95fe8eba9d6c2680dc0eb458644ac91a5bd2f","tarball":"https://registry.npmjs.org/@anil-labs/collection-js/-/collection-js-0.1.0.tgz","fileCount":64,"integrity":"sha512-lDX8+KcIT6aG5G7uHNPVa8o5xYgpZ5Ir5zMVBH34bNK97bJUEGlegYjN0J4q0Bis3vT9omrMQ6cHZlFV0dbWCg==","signatures":[{"sig":"MEUCIQDA/xShwPFdnisWIT9Sao7aV4f/+UV94ezyoQ9FThBr1wIgJj529tAEEw5erMG96svuevJ8ALuUFN4NdOq+0i6RtlI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214933},"main":"dist/index.umd.cjs","type":"module","types":"dist/src/index.d.ts","module":"dist/index.es.js","engines":{"node":">=16"},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.umd.cjs"}},"gitHead":"c4179cb753764e65a7e5887fb1a4430f8d05343d","private":false,"scripts":{"ctf":"clear && npm run format && npm run lint && npm run test","dev":"vite","lint":"eslint . --fix","test":"jest","build":"tsc && vite build","format":"prettier --write src/ docs/","preview":"vite preview","docs:dev":"vitepress dev docs","docs:build":"vitepress build docs","lint-format":"npm run lint && npm run format","docs:preview":"vitepress preview docs","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"anilkumarthakur","email":"anilkumarthakur60@gmail.com"},"repository":{"url":"git+https://github.com/anilkumarthakur60/collection-js.git","type":"git"},"_npmVersion":"11.11.0","description":"A fluent, Laravel-inspired Collection library for JavaScript and TypeScript. Provides 120+ chainable methods for elegant array manipulation.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","vite":"^8.0.14","eslint":"^10.1.0","ts-jest":"^29.4.11","ts-node":"^10.9.2","prettier":"^3.8.3","vitepress":"^1.6.4","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/jest":"^30.0.0","@types/node":"^25.9.1","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.57.1","@rushstack/eslint-patch":"^1.16.1","@typescript-eslint/parser":"^8.57.1","eslint-plugin-perfectionist":"^5.7.0","@typescript-eslint/eslint-plugin":"^8.57.1"},"peerDependencies":{"@types/node":">=16"},"peerDependenciesMeta":{"@types/node":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/collection-js_0.1.0_1780082099397_0.7167065569279847","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@anil-labs/collection-js","version":"0.2.0","description":"A fluent, Laravel-inspired Collection library for JavaScript and TypeScript. Provides 120+ chainable methods for elegant array manipulation. Framework-independent — works in Node, any JS framework, or straight off a CDN.","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","unpkg":"./dist/index.global.js","jsdelivr":"./dist/index.global.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"sideEffects":false,"keywords":["collection","data-structure","typescript","javascript","library","laravel","laravel-collections","collection-js","array","fluent","chainable","functional","lazy","async"],"engines":{"node":">=18"},"license":"MIT","author":"Er. Anil Kumar Thakur <anilkumarthakur60@gmail.com>","repository":{"type":"git","url":"git+https://github.com/anilkumarthakur60/collection-js.git","directory":"packages/collection-js"},"homepage":"https://github.com/anilkumarthakur60/collection-js/tree/main/packages/collection-js#readme","bugs":"https://github.com/anilkumarthakur60/collection-js/issues","publishConfig":{"access":"public"},"devDependencies":{"@types/node":"^25.9.1","@vitest/coverage-v8":"^4.1.8","tsup":"^8.5.1","typescript":"~6.0.3","vitest":"^4.1.8"},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","typecheck":"tsc --noEmit"},"_nodeVersion":"24.18.0","_id":"@anil-labs/collection-js@0.2.0","dist":{"integrity":"sha512-iQ6bNKBDOmyxc6tRQE7RvqHYz08B7wK2j+Y+jei9ZO5QObJsL8z9ovrAdzVsw9UZ/1mQ8ao/XYPfqhAkIrawBw==","shasum":"642e15abdccd6a42025166d6e75e7c71382a82c3","tarball":"https://registry.npmjs.org/@anil-labs/collection-js/-/collection-js-0.2.0.tgz","fileCount":11,"unpackedSize":1682597,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDD6dSGhsz8RjDt7O9Gl1nWsxDf/MxeHL6JZly7zGb8+QIgb1MekJDvzcoSLW5ueRppFrqp0E+3R1ftxu0FBwqNJyA="}]},"_npmUser":{"name":"anilkumarthakur","email":"anilkumarthakur60@gmail.com"},"directories":{},"maintainers":[{"name":"anilkumarthakur","email":"anilkumarthakur60@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/collection-js_0.2.0_1784260689311_0.4363474480638325"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-29T19:14:59.239Z","modified":"2026-07-17T03:58:09.647Z","0.1.0":"2026-05-29T19:14:59.585Z","0.2.0":"2026-07-17T03:58:09.484Z"},"bugs":"https://github.com/anilkumarthakur60/collection-js/issues","license":"MIT","homepage":"https://github.com/anilkumarthakur60/collection-js/tree/main/packages/collection-js#readme","keywords":["collection","data-structure","typescript","javascript","library","laravel","laravel-collections","collection-js","array","fluent","chainable","functional","lazy","async"],"repository":{"type":"git","url":"git+https://github.com/anilkumarthakur60/collection-js.git","directory":"packages/collection-js"},"description":"A fluent, Laravel-inspired Collection library for JavaScript and TypeScript. Provides 120+ chainable methods for elegant array manipulation. Framework-independent — works in Node, any JS framework, or straight off a CDN.","maintainers":[{"name":"anilkumarthakur","email":"anilkumarthakur60@gmail.com"}],"readme":"# @anil-labs/collection-js\n\nA fluent, Laravel-inspired Collection library for JavaScript and TypeScript. Near-complete parity with the **Laravel 13.x Collections** API (see [Laravel Compatibility](#laravel-compatibility) for the gaps) — plus statistics, SQL-style joins, combinatorics, async streams, and CSV/JSONL I/O that go beyond it.\n\n[![npm version](https://img.shields.io/npm/v/@anil-labs/collection-js)](https://www.npmjs.com/package/@anil-labs/collection-js)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n- **Strict TypeScript** — written in strict mode with deep type inference; no `any` in the public surface.\n- **Immutable by default** — methods return new collections; the handful of mutators mirror Laravel exactly.\n- **Three flavours** — eager `Collection`, generator-backed `LazyCollection`, and `AsyncCollection` for `AsyncIterable` sources.\n- **Standalone operations** — every method is also a pure function (`operations.pluckOf(...)`), usable without the `Collection` class.\n- **Runs anywhere** — Node 18+, any framework, or straight off a CDN as a single `<script>` tag.\n- **Zero runtime dependencies.**\n\n## Installation\n\n```bash\nnpm install @anil-labs/collection-js\n```\n\nRequires Node.js 18+ — or no Node at all: the package ships a browser-ready global build, so a single script tag works with no bundler and no build step:\n\n```html\n<script src=\"https://unpkg.com/@anil-labs/collection-js\"></script>\n<script>\n  const { collect } = CollectionJS\n  collect([1, 2, 3]).sum() // => 6\n</script>\n```\n\nSee the [CDN usage guide](https://github.com/anilkumarthakur60/collection-js/blob/main/docs/guide/cdn.md) (runnable demo in [`examples/cdn`](https://github.com/anilkumarthakur60/collection-js/tree/main/examples/cdn)).\n\n## Quick Start\n\n```typescript\nimport collect from '@anil-labs/collection-js'\n\ncollect([1, 2, 3, 4, 5])\n  .filter((item) => item > 2)\n  .map((item) => item * 10)\n  .all()\n// => [30, 40, 50]\n```\n\n## Working with Objects\n\n```typescript\nconst users = collect([\n  { id: 1, name: 'Alice', role: 'admin', score: 95 },\n  { id: 2, name: 'Bob', role: 'user', score: 80 },\n  { id: 3, name: 'Charlie', role: 'admin', score: 92 },\n  { id: 4, name: 'Diana', role: 'user', score: 88 }\n])\n\nusers.where('role', 'admin').sortByDesc('score').pluck('name').all()\n// => ['Alice', 'Charlie']\n\nconst byRole = users.groupBy('role')\n// => { admin: Collection, user: Collection } — each group stays chainable\nbyRole['admin'].pluck('name').all() // => ['Alice', 'Charlie']\n\nusers.avg('score') // => 88.75\nusers.max('score') // => 95\nusers.median('score') // => 90\n\nconst [admins, regular] = users.partition((u) => u.role === 'admin')\n```\n\n`where`-style filters support dot-notation paths and comparison operators, and `max`/`min` work on numbers, strings, and `Date`s:\n\n```typescript\ncollect(['banana', 'apple', 'cherry']).max() // => 'cherry'\ncollect(orders).where('customer.country', 'FR').sum('total')\n```\n\n### Pattern filtering with `whereLike`\n\n`whereLike` / `whereNotLike` filter by an SQL-`LIKE` pattern, where `%` matches any run of characters and `_` matches a single one (case-insensitive by default):\n\n```typescript\ncollect(users).whereLike('name', '%Smith') // ends with \"Smith\"\ncollect(users).whereLike('email', '%@gmail.com') // gmail addresses\ncollect(users).whereNotLike('name', 'A%', true) // case-sensitive: not starting with \"A\"\n```\n\n## Lazy Collections\n\nFor large or infinite datasets, use generator-backed lazy evaluation — values are produced on demand:\n\n```typescript\nimport { LazyCollection } from '@anil-labs/collection-js'\n\nnew LazyCollection(function* () {\n  for (let i = 0; i < 1_000_000; i++) yield i\n})\n  .filter((n) => n % 2 === 0)\n  .map((n) => n * 2)\n  .take(5)\n  .toArray()\n// => [0, 4, 8, 12, 16] — only 5 items ever evaluated\n```\n\nLazy-only helpers: `tapEach`, `remember` (memoize pulled values), `takeUntilTimeout`, `throttle`, `withHeartbeat`.\n\n## Async Collections\n\nStream and transform `AsyncIterable` sources with bounded concurrency:\n\n```typescript\nimport { AsyncCollection } from '@anil-labs/collection-js'\n\nconst results = await AsyncCollection.from(userIds)\n  .mapAsync((id) => fetchUser(id), { concurrency: 8 }) // ≤ 8 in flight, source order preserved\n  .filter((user) => user.active)\n  .take(100)\n  .toArray()\n```\n\n## Beyond Laravel\n\nThese extend the Laravel API for real-world data work:\n\n**Statistics** — `variance` · `sampleVariance` · `stddev` · `sampleStddev` · `quantile` · `percentileAt` · `histogram` · `correlation`\n\n```typescript\ncollect(samples).stddev('latency')\ncollect(rows).correlation('spend', 'revenue')\ncollect(values).histogram(10)\n```\n\n**SQL-style joins** — `joinOn` (inner) · `leftJoin` · `rightJoin` · `outerJoin`\n\n```typescript\ncollect(orders).joinOn(customers, 'customerId', 'id', (order, customer) => ({\n  ...order,\n  customerName: customer.name\n}))\n```\n\n**Combinatorics & itertools** — `scan` · `pairwise` · `enumerate` · `cycle` · `interleave` · `permutations` · `combinations` · `powerSet`\n\n```typescript\ncollect([1, 2, 3]).permutations().all() // all 3! orderings\ncollect([1, 2, 3, 4]).combinations(2).all()\ncollect([1, 2, 3])\n  .scan((sum, n) => sum + n, 0)\n  .all() // running totals: [1, 3, 6]\n```\n\n**CSV / JSONL / streams**\n\n```typescript\nimport { parseCsv, toCsv, parseJsonl, toJsonl, lines } from '@anil-labs/collection-js'\n\nconst rows = collect(parseCsv(csvText, { header: true }))\nconst csv = toCsv(rows.all())\n```\n\n## Higher-Order Messages\n\nEvery method in `HIGHER_ORDER_TARGETS` (`each`, `map`, `filter`, `sum`, `avg`, `max`, `min`, `groupBy`, `sortBy`, `unique`, …) also accepts its callback as a **property access**, on both `Collection` and `LazyCollection`:\n\n```typescript\nusers.sum.score // => 355   — property form of users.sum((u) => u.score)\nusers.map.name.all() // => ['Alice', 'Bob', 'Charlie', 'Diana']\nusers.where('role', 'admin').each.notify() // calls notify() on every admin\n```\n\n## Extending with Macros\n\nAdd your own methods at runtime — they participate in chaining like built-ins:\n\n```typescript\nimport { Collection } from '@anil-labs/collection-js'\n\nCollection.macro('toUpper', function (this: Collection<string>) {\n  return this.map((s) => s.toUpperCase())\n})\n\ncollect(['a', 'b']).toUpper().all() // => ['A', 'B']\n```\n\n## Laravel Compatibility\n\nThis library tracks [Laravel 13.x Collections](https://laravel.com/docs/13.x/collections) closely — `collect()` is the default export and the overwhelming majority of methods match Laravel's names and behavior, so if you know Laravel's `Collection` you'll feel right at home.\n\nParity is near-complete rather than total. Known gaps and deliberate divergences:\n\n- **Not implemented (yet):** `getOrPut`, `mapToDictionary`, `diffUsing`, `diffKeysUsing`.\n- **Keyed results are plain objects.** A collection always wraps an array, so `groupBy`, `keyBy`, `countBy`, `mapWithKeys`, `mapToGroups`, `combine`, `dot`, and `duplicates` return a `Record` rather than a keyed Collection. The group values of `groupBy`/`mapToGroups` are chainable `Collection`s.\n- **`get(index)` is index-based** (negative indices count from the end). For Laravel's key-based `get($key)`, use `value(key)` or `dataGet`.\n- **`put(key, value)` sets the key on every object element** (mutating in place), rather than setting a single keyed entry.\n- **`has(key)` checks item properties**, not collection keys.\n- **`avg()`/`average()` of an empty collection returns `0`** (Laravel returns `null`), and non-numeric values are skipped rather than coerced.\n- **`combine()` truncates to the shorter side** on a length mismatch (Laravel throws).\n\nSmaller signature differences are called out per-method in the [API reference](https://github.com/anilkumarthakur60/collection-js/blob/main/docs/api/index.md).\n\n## Repository & Development\n\nSource, issues, and the full documentation live in the monorepo:\n\n- **Repository:** https://github.com/anilkumarthakur60/collection-js\n- **Documentation:** [`docs`](https://github.com/anilkumarthakur60/collection-js/tree/main/docs) (a VitePress site)\n- **Playground:** [`examples/playground`](https://github.com/anilkumarthakur60/collection-js/tree/main/examples/playground) — Vite + TypeScript, wired to the workspace build\n- **CDN demo:** [`examples/cdn`](https://github.com/anilkumarthakur60/collection-js/tree/main/examples/cdn) — no-bundler demo of the global build\n\n## License\n\n[MIT](https://github.com/anilkumarthakur60/collection-js/blob/main/LICENSE)\n","readmeFilename":"","author":"Er. Anil Kumar Thakur <anilkumarthakur60@gmail.com>"}