Comparing version 3.0.0 to 4.0.0
# Changelog | ||
## [4.0.0] - 2022-07-01 | ||
_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._ | ||
### Changed | ||
- **Breaking:** bump [`readable-stream`](https://github.com/nodejs/readable-stream) from 3 to 4 ([`082b8d6`](https://github.com/Level/level-ws/commit/082b8d6)) (Vincent Weevers) | ||
- **Breaking:** use classes, requiring `new` ([`dafafb2`](https://github.com/Level/level-ws/commit/dafafb2)) (Vincent Weevers) | ||
- **Breaking:** drop Node.js 10 ([`817c30c`](https://github.com/Level/level-ws/commit/817c30c)) (Vincent Weevers) | ||
### Fixed | ||
- Cleanup README and add missing docs for options ([`94a2a8e`](https://github.com/Level/level-ws/commit/94a2a8e)) (Vincent Weevers). | ||
## [3.0.0] - 2021-04-25 | ||
_**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md)._ | ||
_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._ | ||
@@ -105,2 +119,4 @@ ### Changed | ||
[4.0.0]: https://github.com/Level/level-ws/releases/tag/v4.0.0 | ||
[3.0.0]: https://github.com/Level/level-ws/compare/v2.0.0...v3.0.0 | ||
@@ -107,0 +123,0 @@ |
126
level-ws.js
'use strict' | ||
const Writable = require('readable-stream').Writable | ||
const inherits = require('inherits') | ||
const defaultOptions = { type: 'put' } | ||
class WriteStream extends Writable { | ||
constructor (db, options) { | ||
options = Object.assign({ type: 'put' }, options) | ||
function WriteStream (db, options) { | ||
if (!(this instanceof WriteStream)) { | ||
return new WriteStream(db, options) | ||
super({ | ||
objectMode: true, | ||
highWaterMark: options.highWaterMark || 16, | ||
autoDestroy: true, | ||
emitClose: true | ||
}) | ||
this._options = options | ||
this._db = db | ||
this._buffer = [] | ||
this._flushing = false | ||
this._maxBufferLength = options.maxBufferLength || Infinity | ||
this._flush = this._flush.bind(this) | ||
} | ||
options = Object.assign({}, defaultOptions, options) | ||
_write (data, enc, next) { | ||
if (this.destroyed) return | ||
Writable.call(this, { | ||
objectMode: true, | ||
highWaterMark: options.highWaterMark || 16 | ||
}) | ||
if (!this._flushing) { | ||
this._flushing = true | ||
process.nextTick(this._flush) | ||
} | ||
this._options = options | ||
this._db = db | ||
this._buffer = [] | ||
this._flushing = false | ||
this._maxBufferLength = options.maxBufferLength || Infinity | ||
if (this._buffer.length >= this._maxBufferLength) { | ||
this.once('_flush', (err) => { | ||
if (err) return this.destroy(err) | ||
this._write(data, enc, next) | ||
}) | ||
} else { | ||
this._buffer.push(Object.assign({ type: this._options.type }, data)) | ||
next() | ||
} | ||
} | ||
this.on('finish', () => { | ||
this.emit('close') | ||
}) | ||
} | ||
_flush () { | ||
const buffer = this._buffer | ||
inherits(WriteStream, Writable) | ||
if (this.destroyed) return | ||
WriteStream.prototype._write = function (data, enc, next) { | ||
if (this.destroyed) return | ||
this._buffer = [] | ||
this._db.batch(buffer, (err) => { | ||
this._flushing = false | ||
if (!this._flushing) { | ||
this._flushing = true | ||
process.nextTick(() => { this._flush() }) | ||
} | ||
if (this._buffer.length >= this._maxBufferLength) { | ||
this.once('_flush', (err) => { | ||
if (err) return this.destroy(err) | ||
this._write(data, enc, next) | ||
if (!this.emit('_flush', err) && err) { | ||
// There was no _flush listener. | ||
this.destroy(err) | ||
} | ||
}) | ||
} else { | ||
this._buffer.push(Object.assign({ type: this._options.type }, data)) | ||
next() | ||
} | ||
} | ||
WriteStream.prototype._flush = function () { | ||
const buffer = this._buffer | ||
_final (cb) { | ||
if (this._flushing) { | ||
// Wait for scheduled or in-progress _flush() | ||
this.once('_flush', (err) => { | ||
if (err) return cb(err) | ||
if (this.destroyed) return | ||
this._buffer = [] | ||
this._db.batch(buffer, (err) => { | ||
this._flushing = false | ||
if (!this.emit('_flush', err) && err) { | ||
// There was no _flush listener. | ||
this.destroy(err) | ||
// There could be additional buffered writes | ||
this._final(cb) | ||
}) | ||
} else if (this._buffer && this._buffer.length) { | ||
this.once('_flush', cb) | ||
this._flush() | ||
} else { | ||
cb() | ||
} | ||
}) | ||
} | ||
} | ||
WriteStream.prototype._final = function (cb) { | ||
if (this._flushing) { | ||
// Wait for scheduled or in-progress _flush() | ||
this.once('_flush', (err) => { | ||
if (err) return cb(err) | ||
// There could be additional buffered writes | ||
this._final(cb) | ||
}) | ||
} else if (this._buffer && this._buffer.length) { | ||
this.once('_flush', cb) | ||
this._flush() | ||
} else { | ||
cb() | ||
_destroy (err, cb) { | ||
this._buffer = null | ||
cb(err) | ||
} | ||
} | ||
WriteStream.prototype._destroy = function (err, cb) { | ||
this._buffer = null | ||
cb(err) | ||
} | ||
module.exports = WriteStream |
{ | ||
"name": "level-ws", | ||
"version": "3.0.0", | ||
"description": "A basic WriteStream implementation for LevelUP", | ||
"version": "4.0.0", | ||
"description": "A basic writable stream for abstract-level databases", | ||
"license": "MIT", | ||
@@ -9,6 +9,3 @@ "main": "level-ws.js", | ||
"test": "standard && hallmark && nyc node test.js", | ||
"coverage": "nyc report -r lcovonly", | ||
"hallmark": "hallmark --fix", | ||
"dependency-check": "dependency-check . test.js", | ||
"prepublishOnly": "npm run dependency-check" | ||
"coverage": "nyc report -r lcovonly" | ||
}, | ||
@@ -21,13 +18,10 @@ "files": [ | ||
"dependencies": { | ||
"inherits": "^2.0.3", | ||
"readable-stream": "^3.1.0" | ||
"readable-stream": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"dependency-check": "^3.3.0", | ||
"hallmark": "^3.1.0", | ||
"level": "^7.0.0", | ||
"level-concat-iterator": "^3.0.0", | ||
"hallmark": "^4.1.0", | ||
"level": "^8.0.0", | ||
"nyc": "^15.1.0", | ||
"secret-event-listener": "^1.0.0", | ||
"standard": "^16.0.3", | ||
"standard": "^17.0.0", | ||
"tape": "^5.0.1", | ||
@@ -48,4 +42,4 @@ "tempy": "^1.0.1" | ||
"engines": { | ||
"node": ">=10" | ||
"node": ">=12" | ||
} | ||
} |
126
README.md
# level-ws | ||
> A basic WriteStream implementation for [levelup](https://github.com/Level/levelup) | ||
**A basic writable stream for [`abstract-level`](https://github.com/Level/abstract-level) databases, using Node.js core streams.** This is not a high-performance stream. If benchmarking shows that your particular usage does not fit then try one of the alternative writable streams that are optimized for different use cases. | ||
> :pushpin: To instead write data using Web Streams, see [`level-web-stream`](https://github.com/Level/web-stream). | ||
[![level badge][level-badge]](https://github.com/Level/awesome) | ||
[![npm](https://img.shields.io/npm/v/level-ws.svg?label=&logo=npm)](https://www.npmjs.com/package/level-ws) | ||
[![npm](https://img.shields.io/npm/v/level-ws.svg)](https://www.npmjs.com/package/level-ws) | ||
[![Node version](https://img.shields.io/node/v/level-ws.svg)](https://www.npmjs.com/package/level-ws) | ||
[![Test](https://github.com/Level/level-ws/actions/workflows/test.yml/badge.svg)](https://github.com/Level/level-ws/actions/workflows/test.yml) | ||
[![npm](https://img.shields.io/npm/dm/level-ws.svg?label=dl)](https://www.npmjs.com/package/level-ws) | ||
[![Coverage Status](https://codecov.io/gh/Level/level-ws/branch/master/graph/badge.svg)](https://codecov.io/gh/Level/level-ws) | ||
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) | ||
[![Funding](https://opencollective.com/level/tiers/badge.svg)](#donate) | ||
[![Test](https://img.shields.io/github/workflow/status/Level/level-ws/Test?label=test)](https://github.com/Level/level-ws/actions/workflows/test.yml) | ||
[![Coverage](https://img.shields.io/codecov/c/github/Level/level-ws?label=\&logo=codecov\&logoColor=fff)](https://codecov.io/gh/Level/level-ws) | ||
[![Standard](https://img.shields.io/badge/standard-informational?logo=javascript\&logoColor=fff)](https://standardjs.com) | ||
[![Common Changelog](https://common-changelog.org/badge.svg)](https://common-changelog.org) | ||
[![Donate](https://img.shields.io/badge/donate-orange?logo=open-collective\&logoColor=fff)](https://opencollective.com/level) | ||
`level-ws` provides the most basic general-case WriteStream for `levelup`. It was extracted from the core `levelup` at version 0.18.0. | ||
## Usage | ||
`level-ws` is not a high-performance WriteStream. If your benchmarking shows that your particular usage pattern and data types do not perform well with this WriteStream then you should try one of the alternative WriteStreams available for `levelup` that are optimised for different use-cases. | ||
_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._ | ||
**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md). | ||
## Usage | ||
```js | ||
var level = require('level') | ||
var WriteStream = require('level-ws') | ||
const { Level } = require('level') | ||
const WriteStream = require('level-ws') | ||
var db = level('/path/to/db') | ||
var ws = WriteStream(db) // ... | ||
``` | ||
const db = new Level('./db', { valueEncoding: 'json' }) | ||
const ws = new WriteStream(db) | ||
## API | ||
### `ws = WriteStream(db[, options])` | ||
Creates a [Writable](https://nodejs.org/dist/latest-v8.x/docs/api/stream.html#stream_class_stream_writable) stream which operates in **objectMode**, accepting objects with `'key'` and `'value'` pairs on its `write()` method. | ||
The optional `options` argument may contain: | ||
- `type` _(string, default: `'put'`)_: Default batch operation for missing `type` property during `ws.write()`. | ||
The WriteStream will buffer writes and submit them as a `batch()` operations where writes occur _within the same tick_. | ||
```js | ||
var ws = WriteStream(db) | ||
ws.on('error', function (err) { | ||
console.log('Oh my!', err) | ||
}) | ||
ws.on('close', function () { | ||
console.log('Stream closed') | ||
console.log('Done!') | ||
}) | ||
ws.write({ key: 'name', value: 'Yuri Irsenovich Kim' }) | ||
ws.write({ key: 'dob', value: '16 February 1941' }) | ||
ws.write({ key: 'spouse', value: 'Kim Young-sook' }) | ||
ws.write({ key: 'occupation', value: 'Clown' }) | ||
ws.end() | ||
``` | ||
ws.write({ key: 'alice', value: 42 }) | ||
ws.write({ key: 'bob', value: 7 }) | ||
The standard `write()`, `end()` and `destroy()` methods are implemented on the WriteStream. `'drain'`, `'error'`, `'close'` and `'pipe'` events are emitted. | ||
// To delete entries, specify an explicit type | ||
ws.write({ type: 'del', key: 'tomas' }) | ||
ws.write({ type: 'put', key: 'sara', value: 16 }) | ||
You can specify encodings for individual entries by setting `.keyEncoding` and/or `.valueEncoding`: | ||
```js | ||
writeStream.write({ | ||
key: new Buffer([1, 2, 3]), | ||
value: { some: 'json' }, | ||
keyEncoding: 'binary', | ||
valueEncoding : 'json' | ||
}) | ||
``` | ||
If individual `write()` operations are performed with a `'type'` property of `'del'`, they will be passed on as `'del'` operations to the batch. | ||
```js | ||
var ws = WriteStream(db) | ||
ws.on('error', function (err) { | ||
console.log('Oh my!', err) | ||
}) | ||
ws.on('close', function () { | ||
console.log('Stream closed') | ||
}) | ||
ws.write({ type: 'del', key: 'name' }) | ||
ws.write({ type: 'del', key: 'dob' }) | ||
ws.write({ type: 'put', key: 'spouse' }) | ||
ws.write({ type: 'del', key: 'occupation' }) | ||
ws.end() | ||
``` | ||
If the _WriteStream_ is created with a `'type'` option of `'del'`, all `write()` operations will be interpreted as `'del'`, unless explicitly specified as `'put'`. | ||
## API | ||
```js | ||
var ws = WriteStream(db, { type: 'del' }) | ||
### `ws = new WriteStream(db[, options])` | ||
ws.on('error', function (err) { | ||
console.log('Oh my!', err) | ||
}) | ||
ws.on('close', function () { | ||
console.log('Stream closed') | ||
}) | ||
Create a [writable stream](https://nodejs.org/dist/latest-v18.x/docs/api/stream.html#stream_class_stream_writable) that operates in object mode, accepting batch operations to be committed with `db.batch()` on each tick of the Node.js event loop. The optional `options` argument may contain: | ||
ws.write({ key: 'name' }) | ||
ws.write({ key: 'dob' }) | ||
// but it can be overridden | ||
ws.write({ type: 'put', key: 'spouse', value: 'Ri Sol-ju' }) | ||
ws.write({ key: 'occupation' }) | ||
ws.end() | ||
``` | ||
- `type` (string, default: `'put'`): default batch operation type if not set on indididual operations. | ||
- `maxBufferLength` (number, default `Infinity`): limit the size of batches. When exceeded, the stream will stop processing writes until the current batch has been committed. | ||
- `highWaterMark` (number, default `16`): buffer level when `stream.write()` starts returning false. | ||
@@ -119,14 +59,2 @@ ## Contributing | ||
## Donate | ||
Support us with a monthly donation on [Open Collective](https://opencollective.com/level) and help us continue our work. Your logo or avatar will be displayed on our 28+ [GitHub repositories](https://github.com/Level) and [npm](https://www.npmjs.com/) packages. 💖 | ||
**Active financial contributors** | ||
[![Open Collective backers](https://opencollective.com/level/tiers/backer.svg?button=false)](https://opencollective.com/level) [![Open Collective sponsors](https://opencollective.com/level/tiers/sponsor.svg?button=false)](https://opencollective.com/level) | ||
**Past financial contributors** | ||
[![Open Collective sponsors](https://opencollective.com/level/sponsors.svg?button=false&avatarHeight=36)](https://opencollective.com/level) [![Open Collective backers](https://opencollective.com/level/backers.svg?button=false&avatarHeight=36)](https://opencollective.com/level) | ||
## License | ||
@@ -133,0 +61,0 @@ |
@@ -5,2 +5,18 @@ # Upgrade Guide | ||
## 4.0.0 | ||
Drops support of Node.js 10, upgrades to `readable-stream@4` ([`082b8d6`](https://github.com/Level/level-ws/commit/082b8d6)) and uses classes which means `new` is now required. If you previously did: | ||
```js | ||
const WriteStream = require('level-ws') | ||
const ws = WriteStream(db) | ||
``` | ||
You must now do: | ||
```js | ||
const WriteStream = require('level-ws') | ||
const ws = new WriteStream(db) | ||
``` | ||
## 3.0.0 | ||
@@ -23,3 +39,3 @@ | ||
* * * | ||
--- | ||
@@ -44,3 +60,3 @@ The API only exports a single function and no longer patches `levelup`. | ||
* * * | ||
--- | ||
@@ -65,15 +81,15 @@ The parameters to the stream constructor were flipped. | ||
* * * | ||
--- | ||
The behavior of `maxBufferLength` was changed. Previously all write operations exceeding `maxBufferLength` in the same tick were dropped. Instead the stream is now paused until a batch has been flushed and unpaused once the batch has been completed. | ||
* * * | ||
--- | ||
`WriteStream#destroySoon()` was removed. | ||
* * * | ||
--- | ||
Internally `this.writable` and `this.readable` were removed. However, `this.writable` still exists due to inheritance, but `this.readable` is now `undefined`. | ||
* * * | ||
--- | ||
@@ -80,0 +96,0 @@ Default `'utf8'` encoding was removed and also per stream encodings. However, it's still possible to specify encodings for individual entries. This means if you previously relied on per stream encodings, you must specify this in calls to `.write()`: |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1
7
0
17022
67
64
+ Addedabort-controller@3.0.0(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbuffer@6.0.3(transitive)
+ Addedevent-target-shim@5.0.1(transitive)
+ Addedevents@3.3.0(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedprocess@0.11.10(transitive)
+ Addedreadable-stream@4.5.2(transitive)
- Removedinherits@^2.0.3
- Removedinherits@2.0.4(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedutil-deprecate@1.0.2(transitive)
Updatedreadable-stream@^4.0.0