{"_id":"2dollars","_rev":"7-1ed41618101b14bbfd0a8c718286c519","name":"2dollars","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"2dollars","version":"1.0.0","author":"","license":"ISC","_id":"2dollars@1.0.0","maintainers":[{"name":"isuvorov","email":"npm@coder24.ru"}],"homepage":"https://github.com/isuvorov/2dollars","bugs":{"url":"https://github.com/isuvorov/2dollars/issues"},"dist":{"shasum":"647dfa2e61db8ebadda2e5cf40d023c5a2edd736","tarball":"https://registry.npmjs.org/2dollars/-/2dollars-1.0.0.tgz","integrity":"sha512-4/8mBuRr5shOTKv8F6pNYniPBU09QTG1ZFd1kfG/TyIn0YOOolhW2dG6ZFbh9gm2/nQDNeO8HTdhtZP8XnS1qA==","signatures":[{"sig":"MEYCIQCumqa2YZCEVaD35cyhyWnkzIt4I3K/paAifFO/paSoXQIhAO9DV8j6nRvNIn5nV4STWonvHFBMQamB3grk+5WcGJ2D","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","_shasum":"647dfa2e61db8ebadda2e5cf40d023c5a2edd736","gitHead":"ca708aca76e574b5ef001eb282901f11e4a2f175","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"isuvorov","email":"npm@coder24.ru"},"repository":{"url":"https://github.com/isuvorov/2dollars.git","type":"git"},"_npmVersion":"1.4.28","description":"write less, do more, save $$ dollars","directories":{}},"1.0.1":{"name":"2dollars","version":"1.0.1","author":"","license":"ISC","_id":"2dollars@1.0.1","maintainers":[{"name":"isuvorov","email":"suvorov.igor.90@gmail.com"}],"homepage":"https://github.com/isuvorov/2dollars","bugs":{"url":"https://github.com/isuvorov/2dollars/issues"},"dist":{"shasum":"f90752640ef038704c33f0cddf8beebf12ff770c","tarball":"https://registry.npmjs.org/2dollars/-/2dollars-1.0.1.tgz","integrity":"sha512-Ux9q2T57qdGksgNgLiWX4OkaMa30vajHfYjMeVwDFWfJ9ukxLNxHCLMVmUsFJkhP2BrqOv7fQw1IfO5xx2GJoQ==","signatures":[{"sig":"MEUCIEVSvPG55VckcCS+k+0hwPTR0PL99asiiPgr8zv1Y2OxAiEAiqjh4aBTYuaB6XcBAhPlFejtJD43pAZcmrVuluNFVgI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","_shasum":"f90752640ef038704c33f0cddf8beebf12ff770c","gitHead":"960f047421434f7f276d60c8ec34daeaa54fc353","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"isuvorov","email":"npm@coder24.ru"},"repository":{"url":"https://github.com/isuvorov/2dollars.git","type":"git"},"_npmVersion":"1.4.28","description":"write less, do more, save $$ dollars","directories":{}},"1.0.2":{"name":"2dollars","version":"1.0.2","author":"","license":"ISC","_id":"2dollars@1.0.2","maintainers":[{"name":"isuvorov","email":"suvorov.igor.90@gmail.com"}],"homepage":"https://github.com/isuvorov/2dollars","bugs":{"url":"https://github.com/isuvorov/2dollars/issues"},"dist":{"shasum":"91fd984831f6c9a7f4c046886f822004696c0aaf","tarball":"https://registry.npmjs.org/2dollars/-/2dollars-1.0.2.tgz","integrity":"sha512-DVKfRGriGOOQZt58InKL7TjhFbpqs05Cx1vXTdWB7Gna9TH58aurjsxvZrsJiGpxILvFw3TzjHgu9EaC2Db/rw==","signatures":[{"sig":"MEQCID3tv7mMJ9+M/+LyhAsguNa+LTp1/KuGaLJTUUcRkVViAiBoaoUvi0HT74FGhUBGDIiMQl1pifF0zWcopyqfZw6aFA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"index.js","_from":".","_shasum":"91fd984831f6c9a7f4c046886f822004696c0aaf","gitHead":"960f047421434f7f276d60c8ec34daeaa54fc353","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"isuvorov","email":"npm@coder24.ru"},"repository":{"url":"https://github.com/isuvorov/2dollars.git","type":"git"},"_npmVersion":"1.4.28","description":"write less, do more, save $$ dollars","directories":{}},"1.0.3":{"type":"module","name":"2dollars","name2":"fishdash","version":"1.0.3","description":"Functional utility library for modern TypeScript, ESM, ES6+","author":{"name":"Igor Suvorov","email":"hi@isuvorov.com","url":"https://github.com/isuvorov"},"private":false,"scripts":{"build":"            bunup","dev":"              bunup --watch","test:node":"        node --import=tsx --test tests/*.test.ts","test:node:watch":"  node --import=tsx --test --watch tests/*.test.ts","test":"             npm run test:node","test:watch":"       npm run test:node:watch","version:release":"  npm version patch && git push && git push --tags","release":"          npm run build && npm run test && npm run version:release && npm publish"},"devDependencies":{"@types/node":"^24.9.1","bunup":"^0.15.12","tsx":"^4.20.6","typescript":"5.9.3"},"//":"///////////========================/////////========================/////////========================/////////","main":"lib/index.js","types":"lib/index.d.ts","exports":{".":{"import":"./lib/index.js","types":"./lib/index.d.ts","default":"./lib/index.js"},"./*":{"import":"./lib/*.js","types":"./lib/*.d.ts","default":"./lib/*.js"}},"size-limit":[{"path":"lib/index.js","limit":"1.4kb"},{"path":"lib/any.js","limit":"1kb"},{"path":"lib/count.js","limit":"1kb"},{"path":"lib/countBy.js","limit":"1kb"},{"path":"lib/each.js","limit":"1kb"},{"path":"lib/every.js","limit":"1kb"},{"path":"lib/fromPairs.js","limit":"1kb"},{"path":"lib/isPlainObject.js","limit":"1kb"},{"path":"lib/map.js","limit":"1kb"},{"path":"lib/mapValues.js","limit":"1kb"},{"path":"lib/omit.js","limit":"1kb"},{"path":"lib/omitBy.js","limit":"1kb"},{"path":"lib/omitNull.js","limit":"1kb"},{"path":"lib/pad.js","limit":"1kb"},{"path":"lib/pick.js","limit":"1kb"},{"path":"lib/pickBy.js","limit":"1kb"},{"path":"lib/set.js","limit":"1kb"},{"path":"lib/setProps.js","limit":"1kb"},{"path":"lib/toPairs.js","limit":"1kb"},{"path":"lib/types.js","limit":"1kb"},{"path":"lib/uniq.js","limit":"1kb"},{"path":"lib/uniqBy.js","limit":"1kb"}],"///":"//////////========================/////////========================/////////========================/////////","repository":{"type":"git","url":"git+https://github.com/isuvorov/fishdash.git"},"homepage":"https://github.com/isuvorov/fishdash","bugs":{"url":"https://github.com/isuvorov/fishdash/issues"},"license":"MIT","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"keywords":["utility","library","typescript","esm","es6","functional","programming","utils","helpers"],"////":"/////////========================/////////========================/////////========================/////////","_id":"2dollars@1.0.3","gitHead":"2c72a40f30b6efe42d05b9d3f54efffd1d13aaf4","_nodeVersion":"24.10.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-KMSn+WFQLf4z7+1V3hjGMArOTq2ahhEf88ZLmkNWyP+n4OYjbIN/OSQzZ94FehJx3W9sDMeI5dsSD4RH/hGwgQ==","shasum":"995941dd7fdcb47791c83745bb9564ae0a8dbe4d","tarball":"https://registry.npmjs.org/2dollars/-/2dollars-1.0.3.tgz","fileCount":58,"unpackedSize":65167,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGpX32L8ak7nrv1Z7MU8mmanBaesR/v9bimVWzWdEWg4AiEA+IXyrTbbrDdtdHu71wURHiu2WNADoX1VBkE+euoBaEI="}]},"_npmUser":{"name":"isuvorov","email":"hi@isuvorov.com"},"directories":{},"maintainers":[{"name":"isuvorov","email":"hi@isuvorov.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/2dollars_1.0.3_1761656900584_0.16697419845654649"},"_hasShrinkwrap":false}},"time":{"created":"2015-06-25T06:23:01.782Z","modified":"2025-10-28T13:08:20.966Z","1.0.0":"2015-06-25T06:23:01.782Z","1.0.1":"2015-08-02T11:53:27.294Z","1.0.2":"2015-08-02T12:02:30.719Z","1.0.3":"2025-10-28T13:08:20.771Z"},"bugs":{"url":"https://github.com/isuvorov/fishdash/issues"},"license":"MIT","homepage":"https://github.com/isuvorov/fishdash","repository":{"type":"git","url":"git+https://github.com/isuvorov/fishdash.git"},"description":"Functional utility library for modern TypeScript, ESM, ES6+","maintainers":[{"name":"isuvorov","email":"hi@isuvorov.com"}],"readme":"# Fishdash\n\n[![NPM version](https://badgen.net/npm/v/fishdash)](https://www.npmjs.com/package/fishdash)\n[![Tests](https://github.com/isuvorov/fishdash/actions/workflows/release.yml/badge.svg)](https://github.com/isuvorov/fishdash/actions/workflows/npm-publish.yml)\n[![Install size](https://packagephobia.now.sh/badge?p=fishdash)](https://packagephobia.now.sh/result?p=fishdash)\n[![Bundle size](https://img.shields.io/bundlephobia/minzip/fishdash.svg)](https://bundlephobia.com/result?p=fishdash)\n[![License](https://badgen.net//github/license/isuvorov/fishdash)](https://github.com/isuvorov/fishdash/blob/master/LICENSE)\n[![Ask me in Telegram](https://img.shields.io/badge/Ask%20me%20in-Telegram-brightblue.svg)](https://t.me/isuvorov)\n\n<div align=\"center\">\n  <img src=\"https://isuvorov.github.io/fishdash/logo.png\" align=\"right\" width=\"120\" height=\"120\" />\n  <p>Modern utility library inspired by Lodash, built with <strong>ESM6</strong> and <strong>TypeScript</strong></p>\n</div>\n\n[![npm version](https://img.shields.io/npm/v/fishdash.svg)](https://www.npmjs.com/package/fishdash)\n[![Bundle Size](https://img.shields.io/bundlephobia/minzip/fishdash)](https://bundlephobia.com/package/fishdash)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\n[![ESM](https://img.shields.io/badge/ESM-Ready-brightgreen.svg)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)\n\n## Features\n\n- **🚀 Modern**: Built with ESM6 modules and TypeScript\n- **🪶 Lightweight**: Tree-shakable functions for optimal bundle size\n- **💪 Type-safe**: Full TypeScript support with comprehensive type definitions\n- **⚡ Fast**: Optimized algorithms for maximum performance\n- **🎯 Focused**: Essential utility functions without bloat\n- **📦 Zero Dependencies**: No external dependencies\n\n## Installation\n\n### Package Manager\n\nUsing npm:\n```bash\nnpm install fishdash\n```\n\nUsing yarn:\n```bash\nyarn add fishdash\n```\n\nUsing pnpm:\n```bash\npnpm add fishdash\n```\n\nUsing bun:\n```bash\nbun add fishdash\n```\n\n### Import\n\nImport specific functions (recommended for tree-shaking):\n```typescript\nimport { map, groupBy, pick } from 'fishdash';\n```\n\nImport all functions:\n```typescript\nimport fishdash from 'fishdash';\n// or\nimport * as fishdash from 'fishdash';\n```\n\n## Quick Start\n\n```typescript\nimport { map, groupBy, pick, deepMerge } from 'fishdash';\n\n// Working with arrays\nconst users = [\n  { id: 1, name: 'Alice', age: 25, department: 'Engineering' },\n  { id: 2, name: 'Bob', age: 30, department: 'Engineering' },\n  { id: 3, name: 'Carol', age: 28, department: 'Marketing' }\n];\n\n// Extract names\nconst names = map(users, user => user.name);\n// ['Alice', 'Bob', 'Carol']\n\n// Group by department\nconst byDepartment = groupBy(users, user => user.department);\n// {\n//   Engineering: [{ id: 1, name: 'Alice', ... }, { id: 2, name: 'Bob', ... }],\n//   Marketing: [{ id: 3, name: 'Carol', ... }]\n// }\n\n// Pick specific properties\nconst summary = pick(users[0], ['id', 'name']);\n// { id: 1, name: 'Alice' }\n\n// Deep merge objects\nconst config = deepMerge(\n  { api: { timeout: 5000 } },\n  { api: { retries: 3 }, debug: true }\n);\n// { api: { timeout: 5000, retries: 3 }, debug: true }\n```\n\n## API Reference\n\n### Array Functions\n\n#### `map(object, mapper)`\nTransforms each value in an object using the mapper function and returns an array.\n\n```typescript\nconst users = { user1: { name: 'Alice' }, user2: { name: 'Bob' } };\nconst names = map(users, user => user.name);\n// ['Alice', 'Bob']\n```\n\n#### `groupBy(array, iteratee)`\nGroups array elements by the result of running each element through iteratee.\n\n```typescript\nconst inventory = [\n  { name: 'apple', category: 'fruit' },\n  { name: 'carrot', category: 'vegetable' },\n  { name: 'banana', category: 'fruit' }\n];\n\nconst grouped = groupBy(inventory, item => item.category);\n// {\n//   fruit: [{ name: 'apple', category: 'fruit' }, { name: 'banana', category: 'fruit' }],\n//   vegetable: [{ name: 'carrot', category: 'vegetable' }]\n// }\n```\n\n#### `sortBy(array, iteratee)`\nSorts array elements by the result of running each element through iteratee.\n\n```typescript\nconst users = [\n  { name: 'Charlie', age: 30 },\n  { name: 'Alice', age: 25 },\n  { name: 'Bob', age: 35 }\n];\n\nconst sortedByAge = sortBy(users, user => user.age);\n// [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 30 }, { name: 'Bob', age: 35 }]\n```\n\n#### `uniq(array)` & `uniqBy(array, iteratee)`\nRemoves duplicate values from an array.\n\n```typescript\n// Simple deduplication\nconst numbers = uniq([1, 2, 2, 3, 1, 4]);\n// [1, 2, 3, 4]\n\n// Deduplication by property\nconst users = [\n  { id: 1, name: 'Alice' },\n  { id: 2, name: 'Bob' },\n  { id: 1, name: 'Alice' }\n];\nconst uniqueUsers = uniqBy(users, user => user.id);\n// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n```\n\n#### `count(array, predicate)` & `countBy(array, iteratee)`\nCounts elements in an array.\n\n```typescript\n// Count with predicate\nconst numbers = [1, 2, 3, 4, 5];\nconst evenCount = count(numbers, n => n % 2 === 0);\n// 2\n\n// Count by grouping\nconst fruits = ['apple', 'banana', 'apple', 'orange'];\nconst counts = countBy(fruits, fruit => fruit);\n// { apple: 2, banana: 1, orange: 1 }\n```\n\n### Object Functions\n\n#### `pick(object, keys)` & `pickBy(object, predicate)`\nSelects specific properties from an object.\n\n```typescript\nconst user = { id: 1, name: 'Alice', email: 'alice@example.com', password: 'secret' };\n\n// Pick specific keys\nconst publicInfo = pick(user, ['id', 'name', 'email']);\n// { id: 1, name: 'Alice', email: 'alice@example.com' }\n\n// Pick by predicate\nconst nonSensitive = pickBy(user, (value, key) => key !== 'password');\n// { id: 1, name: 'Alice', email: 'alice@example.com' }\n```\n\n#### `omit(object, keys)` & `omitBy(object, predicate)`\nExcludes specific properties from an object.\n\n```typescript\nconst user = { id: 1, name: 'Alice', email: 'alice@example.com', password: 'secret' };\n\n// Omit specific keys\nconst publicInfo = omit(user, ['password']);\n// { id: 1, name: 'Alice', email: 'alice@example.com' }\n\n// Omit by predicate\nconst withoutEmpty = omitBy({ a: 1, b: '', c: 3, d: null }, value => !value);\n// { a: 1, c: 3 }\n```\n\n#### `mapValues(object, iteratee)`\nTransforms values in an object while preserving keys.\n\n```typescript\nconst scores = { math: 85, science: 92, english: 78 };\nconst grades = mapValues(scores, score => score >= 90 ? 'A' : score >= 80 ? 'B' : 'C');\n// { math: 'B', science: 'A', english: 'C' }\n```\n\n#### `keyBy(array, iteratee)`\nCreates an object keyed by the result of running each array element through iteratee.\n\n```typescript\nconst users = [\n  { id: 1, name: 'Alice' },\n  { id: 2, name: 'Bob' }\n];\nconst usersById = keyBy(users, user => user.id);\n// { 1: { id: 1, name: 'Alice' }, 2: { id: 2, name: 'Bob' } }\n```\n\n#### `deepMerge(...objects)`\nRecursively merges objects, concatenating arrays.\n\n```typescript\nconst obj1 = {\n  api: { timeout: 5000 },\n  features: ['auth']\n};\n\nconst obj2 = {\n  api: { retries: 3 },\n  features: ['logging'],\n  debug: true\n};\n\nconst merged = deepMerge(obj1, obj2);\n// {\n//   api: { timeout: 5000, retries: 3 },\n//   features: ['auth', 'logging'],\n//   debug: true\n// }\n```\n\n### Utility Functions\n\n#### `fromPairs(pairs)` & `toPairs(object)`\nConverts between arrays of key-value pairs and objects.\n\n```typescript\n// From pairs to object\nconst pairs = [['a', 1], ['b', 2], ['c', 3]];\nconst obj = fromPairs(pairs);\n// { a: 1, b: 2, c: 3 }\n\n// From object to pairs\nconst object = { x: 1, y: 2 };\nconst converted = toPairs(object);\n// [['x', 1], ['y', 2]]\n```\n\n#### `set(object, path, value)` & `setProps(object, props)`\nSets values in objects.\n\n```typescript\n// Set nested property\nconst user = {};\nset(user, 'profile.name', 'Alice');\n// { profile: { name: 'Alice' } }\n\n// Set multiple properties\nconst updated = setProps(user, { age: 25, 'profile.email': 'alice@example.com' });\n// { profile: { name: 'Alice', email: 'alice@example.com' }, age: 25 }\n```\n\n#### `pad(string, length, chars)`\nPads a string to a specified length.\n\n```typescript\nconst padded = pad('hello', 10, '-');\n// '--hello---'\n```\n\n### Conditional Functions\n\n#### `any(array, predicate)` & `every(array, predicate)`\nTests array elements against a predicate.\n\n```typescript\nconst numbers = [1, 2, 3, 4, 5];\n\nconst hasEven = any(numbers, n => n % 2 === 0);\n// true\n\nconst allPositive = every(numbers, n => n > 0);\n// true\n```\n\n#### `maxBy(array, iteratee)` & `minBy(array, iteratee)`\nFinds maximum/minimum values by a given criteria.\n\n```typescript\nconst users = [\n  { name: 'Alice', age: 25 },\n  { name: 'Bob', age: 30 },\n  { name: 'Carol', age: 22 }\n];\n\nconst oldest = maxBy(users, user => user.age);\n// { name: 'Bob', age: 30 }\n\nconst youngest = minBy(users, user => user.age);\n// { name: 'Carol', age: 22 }\n```\n\n## Type Definitions\n\nFishdash includes comprehensive TypeScript definitions:\n\n```typescript\n// Generic mapper function type\ntype ObjectMapper<T> = (value: T, key?: string | number) => any;\n\n// Object-like type for flexible input\ntype ObjectLike<T> = Record<string | number, T>;\n\n// All functions are properly typed for intellisense and type safety\nconst users: User[] = [/* ... */];\nconst names: string[] = map(users, user => user.name); // Type-safe!\n```\n\n## Tree Shaking\n\nFishdash is built with tree-shaking in mind. Import only what you need:\n\n```typescript\n// ✅ Good - only imports the functions you use\nimport { map, filter } from 'fishdash';\n\n// ❌ Avoid - imports the entire library\nimport fishdash from 'fishdash';\nconst result = fishdash.map(/* ... */);\n```\n\n## Browser Support\n\nFishdash supports all modern browsers that support ES6+ features:\n\n- Chrome 61+\n- Firefox 60+\n- Safari 11+\n- Edge 79+\n\n## Performance\n\nFishdash is optimized for performance while maintaining readability:\n\n- Minimal runtime overhead\n- Efficient algorithms\n- No unnecessary object creation\n- Optimized for V8 engine\n\n## Inspired by\n\n- [Lodash](https://lodash.com/) - A modern JavaScript utility library delivering modularity, performance & extras\n- [Ramda](https://ramdajs.com/) - A practical functional library for JavaScript programmers\n- [Underscore.js](https://underscorejs.org/) - JavaScript's utility belt\n\n## How to write TypeScript Libraries in 2025-2026\n\n- [Building a TypeScript Library in 2025](https://dev.to/arshadyaseen/building-a-typescript-library-in-2025-2h0i)\n- \n\n## Contributing\n\nWe welcome contributions! Please follow these steps:\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes and add tests\n4. Ensure all tests pass (`npm test`)\n5. Commit your changes (`git commit -m 'Add some amazing feature'`)\n6. Push to the branch (`git push origin feature/amazing-feature`)\n7. Open a Pull Request\n\nPlease read our [Contributing Guide](CONTRIBUTING.md) for detailed information.\n\n## Resources\n\n- [Documentation](https://isuvorov.github.io/fishdash/)\n- [GitHub Repository](https://github.com/isuvorov/fishdash)\n- [NPM Package](https://www.npmjs.com/package/fishdash)\n- [Issues & Bug Reports](https://github.com/isuvorov/fishdash/issues)\n\n## License\n\nMIT © [Igor Suvorov](https://github.com/isuvorov)\n\n---\n\n**fishdash** - _Swimming in utilities_ 🐠\n","readmeFilename":"README.md","keywords":["utility","library","typescript","esm","es6","functional","programming","utils","helpers"],"author":{"name":"Igor Suvorov","email":"hi@isuvorov.com","url":"https://github.com/isuvorov"}}