diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..0bc3b42d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "10:00" + open-pull-requests-limit: 10 + commit-message: + prefix: "deps" + prefix-development: "deps(dev)" diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 00000000..d57c2a02 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,8 @@ +name: Automerge +on: [ pull_request ] + +jobs: + automerge: + uses: protocol/.github/.github/workflows/automerge.yml@master + with: + job: 'automerge' diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml new file mode 100644 index 00000000..d155996c --- /dev/null +++ b/.github/workflows/js-test-and-release.yml @@ -0,0 +1,145 @@ +name: test & maybe release +on: + push: + branches: + - master # with #262 - ${{{ github.default_branch }}} + pull_request: + branches: + - master # with #262 - ${{{ github.default_branch }}} + +jobs: + + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present lint + - run: npm run --if-present dep-check + + test-node: + needs: check + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + node: [16] + fail-fast: true + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node }} + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:node + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: node + + test-chrome: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: chrome + + test-chrome-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:chrome-webworker + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: chrome-webworker + + test-firefox: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: firefox + + test-firefox-webworker: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npm run --if-present test:firefox-webworker + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: firefox-webworker + + test-electron-main: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe npm run --if-present test:electron-main + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: electron-main + + test-electron-renderer: + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - run: npx xvfb-maybe npm run --if-present test:electron-renderer + - uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.1.0 + with: + flags: electron-renderer + + release: + needs: [test-node, test-chrome, test-chrome-webworker, test-firefox, test-firefox-webworker, test-electron-main, test-electron-renderer] + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/master' # with #262 - 'refs/heads/${{{ github.default_branch }}}' + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + with: + node-version: lts/* + - uses: ipfs/aegir/actions/cache-node-modules@master + - uses: ipfs/aegir/actions/docker-login@master + with: + docker-token: ${{ secrets.DOCKER_TOKEN }} + docker-username: ${{ secrets.DOCKER_USERNAME }} + - run: npm run --if-present release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 213d3a80..c791b991 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,83 @@ -# it - -Utility modules to make dealing with async iterators easier, some trivial, some not. - -* [blob-to-it](./packages/blob-to-it) Turn a Blob into an iterable -* [browser-readablestream-to-it](./packages/browser-readablestream-to-it) Turn a browser ReadableStream into an iterable -* [it-all](./packages/it-all) Collect the contents of an iterable into an array -* [it-batch](./packages/it-batch) Batch up the contents of an iterable into arrays -* [it-buffer-stream](./packages/it-buffer-stream) Creates an iterable of buffers -* [it-drain](./packages/it-drain) Consume an iterable and ignore any output -* [it-filter](./packages/it-filter) Skip some items in an iterable based on a filter function -* [it-first](./packages/it-first) Return the first item in an iterable -* [it-flat-batch](./packages/it-flat-batch) Take an iterable of variable length arrays and make them all the same length -* [it-foreach](./packages/it-foreach) Invoke a function for every member of an iterable -* [it-glob](./packages/it-glob) Glob matcher for file systems -* [it-last](./packages/it-last) Return the last item in an iterable -* [it-length](./packages/it-length) Consume an iterable and return its length -* [it-map](./packages/it-map) Map the output of an iterable -* [it-merge](./packages/it-merge) Treat multiple iterables as one -* [it-multipart](./packages/it-multipart) Parse multipart message bodies as an iterable -* [it-ndjson](./packages/it-ndjson) Parse multipart message bodies as an iterable -* [it-parallel](./packages/it-parallel) Take an iterable of functions that return promises and run them in parallel up to a concurrency limit -* [it-parallel-batch](./packages/it-parallel-batch) Take an iterable of functions that return promises and run them in parallel in batches -* [it-peekable](./packages/it-peekable) Peek/push an iterable -* [it-reduce](./packages/it-reduce) Reduce the output of an iterable -* [it-skip](./packages/it-skip) Skip items at the start of an iterable -* [it-sort](./packages/it-sort) Sort an iterable using a passed sort function -* [it-split](./packages/it-split) Split an iterable of buffers by linebreaks -* [it-take](./packages/it-take) Limit the number of items you want from an iterable -* [it-to-browser-readablestream](./packages/it-to-browser-readablestream) Turns an iterable into a WhatWG [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) -* [it-to-buffer](./packages/it-to-buffer) Takes an iterable of Buffers and concatenates them +# it + +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) + +> A collection of utilities for making working with iterables more bearable + +## Table of contents + +- [Structure](#structure) +- [License](#license) +- [Contribute](#contribute) + +## Structure + +- [`/packages/blob-to-it`](./packages/blob-to-it) Turns a blob into an async iterator +- [`/packages/browser-readablestream-to-it`](./packages/browser-readablestream-to-it) Turns a browser readble stream into an async iterator +- [`/packages/it-all`](./packages/it-all) Collects all values from an (async) iterable and returns them as an array +- [`/packages/it-batch`](./packages/it-batch) Takes an async iterator that emits things and emits them as fixed size batches +- [`/packages/it-buffer-stream`](./packages/it-buffer-stream) An async iterator that emits buffers containing bytes up to a certain length +- [`/packages/it-drain`](./packages/it-drain) Empties an async iterator +- [`/packages/it-filter`](./packages/it-filter) Filters the passed iterable by using the filter function +- [`/packages/it-first`](./packages/it-first) Returns the first result from an async iterator +- [`/packages/it-flat-batch`](./packages/it-flat-batch) Takes an async iterator that emits variable length arrays and emits them as fixed size batches +- [`/packages/it-foreach`](./packages/it-foreach) Invokes the passed function for each item in an iterable +- [`/packages/it-glob`](./packages/it-glob) Async iterable filename pattern matcher +- [`/packages/it-last`](./packages/it-last) Returns the last result from an async iterator +- [`/packages/it-length`](./packages/it-length) Counts the number of items in an async iterable +- [`/packages/it-map`](./packages/it-map) Maps the values yielded by an async iterator +- [`/packages/it-merge`](./packages/it-merge) Treat one or more iterables as a single iterable +- [`/packages/it-multipart`](./packages/it-multipart) Async iterable http multipart message parser +- [`/packages/it-ndjson`](./packages/it-ndjson) Parse iterators as ndjson and transform iterators to ndjson +- [`/packages/it-parallel`](./packages/it-parallel) Takes an (async) iterable that emits promise-returning functions, invokes them in parallel up to the concurrency limit and emits the results as they become available, optionally in the same order as the input +- [`/packages/it-parallel-batch`](./packages/it-parallel-batch) Takes an async iterator that emits promise-returning functions, invokes them in parallel and emits the results in the same order as the input +- [`/packages/it-peekable`](./packages/it-peekable) Allows peeking/pushing an iterable +- [`/packages/it-reduce`](./packages/it-reduce) Reduces the values yielded from an async iterator +- [`/packages/it-skip`](./packages/it-skip) Skip items from an iterable +- [`/packages/it-sort`](./packages/it-sort) Collects all values from an async iterator, sorts them using the passed function and yields them +- [`/packages/it-split`](./packages/it-split) Splits Uint8Arrays emitted by an (async) iterable by a delimiter +- [`/packages/it-take`](./packages/it-take) Stop iteration after n items have been received +- [`/packages/it-to-browser-readablestream`](./packages/it-to-browser-readablestream) Takes an async iterator and turns it into a browser readable stream +- [`/packages/it-to-buffer`](./packages/it-to-buffer) Takes an async iterator that yields buffers and concatenates them all together + + + +- [blob-to-it](./packages/blob-to-it) Turn a Blob into an iterable +- [browser-readablestream-to-it](./packages/browser-readablestream-to-it) Turn a browser ReadableStream into an iterable +- [it-all](./packages/it-all) Collect the contents of an iterable into an array +- [it-batch](./packages/it-batch) Batch up the contents of an iterable into arrays +- [it-buffer-stream](./packages/it-buffer-stream) Creates an iterable of buffers +- [it-drain](./packages/it-drain) Consume an iterable and ignore any output +- [it-filter](./packages/it-filter) Skip some items in an iterable based on a filter function +- [it-first](./packages/it-first) Return the first item in an iterable +- [it-flat-batch](./packages/it-flat-batch) Take an iterable of variable length arrays and make them all the same length +- [it-foreach](./packages/it-foreach) Invoke a function for every member of an iterable +- [it-glob](./packages/it-glob) Glob matcher for file systems +- [it-last](./packages/it-last) Return the last item in an iterable +- [it-length](./packages/it-length) Consume an iterable and return its length +- [it-map](./packages/it-map) Map the output of an iterable +- [it-merge](./packages/it-merge) Treat multiple iterables as one +- [it-multipart](./packages/it-multipart) Parse multipart message bodies as an iterable +- [it-ndjson](./packages/it-ndjson) Parse multipart message bodies as an iterable +- [it-parallel](./packages/it-parallel) Take an iterable of functions that return promises and run them in parallel up to a concurrency limit +- [it-parallel-batch](./packages/it-parallel-batch) Take an iterable of functions that return promises and run them in parallel in batches +- [it-peekable](./packages/it-peekable) Peek/push an iterable +- [it-reduce](./packages/it-reduce) Reduce the output of an iterable +- [it-skip](./packages/it-skip) Skip items at the start of an iterable +- [it-sort](./packages/it-sort) Sort an iterable using a passed sort function +- [it-split](./packages/it-split) Split an iterable of buffers by linebreaks +- [it-take](./packages/it-take) Limit the number of items you want from an iterable +- [it-to-browser-readablestream](./packages/it-to-browser-readablestream) Turns an iterable into a WhatWG [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) +- [it-to-buffer](./packages/it-to-buffer) Takes an iterable of Buffers and concatenates them + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/lerna.json b/lerna.json index 11274111..fe9f1a3a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,15 +1,13 @@ { - "lerna": "2.9.0", - "packages": [ - "packages/*" - ], + "lerna": "5.4.0", + "useWorkspaces": true, "version": "independent", "command": { - "bootstrap": { - "hoist": true - }, "run": { "stream": true } - } + }, + "packages": [ + "packages/*" + ] } diff --git a/package.json b/package.json index bf31d096..ca5626d9 100644 --- a/package.json +++ b/package.json @@ -2,22 +2,38 @@ "name": "it", "version": "1.0.0", "description": "A collection of utilities for making working with iterables more bearable", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/achingbrain/it#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, "private": true, "scripts": { "postinstall": "lerna bootstrap", - "reset": "lerna run clean && rm -rf packages/*/node_modules packages/*/package-lock.json node_modules", + "reset": "rm -rf packages/*/dist packages/*/node_modules packages/*/package-lock.json node_modules package-lock.json", "test": "lerna run test", "coverage": "lerna run coverage", - "build": "lerna run build", + "build": "lerna exec -- tsc && lerna run build", "deploy": "lerna run deploy", "start": "NODE_ENV=development lerna run start", "clean": "lerna run clean", "lint": "lerna run lint", + "dep-check": "lerna run dep-check", "check": "lerna run check", "publish": "lerna publish" }, - "devDependencies": { - "coveralls-lerna": "0.0.5", - "lerna": "^4.0.0" - } + "dependencies": { + "lerna": "^6.0.0" + }, + "workspaces": [ + "packages/*" + ] } diff --git a/packages/blob-to-it/.npmignore b/packages/blob-to-it/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/blob-to-it/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/blob-to-it/LICENSE b/packages/blob-to-it/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/blob-to-it/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/blob-to-it/LICENSE-APACHE b/packages/blob-to-it/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/blob-to-it/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/blob-to-it/LICENSE-MIT b/packages/blob-to-it/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/blob-to-it/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/blob-to-it/README.md b/packages/blob-to-it/README.md index 5aa9a0d3..29051c82 100644 --- a/packages/blob-to-it/README.md +++ b/packages/blob-to-it/README.md @@ -1,20 +1,28 @@ -# blob-to-it +# blob-to-it -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-all)](https://david-dm.org/achingbrain/it?path=packages/it-all) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Turns a Blob into an async iterator +> Turns a blob into an async iterator + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save blob-to-it +```console +$ npm i blob-to-it ``` ## Usage ```javascript -const toIt = require('blob-to-it') -const all = require('it-all') +import toIt from 'blob-to-it' +import all from 'it-all' const content = [ Uint8Array.from([0, 1, 2, 3, 4]) ] const blob = new Blob(content) @@ -22,3 +30,14 @@ const arr = await all(toIt(blob)) console.info(arr) // [ [ 0, 1, 2, 3, 4 ] ] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/blob-to-it/index.js b/packages/blob-to-it/index.js deleted file mode 100644 index c3d090be..00000000 --- a/packages/blob-to-it/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-env browser */ - -'use strict' - -const browserReadableStreamToIt = require('browser-readablestream-to-it') - -/** - * @param {Blob} blob - * @returns {AsyncIterable} - */ -function blobToIt (blob) { - if (typeof blob.stream === 'function') { - // @ts-ignore missing some properties - return browserReadableStreamToIt(blob.stream()) - } - - // firefox < 69 does not support blob.stream() - // @ts-ignore - response.body is optional, but in practice it's a stream. - return browserReadableStreamToIt(new Response(blob).body) -} - -module.exports = blobToIt diff --git a/packages/blob-to-it/package.json b/packages/blob-to-it/package.json index db15751d..85762f86 100644 --- a/packages/blob-to-it/package.json +++ b/packages/blob-to-it/package.json @@ -2,33 +2,142 @@ "name": "blob-to-it", "version": "1.0.4", "description": "Turns a blob into an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/blob-to-it#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "playwright-test", - "lint": "standard", - "coverage": "playwright-test", - "clean": "rm -rf dist", - "check": "npm run build:dep:types && tsc --noEmit", - "build": "npm run build:types", - "build:dep:types": "cd node_modules/browser-readablestream-to-it && npm run build:types", - "build:types": "npm run build:dep:types && tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test -t browser", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { - "browser-readablestream-to-it": "^1.0.3" + "browser-readablestream-to-it": "^1.0.0" }, "devDependencies": { - "chai": "^4.2.0", - "it-all": "^1.0.6", - "mocha": "8.0.1", - "playwright-test": "^0.7.1", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/blob-to-it/src/index.ts b/packages/blob-to-it/src/index.ts new file mode 100644 index 00000000..2035e548 --- /dev/null +++ b/packages/blob-to-it/src/index.ts @@ -0,0 +1,13 @@ +/* eslint-env browser */ + +import browserReadableStreamToIt from 'browser-readablestream-to-it' + +export default function blobToIt (blob: Blob): AsyncIterable { + if (typeof blob.stream === 'function') { + return browserReadableStreamToIt(blob.stream()) + } + + // firefox < 69 does not support blob.stream() + // @ts-expect-error - response.body is optional, but in practice it's a stream. + return browserReadableStreamToIt(new Response(blob).body) +} diff --git a/packages/blob-to-it/test.js b/packages/blob-to-it/test/index.spec.ts similarity index 73% rename from packages/blob-to-it/test.js rename to packages/blob-to-it/test/index.spec.ts index 5b02f5b7..8fbf3188 100644 --- a/packages/blob-to-it/test.js +++ b/packages/blob-to-it/test/index.spec.ts @@ -1,10 +1,8 @@ /* eslint-env mocha, browser */ -'use strict' - -const all = require('it-all') -const { expect } = require('chai') -const toIt = require('./index') +import all from 'it-all' +import { expect } from 'aegir/chai' +import toIt from '../src/index.js' describe('blob-to-it', () => { it('should convert a blob to an async iterator', async () => { diff --git a/packages/blob-to-it/tsconfig.json b/packages/blob-to-it/tsconfig.json index f5e4524f..36fff505 100644 --- a/packages/blob-to-it/tsconfig.json +++ b/packages/blob-to-it/tsconfig.json @@ -1,6 +1,18 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../browser-readablestream-to-it" + }, + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/browser-readablestream-to-it/.npmignore b/packages/browser-readablestream-to-it/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/browser-readablestream-to-it/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/browser-readablestream-to-it/LICENSE b/packages/browser-readablestream-to-it/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/browser-readablestream-to-it/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/browser-readablestream-to-it/LICENSE-APACHE b/packages/browser-readablestream-to-it/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/browser-readablestream-to-it/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/browser-readablestream-to-it/LICENSE-MIT b/packages/browser-readablestream-to-it/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/browser-readablestream-to-it/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/browser-readablestream-to-it/README.md b/packages/browser-readablestream-to-it/README.md index 8f9ce89c..cd99078e 100644 --- a/packages/browser-readablestream-to-it/README.md +++ b/packages/browser-readablestream-to-it/README.md @@ -1,20 +1,29 @@ -# browser-readablestream-to-it +# browser-readablestream-to-it -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-all)](https://david-dm.org/achingbrain/it?path=packages/it-all) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Turns a browser readable stream into an async iterator +> Turns a browser readble stream into an async iterator + +## Table of contents + +- [Install](#install) +- [Usage](#usage) + - [preventCancel](#preventcancel) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save browser-readablestream-to-it +```console +$ npm i browser-readablestream-to-it ``` ## Usage ```javascript -const toIt = require('browser-readablestream-to-it') -const all = require('it-all') +import toIt from 'browser-readablestream-to-it' +import all from 'it-all' const content = [0, 1, 2, 3, 4] @@ -45,3 +54,14 @@ const arr = await all(toIt(stream, { preventCancel: true })) console.info(arr) // 0, 1, 2, 3, 4 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/browser-readablestream-to-it/package.json b/packages/browser-readablestream-to-it/package.json index 2258c2de..ea47bd62 100644 --- a/packages/browser-readablestream-to-it/package.json +++ b/packages/browser-readablestream-to-it/package.json @@ -2,29 +2,139 @@ "name": "browser-readablestream-to-it", "version": "1.0.3", "description": "Turns a browser readble stream into an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/browser-readablestream-to-it#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "playwright-test", - "lint": "standard", - "coverage": "playwright-test", - "check": "tsc --noEmit", - "clean": "rm -rf dist", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test -t browser", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "chai": "^4.2.0", - "it-all": "^1.0.6", - "mocha": "8.0.1", - "playwright-test": "^0.7.1", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/browser-readablestream-to-it/index.js b/packages/browser-readablestream-to-it/src/index.ts similarity index 67% rename from packages/browser-readablestream-to-it/index.js rename to packages/browser-readablestream-to-it/src/index.ts index 15e5395f..d2f000c6 100644 --- a/packages/browser-readablestream-to-it/index.js +++ b/packages/browser-readablestream-to-it/src/index.ts @@ -1,4 +1,7 @@ -'use strict' + +export interface BrowserReadableStreamToItOptions { + preventCancel?: boolean +} /** * Turns a browser readable stream into an async iterable. Async iteration over @@ -6,13 +9,8 @@ * acquiring a reader. The lock will be released if iteration loop is broken. To * prevent stream cancelling optional `{ preventCancel: true }` could be passed * as a second argument. - * @template T - * @param {ReadableStream} stream - * @param {Object} [options] - * @param {boolean} [options.preventCancel=boolean] - * @returns {AsyncIterable} */ -async function * browserReadableStreamToIt (stream, options = {}) { +export default async function * browserReadableStreamToIt (stream: ReadableStream, options: BrowserReadableStreamToItOptions = {}): AsyncGenerator { const reader = stream.getReader() try { @@ -27,11 +25,9 @@ async function * browserReadableStreamToIt (stream, options = {}) { } } finally { if (options.preventCancel !== true) { - reader.cancel() + await reader.cancel() } reader.releaseLock() } } - -module.exports = browserReadableStreamToIt diff --git a/packages/browser-readablestream-to-it/test.js b/packages/browser-readablestream-to-it/test/index.spec.ts similarity index 95% rename from packages/browser-readablestream-to-it/test.js rename to packages/browser-readablestream-to-it/test/index.spec.ts index 80f34398..dd02041c 100644 --- a/packages/browser-readablestream-to-it/test.js +++ b/packages/browser-readablestream-to-it/test/index.spec.ts @@ -1,10 +1,8 @@ /* eslint-env mocha, browser */ -'use strict' - -const all = require('it-all') -const { expect } = require('chai') -const toIt = require('./index') +import all from 'it-all' +import { expect } from 'aegir/chai' +import toIt from '../src/index.js' describe('browser-readablestream-to-it', () => { it('should convert a readablestream to an async iterator', async () => { @@ -57,7 +55,7 @@ describe('browser-readablestream-to-it', () => { it('should cancel stream', async () => { const source = [1, 2, 3, 4, 5] - const cancel = [] + const cancel: any = [] const stream = new ReadableStream({ pull (controller) { controller.enqueue(source.shift()) @@ -85,7 +83,7 @@ describe('browser-readablestream-to-it', () => { it('should not cancel stream if preventCancel is set', async () => { const source = [1, 2, 3, 4, 5] - const cancel = [] + const cancel: any = [] const stream = new ReadableStream({ pull (controller) { controller.enqueue(source.shift()) @@ -113,7 +111,7 @@ describe('browser-readablestream-to-it', () => { it('error cancels the stream', async () => { const source = [1, 2, 3, 4, 5] - const cancel = [] + const cancel: any = [] const stream = new ReadableStream({ pull (controller) { controller.enqueue(source.shift()) @@ -143,7 +141,7 @@ describe('browser-readablestream-to-it', () => { it('error does not cancels the stream if preventCancel is set', async () => { const source = [1, 2, 3, 4, 5] - const cancel = [] + const cancel: any = [] const stream = new ReadableStream({ pull (controller) { controller.enqueue(source.shift()) diff --git a/packages/browser-readablestream-to-it/tsconfig.json b/packages/browser-readablestream-to-it/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/browser-readablestream-to-it/tsconfig.json +++ b/packages/browser-readablestream-to-it/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-all/.npmignore b/packages/it-all/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-all/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-all/LICENSE b/packages/it-all/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-all/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-all/LICENSE-APACHE b/packages/it-all/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-all/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-all/LICENSE-MIT b/packages/it-all/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-all/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-all/README.md b/packages/it-all/README.md index c7faf3cb..d9f96421 100644 --- a/packages/it-all/README.md +++ b/packages/it-all/README.md @@ -1,21 +1,29 @@ -# it-all +# it-all -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-all)](https://david-dm.org/achingbrain/it?path=packages/it-all) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Collects all values from an (async) iterable into an array and returns it. +> Collects all values from an (async) iterable and returns them as an array -For when you need a one-liner to collect iterable values. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-all +```console +$ npm i it-all ``` +For when you need a one-liner to collect iterable values. + ## Usage ```javascript -const all = require('it-all') +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -24,3 +32,14 @@ const arr = await all(values) console.info(arr) // 0, 1, 2, 3, 4 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-all/index.js b/packages/it-all/index.js deleted file mode 100644 index f938d233..00000000 --- a/packages/it-all/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -/** - * Collects all values from an (async) iterable into an array and returns it. - * - * @template T - * @param {AsyncIterable|Iterable} source - */ -const all = async (source) => { - const arr = [] - - for await (const entry of source) { - arr.push(entry) - } - - return arr -} - -module.exports = all diff --git a/packages/it-all/package.json b/packages/it-all/package.json index a9b614ba..e2f24b29 100644 --- a/packages/it-all/package.json +++ b/packages/it-all/package.json @@ -1,28 +1,140 @@ { "name": "it-all", "version": "1.0.6", - "description": "Collects all values from an async iterator and returns them as an array", - "main": "index.js", - "repository": "github:achingbrain/it", + "description": "Collects all values from an (async) iterable and returns them as an array", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-all#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-all/src/index.ts b/packages/it-all/src/index.ts new file mode 100644 index 00000000..1e734de0 --- /dev/null +++ b/packages/it-all/src/index.ts @@ -0,0 +1,13 @@ + +/** + * Collects all values from an (async) iterable and returns them as an array + */ +export default async function all (source: AsyncIterable|Iterable): Promise { + const arr = [] + + for await (const entry of source) { + arr.push(entry) + } + + return arr +} diff --git a/packages/it-all/test.js b/packages/it-all/test.js deleted file mode 100644 index 30914a75..00000000 --- a/packages/it-all/test.js +++ /dev/null @@ -1,10 +0,0 @@ -const all = require('./') -const test = require('ava') - -test('Should collect all entries of an async iterator as an array', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await all(values) - - t.deepEqual(res, values) -}) diff --git a/packages/it-all/test/index.spec.ts b/packages/it-all/test/index.spec.ts new file mode 100644 index 00000000..b85f5487 --- /dev/null +++ b/packages/it-all/test/index.spec.ts @@ -0,0 +1,14 @@ +/* eslint-env mocha */ + +import { expect } from 'aegir/chai' +import all from '../src/index.js' + +describe('it-all', () => { + it('Should collect all entries of an async iterator as an array', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await all(values) + + expect(res).to.deep.equal(values) + }) +}) diff --git a/packages/it-all/tsconfig.json b/packages/it-all/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-all/tsconfig.json +++ b/packages/it-all/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-batch/.npmignore b/packages/it-batch/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-batch/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-batch/LICENSE b/packages/it-batch/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-batch/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-batch/LICENSE-APACHE b/packages/it-batch/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-batch/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-batch/LICENSE-MIT b/packages/it-batch/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-batch/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-batch/README.md b/packages/it-batch/README.md index 3927ab77..2493ec55 100644 --- a/packages/it-batch/README.md +++ b/packages/it-batch/README.md @@ -1,22 +1,30 @@ -# it-batch +# it-batch -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-batch)](https://david-dm.org/achingbrain/it?path=packages/it-batch) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Takes an (async) iterable that emits things and returns an async iterable that emits those things in fixed-sized batches. +> Takes an async iterator that emits things and emits them as fixed size batches -The final batch may be smaller than the max. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-batch +```console +$ npm i it-batch ``` +The final batch may be smaller than the max. + ## Usage ```javascript -const batch = require('it-batch') -const all = require('it-all') +import batch from 'it-batch' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -26,3 +34,14 @@ const result = await all(batch(values, batchSize)) console.info(result) // [0, 1], [2, 3], [4] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-batch/package.json b/packages/it-batch/package.json index c146f1f7..577aaf55 100644 --- a/packages/it-batch/package.json +++ b/packages/it-batch/package.json @@ -2,28 +2,140 @@ "name": "it-batch", "version": "1.0.9", "description": "Takes an async iterator that emits things and emits them as fixed size batches", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-batch#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-batch/index.js b/packages/it-batch/src/index.ts similarity index 54% rename from packages/it-batch/index.js rename to packages/it-batch/src/index.ts index a9829c7b..fbbc5171 100644 --- a/packages/it-batch/index.js +++ b/packages/it-batch/src/index.ts @@ -1,17 +1,9 @@ -'use strict' - /** * Takes an (async) iterable that emits things and returns an async iterable that - * emits those things in fixed-sized batches. - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {number} [size=1] - * @returns {AsyncIterable} + * emits those things in fixed-sized batches */ -async function * batch (source, size = 1) { - /** @type {T[]} */ - let things = [] +export default async function * batch (source: AsyncIterable | Iterable, size: number = 1): AsyncGenerator { + let things: T[] = [] if (size < 1) { size = 1 @@ -27,11 +19,9 @@ async function * batch (source, size = 1) { } } - while (things.length) { + while (things.length > 0) { yield things.slice(0, size) things = things.slice(size) } } - -module.exports = batch diff --git a/packages/it-batch/test.js b/packages/it-batch/test.js deleted file mode 100644 index 57b694c9..00000000 --- a/packages/it-batch/test.js +++ /dev/null @@ -1,50 +0,0 @@ -const batch = require('./') -const test = require('ava') -const all = require('it-all') - -test('Should batch up entries', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = 2 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) - -test('Should batch up entries without batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const res = await all(batch(values)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with negative batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = -1 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with zero batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = 0 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with string batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = '2' - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) - -test('Should batch up entries with non-integer batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = 2.5 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) diff --git a/packages/it-batch/test/index.spec.ts b/packages/it-batch/test/index.spec.ts new file mode 100644 index 00000000..a9bbd23d --- /dev/null +++ b/packages/it-batch/test/index.spec.ts @@ -0,0 +1,55 @@ +/* eslint-env mocha */ + +import batch from '../src/index.js' +import { expect } from 'aegir/chai' +import all from 'it-all' + +describe('it-batch', () => { + it('should batch up entries', async () => { + const values = [0, 1, 2, 3, 4] + const batchSize = 2 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) + + it('should batch up entries without batch size', async () => { + const values = [0, 1, 2, 3, 4] + const res = await all(batch(values)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with negative batch size', async () => { + const values = [0, 1, 2, 3, 4] + const batchSize = -1 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with zero batch size', async () => { + const values = [0, 1, 2, 3, 4] + const batchSize = 0 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with string batch size', async () => { + const values = [0, 1, 2, 3, 4] + const batchSize = '2' + // @ts-expect-error batchSize type is incorrect + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) + + it('should batch up entries with non-integer batch size', async () => { + const values = [0, 1, 2, 3, 4] + const batchSize = 2.5 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) +}) diff --git a/packages/it-batch/tsconfig.json b/packages/it-batch/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-batch/tsconfig.json +++ b/packages/it-batch/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-buffer-stream/.npmignore b/packages/it-buffer-stream/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-buffer-stream/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-buffer-stream/LICENSE b/packages/it-buffer-stream/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-buffer-stream/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-buffer-stream/LICENSE-APACHE b/packages/it-buffer-stream/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-buffer-stream/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-buffer-stream/LICENSE-MIT b/packages/it-buffer-stream/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-buffer-stream/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-buffer-stream/README.md b/packages/it-buffer-stream/README.md index a5453837..6a46afbb 100644 --- a/packages/it-buffer-stream/README.md +++ b/packages/it-buffer-stream/README.md @@ -1,18 +1,28 @@ -# it-buffer-stream +# it-buffer-stream -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-buffer-stream)](https://david-dm.org/achingbrain/it?path=packages/it-buffer-stream) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> An async iterable that emits buffers containing bytes up to a certain length +> An async iterator that emits buffers containing bytes up to a certain length + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-buffer-stream +```console +$ npm i it-buffer-stream ``` ## Usage ```javascript +import bufferStream from 'it-buffer-stream' + const totalLength = //... a big number // all options are optional, defaults are shown @@ -37,3 +47,14 @@ for await (buf of bufferStream(totalLength, options)) { // `buffers` is an array of Buffers the combined length of which === totalLength ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-buffer-stream/index.js b/packages/it-buffer-stream/index.js deleted file mode 100644 index 524d953b..00000000 --- a/packages/it-buffer-stream/index.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict' - -// @ts-ignore - untyped dependency -const randomBytes = require('iso-random-stream/src/random') - -/** - * @typedef {Object} Options - * @property {number} [chunkSize] - * @property {function(Uint8Array):void} [collector] - * @property {function(number):Promise|Uint8Array} [generator] - */ - -/** - * @typedef {Object} ActualOptions - * @property {number} chunkSize - * @property {function(Uint8Array):void} collector - * @property {function(number):Promise|Uint8Array} generator - */ - -/** @type {ActualOptions} */ -const defaultOptions = { - chunkSize: 4096, - collector: () => {}, - generator: (size) => Promise.resolve(randomBytes(size)) -} - -/** - * An async iterable that emits buffers containing bytes up to a certain length. - * - * @param {number} limit - * @param {Options} [options] - */ -async function * bufferStream (limit, options = {}) { - /** @type {ActualOptions} */ - const opts = Object.assign({}, defaultOptions, options) - let emitted = 0 - - const arr = [] - arr.length = Math.ceil(limit / opts.chunkSize) - - while (emitted < limit) { - const nextLength = emitted + opts.chunkSize - let nextChunkSize = opts.chunkSize - - if (nextLength > limit) { - // emit the final chunk - nextChunkSize = limit - emitted - } - - let bytes = await opts.generator(nextChunkSize) - bytes = bytes.slice(0, nextChunkSize) - - opts.collector(bytes) - emitted += nextChunkSize - - yield bytes - } -} - -module.exports = bufferStream diff --git a/packages/it-buffer-stream/package.json b/packages/it-buffer-stream/package.json index 1ed65ae0..21e994a0 100644 --- a/packages/it-buffer-stream/package.json +++ b/packages/it-buffer-stream/package.json @@ -2,31 +2,143 @@ "name": "it-buffer-stream", "version": "2.0.2", "description": "An async iterator that emits buffers containing bytes up to a certain length", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-buffer-stream#readme", - "bugs": "https://github.com/achingbrain/it/issues", - "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" }, - "author": "Alex Potsides ", - "license": "ISC", - "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2", - "uint8arrays": "^3.0.0" + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, "dependencies": { - "iso-random-stream": "^1.1.1" + "iso-random-stream": "^2.0.2" }, - "types": "dist/index.d.ts" + "devDependencies": { + "aegir": "^37.5.0", + "uint8arrays": "^4.0.2" + } } diff --git a/packages/it-buffer-stream/src/index.ts b/packages/it-buffer-stream/src/index.ts new file mode 100644 index 00000000..9755fdab --- /dev/null +++ b/packages/it-buffer-stream/src/index.ts @@ -0,0 +1,42 @@ +import randomBytes from 'iso-random-stream/src/random.js' + +export interface BufferStreamOptions { + chunkSize?: number + collector?: (arr: Uint8Array) => void + generator?: (lenght: number) => Uint8Array | Promise +} + +const defaultOptions: Required = { + chunkSize: 4096, + collector: () => {}, + generator: async (size) => await Promise.resolve(randomBytes(size)) +} + +/** + * An async iterable that emits buffers containing bytes up to a certain length + */ +export default async function * bufferStream (limit: number, options: BufferStreamOptions = {}) { + const opts: Required = Object.assign({}, defaultOptions, options) + let emitted = 0 + + const arr = [] + arr.length = Math.ceil(limit / opts.chunkSize) + + while (emitted < limit) { + const nextLength = emitted + opts.chunkSize + let nextChunkSize = opts.chunkSize + + if (nextLength > limit) { + // emit the final chunk + nextChunkSize = limit - emitted + } + + let bytes = await opts.generator(nextChunkSize) + bytes = bytes.slice(0, nextChunkSize) + + opts.collector(bytes) + emitted += nextChunkSize + + yield bytes + } +} diff --git a/packages/it-buffer-stream/test.js b/packages/it-buffer-stream/test.js deleted file mode 100644 index f97b4635..00000000 --- a/packages/it-buffer-stream/test.js +++ /dev/null @@ -1,87 +0,0 @@ -const bufferStream = require('./') -const test = require('ava') -const { concat: uint8ArrayConcat } = require('uint8arrays/concat') - -test('Should emit bytes', async (t) => { - const expected = 100 - const buffers = [] - - for await (const buf of bufferStream(expected)) { - buffers.push(buf) - } - - t.is(buffers.length, 1) - t.is(buffers[0].length, expected) -}) - -test('Should emit a number of buffers', async (t) => { - const expected = 100 - const chunkSize = 10 - const buffers = [] - - for await (const buf of bufferStream(expected, { - chunkSize - })) { - buffers.push(buf) - } - - t.is(buffers.length, 10) - t.is(buffers[0].length, expected / chunkSize) - - const total = buffers.reduce((acc, cur) => acc + cur.length, 0) - - t.is(expected, total) -}) - -test('Should allow collection of buffers', async (t) => { - const expected = 100 - let emitted = new Uint8Array(0) - const buffers = [] - - for await (const buf of bufferStream(expected, { - collector: (buffer) => { - emitted = uint8ArrayConcat([emitted, buffer]) - } - })) { - buffers.push(buf) - } - - t.deepEqual(Uint8Array.from(emitted), Uint8Array.from(buffers[0])) -}) - -test('Should allow generation of buffers', async (t) => { - const expected = 100 - let emitted = new Uint8Array(0) - const buffers = [] - - for await (const buf of bufferStream(expected, { - generator: (size) => { - const output = new Uint8Array(size) - emitted = uint8ArrayConcat([emitted, output]) - - return output - } - })) { - buffers.push(buf) - } - - t.deepEqual(emitted, buffers[0]) -}) - -test('Should propagate byte generation errors', async (t) => { - const generationError = new Error('Urk!') - - try { - for await (const _ of bufferStream(5, { // eslint-disable-line no-unused-vars - generator: async () => { - throw generationError - } - })) { // eslint-disable-line no-empty - - } - - throw new Error('No error was thrown') - } catch (err) { - t.is(err, generationError) - } -}) diff --git a/packages/it-buffer-stream/test/index.spec.ts b/packages/it-buffer-stream/test/index.spec.ts new file mode 100644 index 00000000..987d9c66 --- /dev/null +++ b/packages/it-buffer-stream/test/index.spec.ts @@ -0,0 +1,89 @@ +import { expect } from 'aegir/chai' +import { concat as uint8ArrayConcat } from 'uint8arrays/concat' +import bufferStream from '../src/index.js' + +describe('it-buffer-stream', () => { + it('should emit bytes', async () => { + const expected = 100 + const buffers = [] + + for await (const buf of bufferStream(expected)) { + buffers.push(buf) + } + + expect(buffers).to.have.lengthOf(1) + expect(buffers[0]).to.have.lengthOf(expected) + }) + + it('should emit a number of buffers', async () => { + const expected = 100 + const chunkSize = 10 + const buffers = [] + + for await (const buf of bufferStream(expected, { + chunkSize + })) { + buffers.push(buf) + } + + expect(buffers).to.have.lengthOf(10) + expect(buffers[0]).to.have.lengthOf(expected / chunkSize) + + const total = buffers.reduce((acc, cur) => acc + cur.length, 0) + + expect(expected).to.equal(total) + }) + + it('should allow collection of buffers', async () => { + const expected = 100 + let emitted = new Uint8Array(0) + const buffers = [] + + for await (const buf of bufferStream(expected, { + collector: (buffer) => { + emitted = uint8ArrayConcat([emitted, buffer]) + } + })) { + buffers.push(buf) + } + + expect(Uint8Array.from(emitted)).to.equalBytes(Uint8Array.from(buffers[0])) + }) + + it('should allow generation of buffers', async () => { + const expected = 100 + let emitted = new Uint8Array(0) + const buffers = [] + + for await (const buf of bufferStream(expected, { + generator: (size) => { + const output = new Uint8Array(size) + emitted = uint8ArrayConcat([emitted, output]) + + return output + } + })) { + buffers.push(buf) + } + + expect(emitted).to.equalBytes(buffers[0]) + }) + + it('should propagate byte generation errors', async () => { + const generationError = new Error('Urk!') + + try { + for await (const _ of bufferStream(5, { // eslint-disable-line no-unused-vars,@typescript-eslint/no-unused-vars + generator: async () => { + throw generationError + } + })) { // eslint-disable-line no-empty + + } + + throw new Error('No error was thrown') + } catch (err) { + expect(err).to.equal(generationError) + } + }) +}) diff --git a/packages/it-buffer-stream/tsconfig.json b/packages/it-buffer-stream/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-buffer-stream/tsconfig.json +++ b/packages/it-buffer-stream/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-drain/.npmignore b/packages/it-drain/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-drain/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-drain/LICENSE b/packages/it-drain/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-drain/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-drain/LICENSE-APACHE b/packages/it-drain/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-drain/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-drain/LICENSE-MIT b/packages/it-drain/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-drain/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-drain/README.md b/packages/it-drain/README.md index e8e379b3..2d3d933b 100644 --- a/packages/it-drain/README.md +++ b/packages/it-drain/README.md @@ -1,24 +1,43 @@ -# it-drain +# it-drain -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml/) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-drain)](https://david-dm.org/achingbrain/it?path=packages/it-drain) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Drains an (async) iterable discarding its content and does not return anything. +> Empties an async iterator -Mostly useful for tests or when you want to be explicit about consuming an iterable without doing anything with any yielded values. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-drain +```console +$ npm i it-drain ``` +Mostly useful for tests or when you want to be explicit about consuming an iterable without doing anything with any yielded values. + ## Usage ```javascript -const drain = require('it-drain') +import drain from 'it-drain' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] await drain(values) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-drain/index.js b/packages/it-drain/index.js deleted file mode 100644 index 86fb80fa..00000000 --- a/packages/it-drain/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -/** - * Drains an (async) iterable discarding its' content and does not return - * anything. - * - * @template T - * @param {AsyncIterable|Iterable} source - * @returns {Promise} - */ -const drain = async (source) => { - for await (const _ of source) { } // eslint-disable-line no-unused-vars,no-empty -} - -module.exports = drain diff --git a/packages/it-drain/package.json b/packages/it-drain/package.json index 2fdcb787..2851a828 100644 --- a/packages/it-drain/package.json +++ b/packages/it-drain/package.json @@ -2,27 +2,139 @@ "name": "it-drain", "version": "1.0.5", "description": "Empties an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-drain#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-drain/src/index.ts b/packages/it-drain/src/index.ts new file mode 100644 index 00000000..3f007a50 --- /dev/null +++ b/packages/it-drain/src/index.ts @@ -0,0 +1,7 @@ +/** + * Drains an (async) iterable discarding its' content and does not return + * anything + */ +export default async function drain (source: AsyncIterable|Iterable): Promise { + for await (const _ of source) { } // eslint-disable-line no-unused-vars,no-empty,@typescript-eslint/no-unused-vars +} diff --git a/packages/it-drain/test.js b/packages/it-drain/test.js deleted file mode 100644 index 8f9abbdb..00000000 --- a/packages/it-drain/test.js +++ /dev/null @@ -1,16 +0,0 @@ -const drain = require('./') -const test = require('ava') - -test('Should empty an async iterator', async (t) => { - let done = false - const iter = function * () { - yield 1 - yield 2 - yield 3 - done = true - } - - await drain(iter()) - - t.truthy(done) -}) diff --git a/packages/it-drain/test/index.spec.ts b/packages/it-drain/test/index.spec.ts new file mode 100644 index 00000000..594dbd9f --- /dev/null +++ b/packages/it-drain/test/index.spec.ts @@ -0,0 +1,18 @@ +import { expect } from 'aegir/chai' +import drain from '../src/index.js' + +describe('it-drain', () => { + it('should empty an async iterator', async () => { + let done = false + const iter = function * () { + yield 1 + yield 2 + yield 3 + done = true + } + + await drain(iter()) + + expect(done).to.be.true() + }) +}) diff --git a/packages/it-drain/tsconfig.json b/packages/it-drain/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-drain/tsconfig.json +++ b/packages/it-drain/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-filter/.npmignore b/packages/it-filter/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-filter/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-filter/LICENSE b/packages/it-filter/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-filter/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-filter/LICENSE-APACHE b/packages/it-filter/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-filter/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-filter/LICENSE-MIT b/packages/it-filter/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-filter/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-filter/README.md b/packages/it-filter/README.md index d3092306..dc3701b4 100644 --- a/packages/it-filter/README.md +++ b/packages/it-filter/README.md @@ -1,20 +1,28 @@ -# it-filter +# it-filter -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-all)](https://david-dm.org/achingbrain/it?path=packages/it-all) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Filters the passed (async) iterable by using the filter function +> Filters the passed iterable by using the filter function + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-filter +```console +$ npm i it-filter ``` ## Usage ```javascript -const all = require('it-all') -const filter = require('it-filter') +import all from 'it-all' +import filter from 'it-filter' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -25,3 +33,14 @@ const arr = await all(filter(values, fn)) console.info(arr) // 3, 4 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-filter/index.js b/packages/it-filter/index.js deleted file mode 100644 index bfbac0e6..00000000 --- a/packages/it-filter/index.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -/** - * Filters the passed (async) iterable by using the filter function - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {function(T):boolean|Promise} fn - */ -const filter = async function * (source, fn) { - for await (const entry of source) { - if (await fn(entry)) { - yield entry - } - } -} - -module.exports = filter diff --git a/packages/it-filter/package.json b/packages/it-filter/package.json index 904b0b72..6a7a44d5 100644 --- a/packages/it-filter/package.json +++ b/packages/it-filter/package.json @@ -2,28 +2,140 @@ "name": "it-filter", "version": "1.0.3", "description": "Filters the passed iterable by using the filter function", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-filter#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-filter/src/index.ts b/packages/it-filter/src/index.ts new file mode 100644 index 00000000..9f833cbf --- /dev/null +++ b/packages/it-filter/src/index.ts @@ -0,0 +1,11 @@ + +/** + * Filters the passed (async) iterable by using the filter function + */ +export default async function * filter (source: AsyncIterable|Iterable, fn: (val: T) => boolean|Promise): AsyncGenerator { + for await (const entry of source) { + if (await fn(entry)) { + yield entry + } + } +} diff --git a/packages/it-filter/test.js b/packages/it-filter/test.js deleted file mode 100644 index 2c157e59..00000000 --- a/packages/it-filter/test.js +++ /dev/null @@ -1,19 +0,0 @@ -const all = require('it-all') -const filter = require('./') -const test = require('ava') - -test('Should filter all values greater than 2', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await all(filter(values, val => val > 2)) - - t.deepEqual(res, [3, 4]) -}) - -test('Should filter all values greater than 2 with a promise', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await all(filter(values, async val => val > 2)) - - t.deepEqual(res, [3, 4]) -}) diff --git a/packages/it-filter/test/index.spec.ts b/packages/it-filter/test/index.spec.ts new file mode 100644 index 00000000..1efebf08 --- /dev/null +++ b/packages/it-filter/test/index.spec.ts @@ -0,0 +1,21 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import filter from '../src/index.js' + +describe('it-filter', () => { + it('should filter all values greater than 2', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await all(filter(values, val => val > 2)) + + expect(res).to.deep.equal([3, 4]) + }) + + it('should filter all values greater than 2 with a promise', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await all(filter(values, async val => val > 2)) + + expect(res).to.deep.equal([3, 4]) + }) +}) diff --git a/packages/it-filter/tsconfig.json b/packages/it-filter/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-filter/tsconfig.json +++ b/packages/it-filter/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-first/.npmignore b/packages/it-first/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-first/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-first/LICENSE b/packages/it-first/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-first/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-first/LICENSE-APACHE b/packages/it-first/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-first/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-first/LICENSE-MIT b/packages/it-first/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-first/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-first/README.md b/packages/it-first/README.md index 3e03abf9..e8fc4d54 100644 --- a/packages/it-first/README.md +++ b/packages/it-first/README.md @@ -1,21 +1,29 @@ -# it-first +# it-first -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-first)](https://david-dm.org/achingbrain/it?path=packages/it-first) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Returns the first result from an (async) iterable. +> Returns the first result from an async iterator -Mostly useful for tests. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-first +```console +$ npm i it-first ``` +Mostly useful for tests. + ## Usage ```javascript -const first = require('it-first') +import first from 'it-first' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -24,3 +32,14 @@ const res = await first(values) console.info(res) // 0 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-first/package.json b/packages/it-first/package.json index b906ddbf..eada4313 100644 --- a/packages/it-first/package.json +++ b/packages/it-first/package.json @@ -2,27 +2,139 @@ "name": "it-first", "version": "1.0.7", "description": "Returns the first result from an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-first#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-first/index.js b/packages/it-first/src/index.ts similarity index 55% rename from packages/it-first/index.js rename to packages/it-first/src/index.ts index 1fb5198a..631ce02b 100644 --- a/packages/it-first/index.js +++ b/packages/it-first/src/index.ts @@ -1,18 +1,12 @@ -'use strict' /** * Returns the first result from an (async) iterable, unless empty, in which - * case returns `undefined`. - * - * @template T - * @param {AsyncIterable|Iterable} source + * case returns `undefined` */ -const first = async (source) => { +export default async function first (source: AsyncIterable|Iterable): Promise { for await (const entry of source) { // eslint-disable-line no-unreachable-loop return entry } return undefined } - -module.exports = first diff --git a/packages/it-first/test.js b/packages/it-first/test.js deleted file mode 100644 index dcdc6f0d..00000000 --- a/packages/it-first/test.js +++ /dev/null @@ -1,10 +0,0 @@ -const first = require('./') -const test = require('ava') - -test('Should return only the first result from an async iterator', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await first(values) - - t.is(res, 0) -}) diff --git a/packages/it-first/test/index.spec.ts b/packages/it-first/test/index.spec.ts new file mode 100644 index 00000000..b86a91cb --- /dev/null +++ b/packages/it-first/test/index.spec.ts @@ -0,0 +1,12 @@ +import { expect } from 'aegir/chai' +import first from '../src/index.js' + +describe('it-first', () => { + it('should return only the first result from an async iterator', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await first(values) + + expect(res).to.equal(0) + }) +}) diff --git a/packages/it-first/tsconfig.json b/packages/it-first/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-first/tsconfig.json +++ b/packages/it-first/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-flat-batch/.npmignore b/packages/it-flat-batch/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-flat-batch/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-flat-batch/LICENSE b/packages/it-flat-batch/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-flat-batch/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-flat-batch/LICENSE-APACHE b/packages/it-flat-batch/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-flat-batch/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-flat-batch/LICENSE-MIT b/packages/it-flat-batch/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-flat-batch/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-flat-batch/README.md b/packages/it-flat-batch/README.md index 430d3e90..e8aeaeae 100644 --- a/packages/it-flat-batch/README.md +++ b/packages/it-flat-batch/README.md @@ -1,22 +1,30 @@ -# it-flat-batch +# it-flat-batch -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-flat-batch)](https://david-dm.org/achingbrain/it?path=packages/it-flat-batch) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Takes an (async) iterable that emits variable length arrays of things and returns an async iterable that emits those thnigs in fixed-size batches. +> Takes an async iterator that emits variable length arrays and emits them as fixed size batches -The final batch may be smaller than requested batch size. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-flat-batch +```console +$ npm i it-flat-batch ``` +The final batch may be smaller than requested batch size. + ## Usage ```javascript -const batch = require('it-flat-batch') -const all = require('it-all') +import batch from 'it-flat-batch' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [[0, 1, 2], [3], [4]] @@ -26,3 +34,14 @@ const result = await all(batch(values, batchSize)) console.info(result) // [0, 1], [2, 3], [4] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-flat-batch/package.json b/packages/it-flat-batch/package.json index ba2bbb17..0d497da0 100644 --- a/packages/it-flat-batch/package.json +++ b/packages/it-flat-batch/package.json @@ -2,28 +2,140 @@ "name": "it-flat-batch", "version": "1.0.7", "description": "Takes an async iterator that emits variable length arrays and emits them as fixed size batches", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-flat-batch#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-flat-batch/index.js b/packages/it-flat-batch/src/index.ts similarity index 58% rename from packages/it-flat-batch/index.js rename to packages/it-flat-batch/src/index.ts index 3fa6fee2..7597eb46 100644 --- a/packages/it-flat-batch/index.js +++ b/packages/it-flat-batch/src/index.ts @@ -1,24 +1,17 @@ -'use strict' /** * Takes an (async) iterable that emits variable length arrays of things and - * returns an async iterable that emits those things in fixed-size batches. - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {number|string} [batchSize=1] - * @returns {AsyncIterable} + * returns an async iterable that emits those things in fixed-size batches */ -async function * batch (source, batchSize) { - // @ts-ignore - expects string not a number +export default async function * batch (source: AsyncIterable|Iterable, batchSize: number = 1): AsyncGenerator { + // @ts-expect-error - expects string not a number let size = parseInt(batchSize) if (isNaN(size) || size < 1) { size = 1 } - /** @type {T[]} */ - let things = [] + let things: T[] = [] for await (const set of source) { things = things.concat(set) @@ -30,11 +23,9 @@ async function * batch (source, batchSize) { } } - while (things.length) { + while (things.length > 0) { yield things.slice(0, size) things = things.slice(size) } } - -module.exports = batch diff --git a/packages/it-flat-batch/test.js b/packages/it-flat-batch/test.js deleted file mode 100644 index 3a9c3b30..00000000 --- a/packages/it-flat-batch/test.js +++ /dev/null @@ -1,70 +0,0 @@ -const batch = require('./') -const test = require('ava') -const all = require('it-all') - -test('Should batch up emitted arrays', async (t) => { - const values = [[0, 1, 2], [3], [4]] - const res = await all(batch(values, 2)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) - -test('Should batch up emitted arrays in singles', async (t) => { - const values = [[0, 1, 2], [3], [4]] - const res = await all(batch(values, 1)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up emitted arrays in one array', async (t) => { - const values = [[0, 1, 2], [3], [4]] - const res = await all(batch(values, 100)) - - t.deepEqual(res, [[0, 1, 2, 3, 4]]) -}) - -test('Should batch up emitted arrays in small arrays', async (t) => { - const values = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10]] - const res = await all(batch(values, 1)) - - t.deepEqual(res, [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]) -}) - -test('Should batch up emitted arrays when no batch size is passed', async (t) => { - const values = [[0, 1, 2], [3], [4]] - const res = await all(batch(values)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with negative batch size', async (t) => { - const values = [0, 1, 2, 3, 4] - const batchSize = -1 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with zero batch size', async (t) => { - const values = [[0, 1, 2], [3, 4]] - const batchSize = 0 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0], [1], [2], [3], [4]]) -}) - -test('Should batch up entries with string batch size', async (t) => { - const values = [[0, 1, 2], [3, 4]] - const batchSize = '2' - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) - -test('Should batch up entries with non-integer batch size', async (t) => { - const values = [[0, 1, 2], [3, 4]] - const batchSize = 2.5 - const res = await all(batch(values, batchSize)) - - t.deepEqual(res, [[0, 1], [2, 3], [4]]) -}) diff --git a/packages/it-flat-batch/test/index.spec.ts b/packages/it-flat-batch/test/index.spec.ts new file mode 100644 index 00000000..cec0d70f --- /dev/null +++ b/packages/it-flat-batch/test/index.spec.ts @@ -0,0 +1,73 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import batch from '../src/index.js' + +describe('it-batch', () => { + it('should batch up emitted arrays', async () => { + const values = [[0, 1, 2], [3], [4]] + const res = await all(batch(values, 2)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) + + it('should batch up emitted arrays in singles', async () => { + const values = [[0, 1, 2], [3], [4]] + const res = await all(batch(values, 1)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up emitted arrays in one array', async () => { + const values = [[0, 1, 2], [3], [4]] + const res = await all(batch(values, 100)) + + expect(res).to.deep.equal([[0, 1, 2, 3, 4]]) + }) + + it('should batch up emitted arrays in small arrays', async () => { + const values = [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10]] + const res = await all(batch(values, 1)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]) + }) + + it('should batch up emitted arrays when no batch size is passed', async () => { + const values = [[0, 1, 2], [3], [4]] + const res = await all(batch(values)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with negative batch size', async () => { + const values = [[0, 1, 2], [3], [4]] + const batchSize = -1 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with zero batch size', async () => { + const values = [[0, 1, 2], [3, 4]] + const batchSize = 0 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0], [1], [2], [3], [4]]) + }) + + it('should batch up entries with string batch size', async () => { + const values = [[0, 1, 2], [3, 4]] + const batchSize = '2' + // @ts-expect-error batchSize type is wrong + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) + + it('should batch up entries with non-integer batch size', async () => { + const values = [[0, 1, 2], [3, 4]] + const batchSize = 2.5 + const res = await all(batch(values, batchSize)) + + expect(res).to.deep.equal([[0, 1], [2, 3], [4]]) + }) +}) diff --git a/packages/it-flat-batch/tsconfig.json b/packages/it-flat-batch/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-flat-batch/tsconfig.json +++ b/packages/it-flat-batch/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-foreach/.npmignore b/packages/it-foreach/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-foreach/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-foreach/LICENSE b/packages/it-foreach/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-foreach/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-foreach/LICENSE-APACHE b/packages/it-foreach/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-foreach/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-foreach/LICENSE-MIT b/packages/it-foreach/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-foreach/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-foreach/README.md b/packages/it-foreach/README.md index 71b7a5fd..71c5160f 100644 --- a/packages/it-foreach/README.md +++ b/packages/it-foreach/README.md @@ -1,22 +1,30 @@ -# it-foreach +# it-foreach -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-foreach)](https://david-dm.org/achingbrain/it?path=packages/it-foreach) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Invokes the passed function for each item in an iterable -For when you need a one-liner to collect iterable values. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-foreach +```console +$ npm i it-foreach ``` +For when you need a one-liner to collect iterable values. + ## Usage ```javascript -const each = require('it-foreach') -const drain = require('it-drain') +import each from 'it-foreach' +import drain from 'it-drain' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -26,3 +34,14 @@ const arr = await drain( each(values, console.info) ) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-foreach/index.js b/packages/it-foreach/index.js deleted file mode 100644 index ce5f3daf..00000000 --- a/packages/it-foreach/index.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -/** - * Invokes the passed function for each item in an iterable - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {(thing: T) => void | Promise} fn - */ -const each = async function * (source, fn) { - for await (const thing of source) { - await fn(thing) - yield thing - } -} - -module.exports = each diff --git a/packages/it-foreach/package.json b/packages/it-foreach/package.json index eaba9f04..9c89862c 100644 --- a/packages/it-foreach/package.json +++ b/packages/it-foreach/package.json @@ -2,28 +2,140 @@ "name": "it-foreach", "version": "0.1.1", "description": "Invokes the passed function for each item in an iterable", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-foreach#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-foreach/src/index.ts b/packages/it-foreach/src/index.ts new file mode 100644 index 00000000..6c8d7979 --- /dev/null +++ b/packages/it-foreach/src/index.ts @@ -0,0 +1,10 @@ + +/** + * Invokes the passed function for each item in an iterable + */ +export default async function * forEach (source: AsyncIterable|Iterable, fn: (thing: T) => void | Promise): AsyncGenerator { + for await (const thing of source) { + await fn(thing) + yield thing + } +} diff --git a/packages/it-foreach/test.js b/packages/it-foreach/test.js deleted file mode 100644 index 54219090..00000000 --- a/packages/it-foreach/test.js +++ /dev/null @@ -1,36 +0,0 @@ -const each = require('./') -const all = require('it-all') -const test = require('ava') - -test('Should iterate over every value', async (t) => { - const values = [0, 1, 2, 3, 4] - let sum = 0 - - const res = await all(each(values, (val) => { - sum += val - })) - - t.deepEqual(res, values) - t.is(10, sum) -}) - -test('Should abort source', async (t) => { - const values = [0, 1, 2, 3, 4] - let sum = 0 - const err = new Error('wat') - - try { - await all(each(values, (val) => { - sum += val - - if (val === 3) { - throw err - } - })) - - throw new Error('Did not abort') - } catch (e) { - t.is(e, err) - t.is(6, sum) - } -}) diff --git a/packages/it-foreach/test/index.spec.ts b/packages/it-foreach/test/index.spec.ts new file mode 100644 index 00000000..530511cd --- /dev/null +++ b/packages/it-foreach/test/index.spec.ts @@ -0,0 +1,38 @@ +import all from 'it-all' +import { expect } from 'aegir/chai' +import forEach from '../src/index.js' + +describe('it-for-each', () => { + it('should iterate over every value', async () => { + const values = [0, 1, 2, 3, 4] + let sum = 0 + + const res = await all(forEach(values, (val) => { + sum += val + })) + + expect(res).to.deep.equal(values) + expect(10).to.equal(sum) + }) + + it('should abort source', async () => { + const values = [0, 1, 2, 3, 4] + let sum = 0 + const err = new Error('wat') + + try { + await all(forEach(values, (val) => { + sum += val + + if (val === 3) { + throw err + } + })) + + throw new Error('Did not abort') + } catch (e) { + expect(e).to.equal(err) + expect(6).to.equal(sum) + } + }) +}) diff --git a/packages/it-foreach/tsconfig.json b/packages/it-foreach/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-foreach/tsconfig.json +++ b/packages/it-foreach/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-glob/.npmignore b/packages/it-glob/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-glob/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-glob/LICENSE b/packages/it-glob/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-glob/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-glob/LICENSE-APACHE b/packages/it-glob/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-glob/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-glob/LICENSE-MIT b/packages/it-glob/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-glob/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-glob/README.md b/packages/it-glob/README.md index 0742e6f6..df22b57d 100644 --- a/packages/it-glob/README.md +++ b/packages/it-glob/README.md @@ -1,21 +1,29 @@ -# it-glob +# it-glob -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-glob)](https://david-dm.org/achingbrain/it?path=packages/it-glob) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Async iterable filename pattern matcher -Like [`glob`](https://npmjs.com/package/glob) but async iterable. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) -## Installation +## Install ```console -$ npm install --save it-glob +$ npm i it-glob ``` +Like [`glob`](https://npmjs.com/package/glob) but async iterable. + ## Usage ```javascript -const glob = require('it-glob') +import glob from 'it-glob' const options = { cwd // defaults to process.cwd @@ -31,3 +39,14 @@ for await (const path of glob('/path/to/file', '**/*', options)) { ``` See the [minimatch docs](https://www.npmjs.com/package/minimatch#options) for the full list of options. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-glob/index.js b/packages/it-glob/index.js deleted file mode 100644 index a8b43ff9..00000000 --- a/packages/it-glob/index.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict' - -const fs = require('fs').promises -const path = require('path') -const minimatch = require('minimatch') - -/** - * @typedef {string} Glob - * @typedef {object} OptionsExt - * @property {string} [cwd=process.cwd()] - * @property {boolean} [absolute=false] - If true produces absolute paths - * @property {boolean} [nodir] - If true yields file paths and skip directories - * - * @typedef {OptionsExt & minimatch.IOptions} Options - */ - -/** - * Async iterable filename pattern matcher - * - * @param {string} dir - * @param {string} pattern - * @param {Options} [options] - * @returns {AsyncIterable} - */ -async function * glob (dir, pattern, options = {}) { - const absoluteDir = path.resolve(dir) - const relativeDir = path.relative(options.cwd || process.cwd(), dir) - - const stats = await fs.stat(absoluteDir) - - if (stats.isDirectory()) { - for await (const entry of _glob(absoluteDir, '', pattern, options)) { - yield entry - } - - return - } - - if (minimatch(relativeDir, pattern, options)) { - yield options.absolute ? absoluteDir : relativeDir - } -} - -/** - * @param {string} base - * @param {string} dir - * @param {Glob} pattern - * @param {Options} options - * @returns {AsyncIterable} - */ -async function * _glob (base, dir, pattern, options) { - for await (const entry of await fs.opendir(path.join(base, dir))) { - const relativeEntryPath = path.join(dir, entry.name) - const absoluteEntryPath = path.join(base, dir, entry.name) - - let match = minimatch(relativeEntryPath, pattern, options) - - const isDirectory = entry.isDirectory() - - if (isDirectory && options.nodir) { - match = false - } - - if (match) { - yield options.absolute ? absoluteEntryPath : relativeEntryPath - } - - if (isDirectory) { - yield * _glob(base, relativeEntryPath, pattern, options) - } - } -} - -module.exports = glob diff --git a/packages/it-glob/package.json b/packages/it-glob/package.json index e46467d3..bc2c448f 100644 --- a/packages/it-glob/package.json +++ b/packages/it-glob/package.json @@ -2,36 +2,144 @@ "name": "it-glob", "version": "1.0.2", "description": "Async iterable filename pattern matcher", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-glob#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test -t node", + "test:node": "aegir test -t node --cov", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { - "@types/minimatch": "^3.0.4", - "minimatch": "^3.0.4" + "@types/minimatch": "^5.1.2", + "minimatch": "^5.1.0" }, "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" + "aegir": "^37.5.0", + "it-all": "^1.0.0" }, "browser": { - "fs": false, + "fs/promises": false, "path": false - }, - "types": "dist/index.d.ts" + } } diff --git a/packages/it-glob/src/index.ts b/packages/it-glob/src/index.ts new file mode 100644 index 00000000..e286896d --- /dev/null +++ b/packages/it-glob/src/index.ts @@ -0,0 +1,66 @@ +import fs from 'fs/promises' +import path from 'path' +import minimatch from 'minimatch' +import type { IOptions } from 'minimatch' + +export interface GlobOptions extends IOptions { + /** + * The current working directory + */ + cwd?: string + + /** + * If true produces absolute paths (default: false) + */ + absolute?: boolean + + /** + * If true yields file paths and skip directories (default: false) + */ + nodir?: boolean +} + +/** + * Async iterable filename pattern matcher + */ +export default async function * glob (dir: string, pattern: string, options: GlobOptions = {}): AsyncGenerator { + const absoluteDir = path.resolve(dir) + const relativeDir = path.relative(options.cwd ?? process.cwd(), dir) + + const stats = await fs.stat(absoluteDir) + + if (stats.isDirectory()) { + for await (const entry of _glob(absoluteDir, '', pattern, options)) { + yield entry + } + + return + } + + if (minimatch(relativeDir, pattern, options)) { + yield options.absolute === true ? absoluteDir : relativeDir + } +} + +async function * _glob (base: string, dir: string, pattern: string, options: GlobOptions): AsyncGenerator { + for await (const entry of await fs.opendir(path.join(base, dir))) { + const relativeEntryPath = path.join(dir, entry.name) + const absoluteEntryPath = path.join(base, dir, entry.name) + + let match = minimatch(relativeEntryPath, pattern, options) + + const isDirectory = entry.isDirectory() + + if (isDirectory && options.nodir === true) { + match = false + } + + if (match) { + yield options.absolute === true ? absoluteEntryPath : relativeEntryPath + } + + if (isDirectory) { + yield * _glob(base, relativeEntryPath, pattern, options) + } + } +} diff --git a/packages/it-glob/test.js b/packages/it-glob/test.js deleted file mode 100644 index f11ee81d..00000000 --- a/packages/it-glob/test.js +++ /dev/null @@ -1,76 +0,0 @@ -const test = require('ava') -const all = require('it-all') -const glob = require('.') -const path = require('path') - -test('it should match file', async t => { - const files = await all(glob('.', '**/*')) - - t.truthy(files.includes('README.md')) -}) - -test('it should match file in subdirectory', async t => { - const files = await all(glob('.', '**/*')) - - t.truthy(files.includes(path.join('node_modules', 'it-all'))) -}) - -test('it should match one', async t => { - const files = await all(glob('.', 'README.md')) - - t.deepEqual(files, ['README.md']) -}) - -test('it should match files', async t => { - const files = await all(glob('README.md', 'README.md')) - - t.deepEqual(files, ['README.md']) -}) - -test('it should ignore files', async t => { - const files = await all(glob('.', '**/*!(*/index.js|**/node_modules/**)')) - - t.falsy(files.includes('test/index.js')) -}) - -test('it should ignore files from absolute directory', async t => { - const files = await all(glob(__dirname, '**/*!(test/index.js|)**/node_modules/**')) - - t.falsy(files.includes(path.resolve(__dirname, 'index.js'))) -}) - -test('it returns absolute paths', async t => { - const files = await all(glob(__dirname, '**/*', { - absolute: true - })) - - files.forEach(file => { - t.truthy(path.isAbsolute(file)) - }) -}) - -test('it returns relative paths', async t => { - const files = await all(glob(__dirname, '**/*', { - absolute: false - })) - - files.forEach(file => { - t.falsy(path.isAbsolute(file)) - }) -}) - -test('it matches directories', async t => { - const files = await all(glob(__dirname, 'node_modules/*')) - - t.truthy(files.includes(path.join('node_modules', 'it-all'))) -}) - -test('it skips directories', async t => { - const files = await all(glob(__dirname, 'node_modules/**/*', { - nodir: true, - dot: true - })) - - t.falsy(files.includes(path.join('node_modules', '.bin'))) - t.truthy(files.includes(path.join('node_modules', '.bin', 'ava'))) -}) diff --git a/packages/it-glob/test/index.spec.ts b/packages/it-glob/test/index.spec.ts new file mode 100644 index 00000000..9e4566d2 --- /dev/null +++ b/packages/it-glob/test/index.spec.ts @@ -0,0 +1,81 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import glob from '../src/index.js' +import path, { dirname } from 'path' +import { fileURLToPath } from 'url' + +const dir = dirname(fileURLToPath(import.meta.url)) + +describe('it-glob', () => { + it('should match file', async () => { + const files = await all(glob('.', '**/*')) + + expect(files.includes('README.md')).to.be.true() + }) + + it('should match file in subdirectory', async () => { + const files = await all(glob('.', '**/*')) + + expect(files.includes(path.join('dist', 'src', 'index.d.ts'))).to.be.true() + }) + + it('should match one', async () => { + const files = await all(glob('.', 'README.md')) + + expect(files).to.deep.equal(['README.md']) + }) + + it('should match files', async () => { + const files = await all(glob('README.md', 'README.md')) + + expect(files).to.deep.equal(['README.md']) + }) + + it('should ignore files', async () => { + const files = await all(glob('.', '**/*!(*/index.js|**/dist/**)')) + + expect(files.includes('test/index.js')).to.be.false() + }) + + it('should ignore files from absolute directory', async () => { + const files = await all(glob(dir, '**/*!(test/index.js|)**/dist/**')) + + expect(files.includes(path.resolve(dir, 'index.js'))).to.be.false() + }) + + it('should return absolute paths', async () => { + const files = await all(glob(dir, '**/*', { + absolute: true + })) + + files.forEach(file => { + expect(path.isAbsolute(file)).to.be.true() + }) + }) + + it('should return relative paths', async () => { + const files = await all(glob(dir, '**/*', { + absolute: false + })) + + files.forEach(file => { + expect(path.isAbsolute(file)).to.be.false() + }) + }) + + it('should match directories', async () => { + const files = await all(glob(path.resolve(dir, '..', '..'), 'dist/*')) + + expect(files.includes(path.join('dist', 'src'))).to.be.true() + }) + + it('should skip directories', async () => { + const files = await all(glob(path.resolve(dir, '..', '..'), 'dist/**/*', { + nodir: true, + dot: true + })) + + expect(files.includes(path.join('dist', 'src'))).to.be.false() + expect(files.includes(path.join('dist', 'src', 'index.js'))).to.be.true() + }) +}) diff --git a/packages/it-glob/tsconfig.json b/packages/it-glob/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-glob/tsconfig.json +++ b/packages/it-glob/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-last/.npmignore b/packages/it-last/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-last/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-last/LICENSE b/packages/it-last/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-last/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-last/LICENSE-APACHE b/packages/it-last/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-last/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-last/LICENSE-MIT b/packages/it-last/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-last/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-last/README.md b/packages/it-last/README.md index 80f493c7..d87900d0 100644 --- a/packages/it-last/README.md +++ b/packages/it-last/README.md @@ -1,21 +1,29 @@ -# it-last +# it-last -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-last)](https://david-dm.org/achingbrain/it?path=packages/it-last) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Returns the last item of an (async) iterable +> Returns the last result from an async iterator -Mostly useful for tests. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-last +```console +$ npm i it-last ``` +Mostly useful for tests. + ## Usage ```javascript -const last = require('it-last') +import last from 'it-last' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -24,3 +32,14 @@ const res = await last(values) console.info(res) // 4 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-last/package.json b/packages/it-last/package.json index 53597092..cc9f0090 100644 --- a/packages/it-last/package.json +++ b/packages/it-last/package.json @@ -2,27 +2,139 @@ "name": "it-last", "version": "1.0.6", "description": "Returns the last result from an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-last#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-last/index.js b/packages/it-last/src/index.ts similarity index 51% rename from packages/it-last/index.js rename to packages/it-last/src/index.ts index 20dbe680..1505b219 100644 --- a/packages/it-last/index.js +++ b/packages/it-last/src/index.ts @@ -1,13 +1,8 @@ -'use strict' - /** * Returns the last item of an (async) iterable, unless empty, in which case - * return `undefined`. - * - * @template T - * @param {AsyncIterable|Iterable} source + * return `undefined` */ -const last = async (source) => { +export default async function last (source: AsyncIterable|Iterable): Promise { let res for await (const entry of source) { @@ -16,5 +11,3 @@ const last = async (source) => { return res } - -module.exports = last diff --git a/packages/it-last/test.js b/packages/it-last/test.js deleted file mode 100644 index fcdc7e8d..00000000 --- a/packages/it-last/test.js +++ /dev/null @@ -1,10 +0,0 @@ -const last = require('./') -const test = require('ava') - -test('Should return only the last result from an async iterator', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await last(values) - - t.is(res, 4) -}) diff --git a/packages/it-last/test/index.spec.ts b/packages/it-last/test/index.spec.ts new file mode 100644 index 00000000..dfd1f013 --- /dev/null +++ b/packages/it-last/test/index.spec.ts @@ -0,0 +1,20 @@ +import { expect } from 'aegir/chai' +import last from '../src/index.js' + +describe('it-last', () => { + it('should return only the last result from an async iterator', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await last(values) + + expect(res).to.equal(4) + }) + + it('should return undefined if the async iterator was empty', async () => { + const values: any[] = [] + + const res = await last(values) + + expect(res).to.be.undefined() + }) +}) diff --git a/packages/it-last/tsconfig.json b/packages/it-last/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-last/tsconfig.json +++ b/packages/it-last/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-length/.npmignore b/packages/it-length/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-length/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-length/LICENSE b/packages/it-length/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-length/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-length/LICENSE-APACHE b/packages/it-length/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-length/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-length/LICENSE-MIT b/packages/it-length/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-length/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-length/README.md b/packages/it-length/README.md index 3a8cc1cb..5bbadcc1 100644 --- a/packages/it-length/README.md +++ b/packages/it-length/README.md @@ -1,21 +1,29 @@ -# it-length +# it-length -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-last)](https://david-dm.org/achingbrain/it?path=packages/it-last) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Counts the items in an async iterable +> Counts the number of items in an async iterable -N.b. will consume the iterable +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-length +```console +$ npm i it-length ``` +N.b. will consume the iterable + ## Usage ```javascript -const length = require('it-length') +import length from 'it-length' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -24,3 +32,14 @@ const res = await length(values) console.info(res) // 5 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-length/index.js b/packages/it-length/index.js deleted file mode 100644 index b99e4e21..00000000 --- a/packages/it-length/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -/** - * Consumes the passed iterator and returns the number of items it contained. - * - * @param {AsyncIterable | Iterable} iterator - * @returns {Promise} - */ -const length = async (iterator) => { - let count = 0 - - for await (const _ of iterator) { // eslint-disable-line no-unused-vars - count++ - } - - return count -} - -module.exports = length diff --git a/packages/it-length/package.json b/packages/it-length/package.json index 3e22dfe2..0ca4f485 100644 --- a/packages/it-length/package.json +++ b/packages/it-length/package.json @@ -2,27 +2,139 @@ "name": "it-length", "version": "1.0.4", "description": "Counts the number of items in an async iterable", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-length#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-length/src/index.ts b/packages/it-length/src/index.ts new file mode 100644 index 00000000..7eb21b2f --- /dev/null +++ b/packages/it-length/src/index.ts @@ -0,0 +1,12 @@ +/** + * Consumes the passed iterator and returns the number of items it contained + */ +export default async function length (iterator: AsyncIterable | Iterable): Promise { + let count = 0 + + for await (const _ of iterator) { // eslint-disable-line no-unused-vars,@typescript-eslint/no-unused-vars + count++ + } + + return count +} diff --git a/packages/it-length/test.js b/packages/it-length/test.js deleted file mode 100644 index 8d4f6191..00000000 --- a/packages/it-length/test.js +++ /dev/null @@ -1,10 +0,0 @@ -const length = require('./') -const test = require('ava') - -test('Should count the items in an async iterator', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await length(values) - - t.is(res, 5) -}) diff --git a/packages/it-length/test/index.spec.ts b/packages/it-length/test/index.spec.ts new file mode 100644 index 00000000..cf3cdac6 --- /dev/null +++ b/packages/it-length/test/index.spec.ts @@ -0,0 +1,12 @@ +import { expect } from 'aegir/chai' +import length from '../src/index.js' + +describe('it-length', () => { + it('should count the items in an async iterator', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await length(values) + + expect(res).to.equal(5) + }) +}) diff --git a/packages/it-length/tsconfig.json b/packages/it-length/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-length/tsconfig.json +++ b/packages/it-length/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-map/.npmignore b/packages/it-map/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-map/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-map/LICENSE b/packages/it-map/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-map/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-map/LICENSE-APACHE b/packages/it-map/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-map/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-map/LICENSE-MIT b/packages/it-map/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-map/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-map/README.md b/packages/it-map/README.md index 46b4ee98..c7c5a2a0 100644 --- a/packages/it-map/README.md +++ b/packages/it-map/README.md @@ -1,20 +1,27 @@ +# it-map -# it-map +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-map)](https://david-dm.org/achingbrain/it?path=packages/it-map) +> Maps the values yielded by an async iterator -> Maps the values yielded by an (async) iterator +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-map +```console +$ npm i it-map ``` ## Usage ```javascript -const map = require('it-map') +import map from 'it-map' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -23,3 +30,14 @@ const result = await map(values, (val) => val++) console.info(result) // 15 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-map/index.js b/packages/it-map/index.js deleted file mode 100644 index fb6552f6..00000000 --- a/packages/it-map/index.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -/** - * Takes an (async) iterable and returns one with each item mapped by the passed - * function. - * - * @template I,O - * @param {AsyncIterable|Iterable} source - * @param {function(I):O|Promise} func - * @returns {AsyncIterable} - */ -const map = async function * (source, func) { - for await (const val of source) { - yield func(val) - } -} - -module.exports = map diff --git a/packages/it-map/package.json b/packages/it-map/package.json index 867c430e..8befa874 100644 --- a/packages/it-map/package.json +++ b/packages/it-map/package.json @@ -2,27 +2,139 @@ "name": "it-map", "version": "1.0.6", "description": "Maps the values yielded by an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-map#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-map/src/index.ts b/packages/it-map/src/index.ts new file mode 100644 index 00000000..373521f0 --- /dev/null +++ b/packages/it-map/src/index.ts @@ -0,0 +1,9 @@ +/** + * Takes an (async) iterable and returns one with each item mapped by the passed + * function + */ +export default async function * map (source: AsyncIterable|Iterable, func: (val: I) => O | Promise): AsyncGenerator { + for await (const val of source) { + yield func(val) + } +} diff --git a/packages/it-map/test.js b/packages/it-map/test.js deleted file mode 100644 index 38dc4521..00000000 --- a/packages/it-map/test.js +++ /dev/null @@ -1,22 +0,0 @@ -const map = require('./') -const test = require('ava') - -test('Should map an async iterator', async (t) => { - const iter = function * () { - yield 1 - } - - for await (const result of map(iter(), (val) => val + 1)) { - t.is(result, 2) - } -}) - -test('Should map an async iterator to a promise', async (t) => { - const iter = function * () { - yield 1 - } - - for await (const result of map(iter(), async (val) => val + 1)) { - t.is(result, 2) - } -}) diff --git a/packages/it-map/test/index.spec.ts b/packages/it-map/test/index.spec.ts new file mode 100644 index 00000000..5005dce2 --- /dev/null +++ b/packages/it-map/test/index.spec.ts @@ -0,0 +1,24 @@ +import { expect } from 'aegir/chai' +import map from '../src/index.js' + +describe('it-map', () => { + it('should map an async iterator', async () => { + const iter = function * () { + yield 1 + } + + for await (const result of map(iter(), (val) => val + 1)) { + expect(result).to.equal(2) + } + }) + + it('should map an async iterator to a promise', async () => { + const iter = function * () { + yield 1 + } + + for await (const result of map(iter(), async (val) => val + 1)) { + expect(result).to.equal(2) + } + }) +}) diff --git a/packages/it-map/tsconfig.json b/packages/it-map/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-map/tsconfig.json +++ b/packages/it-map/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-merge/.npmignore b/packages/it-merge/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-merge/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-merge/LICENSE b/packages/it-merge/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-merge/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-merge/LICENSE-APACHE b/packages/it-merge/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-merge/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-merge/LICENSE-MIT b/packages/it-merge/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-merge/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-merge/README.md b/packages/it-merge/README.md index 9b4f922a..7b753812 100644 --- a/packages/it-merge/README.md +++ b/packages/it-merge/README.md @@ -1,21 +1,30 @@ -# it-merge +# it-merge -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-merge)](https://david-dm.org/achingbrain/it?path=packages/it-merge) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Treat a number of (async) iterables as if they were one +> Treat one or more iterables as a single iterable -Nb. sources are iterated over in parallel so the order of emitted items is not guaranteed. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-merge +```console +$ npm i it-merge ``` +Nb. sources are iterated over in parallel so the order of emitted items is not guaranteed. + ## Usage ```javascript -const all = require('it-merge') +import merge from 'it-merge' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values1 = [0, 1, 2, 3, 4] @@ -25,3 +34,14 @@ const arr = await all(merge(values1, values2)) console.info(arr) // 0, 1, 5, 6, 2, 3, 4, 7, 8, 9 <- nb. order is not guaranteed ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-merge/package.json b/packages/it-merge/package.json index 2e90ea19..405bd079 100644 --- a/packages/it-merge/package.json +++ b/packages/it-merge/package.json @@ -2,31 +2,143 @@ "name": "it-merge", "version": "1.0.4", "description": "Treat one or more iterables as a single iterable", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-merge#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { - "it-pushable": "^1.4.0" + "it-pushable": "^3.1.0" }, "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-merge/index.js b/packages/it-merge/src/index.ts similarity index 55% rename from packages/it-merge/index.js rename to packages/it-merge/src/index.ts index 40652836..7ff40fd5 100644 --- a/packages/it-merge/index.js +++ b/packages/it-merge/src/index.ts @@ -1,21 +1,17 @@ -'use strict' - -const pushable = require('it-pushable') +import { pushable } from 'it-pushable' /** * Treat one or more iterables as a single iterable. * * Nb. sources are iterated over in parallel so the * order of emitted items is not guaranteed. - * - * @template T - * @param {...AsyncIterable|Iterable} sources - * @returns {AsyncIterable} */ -const merge = async function * (...sources) { - const output = pushable() +export default async function * merge (...sources: Array|Iterable>): AsyncGenerator { + const output = pushable({ + objectMode: true + }) - setTimeout(async () => { + void Promise.resolve().then(async () => { try { await Promise.all( sources.map(async (source) => { @@ -26,12 +22,10 @@ const merge = async function * (...sources) { ) output.end() - } catch (/** @type {any} */ err) { + } catch (err: any) { output.end(err) } - }, 0) + }) yield * output } - -module.exports = merge diff --git a/packages/it-merge/test.js b/packages/it-merge/test.js deleted file mode 100644 index bb4c21fe..00000000 --- a/packages/it-merge/test.js +++ /dev/null @@ -1,12 +0,0 @@ -const merge = require('./') -const all = require('it-all') -const test = require('ava') - -test('Should merge multiple arrays', async (t) => { - const values1 = [0, 1, 2, 3, 4] - const values2 = [5, 6, 7, 8, 9] - - const res = await all(merge(values1, values2)) - - t.deepEqual(res.sort(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) -}) diff --git a/packages/it-merge/test/index.spec.ts b/packages/it-merge/test/index.spec.ts new file mode 100644 index 00000000..38f39880 --- /dev/null +++ b/packages/it-merge/test/index.spec.ts @@ -0,0 +1,24 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import merge from '../src/index.js' + +describe('it-merge', () => { + it('should merge multiple arrays', async () => { + const values1 = [0, 1, 2, 3, 4] + const values2 = [5, 6, 7, 8, 9] + + const res = await all(merge(values1, values2)) + + expect(res.sort((a, b) => { + if (a < b) { + return -1 + } + + if (a > b) { + return 1 + } + + return 0 + })).to.deep.equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + }) +}) diff --git a/packages/it-merge/tsconfig.json b/packages/it-merge/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-merge/tsconfig.json +++ b/packages/it-merge/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-multipart/.npmignore b/packages/it-multipart/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-multipart/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-multipart/LICENSE b/packages/it-multipart/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-multipart/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-multipart/LICENSE-APACHE b/packages/it-multipart/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-multipart/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-multipart/LICENSE-MIT b/packages/it-multipart/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-multipart/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-multipart/README.md b/packages/it-multipart/README.md index 589b6bf2..903bac43 100644 --- a/packages/it-multipart/README.md +++ b/packages/it-multipart/README.md @@ -1,14 +1,28 @@ -# it-multipart +# it-multipart -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-multipart)](https://david-dm.org/achingbrain/it?path=packages/it-multipart) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Streaming multipart HTTP message parser +> Async iterable http multipart message parser + +## Table of contents + +- [Install](#install) +- [Example](#example) +- [License](#license) +- [Contribute](#contribute) + +## Install + +```console +$ npm i it-multipart +``` ## Example ```javascript -const http = require('http') -const multipart = require('it-multipart') +import http from 'http' +import multipart from 'it-multipart' http.createServer(async (req, res) => { if (req.method === 'POST' && req.headers['content-type']) { @@ -32,3 +46,14 @@ http.createServer(async (req, res) => { console.log('server listening on port 5001') }) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-multipart/package.json b/packages/it-multipart/package.json index 2156a0b0..0bc04990 100644 --- a/packages/it-multipart/package.json +++ b/packages/it-multipart/package.json @@ -2,34 +2,148 @@ "name": "it-multipart", "version": "2.0.2", "description": "Async iterable http multipart message parser", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-multipart#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test -t node", + "test:node": "aegir test -t node --cov", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { - "formidable": "^1.2.2", - "it-pushable": "^1.4.2" + "formidable": "^2.0.1", + "it-pushable": "^3.1.0" }, "devDependencies": { - "@types/formidable": "^1.2.1", - "ava": "^3.12.1", - "form-data": "^3.0.0", - "node-fetch": "^2.6.0", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "@types/formidable": "^2.0.5", + "aegir": "^37.5.0", + "form-data": "^4.0.0", + "it-drain": "^1.0.5", + "node-fetch": "^3.2.10", + "uint8arrays": "^4.0.2" + }, + "browser": { + "http": false, + "formidable": false + } } diff --git a/packages/it-multipart/index.js b/packages/it-multipart/src/index.ts similarity index 51% rename from packages/it-multipart/index.js rename to packages/it-multipart/src/index.ts index 41432c81..a5480f68 100644 --- a/packages/it-multipart/index.js +++ b/packages/it-multipart/src/index.ts @@ -1,26 +1,21 @@ -'use strict' +import formidable from 'formidable' +import { pushable } from 'it-pushable' +import type { IncomingMessage, IncomingHttpHeaders } from 'http' -const formidable = require('formidable') -const pushable = require('it-pushable') - -/** - * @typedef {import('http').IncomingMessage} IncomingMessage - * @typedef {import('http').IncomingHttpHeaders} IncomingHttpHeaders - * @typedef {Object} Part - * @property {IncomingHttpHeaders} headers - * @property {AsyncIterable} body - */ +export interface Part { + headers: IncomingHttpHeaders + body: AsyncIterable +} /** * Streaming multipart HTTP message parser - * - * @param {IncomingMessage} request - * @returns {AsyncIterable} */ -async function * multipart (request) { - const output = pushable() +export default async function * multipart (request: IncomingMessage): AsyncGenerator { + const output = pushable({ + objectMode: true + }) - if (!request) { + if (request == null) { output.end(new Error('request missing')) yield * output @@ -48,6 +43,7 @@ async function * multipart (request) { }) output.push({ + // @ts-expect-error headers is not part of formidable api but is present headers: part.headers, body }) @@ -55,5 +51,3 @@ async function * multipart (request) { yield * output } - -module.exports = multipart diff --git a/packages/it-multipart/test.js b/packages/it-multipart/test.js deleted file mode 100644 index 69ab46a8..00000000 --- a/packages/it-multipart/test.js +++ /dev/null @@ -1,127 +0,0 @@ -const test = require('ava') -const http = require('http') -const handler = require('.') -// @ts-ignore -const fetch = require('node-fetch') -const FormData = require('form-data') - -/** @type {string} */ -let port -/** @type {import('http').Server} */ -let server - -test.before.cb((t) => { - /** - * @param {import('http').IncomingMessage} req - */ - async function echo (req) { - /** @type {Record} */ - const files = {} - - for await (const part of handler(req)) { - // @ts-ignore - header may not be present - const name = part.headers['content-disposition'].match(/name="(.*)"/)[1] - - files[name] = '' - - for await (const str of part.body) { - files[name] += str - } - } - - return JSON.stringify(files) - } - - server = http.createServer((req, res) => { - echo(req) - .then((files) => { - res.writeHead(200, { - 'content-length': files.length, - 'content-type': 'application/json' - }) - res.end(files) - }) - .catch(err => { - if (err.message.includes('bad content-type header')) { - res.writeHead(400) - } else { - res.writeHead(500) - } - - res.end(err.stack) - }) - }).listen(() => { - // @ts-ignore - address() returns `null|string|object` and TS can't infer - // it's last one even though it's inside listen callback. - port = server.address().port - t.end() - }) -}) - -test.after.cb((t) => { - server.close(() => t.end()) -}) - -test('it parses files from a multipart request', async (t) => { - const formData = new FormData() - formData.append('file-1.txt', Buffer.from('file 1 contents')) - formData.append('file-2.txt', Buffer.from('file 2 contents')) - - const result = await fetch(`http://localhost:${port}`, { - method: 'POST', - headers: formData.getHeaders(), - body: formData - }) - - t.is(result.status, 200) - - const response = await result.json() - - t.deepEqual(response, { - 'file-1.txt': 'file 1 contents', - 'file-2.txt': 'file 2 contents' - }) -}) - -test('it parses loads of files from multipart requests', async (t) => { - await Promise.all( - [1, 2, 3, 4, 5].map(async (index) => { - const formData = new FormData() - - for (let i = 0; i < (100 * index); i++) { - formData.append(`file-${i}.txt`, Buffer.from(`file ${i} contents`)) - } - - const result = await fetch(`http://localhost:${port}`, { - method: 'POST', - headers: formData.getHeaders(), - body: formData - }) - - t.is(result.status, 200) - - const response = await result.json() - - for (let i = 0; i < (10 * index); i++) { - t.is(response[`file-${i}.txt`], `file ${i} contents`) - } - }) - ) -}) - -test('it throws when request is not passed', async (t) => { - await t.throwsAsync(async () => { - for await (const _ of handler()) { // eslint-disable-line no-unused-vars - - } - }, { message: 'request missing' }) -}) - -test('it throws when request is not multipart', async (t) => { - const result = await fetch(`http://localhost:${port}`, { - method: 'POST', - body: 'not multipart' - }) - - t.is(result.status, 400) -}) diff --git a/packages/it-multipart/test/index.spec.ts b/packages/it-multipart/test/index.spec.ts new file mode 100644 index 00000000..3caf9af0 --- /dev/null +++ b/packages/it-multipart/test/index.spec.ts @@ -0,0 +1,131 @@ +import { expect } from 'aegir/chai' +import http from 'http' +import handler from '../src/index.js' +import fetch from 'node-fetch' +import FormData from 'form-data' +import drain from 'it-drain' +import { toString as uint8ArrayToString } from 'uint8arrays/to-string' +import type { Server, IncomingMessage } from 'http' + +describe('it-multipart', () => { + let port: string + let server: Server + + before(async () => { + async function echo (req: IncomingMessage) { + const files: Record = {} + + for await (const part of handler(req)) { + // @ts-expect-error - header may not be present + const name = part.headers['content-disposition'].match(/name="(.*)"/)[1] + + files[name] = '' + + for await (const str of part.body) { + files[name] += uint8ArrayToString(str) + } + } + + return JSON.stringify(files) + } + + port = await new Promise((resolve, reject) => { + server = http.createServer((req, res) => { + echo(req) + .then((files) => { + res.writeHead(200, { + 'content-length': files.length, + 'content-type': 'application/json' + }) + res.end(files) + }) + .catch(err => { + if (err.message.includes('bad content-type header') === true || err.message.includes('no parser found') === true) { + res.writeHead(400) + } else { + res.writeHead(500) + } + + res.end(err.stack) + }) + }) + server.on('error', (err) => { + reject(err) + }) + server.listen(() => { + // @ts-expect-error - address() returns `null|string|object` and TS can't infer + // it's last one even though it's inside listen callback. + resolve(server.address().port) + }) + }) + }) + + after((cb) => { + if (port != null && server != null) { + server.close(() => { + cb() + }) + } + }) + + it('should parse files from a multipart request', async () => { + const formData = new FormData() + formData.append('file-1.txt', Buffer.from('file 1 contents')) + formData.append('file-2.txt', Buffer.from('file 2 contents')) + + const result = await fetch(`http://127.0.0.1:${port}`, { + method: 'POST', + headers: formData.getHeaders(), + body: formData + }) + + expect(result.status).to.equal(200) + + const response = await result.json() + + expect(response).to.deep.equal({ + 'file-1.txt': 'file 1 contents', + 'file-2.txt': 'file 2 contents' + }) + }) + + it('should parse loads of files from multipart requests', async () => { + await Promise.all( + [1, 2, 3, 4, 5].map(async (index) => { + const formData = new FormData() + + for (let i = 0; i < (100 * index); i++) { + formData.append(`file-${i}.txt`, Buffer.from(`file ${i} contents`)) + } + + const result = await fetch(`http://localhost:${port}`, { + method: 'POST', + headers: formData.getHeaders(), + body: formData + }) + + expect(result.status).to.equal(200) + + const response: any = await result.json() + + for (let i = 0; i < (10 * index); i++) { + expect(response[`file-${i}.txt`]).to.equal(`file ${i} contents`) + } + }) + ) + }) + + it('should throw when request is not passed', async () => { + // @ts-expect-error missing argument + await expect(drain(handler())).to.eventually.be.rejected().with.property('message', 'request missing') + }) + + it('should throw when request is not multipart', async () => { + const result = await fetch(`http://localhost:${port}`, { + method: 'POST', + body: 'not multipart' + }) + + expect(result.status).to.equal(400) + }) +}) diff --git a/packages/it-multipart/tsconfig.json b/packages/it-multipart/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-multipart/tsconfig.json +++ b/packages/it-multipart/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-ndjson/.npmignore b/packages/it-ndjson/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-ndjson/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-ndjson/LICENSE b/packages/it-ndjson/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-ndjson/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-ndjson/LICENSE-APACHE b/packages/it-ndjson/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-ndjson/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-ndjson/LICENSE-MIT b/packages/it-ndjson/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-ndjson/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-ndjson/README.md b/packages/it-ndjson/README.md index 45b2b995..4bf603e8 100644 --- a/packages/it-ndjson/README.md +++ b/packages/it-ndjson/README.md @@ -1,20 +1,28 @@ -# it-ndjson +# it-ndjson -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-ndjson)](https://david-dm.org/achingbrain/it?path=packages/it-ndjson) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Parse iterators as ndjson and transform iterators to ndjson +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) + ## Install -```sh -$ npm install --save it-ndjson +```console +$ npm i it-ndjson ``` ## Usage ```javascript -const ndjson = require('it-ndjson') -const all = require('it-all') +import ndjson from 'it-ndjson' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -27,3 +35,14 @@ const res = await all(ndjson.parse(arr)) console.info(res) // [0, 1, 2, 3, 4] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-ndjson/index.js b/packages/it-ndjson/index.js deleted file mode 100644 index a66cd743..00000000 --- a/packages/it-ndjson/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const parse = require('./parse') -const stringify = require('./stringify') - -module.exports = { - parse, - stringify -} diff --git a/packages/it-ndjson/package.json b/packages/it-ndjson/package.json index e82b190e..33a875e9 100644 --- a/packages/it-ndjson/package.json +++ b/packages/it-ndjson/package.json @@ -2,29 +2,141 @@ "name": "it-ndjson", "version": "0.1.1", "description": "Parse iterators as ndjson and transform iterators to ndjson", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-ndjson#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", + "aegir": "^37.5.0", "buffer": "^6.0.3", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "it-all": "^1.0.0" + } } diff --git a/packages/it-ndjson/src/index.ts b/packages/it-ndjson/src/index.ts new file mode 100644 index 00000000..87ae384d --- /dev/null +++ b/packages/it-ndjson/src/index.ts @@ -0,0 +1,3 @@ + +export { default as parse } from './parse.js' +export { default as stringify } from './stringify.js' diff --git a/packages/it-ndjson/parse.js b/packages/it-ndjson/src/parse.ts similarity index 68% rename from packages/it-ndjson/parse.js rename to packages/it-ndjson/src/parse.ts index 2ea9b21e..98d30c6e 100644 --- a/packages/it-ndjson/parse.js +++ b/packages/it-ndjson/src/parse.ts @@ -1,7 +1,5 @@ -/** - * @param {AsyncIterable | Iterable} source - */ -async function * parse (source) { + +export default async function * parse (source: AsyncIterable | Iterable): AsyncGenerator { const matcher = /\r?\n/ const decoder = new TextDecoder('utf8') let buffer = '' @@ -13,7 +11,7 @@ async function * parse (source) { buffer += decoder.decode(chunk, { stream: true }) const parts = buffer.split(matcher) - buffer = parts.pop() || '' + buffer = parts.pop() ?? '' for (let i = 0; i < parts.length; i++) { yield JSON.parse(parts[i]) @@ -22,9 +20,7 @@ async function * parse (source) { buffer += decoder.decode() - if (buffer) { + if (buffer !== '') { yield JSON.parse(buffer) } } - -module.exports = parse diff --git a/packages/it-ndjson/src/stringify.ts b/packages/it-ndjson/src/stringify.ts new file mode 100644 index 00000000..3fee4139 --- /dev/null +++ b/packages/it-ndjson/src/stringify.ts @@ -0,0 +1,6 @@ + +export default async function * stringify (source: AsyncIterable | Iterable): AsyncGenerator { + for await (const obj of source) { + yield JSON.stringify(obj) + '\n' + } +} diff --git a/packages/it-ndjson/stringify.js b/packages/it-ndjson/stringify.js deleted file mode 100644 index bf98e9bb..00000000 --- a/packages/it-ndjson/stringify.js +++ /dev/null @@ -1,11 +0,0 @@ - -/** - * @param {AsyncIterable | Iterable} source - */ -async function * stringify (source) { - for await (const obj of source) { - yield JSON.stringify(obj) + '\n' - } -} - -module.exports = stringify diff --git a/packages/it-ndjson/test.js b/packages/it-ndjson/test.js deleted file mode 100644 index f58a7e4d..00000000 --- a/packages/it-ndjson/test.js +++ /dev/null @@ -1,90 +0,0 @@ -const test = require('ava') -const ndjson = require('.') -const { Buffer } = require('buffer') -const all = require('it-all') - -/** - * @template T - * @param {T[]} array - * @returns {AsyncIterable} - */ -async function * toAsyncIterator (array) { - for (let i = 0; i < array.length; i++) { - yield new Promise(resolve => setTimeout(() => resolve(array[i]))) - } -} - -/** - * @param {string} str - */ -function toUint8Array (str) { - const arr = new Uint8Array(str.length) - for (let i = 0; i < str.length; i++) { - arr[i] = str.charCodeAt(i) - } - return arr -} - -test('should split 1 item from 1 chunk', async t => { - const source = toAsyncIterator(['{ "id": 1 }\n']) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }]) -}) - -test('should split 1 item from 2 chunks', async t => { - const source = toAsyncIterator(['{ "id', '": 1 }\n']) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }]) -}) - -test('should split 2 items from 2 chunks', async t => { - const source = toAsyncIterator(['{ "id": 1 }\n', '{ "id": 2 }']) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }, { id: 2 }]) -}) - -test('should split 2 items from 1 chunk', async t => { - const source = toAsyncIterator(['{ "id": 1 }\n{ "id": 2 }']) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }, { id: 2 }]) -}) - -test('should split 3 items from 2 chunks', async t => { - const source = toAsyncIterator(['{ "id": 1 }\n{ "i', 'd": 2 }', '\n{"id":3}']) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }, { id: 2 }, { id: 3 }]) -}) - -test('should split from Buffers', async t => { - const source = toAsyncIterator([Buffer.from('{ "id": 1 }\n{ "i'), Buffer.from('d": 2 }'), Buffer.from('\n{"id":3}')]) - const results = await all(ndjson.parse(source)) - t.deepEqual(results, [{ id: 1 }, { id: 2 }, { id: 3 }]) -}) - -test('should split from Uint8Arrays', async t => { - const source = toAsyncIterator([toUint8Array('{ "id": 1 }\n{ "i'), toUint8Array('d": 2 }'), toUint8Array('\n{"id":3}')]) - const results = await all(ndjson.parse(source)) - - t.deepEqual(results, [{ id: 1 }, { id: 2 }, { id: 3 }]) -}) - -test('should round trip', async t => { - const input = '{"id":1}\n{"id":2}\n{"id":3}\n' - const source = toAsyncIterator([input]) - const results = await all(ndjson.stringify(ndjson.parse(source))) - - t.is(results.join(''), input) -}) - -test('should stringify trip', async t => { - const input = [{ id: 1 }, { id: 2 }, { id: 3 }] - const source = toAsyncIterator(input) - const results = await all(ndjson.stringify(source)) - - t.is(results.join(''), '{"id":1}\n{"id":2}\n{"id":3}\n') -}) diff --git a/packages/it-ndjson/test/index.spec.ts b/packages/it-ndjson/test/index.spec.ts new file mode 100644 index 00000000..fc26c42f --- /dev/null +++ b/packages/it-ndjson/test/index.spec.ts @@ -0,0 +1,85 @@ +import { expect } from 'aegir/chai' +import * as ndjson from '../src/index.js' +import { Buffer } from 'buffer' +import all from 'it-all' + +async function * toAsyncIterator (array: T[]): AsyncIterable { + for (let i = 0; i < array.length; i++) { + await new Promise(resolve => setTimeout(() => resolve())) + yield array[i] + } +} + +function toUint8Array (str: string): Uint8Array { + const arr = new Uint8Array(str.length) + for (let i = 0; i < str.length; i++) { + arr[i] = str.charCodeAt(i) + } + return arr +} + +describe('it-ndjson', () => { + it('should split 1 item from 1 chunk', async () => { + const source = toAsyncIterator(['{ "id": 1 }\n']) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }]) + }) + + it('should split 1 item from 2 chunks', async () => { + const source = toAsyncIterator(['{ "id', '": 1 }\n']) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }]) + }) + + it('should split 2 items from 2 chunks', async () => { + const source = toAsyncIterator(['{ "id": 1 }\n', '{ "id": 2 }']) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }, { id: 2 }]) + }) + + it('should split 2 items from 1 chunk', async () => { + const source = toAsyncIterator(['{ "id": 1 }\n{ "id": 2 }']) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }, { id: 2 }]) + }) + + it('should split 3 items from 2 chunks', async () => { + const source = toAsyncIterator(['{ "id": 1 }\n{ "i', 'd": 2 }', '\n{"id":3}']) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }, { id: 2 }, { id: 3 }]) + }) + + it('should split from Buffers', async () => { + const source = toAsyncIterator([Buffer.from('{ "id": 1 }\n{ "i'), Buffer.from('d": 2 }'), Buffer.from('\n{"id":3}')]) + const results = await all(ndjson.parse(source)) + expect(results).to.deep.equal([{ id: 1 }, { id: 2 }, { id: 3 }]) + }) + + it('should split from Uint8Arrays', async () => { + const source = toAsyncIterator([toUint8Array('{ "id": 1 }\n{ "i'), toUint8Array('d": 2 }'), toUint8Array('\n{"id":3}')]) + const results = await all(ndjson.parse(source)) + + expect(results).to.deep.equal([{ id: 1 }, { id: 2 }, { id: 3 }]) + }) + + it('should round trip', async () => { + const input = '{"id":1}\n{"id":2}\n{"id":3}\n' + const source = toAsyncIterator([input]) + const results = await all(ndjson.stringify(ndjson.parse(source))) + + expect(results.join('')).to.equal(input) + }) + + it('should stringify trip', async () => { + const input = [{ id: 1 }, { id: 2 }, { id: 3 }] + const source = toAsyncIterator(input) + const results = await all(ndjson.stringify(source)) + + expect(results.join('')).to.equal('{"id":1}\n{"id":2}\n{"id":3}\n') + }) +}) diff --git a/packages/it-ndjson/tsconfig.json b/packages/it-ndjson/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-ndjson/tsconfig.json +++ b/packages/it-ndjson/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-parallel-batch/.npmignore b/packages/it-parallel-batch/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-parallel-batch/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-parallel-batch/LICENSE b/packages/it-parallel-batch/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-parallel-batch/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-parallel-batch/LICENSE-APACHE b/packages/it-parallel-batch/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-parallel-batch/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-parallel-batch/LICENSE-MIT b/packages/it-parallel-batch/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-parallel-batch/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-parallel-batch/README.md b/packages/it-parallel-batch/README.md index ce191201..2d92bcaa 100644 --- a/packages/it-parallel-batch/README.md +++ b/packages/it-parallel-batch/README.md @@ -1,23 +1,31 @@ -# it-parallel-batch +# it-parallel-batch -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-parallel-batch)](https://david-dm.org/achingbrain/it?path=packages/it-parallel-batch) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Takes an (async) iterable that emits promise-returning functions, invokes them in parallel and emits the results as they become available but in the same order as the input +> Takes an async iterator that emits promise-returning functions, invokes them in parallel and emits the results in the same order as the input -The final batch may be smaller than the batch size. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-parallel-batch +```console +$ npm i it-parallel-batch ``` +The final batch may be smaller than the batch size. + ## Usage ```javascript -const parallelBatch = require('it-parallel-batch') -const all = require('it-all') -const delay = require('delay') +import parallelBatch from 'it-parallel-batch' +import all from 'it-all' +import delay from 'delay' // This can also be an iterator, async iterator, generator, etc const input = [ @@ -44,3 +52,14 @@ const result = await all(parallelBatch(input, batchSize)) console.info(result) // [1, 2, 3] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-parallel-batch/index.js b/packages/it-parallel-batch/index.js deleted file mode 100644 index dade63cf..00000000 --- a/packages/it-parallel-batch/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict' - -const batch = require('it-batch') - -/** - * @template T - * @typedef {{ok:true, value:T}} Success - */ - -/** - * @typedef {{ok:false, err:Error}} Failure - */ - -/** - * Takes an (async) iterator that emits promise-returning functions, - * invokes them in parallel and emits the results as they become available but - * in the same order as the input - * - * @template T - * @param {AsyncIterable<() => Promise>|Iterable<() => Promise>} source - * @param {number} [size=1] - * @returns {AsyncIterable} - */ -async function * parallelBatch (source, size = 1) { - for await (const tasks of batch(source, size)) { - /** @type {Promise|Failure>[]} */ - const things = tasks.map( - /** - * @param {() => Promise} p - */ - p => { - return p().then(value => ({ ok: true, value }), err => ({ ok: false, err })) - }) - - for (let i = 0; i < things.length; i++) { - const result = await things[i] - - if (result.ok) { - yield result.value - } else { - throw result.err - } - } - } -} - -module.exports = parallelBatch diff --git a/packages/it-parallel-batch/package.json b/packages/it-parallel-batch/package.json index fdeec56f..2ecf374e 100644 --- a/packages/it-parallel-batch/package.json +++ b/packages/it-parallel-batch/package.json @@ -2,40 +2,144 @@ "name": "it-parallel-batch", "version": "1.0.11", "description": "Takes an async iterator that emits promise-returning functions, invokes them in parallel and emits the results in the same order as the input", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-parallel-batch#readme", - "bugs": "https://github.com/achingbrain/it/issues", - "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "npm run build:dep:types && tsc --noEmit", - "build": "npm run build:types", - "build:dep:types": "cd node_modules/it-batch && npm run build:types", - "build:types": "npm run build:dep:types && tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" }, - "author": "Alex Potsides ", - "license": "ISC", - "devDependencies": { - "ava": "^3.12.1", - "delay": "^4.3.0", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" + "bugs": { + "url": "https://github.com/achingbrain/it/issues" }, - "dependencies": { - "it-batch": "^1.0.9" - }, - "typesVersions": { - "*": { - "*": [ - ".", - "dist/*" - ] + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" + }, + "dependencies": { + "it-batch": "^1.0.0" + }, + "devDependencies": { + "aegir": "^37.5.0", + "delay": "^5.0.0", + "it-all": "^1.0.0" } } diff --git a/packages/it-parallel-batch/src/index.ts b/packages/it-parallel-batch/src/index.ts new file mode 100644 index 00000000..45855794 --- /dev/null +++ b/packages/it-parallel-batch/src/index.ts @@ -0,0 +1,35 @@ +import batch from 'it-batch' + +interface Success { + ok: true + value: T +} + +interface Failure { + ok: false + err: Error +} + +/** + * Takes an (async) iterator that emits promise-returning functions, + * invokes them in parallel and emits the results as they become available but + * in the same order as the input + */ +export default async function * parallelBatch (source: AsyncIterable<() => Promise>|Iterable<() => Promise>, size: number = 1): AsyncGenerator { + for await (const tasks of batch(source, size)) { + const things: Array|Failure>> = tasks.map( + async (p: () => Promise) => { + return await p().then(value => ({ ok: true, value }), err => ({ ok: false, err })) + }) + + for (let i = 0; i < things.length; i++) { + const result = await things[i] + + if (result.ok) { + yield result.value + } else { + throw result.err + } + } + } +} diff --git a/packages/it-parallel-batch/test.js b/packages/it-parallel-batch/test.js deleted file mode 100644 index bc2b7b2c..00000000 --- a/packages/it-parallel-batch/test.js +++ /dev/null @@ -1,229 +0,0 @@ -'use strict' - -const parallelBatch = require('./') -const test = require('ava') -const all = require('it-all') -const delay = require('delay') - -test('Should batch up emitted arrays', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - - const res = await all(parallelBatch(input, 2)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up emitted arrays in the right order', async (t) => { - const input = [ - async () => { - await delay(100) - - return 1 - }, - async () => { - await delay(200) - - return 2 - }, - async () => { - await delay(50) - - return 3 - } - ] - - const res = await all(parallelBatch(input, 2)) - - t.deepEqual(res, [1, 2, 3]) -}) - -test('Should propagate errors', async (t) => { - const error = new Error('wat') - - const input = [ - async () => { - await delay(100) - - return 1 - }, - async () => { - await delay(200) - - throw error - }, - async () => { - await delay(50) - - return 3 - } - ] - - try { - await all(parallelBatch(input, 2)) - } catch (err) { - t.is(err, error) - } -}) - -test('Execute batch in parallel', async (t) => { - const error = new Error('wat') - const started = [false, false, false] - - const input = [ - async () => { - started[0] = true - - await delay(200) - - return 1 - }, - async () => { - started[1] = true - - await delay(100) - - throw error - }, - async () => { - // in second batch, should not execute - started[2] = true - - await delay(100) - - return 3 - } - ] - - try { - await all(parallelBatch(input, 2)) - } catch (err) { - t.is(err, error) - } - - t.deepEqual(started, [true, true, false]) -}) - -test('Should work without size parameter', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - - const res = await all(parallelBatch(input)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with negative batch size', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - const batchSize = -1 - const res = await all(parallelBatch(input, batchSize)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with zero batch size', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - const batchSize = 0 - const res = await all(parallelBatch(input, batchSize)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with string batch size', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - const batchSize = '2' - const res = await all(parallelBatch(input, batchSize)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with non-integer batch size', async (t) => { - const input = [ - async () => { - await delay(200) - - return 1 - }, - async () => { - await delay(100) - - return 2 - } - ] - const batchSize = 2.5 - const res = await all(parallelBatch(input, batchSize)) - - t.deepEqual(res, [1, 2]) -}) - -test('Should allow returning errors', async (t) => { - const input = [ - async () => { - await delay(200) - - return new Error('herp') - }, - async () => { - await delay(100) - - return new Error('derp') - } - ] - const batchSize = 2 - const res = await all(parallelBatch(input, batchSize)) - - t.deepEqual(res, [new Error('herp'), new Error('derp')]) -}) diff --git a/packages/it-parallel-batch/test/index.spec.ts b/packages/it-parallel-batch/test/index.spec.ts new file mode 100644 index 00000000..a5dbde1b --- /dev/null +++ b/packages/it-parallel-batch/test/index.spec.ts @@ -0,0 +1,233 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import delay from 'delay' +import parallelBatch from '../src/index.js' + +describe('it-parallel-batch', () => { + it('should batch up emitted arrays', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + + const res = await all(parallelBatch(input, 2)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up emitted arrays in the right order', async () => { + const input = [ + async () => { + await delay(100) + + return 1 + }, + async () => { + await delay(200) + + return 2 + }, + async () => { + await delay(50) + + return 3 + } + ] + + const res = await all(parallelBatch(input, 2)) + + expect(res).to.deep.equal([1, 2, 3]) + }) + + it('should propagate errors', async () => { + const error = new Error('wat') + + const input = [ + async () => { + await delay(100) + + return 1 + }, + async () => { + await delay(200) + + throw error + }, + async () => { + await delay(50) + + return 3 + } + ] + + try { + await all(parallelBatch(input, 2)) + } catch (err) { + expect(err).to.equal(error) + } + }) + + it('should execute batch in parallel', async () => { + const error = new Error('wat') + const started = [false, false, false] + + const input = [ + async () => { + started[0] = true + + await delay(200) + + return 1 + }, + async () => { + started[1] = true + + await delay(100) + + throw error + }, + async () => { + // in second batch, should not execute + started[2] = true + + await delay(100) + + return 3 + } + ] + + try { + await all(parallelBatch(input, 2)) + } catch (err) { + expect(err).to.equal(error) + } + + expect(started).to.deep.equal([true, true, false]) + }) + + it('should work without size parameter', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + + const res = await all(parallelBatch(input)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with negative batch size', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + const batchSize = -1 + const res = await all(parallelBatch(input, batchSize)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with zero batch size', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + const batchSize = 0 + const res = await all(parallelBatch(input, batchSize)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with string batch size', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + const batchSize = '2' + // @ts-expect-error batchSize type is wrong + const res = await all(parallelBatch(input, batchSize)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with non-integer batch size', async () => { + const input = [ + async () => { + await delay(200) + + return 1 + }, + async () => { + await delay(100) + + return 2 + } + ] + const batchSize = 2.5 + const res = await all(parallelBatch(input, batchSize)) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should allow returning errors', async () => { + const herp = new Error('herp') + const derp = new Error('derp') + + const input = [ + async () => { + await delay(200) + + return herp + }, + async () => { + await delay(100) + + return derp + } + ] + const batchSize = 2 + const res = await all(parallelBatch(input, batchSize)) + + expect(res).to.deep.equal([herp, derp]) + }) +}) diff --git a/packages/it-parallel-batch/tsconfig.json b/packages/it-parallel-batch/tsconfig.json index f5e4524f..2bd5d99b 100644 --- a/packages/it-parallel-batch/tsconfig.json +++ b/packages/it-parallel-batch/tsconfig.json @@ -1,6 +1,18 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + }, + { + "path": "../it-batch" + } ] -} \ No newline at end of file +} diff --git a/packages/it-parallel/.npmignore b/packages/it-parallel/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-parallel/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-parallel/LICENSE b/packages/it-parallel/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-parallel/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-parallel/LICENSE-APACHE b/packages/it-parallel/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-parallel/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-parallel/LICENSE-MIT b/packages/it-parallel/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-parallel/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-parallel/README.md b/packages/it-parallel/README.md index b425f29f..b003277e 100644 --- a/packages/it-parallel/README.md +++ b/packages/it-parallel/README.md @@ -1,21 +1,29 @@ -# it-parallel +# it-parallel -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-parallel)](https://david-dm.org/achingbrain/it?path=packages/it-parallel) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Takes an (async) iterable that emits promise-returning functions, invokes them in parallel up to the concurrency limit and emits the results as they become available, optionally in the same order as the input +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) + ## Install -```sh -$ npm install --save it-parallel +```console +$ npm i it-parallel ``` ## Usage ```javascript -const parallel = require('it-parallel') -const all = require('it-all') -const delay = require('delay') +import parallel from 'it-parallel' +import all from 'it-all' +import delay from 'delay' // This can also be an iterator, async iterator, generator, etc const input = [ @@ -75,3 +83,14 @@ const result = await all(parallel(input, { console.info(result) // [1, 2, 3] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-parallel/package.json b/packages/it-parallel/package.json index bc96644d..a06457ba 100644 --- a/packages/it-parallel/package.json +++ b/packages/it-parallel/package.json @@ -2,39 +2,144 @@ "name": "it-parallel", "version": "2.0.2", "description": "Takes an (async) iterable that emits promise-returning functions, invokes them in parallel up to the concurrency limit and emits the results as they become available, optionally in the same order as the input", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-parallel#readme", - "bugs": "https://github.com/achingbrain/it/issues", - "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" }, - "author": "Alex Potsides ", - "license": "ISC", - "devDependencies": { - "ava": "^3.12.1", - "delay": "^4.3.0", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" + "bugs": { + "url": "https://github.com/achingbrain/it/issues" }, - "dependencies": { - "p-defer": "^3.0.0" - }, - "typesVersions": { - "*": { - "*": [ - ".", - "dist/*" - ] + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" + }, + "dependencies": { + "p-defer": "^4.0.0" + }, + "devDependencies": { + "aegir": "^37.5.0", + "delay": "^5.0.0", + "it-all": "^1.0.0" } } diff --git a/packages/it-parallel/index.js b/packages/it-parallel/src/index.ts similarity index 75% rename from packages/it-parallel/index.js rename to packages/it-parallel/src/index.ts index c3b32d77..96713d97 100644 --- a/packages/it-parallel/index.js +++ b/packages/it-parallel/src/index.ts @@ -1,33 +1,31 @@ /* global EventTarget Event */ -'use strict' -const defer = require('p-defer') +import defer from 'p-defer' -/** - * @template T - * @typedef {object} Operation - * @property {boolean} done - * @property {boolean} ok - * @property {Error} err - * @property {T} value - */ +interface Operation { + done: boolean + ok: boolean + err: Error + value: T +} -const CustomEvent = globalThis.CustomEvent || Event +const CustomEvent = globalThis.CustomEvent ?? Event + +export interface ParallelOptions { + /** + * How many jobs to execute in parallel (default: ) + */ + concurrency?: number + ordered?: boolean +} /** * Takes an (async) iterator that emits promise-returning functions, * invokes them in parallel and emits the results as they become available but * in the same order as the input - * - * @template T - * @param {Iterable<() => Promise> | AsyncIterable<() => Promise>} source - * @param {object} [options] - * @param {number} [options.concurrency=Infinity] - * @param {boolean} [options.ordered=false] - * @returns {AsyncIterable} */ -async function * parallel (source, options = {}) { - let concurrency = options.concurrency || Infinity +export default async function * parallel (source: Iterable<() => Promise> | AsyncIterable<() => Promise>, options: ParallelOptions = {}): AsyncGenerator { + let concurrency = options.concurrency ?? Infinity if (concurrency < 1) { concurrency = Infinity @@ -36,19 +34,18 @@ async function * parallel (source, options = {}) { const ordered = options.ordered == null ? false : options.ordered const emitter = new EventTarget() - /** @type {Operation[]}} */ - const ops = [] + const ops: Array> = [] let slotAvailable = defer() let resultAvailable = defer() let sourceFinished = false - let sourceErr + let sourceErr: Error | undefined let opErred = false emitter.addEventListener('task-complete', () => { resultAvailable.resolve() }) - Promise.resolve().then(async () => { + void Promise.resolve().then(async () => { try { for await (const task of source) { if (ops.length === concurrency) { @@ -60,10 +57,7 @@ async function * parallel (source, options = {}) { break } - /** - * @type {any} - */ - const op = { + const op: any = { done: false } ops.push(op) @@ -83,7 +77,7 @@ async function * parallel (source, options = {}) { sourceFinished = true emitter.dispatchEvent(new CustomEvent('task-complete')) - } catch (err) { + } catch (err: any) { sourceErr = err emitter.dispatchEvent(new CustomEvent('task-complete')) } @@ -91,14 +85,14 @@ async function * parallel (source, options = {}) { function valuesAvailable () { if (ordered) { - return Boolean(ops[0] && ops[0].done) + return ops[0]?.done } return Boolean(ops.find(op => op.done)) } function * yieldOrderedValues () { - while (ops.length && ops[0].done) { + while ((ops.length > 0) && ops[0].done) { const op = ops[0] ops.shift() @@ -147,7 +141,7 @@ async function * parallel (source, options = {}) { await resultAvailable.promise } - if (sourceErr) { + if (sourceErr != null) { // the source threw an error, propagate it throw sourceErr } @@ -164,5 +158,3 @@ async function * parallel (source, options = {}) { } } } - -module.exports = parallel diff --git a/packages/it-parallel/test.js b/packages/it-parallel/test.js deleted file mode 100644 index bb8a9a24..00000000 --- a/packages/it-parallel/test.js +++ /dev/null @@ -1,256 +0,0 @@ -'use strict' - -const parallel = require('./') -const test = require('ava') -const all = require('it-all') -const delay = require('delay') - -const createFn = (ms, result) => { - return async () => { - await delay(ms) - - return result - } -} - -test('Should execute and return ordered results', async (t) => { - const input = [ - createFn(1000, 1), - createFn(2000, 2), - createFn(100, 3), - createFn(500, 4) - ] - - const res = await all(parallel(input, { - concurrency: 3, - ordered: true - })) - - t.deepEqual(res, [1, 2, 3, 4]) -}) - -test('Should execute and return unordered results', async (t) => { - const input = [ - createFn(1000, 1), - createFn(2000, 2), - createFn(100, 3), - createFn(500, 4) - ] - - const res = await all(parallel(input, { - concurrency: 3, - ordered: false - })) - - t.deepEqual(res, [3, 4, 1, 2]) -}) - -test('Should not exceed concurrency limit', async (t) => { - let running = 0 - let runningMax = 0 - const concurrency = 3 - - const createFn = (ms, result) => { - return async () => { - running++ - - if (running > runningMax) { - runningMax = running - } - - await delay(ms) - - running-- - - return result - } - } - - const input = [ - createFn(1000, 1), - createFn(100, 2), - createFn(100, 3), - createFn(10, 4), - createFn(10, 5) - ] - - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [1, 2, 3, 4, 5]) - - t.is(runningMax, concurrency) -}) - -test('Should propagate task errors', async (t) => { - const error = new Error('wat') - - const input = [ - createFn(100, 1), - async () => { - await delay(200) - - throw error - }, - createFn(50, 3) - ] - - try { - await all(parallel(input, { concurrency: 2 })) - } catch (err) { - t.is(err, error) - } -}) - -test('Should propagate source errors', async (t) => { - const error = new Error('Urk!') - - async function * source () { - yield async () => 'foo' - - throw error - } - - try { - await all(parallel(source(), { concurrency: 2 })) - } catch (err) { - t.is(err, error) - } -}) - -test('Should allow source to finish if task errors', async (t) => { - let sourceFinished = false - let index = 0 - const values = [ - async () => { - await delay(500) - throw new Error('Urk!') - }, - async () => { - await delay(100) - return 'hello' - }, - async () => { - await delay(200) - return 'hello' - }, - async () => { - await delay(300) - return 'hello' - }, - async () => { - await delay(400) - return 'hello' - }, - async () => { - await delay(500) - return 'world' - }, - async () => { - await delay(600) - return 'world' - } - ] - - const source = { - [Symbol.asyncIterator]: () => source, - async next () { - const value = values[index] - index++ - - return Promise.resolve({ - done: index === values.length, - value - }) - }, - return () { - sourceFinished = true - } - } - - try { - await all(parallel(source, { concurrency: 2, ordered: true })) - } catch { - t.truthy(sourceFinished) - } -}) - -test('Should work without concurrency parameter', async (t) => { - const input = [ - createFn(200, 1), - createFn(100, 2) - ] - - const res = await all(parallel(input, { ordered: true })) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with negative batch size', async (t) => { - const input = [ - createFn(200, 1), - createFn(100, 2) - ] - const concurrency = -1 - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with zero batch size', async (t) => { - const input = [ - createFn(200, 1), - createFn(100, 2) - ] - const concurrency = 0 - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with string batch size', async (t) => { - const input = [ - createFn(200, 1), - createFn(100, 2) - ] - const concurrency = '2' - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [1, 2]) -}) - -test('Should batch up entries with non-integer batch size', async (t) => { - const input = [ - createFn(200, 1), - createFn(100, 2) - ] - const concurrency = 2.5 - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [1, 2]) -}) - -test('Should allow returning errors', async (t) => { - const input = [ - async () => { - await delay(200) - - return new Error('herp') - }, - async () => { - await delay(100) - - return new Error('derp') - } - ] - const concurrency = 2 - const res = await all(parallel(input, { concurrency, ordered: true })) - - t.deepEqual(res, [new Error('herp'), new Error('derp')]) -}) - -test('Should work with empty source', async (t) => { - const input = [] - const res = await all(parallel(input)) - - t.deepEqual(res, []) -}) diff --git a/packages/it-parallel/test/index.spec.ts b/packages/it-parallel/test/index.spec.ts new file mode 100644 index 00000000..b72e9e51 --- /dev/null +++ b/packages/it-parallel/test/index.spec.ts @@ -0,0 +1,260 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import delay from 'delay' +import parallel from '../src/index.js' + +const createFn = (ms: number, result: number) => { + return async () => { + await delay(ms) + + return result + } +} + +describe('it-parallel', () => { + it('should execute and return ordered results', async () => { + const input = [ + createFn(1000, 1), + createFn(2000, 2), + createFn(100, 3), + createFn(500, 4) + ] + + const res = await all(parallel(input, { + concurrency: 3, + ordered: true + })) + + expect(res).to.deep.equal([1, 2, 3, 4]) + }) + + it('should execute and return unordered results', async () => { + const input = [ + createFn(1000, 1), + createFn(2000, 2), + createFn(100, 3), + createFn(500, 4) + ] + + const res = await all(parallel(input, { + concurrency: 3, + ordered: false + })) + + expect(res).to.deep.equal([3, 4, 1, 2]) + }) + + it('should not exceed concurrency limit', async () => { + let running = 0 + let runningMax = 0 + const concurrency = 3 + + const createFn = (ms: number, result: number) => { + return async () => { + running++ + + if (running > runningMax) { + runningMax = running + } + + await delay(ms) + + running-- + + return result + } + } + + const input = [ + createFn(1000, 1), + createFn(100, 2), + createFn(100, 3), + createFn(10, 4), + createFn(10, 5) + ] + + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([1, 2, 3, 4, 5]) + + expect(runningMax).to.equal(concurrency) + }) + + it('should propagate task errors', async () => { + const error = new Error('wat') + + const input = [ + createFn(100, 1), + async () => { + await delay(200) + + throw error + }, + createFn(50, 3) + ] + + try { + await all(parallel(input, { concurrency: 2 })) + } catch (err) { + expect(err).to.equal(error) + } + }) + + it('should propagate source errors', async () => { + const error = new Error('Urk!') + + async function * source () { + yield async () => 'foo' + + throw error + } + + try { + await all(parallel(source(), { concurrency: 2 })) + } catch (err) { + expect(err).to.equal(error) + } + }) + + it('should allow source to finish if task errors', async () => { + let sourceFinished = false + let index = 0 + const values = [ + async () => { + await delay(500) + throw new Error('Urk!') + }, + async () => { + await delay(100) + return 'hello' + }, + async () => { + await delay(200) + return 'hello' + }, + async () => { + await delay(300) + return 'hello' + }, + async () => { + await delay(400) + return 'hello' + }, + async () => { + await delay(500) + return 'world' + }, + async () => { + await delay(600) + return 'world' + } + ] + + const source: any = { + [Symbol.asyncIterator]: () => source, + async next () { + const value = values[index] + index++ + + return await Promise.resolve({ + done: index === values.length, + value + }) + }, + return () { + sourceFinished = true + } + } + + try { + await all(parallel(source, { concurrency: 2, ordered: true })) + } catch { + expect(sourceFinished).to.be.true() + } + }) + + it('should work without concurrency parameter', async () => { + const input = [ + createFn(200, 1), + createFn(100, 2) + ] + + const res = await all(parallel(input, { ordered: true })) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with negative batch size', async () => { + const input = [ + createFn(200, 1), + createFn(100, 2) + ] + const concurrency = -1 + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with zero batch size', async () => { + const input = [ + createFn(200, 1), + createFn(100, 2) + ] + const concurrency = 0 + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with string batch size', async () => { + const input = [ + createFn(200, 1), + createFn(100, 2) + ] + const concurrency = '2' + // @ts-expect-error concurrency is wrong type + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should batch up entries with non-integer batch size', async () => { + const input = [ + createFn(200, 1), + createFn(100, 2) + ] + const concurrency = 2.5 + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([1, 2]) + }) + + it('should allow returning errors', async () => { + const herp = new Error('herp') + const derp = new Error('derp') + + const input = [ + async () => { + await delay(200) + + return herp + }, + async () => { + await delay(100) + + return derp + } + ] + const concurrency = 2 + const res = await all(parallel(input, { concurrency, ordered: true })) + + expect(res).to.deep.equal([herp, derp]) + }) + + it('should work with empty source', async () => { + const input: any[] = [] + const res = await all(parallel(input)) + + expect(res).to.deep.equal([]) + }) +}) diff --git a/packages/it-parallel/tsconfig.json b/packages/it-parallel/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-parallel/tsconfig.json +++ b/packages/it-parallel/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-peekable/.npmignore b/packages/it-peekable/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-peekable/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-peekable/LICENSE b/packages/it-peekable/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-peekable/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-peekable/LICENSE-APACHE b/packages/it-peekable/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-peekable/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-peekable/LICENSE-MIT b/packages/it-peekable/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-peekable/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-peekable/README.md b/packages/it-peekable/README.md index 976d8c3c..34e5c7f6 100644 --- a/packages/it-peekable/README.md +++ b/packages/it-peekable/README.md @@ -1,21 +1,29 @@ -# it-peekable +# it-peekable -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-reduce)](https://david-dm.org/achingbrain/it?path=packages/it-reduce) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> A peekable async iterator +> Allows peeking/pushing an iterable -Lets you look at the contents of an async iterator and decide what to do +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-peekable +```console +$ npm i it-peekable ``` +Lets you look at the contents of an async iterator and decide what to do + ## Usage ```javascript -const peekable = require('it-peekable') +import peekable from 'it-peekable' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -31,3 +39,14 @@ it.push(first) console.info([...it]) // [ 0, 1, 2, 3, 4 ] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-peekable/index.js b/packages/it-peekable/index.js deleted file mode 100644 index 978412fa..00000000 --- a/packages/it-peekable/index.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict' - -/** - * @template T - * @typedef {Object} Peek - * @property {() => IteratorResult} peek - */ - -/** - * @template T - * @typedef {Object} AsyncPeek - * @property {() => Promise>} peek - */ - -/** - * @template T - * @typedef {Object} Push - * @property {(value:T) => void} push - */ - -/** - * @template T - * @typedef {Iterable & Peek & Push & Iterator} Peekable - */ - -/** - * @template T - * @typedef {AsyncIterable & AsyncPeek & Push & AsyncIterator} AsyncPeekable - */ - -/** - * @template {Iterable | AsyncIterable} I - * @param {I} iterable - * @returns {I extends Iterable - * ? Peekable - * : I extends AsyncIterable - * ? AsyncPeekable - * : never - * } - */ -function peekableIterator (iterable) { - // @ts-ignore - const [iterator, symbol] = iterable[Symbol.asyncIterator] - // @ts-ignore - ? [iterable[Symbol.asyncIterator](), Symbol.asyncIterator] - // @ts-ignore - : [iterable[Symbol.iterator](), Symbol.iterator] - - /** @type {any[]} */ - const queue = [] - - // @ts-ignore - return { - peek: () => { - return iterator.next() - }, - push: (value) => { - queue.push(value) - }, - next: () => { - if (queue.length) { - return { - done: false, - value: queue.shift() - } - } - - return iterator.next() - }, - [symbol] () { - return this - } - } -} - -module.exports = peekableIterator diff --git a/packages/it-peekable/package.json b/packages/it-peekable/package.json index 4fa33aca..97bb6ecb 100644 --- a/packages/it-peekable/package.json +++ b/packages/it-peekable/package.json @@ -2,28 +2,140 @@ "name": "it-peekable", "version": "1.0.3", "description": "Allows peeking/pushing an iterable", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-peekable#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-peekable/src/index.ts b/packages/it-peekable/src/index.ts new file mode 100644 index 00000000..9fc15f88 --- /dev/null +++ b/packages/it-peekable/src/index.ts @@ -0,0 +1,54 @@ + +interface Peek { + peek: () => IteratorResult +} + +interface AsyncPeek { + peek: () => Promise> +} + +interface Push { + push: (value: T) => void +} + +type Peekable = Iterable & Peek & Push & Iterator + +type AsyncPeekable = AsyncIterable & AsyncPeek & Push & AsyncIterator + +export default function peekableIterator | AsyncIterable> (iterable: I): I extends Iterable + ? Peekable + : I extends AsyncIterable + ? AsyncPeekable + : never { + // @ts-expect-error + const [iterator, symbol] = iterable[Symbol.asyncIterator] != null + // @ts-expect-error + ? [iterable[Symbol.asyncIterator](), Symbol.asyncIterator] + // @ts-expect-error + : [iterable[Symbol.iterator](), Symbol.iterator] + + const queue: any[] = [] + + // @ts-expect-error + return { + peek: () => { + return iterator.next() + }, + push: (value: any) => { + queue.push(value) + }, + next: () => { + if (queue.length > 0) { + return { + done: false, + value: queue.shift() + } + } + + return iterator.next() + }, + [symbol] () { + return this + } + } +} diff --git a/packages/it-peekable/test.js b/packages/it-peekable/test.js deleted file mode 100644 index 5faa3a10..00000000 --- a/packages/it-peekable/test.js +++ /dev/null @@ -1,53 +0,0 @@ -const peekableIt = require('./') -const test = require('ava') -const all = require('it-all') - -test('Should peek at an iterable', async (t) => { - const iterable = [0, 1, 2, 3] - const peekable = peekableIt(iterable) - const { value, done } = peekable.peek() - - t.is(value, 0) - t.is(done, false) -}) - -test('Should peek at an async iterable', async (t) => { - const content = [0, 1, 2, 3] - const iterable = async function * () { - for (let i = 0; i < content.length; i++) { - yield content[i] - } - } - - const peekable = peekableIt(iterable()) - const { value, done } = await peekable.peek() - - t.is(value, 0) - t.is(done, false) -}) - -test('Should push an iterable', async (t) => { - const iterable = [0, 1, 2, 3] - const peekable = peekableIt(iterable) - const { value } = peekable.peek() - - peekable.push(value) - - t.deepEqual([...peekable], iterable) -}) - -test('Should push an async iterable', async (t) => { - const content = [0, 1, 2, 3] - const iterable = async function * () { - for (let i = 0; i < content.length; i++) { - yield content[i] - } - } - - const peekable = peekableIt(iterable()) - const { value } = await peekable.peek() - - peekable.push(value) - - t.deepEqual(await all(peekable), content) -}) diff --git a/packages/it-peekable/test/index.spec.ts b/packages/it-peekable/test/index.spec.ts new file mode 100644 index 00000000..77558028 --- /dev/null +++ b/packages/it-peekable/test/index.spec.ts @@ -0,0 +1,59 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import peekableIt from '../src/index.js' + +describe('it-peekable', () => { + it('should peek at an iterable', async () => { + const iterable = [0, 1, 2, 3] + const peekable = peekableIt(iterable) + const { value, done } = peekable.peek() + + expect(value).to.equal(0) + expect(done).to.be.false() + }) + + it('should peek at an async iterable', async () => { + const content = [0, 1, 2, 3] + const iterable = async function * () { + for (let i = 0; i < content.length; i++) { + yield content[i] + } + } + + const peekable = peekableIt(iterable()) + const { value, done } = await peekable.peek() + + expect(value).to.equal(0) + expect(done).to.be.false() + }) + + it('should push an iterable', async () => { + const iterable = [0, 1, 2, 3] + const peekable = peekableIt(iterable) + const { value } = peekable.peek() + + if (value != null) { + peekable.push(value) + } + + expect([...peekable]).to.deep.equal(iterable) + }) + + it('should push an async iterable', async () => { + const content = [0, 1, 2, 3] + const iterable = async function * () { + for (let i = 0; i < content.length; i++) { + yield content[i] + } + } + + const peekable = peekableIt(iterable()) + const { value } = await peekable.peek() + + if (value != null) { + peekable.push(value) + } + + expect(await all(peekable)).to.deep.equal(content) + }) +}) diff --git a/packages/it-peekable/tsconfig.json b/packages/it-peekable/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-peekable/tsconfig.json +++ b/packages/it-peekable/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-reduce/.npmignore b/packages/it-reduce/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-reduce/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-reduce/LICENSE b/packages/it-reduce/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-reduce/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-reduce/LICENSE-APACHE b/packages/it-reduce/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-reduce/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-reduce/LICENSE-MIT b/packages/it-reduce/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-reduce/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-reduce/README.md b/packages/it-reduce/README.md index 9ce9f983..d6058925 100644 --- a/packages/it-reduce/README.md +++ b/packages/it-reduce/README.md @@ -1,21 +1,29 @@ -# it-reduce +# it-reduce -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-reduce)](https://david-dm.org/achingbrain/it?path=packages/it-reduce) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Reduces the values yielded by an (async) iterable +> Reduces the values yielded from an async iterator -Mostly useful for tests or when you want to be explicit about consuming an iterable without doing anything with any yielded values. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-reduce +```console +$ npm i it-reduce ``` +Mostly useful for tests or when you want to be explicit about consuming an iterable without doing anything with any yielded values. + ## Usage ```javascript -const reduce = require('it-reduce') +import reduce from 'it-reduce' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -24,3 +32,14 @@ const result = await reduce(values, (acc, curr) => acc + curr, 0) console.info(result) // 10 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-reduce/index.js b/packages/it-reduce/index.js deleted file mode 100644 index 69c66367..00000000 --- a/packages/it-reduce/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -/** - * Reduces the values yielded by an (async) iterable - * - * @template T, V - * @param {AsyncIterable|Iterable} source - * @param {function(V, T):V} func - * @param {V} init - */ -const reduce = async (source, func, init) => { - for await (const val of source) { - init = func(init, val) - } - - return init -} - -module.exports = reduce diff --git a/packages/it-reduce/package.json b/packages/it-reduce/package.json index 423ff56c..ee8394fe 100644 --- a/packages/it-reduce/package.json +++ b/packages/it-reduce/package.json @@ -2,27 +2,139 @@ "name": "it-reduce", "version": "1.0.6", "description": "Reduces the values yielded from an async iterator", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-reduce#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-reduce/src/index.ts b/packages/it-reduce/src/index.ts new file mode 100644 index 00000000..f1329d1a --- /dev/null +++ b/packages/it-reduce/src/index.ts @@ -0,0 +1,11 @@ + +/** + * Reduces the values yielded by an (async) iterable + */ +export default async function reduce (source: AsyncIterable | Iterable, func: (acc: V, curr: T) => V, init: V): Promise { + for await (const val of source) { + init = func(init, val) + } + + return init +} diff --git a/packages/it-reduce/test.js b/packages/it-reduce/test.js deleted file mode 100644 index 07e0192c..00000000 --- a/packages/it-reduce/test.js +++ /dev/null @@ -1,14 +0,0 @@ -const reduce = require('./') -const test = require('ava') - -test('Should reduce the values yielded from an async iterator', async (t) => { - const iter = function * () { - yield 1 - yield 2 - yield 3 - } - - const result = await reduce(iter(), (acc, curr) => acc + curr, 0) - - t.is(result, 6) -}) diff --git a/packages/it-reduce/test/index.spec.ts b/packages/it-reduce/test/index.spec.ts new file mode 100644 index 00000000..6e1f150d --- /dev/null +++ b/packages/it-reduce/test/index.spec.ts @@ -0,0 +1,16 @@ +import { expect } from 'aegir/chai' +import reduce from '../src/index.js' + +describe('it-reduce', () => { + it('should reduce the values yielded from an async iterator', async () => { + const iter = function * () { + yield 1 + yield 2 + yield 3 + } + + const result = await reduce(iter(), (acc, curr) => acc + curr, 0) + + expect(result).to.equal(6) + }) +}) diff --git a/packages/it-reduce/tsconfig.json b/packages/it-reduce/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-reduce/tsconfig.json +++ b/packages/it-reduce/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-skip/.npmignore b/packages/it-skip/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-skip/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-skip/LICENSE b/packages/it-skip/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-skip/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-skip/LICENSE-APACHE b/packages/it-skip/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-skip/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-skip/LICENSE-MIT b/packages/it-skip/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-skip/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-skip/README.md b/packages/it-skip/README.md index d83b2847..54aa6004 100644 --- a/packages/it-skip/README.md +++ b/packages/it-skip/README.md @@ -1,22 +1,30 @@ -# it-skip +# it-skip -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-skip)](https://david-dm.org/achingbrain/it?path=packages/it-skip) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Skip items from an iterable. +> Skip items from an iterable -For when you are only interested in later values from an iterable. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-skip +```console +$ npm i it-skip ``` +For when you are only interested in later values from an iterable. + ## Usage ```javascript -const take = require('it-skip') -const all = require('it-all') +import take from 'it-skip' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -25,3 +33,14 @@ const arr = await all(skip(values, 2)) console.info(arr) // 2, 3, 4 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-skip/index.js b/packages/it-skip/index.js deleted file mode 100644 index 1a929102..00000000 --- a/packages/it-skip/index.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict' - -/** - * Skip items from an iterable. - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {number} offset - * @returns {AsyncIterable} - */ -const skip = async function * (source, offset) { - for await (const entry of source) { - if (offset === 0) { - yield entry - - continue - } - - offset-- - } -} - -module.exports = skip diff --git a/packages/it-skip/package.json b/packages/it-skip/package.json index 062202f7..6e688c62 100644 --- a/packages/it-skip/package.json +++ b/packages/it-skip/package.json @@ -2,28 +2,140 @@ "name": "it-skip", "version": "1.0.2", "description": "Skip items from an iterable", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-skip#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-skip/src/index.ts b/packages/it-skip/src/index.ts new file mode 100644 index 00000000..53dce816 --- /dev/null +++ b/packages/it-skip/src/index.ts @@ -0,0 +1,15 @@ + +/** + * Skip items from an iterable + */ +export default async function * skip (source: AsyncIterable|Iterable, offset: number): AsyncGenerator { + for await (const entry of source) { + if (offset === 0) { + yield entry + + continue + } + + offset-- + } +} diff --git a/packages/it-skip/test.js b/packages/it-skip/test.js deleted file mode 100644 index 72c2fd6b..00000000 --- a/packages/it-skip/test.js +++ /dev/null @@ -1,11 +0,0 @@ -const skip = require('./') -const all = require('it-all') -const test = require('ava') - -test('Should skip values from an iterable', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await all(skip(values, 2)) - - t.deepEqual(res, [2, 3, 4]) -}) diff --git a/packages/it-skip/test/index.spec.ts b/packages/it-skip/test/index.spec.ts new file mode 100644 index 00000000..14f642cb --- /dev/null +++ b/packages/it-skip/test/index.spec.ts @@ -0,0 +1,13 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import skip from '../src/index.js' + +describe('it-skip', () => { + it('should skip values from an iterable', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await all(skip(values, 2)) + + expect(res).to.deep.equal([2, 3, 4]) + }) +}) diff --git a/packages/it-skip/tsconfig.json b/packages/it-skip/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-skip/tsconfig.json +++ b/packages/it-skip/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-sort/.npmignore b/packages/it-sort/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-sort/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-sort/LICENSE b/packages/it-sort/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-sort/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-sort/LICENSE-APACHE b/packages/it-sort/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-sort/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-sort/LICENSE-MIT b/packages/it-sort/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-sort/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-sort/README.md b/packages/it-sort/README.md index 712f0579..3d3af7d6 100644 --- a/packages/it-sort/README.md +++ b/packages/it-sort/README.md @@ -1,20 +1,28 @@ -# it-sort +# it-sort -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-sort)](https://david-dm.org/achingbrain/it?path=packages/it-sort) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Collects all values from an async iterator, sorts them using the passed function and yields them +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) + ## Install -```sh -$ npm install --save it-sort +```console +$ npm i it-sort ``` ## Usage ```javascript -const sort = require('it-sort') -const all = require('it-all') +import sort from 'it-sort' +import all from 'it-all' const sorter = (a, b) => { return a.localeCompare(b) @@ -27,3 +35,14 @@ const arr = await all(sort(values, sorter)) console.info(arr) // 'bar', 'foo' ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-sort/index.js b/packages/it-sort/index.js deleted file mode 100644 index eaa0162c..00000000 --- a/packages/it-sort/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -const all = require('it-all') - -/** - * Collects all values from an async iterator, sorts them - * using the passed function and yields them - * - * @template T - * @param {AsyncIterable | Iterable} source - * @param {(a: T, b: T) => -1 | 0 | 1} sorter - */ -const sort = async function * (source, sorter) { - const arr = await all(source) - - yield * arr.sort(sorter) -} - -module.exports = sort diff --git a/packages/it-sort/package.json b/packages/it-sort/package.json index 2d2228bc..ff056ee0 100644 --- a/packages/it-sort/package.json +++ b/packages/it-sort/package.json @@ -2,30 +2,142 @@ "name": "it-sort", "version": "1.0.1", "description": "Collects all values from an async iterator, sorts them using the passed function and yields them", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-sort#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { - "it-all": "^1.0.6" + "it-all": "^1.0.0" }, "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-sort/src/index.ts b/packages/it-sort/src/index.ts new file mode 100644 index 00000000..886c1287 --- /dev/null +++ b/packages/it-sort/src/index.ts @@ -0,0 +1,15 @@ +import all from 'it-all' + +export interface CompareFunction { + (a: T, b: T): number +} + +/** + * Collects all values from an async iterator, sorts them + * using the passed function and yields them + */ +export default async function * sort (source: AsyncIterable | Iterable, sorter: CompareFunction): AsyncGenerator { + const arr = await all(source) + + yield * arr.sort(sorter) +} diff --git a/packages/it-sort/test.js b/packages/it-sort/test.js deleted file mode 100644 index 36a224e7..00000000 --- a/packages/it-sort/test.js +++ /dev/null @@ -1,14 +0,0 @@ -const sort = require('./') -const all = require('it-all') -const test = require('ava') - -test('Should sort all entries of an array', async (t) => { - const values = ['foo', 'bar'] - const sorter = (a, b) => { - return a.localeCompare(b) - } - - const res = await all(sort(values, sorter)) - - t.deepEqual(res, ['bar', 'foo']) -}) diff --git a/packages/it-sort/test/index.spec.ts b/packages/it-sort/test/index.spec.ts new file mode 100644 index 00000000..4321a978 --- /dev/null +++ b/packages/it-sort/test/index.spec.ts @@ -0,0 +1,16 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import sort, { CompareFunction } from '../src/index.js' + +describe('it-sort', () => { + it('should sort all entries of an array', async () => { + const values = ['foo', 'bar'] + const sorter: CompareFunction = (a, b) => { + return a.localeCompare(b) + } + + const res = await all(sort(values, sorter)) + + expect(res).to.deep.equal(['bar', 'foo']) + }) +}) diff --git a/packages/it-sort/tsconfig.json b/packages/it-sort/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-sort/tsconfig.json +++ b/packages/it-sort/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-split/.npmignore b/packages/it-split/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-split/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-split/LICENSE b/packages/it-split/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-split/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-split/LICENSE-APACHE b/packages/it-split/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-split/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-split/LICENSE-MIT b/packages/it-split/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-split/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-split/README.md b/packages/it-split/README.md index ed052133..6bac2672 100644 --- a/packages/it-split/README.md +++ b/packages/it-split/README.md @@ -1,19 +1,28 @@ -# it-split +# it-split -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-split)](https://david-dm.org/achingbrain/it?path=packages/it-split) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) > Splits Uint8Arrays emitted by an (async) iterable by a delimiter +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) + ## Install -```sh -$ npm install --save it-split +```console +$ npm i it-split ``` ## Usage ```javascript -const split = require('it-split') +import split from 'it-split' + const encoder = new TextEncoder() // This can also be an iterator, async iterator, generator, etc @@ -43,3 +52,14 @@ const arr = await all(split(values, { console.info(arr) // [ Buffer.from([0]), Buffer.from([3, 0]), Buffer.from([3, 1]) ] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-split/index.js b/packages/it-split/index.js deleted file mode 100644 index edc0a638..00000000 --- a/packages/it-split/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict' - -const BufferList = require('bl/BufferList') - -/** - * Splits Uint8Arrays emitted by an (async) iterable by a delimiter - * - * @param {AsyncIterable|Iterable} source - * @param {object} [options] - * @param {Uint8Array} [options.delimiter] - */ -const split = async function * (source, options = {}) { - const bl = new BufferList() - const delimiter = options.delimiter || new TextEncoder().encode('\n') - - for await (const buf of source) { - // @ts-ignore Uint8Array type is missing from add signature - bl.append(buf) - - yield * yieldUntilEnd(bl, delimiter) - } - - yield * yieldUntilEnd(bl, delimiter) - - if (bl.length) { - yield bl.slice() - } -} - -/** - * - * @param {BufferList} bl - * @param {Uint8Array} delimiter - */ -async function * yieldUntilEnd (bl, delimiter) { - let index = bl.indexOf(delimiter) - - while (index !== -1) { - yield bl.slice(0, index) - - bl.consume(index + delimiter.length) - - index = bl.indexOf(delimiter) - } -} - -module.exports = split diff --git a/packages/it-split/package.json b/packages/it-split/package.json index 8330e582..37d9ee6f 100644 --- a/packages/it-split/package.json +++ b/packages/it-split/package.json @@ -2,33 +2,146 @@ "name": "it-split", "version": "1.0.2", "description": "Splits Uint8Arrays emitted by an (async) iterable by a delimiter", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-split#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "dependencies": { "bl": "^5.0.0" }, "devDependencies": { "@types/bl": "^5.0.1", - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2", - "uint8arrays": "^3.0.0" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "buffer": "^6.0.3", + "it-all": "^1.0.0", + "uint8arrays": "^4.0.2" + } } diff --git a/packages/it-split/src/index.ts b/packages/it-split/src/index.ts new file mode 100644 index 00000000..b2ee07e4 --- /dev/null +++ b/packages/it-split/src/index.ts @@ -0,0 +1,38 @@ +import BufferList from 'bl/BufferList.js' + +export interface SplitOptions { + delimiter?: Uint8Array +} + +/** + * Splits Uint8Arrays emitted by an (async) iterable by a delimiter + */ +export default async function * split (source: AsyncIterable|Iterable, options: SplitOptions = {}): AsyncGenerator { + const bl = new BufferList() + const delimiter = options.delimiter ?? new TextEncoder().encode('\n') + + for await (const buf of source) { + // @ts-expect-error Uint8Array type is missing from add signature + bl.append(buf) + + yield * yieldUntilEnd(bl, delimiter) + } + + yield * yieldUntilEnd(bl, delimiter) + + if (bl.length > 0) { + yield bl.slice() + } +} + +async function * yieldUntilEnd (bl: BufferList, delimiter: Uint8Array): AsyncGenerator { + let index = bl.indexOf(delimiter) + + while (index !== -1) { + yield bl.slice(0, index) + + bl.consume(index + delimiter.length) + + index = bl.indexOf(delimiter) + } +} diff --git a/packages/it-split/test.js b/packages/it-split/test.js deleted file mode 100644 index 2182a084..00000000 --- a/packages/it-split/test.js +++ /dev/null @@ -1,38 +0,0 @@ -const split = require('./') -const all = require('it-all') -const test = require('ava') -const { toString } = require('uint8arrays/to-string') - -test('Should split Uint8Arrays by newlines', async (t) => { - const encoder = new TextEncoder() - const values = [ - encoder.encode('hello\nwor'), - encoder.encode('ld') - ] - - const res = await all(split(values)) - - t.deepEqual(res.map(buf => toString(buf)), [ - 'hello', - 'world' - ]) -}) - -test('Should split Uint8Arrays by arbitrary delimiters', async (t) => { - const values = [ - Uint8Array.from([0, 1, 2, 3]), - Uint8Array.from([0, 1, 2, 3]), - Uint8Array.from([1, 1, 2]) - ] - const delimiter = Uint8Array.from([1, 2]) - - const res = await all(split(values, { - delimiter - })) - - t.deepEqual(res, [ - Buffer.from([0]), - Buffer.from([3, 0]), - Buffer.from([3, 1]) - ]) -}) diff --git a/packages/it-split/test/index.spec.ts b/packages/it-split/test/index.spec.ts new file mode 100644 index 00000000..a718305a --- /dev/null +++ b/packages/it-split/test/index.spec.ts @@ -0,0 +1,41 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import { toString } from 'uint8arrays/to-string' +import split from '../src/index.js' +import { Buffer } from 'buffer' + +describe('it-split', () => { + it('should split Uint8Arrays by newlines', async () => { + const encoder = new TextEncoder() + const values = [ + encoder.encode('hello\nwor'), + encoder.encode('ld') + ] + + const res = await all(split(values)) + + expect(res.map(buf => toString(buf))).to.deep.equal([ + 'hello', + 'world' + ]) + }) + + it('should split Uint8Arrays by arbitrary delimiters', async () => { + const values = [ + Uint8Array.from([0, 1, 2, 3]), + Uint8Array.from([0, 1, 2, 3]), + Uint8Array.from([1, 1, 2]) + ] + const delimiter = Uint8Array.from([1, 2]) + + const res = await all(split(values, { + delimiter + })) + + expect(res).to.deep.equal([ + Buffer.from([0]), + Buffer.from([3, 0]), + Buffer.from([3, 1]) + ]) + }) +}) diff --git a/packages/it-split/tsconfig.json b/packages/it-split/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-split/tsconfig.json +++ b/packages/it-split/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-take/.npmignore b/packages/it-take/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-take/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-take/LICENSE b/packages/it-take/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-take/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-take/LICENSE-APACHE b/packages/it-take/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-take/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-take/LICENSE-MIT b/packages/it-take/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-take/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-take/README.md b/packages/it-take/README.md index 22a38d68..daa891c1 100644 --- a/packages/it-take/README.md +++ b/packages/it-take/README.md @@ -1,22 +1,30 @@ -# it-take +# it-take -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-take)](https://david-dm.org/achingbrain/it?path=packages/it-take) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Stop iteration after n items have been received. +> Stop iteration after n items have been received -For when you only want a few values out of an iterable. +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-take +```console +$ npm i it-take ``` +For when you only want a few values out of an iterable. + ## Usage ```javascript -const take = require('it-take') -const all = require('it-all') +import take from 'it-take' +import all from 'it-all' // This can also be an iterator, async iterator, generator, etc const values = [0, 1, 2, 3, 4] @@ -25,3 +33,14 @@ const arr = await all(take(values, 2)) console.info(arr) // 0, 1 ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-take/index.js b/packages/it-take/index.js deleted file mode 100644 index 68a5bd34..00000000 --- a/packages/it-take/index.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict' - -/** - * Stop iteration after n items have been received. - * - * @template T - * @param {AsyncIterable|Iterable} source - * @param {number} limit - * @returns {AsyncIterable} - */ -const take = async function * (source, limit) { - let items = 0 - - if (limit < 1) { - return - } - - for await (const entry of source) { - yield entry - - items++ - - if (items === limit) { - return - } - } -} - -module.exports = take diff --git a/packages/it-take/package.json b/packages/it-take/package.json index 15f55ec4..cb87f3d7 100644 --- a/packages/it-take/package.json +++ b/packages/it-take/package.json @@ -2,28 +2,140 @@ "name": "it-take", "version": "1.0.2", "description": "Stop iteration after n items have been received", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-take#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "it-all": "^1.0.6", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0", + "it-all": "^1.0.0" + } } diff --git a/packages/it-take/src/index.ts b/packages/it-take/src/index.ts new file mode 100644 index 00000000..322badc5 --- /dev/null +++ b/packages/it-take/src/index.ts @@ -0,0 +1,21 @@ + +/** + * Stop iteration after n items have been received + */ +export default async function * take (source: AsyncIterable|Iterable, limit: number): AsyncGenerator { + let items = 0 + + if (limit < 1) { + return + } + + for await (const entry of source) { + yield entry + + items++ + + if (items === limit) { + return + } + } +} diff --git a/packages/it-take/test.js b/packages/it-take/test.js deleted file mode 100644 index d4ccea24..00000000 --- a/packages/it-take/test.js +++ /dev/null @@ -1,11 +0,0 @@ -const take = require('./') -const all = require('it-all') -const test = require('ava') - -test('Should limit the number of values returned from an iterable', async (t) => { - const values = [0, 1, 2, 3, 4] - - const res = await all(take(values, 2)) - - t.deepEqual(res, [0, 1]) -}) diff --git a/packages/it-take/test/index.spec.ts b/packages/it-take/test/index.spec.ts new file mode 100644 index 00000000..3abc178e --- /dev/null +++ b/packages/it-take/test/index.spec.ts @@ -0,0 +1,13 @@ +import { expect } from 'aegir/chai' +import all from 'it-all' +import take from '../src/index.js' + +describe('it-take', () => { + it('should limit the number of values returned from an iterable', async () => { + const values = [0, 1, 2, 3, 4] + + const res = await all(take(values, 2)) + + expect(res).to.deep.equal([0, 1]) + }) +}) diff --git a/packages/it-take/tsconfig.json b/packages/it-take/tsconfig.json index f5e4524f..f9f4589e 100644 --- a/packages/it-take/tsconfig.json +++ b/packages/it-take/tsconfig.json @@ -1,6 +1,15 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" + ], + "references": [ + { + "path": "../it-all" + } ] -} \ No newline at end of file +} diff --git a/packages/it-to-browser-readablestream/.npmignore b/packages/it-to-browser-readablestream/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-to-browser-readablestream/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-to-browser-readablestream/LICENSE b/packages/it-to-browser-readablestream/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-to-browser-readablestream/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-to-browser-readablestream/LICENSE-APACHE b/packages/it-to-browser-readablestream/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-to-browser-readablestream/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-to-browser-readablestream/LICENSE-MIT b/packages/it-to-browser-readablestream/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-to-browser-readablestream/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-to-browser-readablestream/README.md b/packages/it-to-browser-readablestream/README.md index ae0bd8be..df502e78 100644 --- a/packages/it-to-browser-readablestream/README.md +++ b/packages/it-to-browser-readablestream/README.md @@ -1,19 +1,27 @@ -# it-to-browser-readablestream +# it-to-browser-readablestream -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-to-browser-readablestream)](https://david-dm.org/achingbrain/it?path=packages/it-to-browser-readablestream) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Takes an iterable and turns it into a WhatWG browser readablestream +> Takes an async iterator and turns it into a browser readable stream + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-to-browser-readablestream +```console +$ npm i it-to-browser-readablestream ``` ## Usage ```javascript -const toBrowserReadableStream = require('it-to-browser-readablestream') +import toBrowserReadableStream from 'it-to-browser-readablestream' // This can also be an iterator, async iterator, generator, etc const values = [Buffer.from([0, 1]), Buffer.from([2, 3])] @@ -24,3 +32,14 @@ for await (const buf of stream) { console.info(buf) // Buffer[0, 1] } ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-to-browser-readablestream/index.js b/packages/it-to-browser-readablestream/index.js deleted file mode 100644 index 5989b097..00000000 --- a/packages/it-to-browser-readablestream/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict' - -/** - * @typedef {Object} SourceExt - * @property {boolean} [_cancelled] - */ -/** - * @template T - * @typedef {SourceExt & UnderlyingSource} Source - */ - -/** - * @template T - * @param {AsyncIterator|Iterator} source - * @param {QueuingStrategy} [queuingStrategy] - * @returns {ReadableStream} - */ -function itToBrowserReadableStream (source, queuingStrategy = {}) { - return new globalThis.ReadableStream(/** @type {Source} */({ - async start () { - this._cancelled = false - }, - async pull (controller) { - try { - const { value, done } = await source.next() - - if (this._cancelled) { - return - } - - if (done) { - controller.close() - return - } - - controller.enqueue(value) - } catch (err) { - controller.error(err) - } - }, - cancel () { - this._cancelled = true - } - }), queuingStrategy) -} - -module.exports = itToBrowserReadableStream diff --git a/packages/it-to-browser-readablestream/package.json b/packages/it-to-browser-readablestream/package.json index 81814a56..f340121d 100644 --- a/packages/it-to-browser-readablestream/package.json +++ b/packages/it-to-browser-readablestream/package.json @@ -2,27 +2,138 @@ "name": "it-to-browser-readablestream", "version": "1.0.4", "description": "Takes an async iterator and turns it into a browser readable stream", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-to-browser-readablestream#readme", - "bugs": "https://github.com/achingbrain/it/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" + }, + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage dist", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test -t browser", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, - "author": "Alex Potsides ", - "license": "ISC", "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" - }, - "types": "dist/index.d.ts" + "aegir": "^37.5.0" + } } diff --git a/packages/it-to-browser-readablestream/src/index.ts b/packages/it-to-browser-readablestream/src/index.ts new file mode 100644 index 00000000..817ea605 --- /dev/null +++ b/packages/it-to-browser-readablestream/src/index.ts @@ -0,0 +1,42 @@ + +interface SourceExt { + _cancelled: boolean +} + +type Source = SourceExt & UnderlyingSource + +/** + * Converts an (async) iterator into a WHATWG ReadableStream + */ +export default function itToBrowserReadableStream (source: AsyncIterator|Iterator, queuingStrategy: QueuingStrategy = {}): ReadableStream { + const s: Source = { + _cancelled: false, + + async start () { + this._cancelled = false + }, + async pull (controller) { + try { + const { value, done } = await source.next() + + if (this._cancelled) { + return + } + + if (done === true) { + controller.close() + return + } + + controller.enqueue(value) + } catch (err) { + controller.error(err) + } + }, + cancel () { + this._cancelled = true + } + } + + return new globalThis.ReadableStream(s, queuingStrategy) +} diff --git a/packages/it-to-browser-readablestream/test.js b/packages/it-to-browser-readablestream/test.js deleted file mode 100644 index 674adf71..00000000 --- a/packages/it-to-browser-readablestream/test.js +++ /dev/null @@ -1,6 +0,0 @@ -const toBrowserReadbleStream = require('./') -const test = require('ava') - -test('Should export something', async (t) => { - t.true(typeof toBrowserReadbleStream === 'function') -}) diff --git a/packages/it-to-browser-readablestream/test/index.spec.ts b/packages/it-to-browser-readablestream/test/index.spec.ts new file mode 100644 index 00000000..49ce04f0 --- /dev/null +++ b/packages/it-to-browser-readablestream/test/index.spec.ts @@ -0,0 +1,8 @@ +import { expect } from 'aegir/chai' +import toBrowserReadbleStream from '../src/index.js' + +describe('it-to-browser-readable-stream', () => { + it('should export something', async () => { + expect(typeof toBrowserReadbleStream).to.equal('function') + }) +}) diff --git a/packages/it-to-browser-readablestream/tsconfig.json b/packages/it-to-browser-readablestream/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-to-browser-readablestream/tsconfig.json +++ b/packages/it-to-browser-readablestream/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +} diff --git a/packages/it-to-buffer/.npmignore b/packages/it-to-buffer/.npmignore deleted file mode 100644 index 9bb01f4b..00000000 --- a/packages/it-to-buffer/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -*.log -.DS_Store -Thumbs.db -.vscode -.nyc_output -coverage -bin diff --git a/packages/it-to-buffer/LICENSE b/packages/it-to-buffer/LICENSE new file mode 100644 index 00000000..20ce483c --- /dev/null +++ b/packages/it-to-buffer/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/it-to-buffer/LICENSE-APACHE b/packages/it-to-buffer/LICENSE-APACHE new file mode 100644 index 00000000..14478a3b --- /dev/null +++ b/packages/it-to-buffer/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/it-to-buffer/LICENSE-MIT b/packages/it-to-buffer/LICENSE-MIT new file mode 100644 index 00000000..72dc60d8 --- /dev/null +++ b/packages/it-to-buffer/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/it-to-buffer/README.md b/packages/it-to-buffer/README.md index ac3d488e..b02fb4df 100644 --- a/packages/it-to-buffer/README.md +++ b/packages/it-to-buffer/README.md @@ -1,19 +1,27 @@ -# it-to-buffer +# it-to-buffer -[![Build status](https://github.com/achingbrain/it/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/achingbrain/it/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/achingbrain/it/badge.svg?branch=master)](https://coveralls.io/github/achingbrain/it?branch=master) [![Dependencies Status](https://david-dm.org/achingbrain/it/status.svg?path=packages/it-to-buffer)](https://david-dm.org/achingbrain/it?path=packages/it-to-buffer) +[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it) +[![CI](https://img.shields.io/github/workflow/status/achingbrain/it/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml) -> Takes an iterable that yields buffer-like-objects and concats them into one buffer +> Takes an async iterator that yields buffers and concatenates them all together + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) +- [Contribute](#contribute) ## Install -```sh -$ npm install --save it-to-buffer +```console +$ npm i it-to-buffer ``` ## Usage ```javascript -const toBuffer = require('it-to-buffer') +import toBuffer from 'it-to-buffer' // This can also be an iterator, async iterator, generator, etc const values = [Buffer.from([0, 1]), Buffer.from([2, 3])] @@ -22,3 +30,14 @@ const result = await toBuffer(values) console.info(result) // Buffer[0, 1, 2, 3] ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +## Contribute + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/it-to-buffer/package.json b/packages/it-to-buffer/package.json index 1b5dcf0a..aa1998b1 100644 --- a/packages/it-to-buffer/package.json +++ b/packages/it-to-buffer/package.json @@ -2,30 +2,142 @@ "name": "it-to-buffer", "version": "2.0.2", "description": "Takes an async iterator that yields buffers and concatenates them all together", - "main": "index.js", - "repository": "github:achingbrain/it", + "author": "Alex Potsides ", + "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/achingbrain/it/tree/master/packages/it-to-buffer#readme", - "bugs": "https://github.com/achingbrain/it/issues", - "scripts": { - "test": "ava", - "lint": "standard", - "coverage": "nyc --reporter html --reporter lcov ava", - "clean": "rm -rf .nyc_output coverage", - "check": "tsc --noEmit", - "build": "npm run build:types", - "build:types": "tsc --emitDeclarationOnly --declarationDir dist", - "prepublishOnly": "npm run build" + "repository": { + "type": "git", + "url": "git+https://github.com/achingbrain/it.git" }, - "author": "Alex Potsides ", - "license": "ISC", - "devDependencies": { - "ava": "^3.12.1", - "nyc": "^15.1.0", - "standard": "^16.0.3", - "typescript": "^4.0.2" + "bugs": { + "url": "https://github.com/achingbrain/it/issues" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "clean": "aegir clean", + "test": "aegir test", + "test:node": "aegir test -t node --cov", + "test:chrome": "aegir test -t browser --cov", + "test:chrome-webworker": "aegir test -t webworker", + "test:firefox": "aegir test -t browser -- --browser firefox", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "release": "aegir release" }, "dependencies": { - "uint8arrays": "^3.0.0" + "uint8arrays": "^4.0.2" }, - "types": "dist/index.d.ts" + "devDependencies": { + "aegir": "^37.5.0" + } } diff --git a/packages/it-to-buffer/index.js b/packages/it-to-buffer/src/index.ts similarity index 56% rename from packages/it-to-buffer/index.js rename to packages/it-to-buffer/src/index.ts index b2b83c1b..3055ff57 100644 --- a/packages/it-to-buffer/index.js +++ b/packages/it-to-buffer/src/index.ts @@ -1,13 +1,10 @@ -'use strict' - -const { concat: uint8ArrayConcat } = require('uint8arrays/concat') +import { concat as uint8ArrayConcat } from 'uint8arrays/concat' /** * Takes an (async) iterable that yields buffer-like-objects and concats them * into one buffer - * @param {AsyncIterable|Iterable} stream */ -async function toBuffer (stream) { +export default async function toBuffer (stream: AsyncIterable|Iterable): Promise { let buffer = new Uint8Array(0) for await (const buf of stream) { @@ -16,5 +13,3 @@ async function toBuffer (stream) { return buffer } - -module.exports = toBuffer diff --git a/packages/it-to-buffer/test.js b/packages/it-to-buffer/test.js deleted file mode 100644 index 85fdc540..00000000 --- a/packages/it-to-buffer/test.js +++ /dev/null @@ -1,24 +0,0 @@ -const toBuffer = require('./') -const test = require('ava') - -test('Should turn a generator that yields buffers into a buffer', async (t) => { - const iter = function * () { - yield Uint8Array.from([0]) - yield Uint8Array.from([1]) - yield Uint8Array.from([2]) - } - - const result = await toBuffer(iter()) - - t.deepEqual(result, Uint8Array.from([0, 1, 2])) -}) - -test('Should turn an array buffers into a buffer', async (t) => { - const result = await toBuffer([ - Uint8Array.from([0]), - Uint8Array.from([1]), - Uint8Array.from([2]) - ]) - - t.deepEqual(result, Uint8Array.from([0, 1, 2])) -}) diff --git a/packages/it-to-buffer/test/index.spec.ts b/packages/it-to-buffer/test/index.spec.ts new file mode 100644 index 00000000..f2ad41f3 --- /dev/null +++ b/packages/it-to-buffer/test/index.spec.ts @@ -0,0 +1,26 @@ +import { expect } from 'aegir/chai' +import toBuffer from '../src/index.js' + +describe('it-to-buffer', () => { + it('should turn a generator that yields buffers into a buffer', async () => { + const iter = function * () { + yield Uint8Array.from([0]) + yield Uint8Array.from([1]) + yield Uint8Array.from([2]) + } + + const result = await toBuffer(iter()) + + expect(result).to.equalBytes(Uint8Array.from([0, 1, 2])) + }) + + it('should turn an array buffers into a buffer', async () => { + const result = await toBuffer([ + Uint8Array.from([0]), + Uint8Array.from([1]), + Uint8Array.from([2]) + ]) + + expect(result).to.equalBytes(Uint8Array.from([0, 1, 2])) + }) +}) diff --git a/packages/it-to-buffer/tsconfig.json b/packages/it-to-buffer/tsconfig.json index f5e4524f..13a35996 100644 --- a/packages/it-to-buffer/tsconfig.json +++ b/packages/it-to-buffer/tsconfig.json @@ -1,6 +1,10 @@ { - "extends": "../../typescript.json", + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, "include": [ - "." + "src", + "test" ] -} \ No newline at end of file +}