Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wtgtybhertgeghgtwtg committed Jun 3, 2018
0 parents commit e2a4808
Show file tree
Hide file tree
Showing 24 changed files with 1,589 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
modules: process.env.NODE_ENV === 'test' && 'commonjs',
targets: {node: '6'},
},
],
'@babel/preset-flow',
],
};
88 changes: 88 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
jobs:

lint:
docker:
- image: circleci/node:8
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: yarn lint
working_directory: ~/repo

release:
docker:
- image: circleci/node:8
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: yarn build
- run: npx semantic-release

test:
docker:
- image: circleci/node:8
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: yarn test:src
working_directory: ~/repo

test-dist:
docker:
- image: circleci/node:8
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run: yarn build
- run: yarn test:dist
working_directory: ~/repo

version: 2

workflows:
test_and_release:
jobs:
- lint
- test
- test-dist
- release:
filters:
branches:
only: master
requires:
- lint
- test
- test-dist
version: 2
2 changes: 2 additions & 0 deletions .commitlintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extends:
- '@commitlint/config-conventional'
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
coverage/*
dist/*
flow-typed/*
node_modules/*
27 changes: 27 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
env:
jest: true

extends:
- airbnb-base
- plugin:flowtype/recommended
- prettier
- prettier/flowtype

parser: babel-eslint

plugins:
- flowtype

rules:
no-restricted-syntax:
- error
- message: for..in loops iterate over the entire prototype chain, which is virtually
never what you want. Use Object.{keys,values,entries}, and iterate over the resulting
array.
selector: ForInStatement
- message: Labels are a form of GOTO; using them makes code confusing and hard to
maintain and understand.
selector: LabeledStatement
- message: "`with` is disallowed in strict mode because it makes code impossible to
predict and optimize."
selector: WithStatement
11 changes: 11 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[ignore]

[include]

[libs]

[lints]

[options]

[strict]
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
coverage
dist
lib
node_modules
yarn.lock
*.log*
3 changes: 3 additions & 0 deletions .huskyrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hooks:
commit-msg: commitlint -e $HUSKY_GIT_PARAMS
pre-commit: flow && lint-staged && yarn docs
3 changes: 3 additions & 0 deletions .lintstagedrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
linters:
"*.{json,md}": ["prettier --write", "git add"]
"*.{js}": ["prettier --write", "eslint --fix", "git add", "jest --config ./scripts/jest/config.source.js --bail --findRelatedTests"]
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package.json
3 changes: 3 additions & 0 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bracketSpacing: false
singleQuote: true
trailingComma: all
9 changes: 9 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
MIT License

Copyright (c) Matthew Fernando Garcia <wtgtybhertgeghgtwtg@gmail.com>

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.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# buffer-async-iterator

> Buffer an AsyncIterator before iteration.
Create an AsyncIterator over the values of an AsyncIterator, eagerly iterated.

## Install

$ yarn buffer-async-iterator

## API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

- [bufferAsyncIterator](#bufferasynciterator)

### bufferAsyncIterator

Create an AsyncIterator from `iterable`, with the values eagerly buffered.

**Parameters**

- `iterable` **(AsyncIterable&lt;Value> | Iterable&lt;Value>)** The iterable whose values will be buffered.
- `write` **Write** A function that takes `iterable` and `buffer` and returns a Promise. `buffer` will not be iterated through until it resolves. (optional, default `defaultWrite`)
- `buffer` **(AsyncIterable&lt;Value> | Iterable&lt;Value>)** An iterable representing the data being buffered. (optional, default `[]`)

**Examples**

```javascript
import bufferAsyncIterator from 'bufferAsyncIterator';
import got from 'got';

async function* getWebsites(sites) {
for (const site of sites) {
yield await got(site);
}
}

// Immediate start running the generator.
const websiteIterator = bufferAsyncIterator(getWebsites(['google.com', 'bing.com', 'is-yahoo-still-around.com']));

for await (const site of websiteIterator) {
// Iteration begins only after the original generator has finished.
}
```

## License

MIT © Matthew Fernando Garcia
143 changes: 143 additions & 0 deletions __tests__/bufferAsyncIterator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// @flow
/* eslint-disable require-yield */
import bufferAsyncIterator from '../src';

async function* sample(done = () => {}) {
yield 1;
yield 2;
yield 3;
done();
}

function* syncSample(done = () => {}) {
yield 1;
yield 2;
yield 3;
done();
}

describe('bufferAsyncIterator', () => {
describe('invariants', () => {
it('throws if "iterable" is neither an AsyncIterable nor an Iterable.', () => {
// $FlowFixMe
expect(() => bufferAsyncIterator(3)).toThrow(
'"iterable" must be an AsyncIterable or Iterable.',
);
});

it('throws if "write" is neither a function nor undefined.', () => {
expect(() =>
// $FlowFixMe
bufferAsyncIterator([], 'Neither a function nor undefined.'),
).toThrow('"write" must be a function or undefined.');
});

it('throws if "buffer" is neither an AsyncIterable, an Iterable, or undefined.', () => {
// $FlowFixMe
expect(() => bufferAsyncIterator([], undefined, 3)).toThrow(
'"buffer" must be an AsyncIterable, an Iterable, or undefined.',
);
});

it('throws if "write" is undefined and "buffer.push" is not a function.', () => {
expect(() => bufferAsyncIterator([], undefined, new Map())).toThrow(
'When using the default "write" function, "buffer.push" must be a function.',
);
});
});

describe('default buffering', () => {
it('buffers an AsyncIterable.', done => {
bufferAsyncIterator(sample(done));
});

it('buffers an Iterable.', done => {
bufferAsyncIterator(syncSample(done));
});

it('passes through all values.', async () => {
const values = [1, 2, 3];
let index = 0;
for await (const value of bufferAsyncIterator(values)) {
expect(values[index]).toEqual(value);
index += 1;
}
});

it('rejects if "iterable" rejects.', async () => {
const message = 'Iterable error.';

async function* rejectSample() {
throw new Error(message);
}

await expect(bufferAsyncIterator(rejectSample()).next()).rejects.toThrow(
message,
);
});

it('rejects if "iterable" throws.', async () => {
const message = 'Iterable error.';

function* rejectSample() {
throw new Error(message);
}

await expect(bufferAsyncIterator(rejectSample()).next()).rejects.toThrow(
message,
);
});
});

describe('with a "write" function.', () => {
it('does not iterate through "buffer" until "write" resolves.', async () => {
let hasResolved = false;
async function write() {
hasResolved = true;
}
await bufferAsyncIterator(sample(), write).next();
expect(hasResolved).toBe(true);
});

it('rejects if "write" rejects.', async () => {
const message = 'Write error.';

async function write() {
throw new Error(message);
}
await expect(bufferAsyncIterator(sample(), write).next()).rejects.toThrow(
message,
);
});

it('yields the values "write" adds to "buffer".', async () => {
async function write(iterable, buffer) {
for (const value of iterable) {
buffer.push(value * 3);
}
}

const values = [1, 2, 3];
let index = 0;

for await (const value of bufferAsyncIterator(values, write)) {
expect(value).toBe(values[index] * 3);
index += 1;
}
});
});

describe('with a "buffer".', () => {
it('rejects if "buffer" rejects.', async () => {
const message = 'Buffer error.';

async function* buffer() {
throw new Error(message);
}

await expect(
bufferAsyncIterator(sample(), () => {}, buffer()).next(),
).rejects.toThrow(message);
});
});
});

0 comments on commit e2a4808

Please sign in to comment.