@supercharge/collections
Advanced tools
Comparing version 2.4.0 to 3.0.0
# Changelog | ||
## [3.0.0](https://github.com/supercharge/collections/compare/v2.4.0...v3.0.0) - 2020-09-03 | ||
### Added | ||
- synchronous collections by default | ||
- all collections were **async** by default until versions `2.x`, you had to await every collection pipeline | ||
- this changes with the release of version `3.0`: all collections are **sync** by default | ||
- synchronous collections work like JavaScript’s array methods | ||
- you must explicitly call `collection.all()` to retrieve the resulting array from a synchronous collection | ||
- a collection becomes async as soon as you provide an **async callback method** to methods like `map`, `filter`, `find`, and so on: | ||
### Updated | ||
- bump dependencies | ||
- change `main` entrypoint in `package.json` to `dist` folder | ||
### Removed | ||
- remove `index.js` file which acted as a middleman to export from `dist` folder | ||
### Breaking Changes | ||
- collections are now synchronous by default, meaning you don’t need to await a collection if you’re not using an async callback | ||
#### Sync Collections | ||
Synchronous collections work like JavaScript’s Array methods. For example, the following pipeline stays a synchronous pipeline: | ||
```js | ||
const Collect = require('@supercharge/collections') | ||
const collection = Collect([1, 2, 3, 4, 5]) | ||
.map(item => item * 2) | ||
.filter(item => item > 5) | ||
.sort((a, b) => b -a) | ||
// on sync collections, you must explicitly call `.all()` to retrieve the result | ||
const result = collection.all() | ||
// [10, 8, 6] | ||
``` | ||
#### Async Collections | ||
In comparison, a collection becomes async as soon as you provide an async callback method to methods like `map`, `filter`, `find`, and so on: | ||
```js | ||
const Collect = require('@supercharge/collections') | ||
const collection = Collect([1, 2, 3, 4, 5]) | ||
.map(async item => item * 2) // the collection is async from here on | ||
.filter(item => item > 5) | ||
.sort((a, b) => b -a) | ||
// async collections must be awaited | ||
const result = await collection | ||
// [10, 8, 6] | ||
``` | ||
## [2.4.0](https://github.com/supercharge/collections/compare/v2.3.0...v2.4.0) - 2020-07-21 | ||
@@ -4,0 +59,0 @@ |
@@ -0,1 +1,15 @@ | ||
interface QueueItem { | ||
/** | ||
* Stores the parameter data for the collection method. | ||
*/ | ||
data?: any; | ||
/** | ||
* Identifies the collection method. | ||
*/ | ||
method: string; | ||
/** | ||
* Stores the user-land callback processing in the collection method. | ||
*/ | ||
callback?: Function; | ||
} | ||
export declare class CollectionProxy<T> { | ||
@@ -17,3 +31,3 @@ /** | ||
*/ | ||
constructor(items: T[], callChain?: any[]); | ||
constructor(items: T[], callChain?: QueueItem[]); | ||
/** | ||
@@ -462,1 +476,2 @@ * Alias for the `.some` method. This function determines | ||
} | ||
export {}; |
@@ -15,5 +15,5 @@ 'use strict'; | ||
*/ | ||
constructor(items, callChain = []) { | ||
constructor(items, callChain) { | ||
this.items = [].concat(items || []); | ||
this.callChain = new queue_datastructure_1.default(callChain); | ||
this.callChain = new queue_datastructure_1.default(...callChain !== null && callChain !== void 0 ? callChain : []); | ||
} | ||
@@ -588,2 +588,3 @@ /** | ||
try { | ||
// @ts-expect-error | ||
const { method, callback, data } = this.callChain.dequeue(); | ||
@@ -590,0 +591,0 @@ collection = await (callback |
@@ -10,3 +10,3 @@ export declare class Collection { | ||
*/ | ||
all(): Promise<any[]>; | ||
all(): any[]; | ||
/** | ||
@@ -13,0 +13,0 @@ * Returns the average of all collection items. |
@@ -14,3 +14,3 @@ 'use strict'; | ||
*/ | ||
async all() { | ||
all() { | ||
return this.items; | ||
@@ -252,3 +252,3 @@ } | ||
isEmpty() { | ||
return this.items.length === 0; | ||
return this.size() === 0; | ||
} | ||
@@ -261,3 +261,3 @@ /** | ||
isNotEmpty() { | ||
return this.items.length > 0; | ||
return !this.isEmpty(); | ||
} | ||
@@ -282,3 +282,3 @@ /** | ||
if (!callback) { | ||
return this.items[this.items.length - 1]; | ||
return this.items[this.size() - 1]; | ||
} | ||
@@ -411,6 +411,5 @@ if (typeof callback === 'function') { | ||
async reduce(reducer, accumulator) { | ||
// eslint-disable-next-line | ||
for (const index in this.items) { | ||
accumulator = await reducer(accumulator, this.items[index], index, this.items); | ||
} | ||
await this.forEach(async (item, index) => { | ||
accumulator = await reducer(accumulator, item, index, this.items); | ||
}); | ||
return accumulator; | ||
@@ -429,3 +428,3 @@ } | ||
async reduceRight(reducer, accumulator) { | ||
let index = this.items.length; | ||
let index = this.size(); | ||
while (index--) { | ||
@@ -487,3 +486,5 @@ accumulator = await reducer(accumulator, this.items[index], index, this.items); | ||
const chunk = this.items.slice(start); | ||
return chunk.slice(0, limit); | ||
return typeof limit === 'number' | ||
? chunk.slice(0, limit) | ||
: chunk.slice(0); | ||
} | ||
@@ -504,3 +505,3 @@ /** | ||
const flattend = Array.prototype.concat(...inserts); | ||
this.items.splice(start, limit || this.items.length, ...flattend); | ||
this.items.splice(start, limit, ...flattend); | ||
return this.items.slice(0); | ||
@@ -507,0 +508,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { CollectionProxy } from './collection-proxy'; | ||
import { SyncCollection } from './sync-collection'; | ||
/** | ||
@@ -8,5 +8,5 @@ * Create a new collection for the given `items`. The `items` | ||
* | ||
* @returns {CollectionProxy} | ||
* @returns {SyncCollection} | ||
*/ | ||
declare const collect: <T>(collection: T[]) => CollectionProxy<T>; | ||
declare const collect: <T>(collection: T[]) => SyncCollection<T>; | ||
export = collect; |
'use strict'; | ||
const collection_proxy_1 = require("./collection-proxy"); | ||
const sync_collection_1 = require("./sync-collection"); | ||
/** | ||
@@ -9,7 +9,7 @@ * Create a new collection for the given `items`. The `items` | ||
* | ||
* @returns {CollectionProxy} | ||
* @returns {SyncCollection} | ||
*/ | ||
const collect = (collection) => { | ||
return new collection_proxy_1.CollectionProxy(collection); | ||
return new sync_collection_1.SyncCollection(collection); | ||
}; | ||
module.exports = collect; |
{ | ||
"name": "@supercharge/collections", | ||
"description": "Supercharge collections", | ||
"version": "2.4.0", | ||
"version": "3.0.0", | ||
"author": "Marcus Pöhls <marcus@superchargejs.com>", | ||
@@ -10,18 +10,19 @@ "bugs": { | ||
"dependencies": { | ||
"@supercharge/queue-datastructure": "~1.3.1" | ||
"@supercharge/goodies": "~1.5.1", | ||
"@supercharge/queue-datastructure": "~2.1.0" | ||
}, | ||
"devDependencies": { | ||
"@hapi/code": "~7.0.0", | ||
"@hapi/lab": "~21.0.0", | ||
"@hapi/code": "~8.0.2", | ||
"@hapi/lab": "~23.0.0", | ||
"@supercharge/tsconfig": "~1.0.0", | ||
"@typescript-eslint/eslint-plugin": "~2.34.0", | ||
"eslint": "~6.8.0", | ||
"@typescript-eslint/eslint-plugin": "~4.0.1", | ||
"eslint": "~7.8.1", | ||
"eslint-config-standard": "~14.1.1", | ||
"eslint-config-standard-with-typescript": "~16.0.0", | ||
"eslint-plugin-import": "~2.20.2", | ||
"eslint-config-standard-with-typescript": "~19.0.1", | ||
"eslint-plugin-import": "~2.22.0", | ||
"eslint-plugin-node": "~11.1.0", | ||
"eslint-plugin-promise": "~4.2.1", | ||
"eslint-plugin-standard": "~4.0.1", | ||
"sinon": "~8.1.1", | ||
"typescript": "~3.9.5" | ||
"sinon": "~9.0.3", | ||
"typescript": "~4.0.2" | ||
}, | ||
@@ -32,4 +33,3 @@ "engines": { | ||
"files": [ | ||
"dist", | ||
"index.js" | ||
"dist" | ||
], | ||
@@ -53,3 +53,3 @@ "homepage": "https://github.com/supercharge/collections", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"main": "dist", | ||
"publishConfig": { | ||
@@ -56,0 +56,0 @@ "access": "public" |
@@ -32,2 +32,6 @@ <div align="center"> | ||
## Introduction | ||
The `@supercharge/collections` package provides a convenient wrapper to work with arrays. | ||
## Installation | ||
@@ -47,36 +51,65 @@ | ||
The package is async/await-ready and supports async functions for most of the methods. | ||
### Sync Collections by default | ||
A created collection (`Collect([1, 2, 3])`) is synchronous by default. That means it behaves like JavaScript’s array methods. | ||
In contrast to JavaScript’s array methods, collections have a lot more methods available making your code a lot simpler. Here are basic examples using a collection: | ||
```js | ||
const User = require('models/user') | ||
const User = require('../models/user') | ||
const Collect = require('@supercharge/collections') | ||
const users = await Collect( | ||
await User.all() | ||
) | ||
.filter(async user => { | ||
return user.notSubscribedToNewsletter() | ||
}) | ||
.map(async user => { | ||
await user.subscribeToNewsletter() | ||
const users = await User.findAll() | ||
return user | ||
const notSubscribedUsers = Collect(users) | ||
.filter(user => { | ||
return user.notSubscribedToNewsletter | ||
}) | ||
.all() | ||
// users = [ <list of newly-subscribed users> ] | ||
// notSubscribedUsers = [ <list of not-yet-subscribed users> ] | ||
``` | ||
You can directly await the result for methods returning a definite value. The function returns a new instance of the collection without altering the original input array: | ||
Here’s another example outlining how to determine whether the array “has” an item: | ||
```js | ||
await Collect([ 1, 2, 3 ]) | ||
.map(item => item * 100) | ||
.reduce((carry, item) => { | ||
return carry + item | ||
}, 0) | ||
// “has” in JS Arrays | ||
const hasNotSubscribedUsers = !![].concat(users).find(user => { | ||
return user.notSubscribedToNewsletter | ||
}) | ||
// result: 600 | ||
// “has” in Collections | ||
const hasNotSubscribedUsers = Collect(users).has(user => { | ||
return user.notSubscribedToNewsletter | ||
}) | ||
``` | ||
All available methods are outlined in the [docs](https://superchargejs.com/docs/collections). | ||
### Async Collections | ||
The package is async/await-ready and supports async callback functions. A collection becomes async (returns a promise) as soon as you provide an async callback method to methods like `map`, `filter`, `find`, and so on. You then need to `await` the collection pipeline: | ||
```js | ||
const User = require('../models/user') | ||
const Collect = require('@supercharge/collections') | ||
const users = await User.findAll() | ||
const subscribedUsers = await Collect(users) | ||
.filter(user => { | ||
return user.notSubscribedToNewsletter | ||
}) | ||
.map(async user => { // <-- providing an async callback creates an async collection that you need to `await` | ||
await user.subscribeToNewsletter() | ||
return user | ||
}) | ||
// subscribedUsers = [ <list of newly-subscribed users> ] | ||
``` | ||
You can directly await async collections without ending the call chain with `.all()`. You can still call `.all()` though, it works as well. | ||
## Contributing | ||
@@ -83,0 +116,0 @@ Do you miss a collection function? We very much appreciate your contribution! Please send in a pull request 😊 |
169254
16
5294
131
2
+ Added@supercharge/goodies@~1.5.1
+ Added@supercharge/goodies@1.5.1(transitive)
+ Added@supercharge/queue-datastructure@2.1.0(transitive)
- Removed@supercharge/queue-datastructure@1.3.1(transitive)