{"id":36955164,"url":"https://github.com/phederal/pools","last_synced_at":"2026-01-13T13:01:55.588Z","repository":{"id":328003032,"uuid":"1113676639","full_name":"phederal/pools","owner":"phederal","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-10T20:14:36.000Z","size":170,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-11T02:26:42.176Z","etag":null,"topics":["array","bun","pool","pools"],"latest_commit_sha":null,"homepage":"https://phederal.github.io/pools/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phederal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-10T10:03:06.000Z","updated_at":"2025-12-10T20:14:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/phederal/pools","commit_stats":null,"previous_names":["phederal/pools"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/phederal/pools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phederal%2Fpools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phederal%2Fpools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phederal%2Fpools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phederal%2Fpools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phederal","download_url":"https://codeload.github.com/phederal/pools/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phederal%2Fpools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28385806,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T12:01:30.995Z","status":"ssl_error","status_checked_at":"2026-01-13T12:00:09.625Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["array","bun","pool","pools"],"created_at":"2026-01-13T13:01:55.236Z","updated_at":"2026-01-13T13:01:55.582Z","avatar_url":"https://github.com/phederal.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pools\n\n\u003e Lightweight TypeScript library for managing data collections with filters, sorting, and composition\n\n## What is Pools?\n\n**Pools** is a modern TypeScript library that replaces arrays, objects, and Maps with a powerful abstraction for working with collections. Think of it as a smart wrapper around your data that gives you filtering, sorting, metadata tracking, and pool composition out of the box.\n\n### Not a replacement for:\n\n-   ORMs or databases\n-   Processing millions of records\n-   Enterprise frameworks\n\n### Perfect for:\n\n-   Daily work with collections in memory\n-   Managing pools of resources (proxies, accounts, sessions)\n-   Quick prototyping with typed data\n-   Building tools that need smart data selection\n\n## Installation\n\n```bash\nbun install\n```\n\n## Quick Start\n\n```typescript\nimport { Pool, Selectors } from './src';\n\ninterface Proxy {\n\tip: string;\n\tcountry: string;\n\tspeed: number;\n}\n\nconst proxies = new Pool\u003cProxy\u003e();\n\n// Add data with metadata\nproxies.add({ ip: '1.1.1.1', country: 'US', speed: 100 }, { usedCount: 0, active: true });\n\n// Query with filters and sorting\nconst bestProxy = proxies\n\t.query()\n\t.where((e) =\u003e e.data.country === 'US')\n\t.where((e) =\u003e e.meta.active === true)\n\t.orderBy('speed', 'desc')\n\t.select(Selectors.first);\n\nconsole.log(bestProxy); // { ip: '1.1.1.1', country: 'US', speed: 100 }\n\n// Pool of pools - store pools as data\nconst usProxies = new Pool\u003cProxy\u003e();\nconst ukProxies = new Pool\u003cProxy\u003e();\nconst poolOfPools = new Pool\u003cPool\u003cProxy\u003e\u003e();\npoolOfPools.add(usProxies);\npoolOfPools.add(ukProxies);\n```\n\n## Core Concepts\n\n### PoolEntry\u003cT\u003e\n\nEvery item in a pool is wrapped in a `PoolEntry`:\n\n```typescript\ntype PoolEntry\u003cT\u003e = {\n\tdata: T; // Your data\n\tmeta: Record\u003cstring, any\u003e; // Metadata (usage stats, flags, etc.)\n};\n```\n\n### Filter\u003cT\u003e\n\nA function that decides whether to include an entry:\n\n```typescript\ntype Filter\u003cT\u003e = (entry: PoolEntry\u003cT\u003e) =\u003e boolean;\n\n// Example\nconst usFilter = (e) =\u003e e.data.country === 'US';\n```\n\n### Selector\u003cT\u003e\n\nA function that picks one entry from filtered results:\n\n```typescript\ntype Selector\u003cT\u003e = (entries: PoolEntry\u003cT\u003e[]) =\u003e PoolEntry\u003cT\u003e | null;\n\n// Built-in selectors\nSelectors.first; // First entry\nSelectors.last; // Last entry\nSelectors.random; // Random entry\nSelectors.minBy('field'); // Entry with minimum value\nSelectors.weighted(fn); // Weighted random\n```\n\n## API Reference\n\n### Pool\u003cT\u003e\n\n#### Creating Pools\n\n```typescript\n// Empty pool\nconst pool = new Pool\u003cProxy\u003e();\n\n// Pool of pools - pools as data\nconst usProxies = new Pool\u003cProxy\u003e();\nconst ukProxies = new Pool\u003cProxy\u003e();\nconst poolOfPools = new Pool\u003cPool\u003cProxy\u003e\u003e();\npoolOfPools.add(usProxies);\npoolOfPools.add(ukProxies);\n\n// Query pools from pool of pools\nconst bestPool = poolOfPools\n\t.query()\n\t.where((e) =\u003e e.data.size \u003e 10)\n\t.select(Selectors.first);\n```\n\n#### CRUD Operations\n\n```typescript\n// Add single entry\npool.add({ ip: '1.1.1.1', country: 'US', speed: 100 }, { usedCount: 0 });\n\n// Add batch\npool.addBatch([\n\t{ data: { ip: '2.2.2.2', country: 'UK', speed: 200 }, meta: {} },\n\t{ data: { ip: '3.3.3.3', country: 'DE', speed: 150 }, meta: {} },\n]);\n\n// Remove entries\npool.remove((data) =\u003e data.country === 'UK');\n\n// Remove batch\npool.removeBatch([(data) =\u003e data.country === 'UK', (data) =\u003e data.speed \u003c 100]);\n```\n\n#### Map-like Operations\n\n```typescript\n// Get by field (like Map.get)\nconst proxy = pool.get('ip', '1.1.1.1');\n\n// Get by predicate\nconst fastProxy = pool.get((e) =\u003e e.data.speed \u003e 200);\n\n// Check existence (like Map.has)\nconst exists = pool.has('ip', '1.1.1.1');\nconst hasFast = pool.has((e) =\u003e e.data.speed \u003e 200);\n\n// Set (update or add)\npool.set('ip', '1.1.1.1', { ip: '1.1.1.1', country: 'US', speed: 150 });\n\n// Delete (like Map.delete)\nconst deleted = pool.delete('ip', '1.1.1.1'); // returns boolean\n```\n\n#### Query API\n\n```typescript\n// Build queries with chaining\nconst result = pool\n\t.query()\n\t.where((e) =\u003e e.data.country === 'US')\n\t.where((e) =\u003e e.meta.active === true)\n\t.orderBy('speed', 'desc')\n\t.orderByMeta('usedCount', 'asc')\n\t.limit(10)\n\t.toArray();\n\n// Select single entry\nconst proxy = pool\n\t.query()\n\t.where((e) =\u003e e.data.country === 'US')\n\t.select(Selectors.random);\n\n// Convert query to pool\nconst usProxies = pool\n\t.query()\n\t.where((e) =\u003e e.data.country === 'US')\n\t.toPool();\n```\n\n#### Events\n\n```typescript\n// Auto-update metadata on use\npool.on('get', (entry) =\u003e {\n\tentry.meta.usedCount++;\n\tentry.meta.lastUsed = new Date();\n});\n\n// Logging\npool.on('add', (entry) =\u003e {\n\tconsole.log(`Added: ${entry.data.ip}`);\n});\n\n// Available events:\n// 'add', 'remove', 'get', 'set'\n// 'batchAdd', 'batchRemove'\n// 'beforeSelect', 'afterSelect'\n```\n\n#### Combining Pools\n\n```typescript\nconst pool1 = new Pool\u003cProxy\u003e();\nconst pool2 = new Pool\u003cProxy\u003e();\n\n// Merge all\npool1.merge(pool2);\n\n// Merge unique by field\npool1.mergeUnique(pool2, 'ip');\n\n// Merge unique by function\npool1.mergeUnique(pool2, (p) =\u003e `${p.ip}:${p.provider}`);\n\n// Union (no duplicates)\npool1.union(pool2, (a, b) =\u003e a.ip === b.ip);\n\n// Intersect (only common)\npool1.intersect(pool2, (a, b) =\u003e a.ip === b.ip);\n\n// Difference (remove items from other)\npool1.difference(pool2, (a, b) =\u003e a.ip === b.ip);\n\n// Remove duplicates\npool.deduplicate('ip');\n```\n\n#### Transformations\n\n```typescript\n// Clone\nconst backup = pool.clone();\n\n// Partition into two pools\nconst [active, inactive] = pool.partition((e) =\u003e e.meta.active === true);\n\n// Random sample\nconst sample = pool.sample(10);\n\n// Shuffle in place\npool.shuffle();\n\n// Group by field\nconst byCountry = pool.groupBy('country');\n// Map\u003cstring, Pool\u003cProxy\u003e\u003e\n\n// Group by function\nconst bySpeed = pool.groupBy((p) =\u003e (p.speed \u003e 200 ? 'fast' : 'slow'));\n```\n\n#### Static Methods\n\n```typescript\n// Merge multiple pools\nconst merged = Pool.merge(pool1, pool2, pool3);\n\n// Merge unique\nconst unique = Pool.mergeUnique([pool1, pool2], 'ip');\n\n// Merge with conflict resolution\nconst best = Pool.mergeUniqueWith([pool1, pool2], 'ip', (existing, duplicate) =\u003e (existing.data.speed \u003e duplicate.data.speed ? existing : duplicate));\n\n// Intersect two pools\nconst common = Pool.intersect(pool1, pool2, (a, b) =\u003e a.provider === b.provider);\n\n// Group multiple sources\nconst groups = Pool.groupBy([pool1, pool2, pool3], 'country');\n```\n\n#### Properties\n\n```typescript\npool.size; // Number of entries\npool.all; // Array of data objects\npool.allEntries; // Array of PoolEntry objects\n```\n\n#### Method Wrapping\n\n```typescript\n// Wrap methods to add custom behavior\npool.wrap('add', (original, data, meta) =\u003e {\n\tconsole.log('Before add');\n\tconst result = original(data, meta);\n\tconsole.log('After add');\n\treturn result;\n});\n\n// Example: Database sync\npool.wrap('add', async (original, data, meta) =\u003e {\n\tconst entry = original(data, meta);\n\tawait db.insert('proxies', { data, meta });\n\treturn entry;\n});\n```\n\n### Query\u003cT\u003e\n\n```typescript\nconst query = pool.query();\n\n// Filtering\nquery.where((e) =\u003e e.data.country === 'US');\nquery.whereOr([(e) =\u003e e.data.provider === 'A', (e) =\u003e e.data.provider === 'B']);\n\n// Sorting (chainable)\nquery.orderBy('speed', 'desc');\nquery.orderBy((a, b) =\u003e a.data.speed - b.data.speed);\nquery.orderByMeta('usedCount', 'asc');\n\n// Pagination\nquery.offset(20).limit(10);\n\n// Materialization\nquery.select(Selectors.first); // Single entry\nquery.toArray(); // Array of data\nquery.toPool(); // Convert query to Pool\nquery.count; // Number of entries\n```\n\n### Binder\n\nBind multiple pools together for complex selections:\n\n```typescript\nconst combo = new Binder()\n\t.bind('proxy', proxies)\n\t.bind('account', accounts)\n\t.bind('service', services)\n\t.where('proxy', (e) =\u003e e.data.country === 'US')\n\t.where('account', (e) =\u003e e.data.service === 'twitter')\n\t.selectWith('proxy', Selectors.minBy('usedCount'))\n\t.selectWith('account', Selectors.random)\n\t.execute();\n\n// Result:\n// {\n//   proxy: { ip: '1.1.1.1', ... },\n//   account: { username: 'user1', ... },\n//   service: { name: 'API', ... }\n// }\n\n// Returns null if any pool has no matching entry\n```\n\n### Built-in Selectors\n\n```typescript\nimport { Selectors } from './src';\n\n// Random entry\npool.query().select(Selectors.random);\n\n// First entry\npool.query().select(Selectors.first);\n\n// Last entry\npool.query().select(Selectors.last);\n\n// Minimum by field (checks both data and meta)\npool.query().select(Selectors.minBy('usedCount'));\n\n// Weighted random (higher weight = higher probability)\npool.query().select(Selectors.weighted((entry) =\u003e 1 / (entry.meta.usedCount + 1)));\n```\n\n## Examples\n\n### Basic Usage\n\nSee [examples/basic.ts](examples/basic.ts):\n\n```bash\nbun run examples/basic.ts\n```\n\n### Proxy Pool Management\n\nSee [examples/proxy-pool.ts](examples/proxy-pool.ts):\n\n```bash\nbun run examples/proxy-pool.ts\n```\n\nThis example demonstrates:\n\n-   CRUD operations\n-   Event handling\n-   Complex queries with multiple filters\n-   Pool combination\n-   Transformations\n-   Binder usage\n-   Weighted selectors\n\n### Map-like Usage\n\nSee [examples/map-like.ts](examples/map-like.ts):\n\n```bash\nbun run examples/map-like.ts\n```\n\nThis example demonstrates:\n\n-   Using Pool as a Map replacement\n-   get/has/set/delete operations\n-   Pool of pools with identifiers\n-   Cache implementation\n-   Config management\n\n### Game Service\n\nSee [examples/game-service.ts](examples/game-service.ts):\n\n```bash\nbun run examples/game-service.ts\n```\n\nComprehensive example demonstrating ALL library features:\n\n-   Multiple interconnected pools (games, accounts, servers, sessions)\n-   Complex matchmaking logic\n-   Event-driven architecture\n-   Pool of pools for regional organization\n-   Weighted server selection\n-   Statistics and analytics\n\n## Use Cases\n\n### Managing Proxies\n\n```typescript\nconst proxies = new Pool\u003cProxy\u003e();\n\n// Auto-track usage\nproxies.on('get', (entry) =\u003e {\n\tentry.meta.usedCount++;\n\tentry.meta.lastUsed = new Date();\n});\n\n// Get least-used US proxy\nconst proxy = proxies\n\t.query()\n\t.where((e) =\u003e e.data.country === 'US')\n\t.where((e) =\u003e e.meta.active)\n\t.orderByMeta('usedCount', 'asc')\n\t.select(Selectors.first);\n```\n\n### Session Management\n\n```typescript\nconst sessions = new Pool\u003cSession\u003e();\n\n// Auto-expire old sessions\nsessions.on('get', (entry) =\u003e {\n\tif (Date.now() - entry.meta.lastUsed \u003e 3600000) {\n\t\tentry.meta.expired = true;\n\t}\n});\n\n// Get valid session\nconst session = sessions\n\t.query()\n\t.where((e) =\u003e !e.meta.expired)\n\t.select(Selectors.random);\n```\n\n### Resource Allocation\n\n```typescript\n// Bind proxy + account + service\nconst resources = new Binder()\n\t.bind('proxy', proxies)\n\t.bind('account', accounts)\n\t.bind('service', services)\n\t.where('proxy', (e) =\u003e e.meta.usedCount \u003c 10)\n\t.where('account', (e) =\u003e !e.meta.banned)\n\t.selectWith('proxy', Selectors.minBy('usedCount'))\n\t.selectWith('account', Selectors.random)\n\t.execute();\n\nif (resources) {\n\tawait doTask(resources.proxy, resources.account, resources.service);\n}\n```\n\n## TypeScript Support\n\nFull TypeScript support with generic types:\n\n```typescript\ninterface MyData {\n\tid: number;\n\tname: string;\n}\n\nconst pool = new Pool\u003cMyData\u003e();\n\n// TypeScript knows the type\nconst result = pool.query().select(Selectors.first);\n// result: MyData | null\n\n// Autocomplete works\nresult?.name; // ✓\nresult?.invalid; // ✗ TypeScript error\n```\n\n## Performance\n\nPools is designed for collections of hundreds to thousands of items. For very large datasets (100k+ items), consider:\n\n-   Using pagination with `offset()` and `limit()`\n-   Filtering early to reduce the working set\n-   Using `query.toPool()` to cache filtered results\n\n## Project Structure\n\n```\npools/\n├── src/\n│   ├── types.ts       # Core types\n│   ├── Pool.ts        # Main Pool class\n│   ├── Query.ts   # Query builder\n│   ├── Binder.ts  # Multi-pool binding\n│   ├── Selectors.ts   # Built-in selectors\n│   └── index.ts       # Public API\n├── examples/\n│   ├── basic.ts       # Basic usage\n│   └── proxy-pool.ts  # Advanced example\n└── README.md\n```\n\n## License\n\nMIT\n\n## Contributing\n\nContributions welcome! This is a learning project but pull requests and issues are appreciated.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphederal%2Fpools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphederal%2Fpools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphederal%2Fpools/lists"}