Full Code of maxogden/level.js for AI

master d510999ee56a cached
21 files
70.9 KB
20.6k tokens
15 symbols
1 requests
Download .txt
Repository: maxogden/level.js
Branch: master
Commit: d510999ee56a
Files: 21
Total size: 70.9 KB

Directory structure:
gitextract_dn_f2s6r/

├── .airtap.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── UPGRADING.md
├── index.js
├── iterator.js
├── package.json
├── test/
│   ├── custom-test.js
│   ├── index.js
│   ├── support-test.js
│   └── upgrade-test.js
└── util/
    ├── clear.js
    ├── deserialize.js
    ├── key-range.js
    ├── serialize.js
    └── support.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .airtap.yml
================================================
providers:
  - airtap-sauce

browsers:
  - name: chrome
  - name: firefox
  - name: safari
    version: 12..latest
  - name: ios_saf
    version: 12..latest
  - name: chrome for android
    version: 6..latest
  - name: msedge

presets:
  local:
    providers:
      - airtap-playwright
    browsers:
      - name: chromium
      - name: firefox


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: monthly
    ignore:
      - dependency-name: dependency-check
      - dependency-name: uuid
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly


================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
  push:
    tags: ['*']
permissions:
  contents: write
jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Create GitHub release
        uses: docker://antonyurchenko/git-release:v4
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on: push
concurrency: sauce-labs
jobs:
  test:
    runs-on: ubuntu-latest
    name: Sauce Labs
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Use node 14
        uses: actions/setup-node@v3
        with:
          node-version: 14
      - name: Install
        run: npm install
        env:
          # Download Sauce Connect binary now instead of on first run
          SAUCE_CONNECT_DOWNLOAD_ON_INSTALL: true
      - name: Add host
        run: echo "127.0.0.1 airtap.local" | sudo tee -a /etc/hosts
      - name: Test
        run: npm run test-browsers
        env:
          SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
          SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
      - name: Coverage
        run: npm run coverage
      - name: Codecov
        uses: codecov/codecov-action@v3
        with:
          file: coverage/lcov.info


================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
npm-debug.log
package-lock.json
.nyc_output/


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## [6.1.0] - 2021-09-28

### Added

- Add `db.getMany(keys)` ([#214](https://github.com/Level/level-js/issues/214)) ([`f5a3ca3`](https://github.com/Level/level-js/commit/f5a3ca3)) (Vincent Weevers).

## [6.0.0] - 2021-04-09

_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._

### Changed

- **Breaking:** bump `abstract-leveldown` ([`720aced`](https://github.com/Level/level-js/commit/720aced)) (Vincent Weevers)
- **Breaking:** bump `buffer` from 5.x to 6.x ([#210](https://github.com/Level/level-js/issues/210)) ([`cc68b21`](https://github.com/Level/level-js/commit/cc68b21)) (Alex Potsides)
- Modernize syntax and bump `standard` ([Level/community#98](https://github.com/Level/community/issues/98)) ([`0ce815f`](https://github.com/Level/level-js/commit/0ce815f)) (Vincent Weevers)
- Every browser in our test matrix now supports binary keys ([`2c20127`](https://github.com/Level/level-js/commit/2c20127)) (Vincent Weevers)

## [5.0.2] - 2020-04-03

### Changed

- Use `nextTick` of `abstract-leveldown` ([#195](https://github.com/Level/level-js/issues/195)) ([**@vweevers**](https://github.com/vweevers)) (same underlying code)
- Upgrade `nyc` devDependency from `^14.0.0` to `^15.0.0` ([#187](https://github.com/Level/level-js/issues/187)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `airtap` devDependency from `^2.0.0` to `^3.0.0` ([#189](https://github.com/Level/level-js/issues/189)) ([**@vweevers**](https://github.com/vweevers))

### Fixed

- Add `buffer` for browsers ([#191](https://github.com/Level/level-js/issues/191)) ([**@hugomrdias**](https://github.com/hugomrdias))

## [5.0.1] - 2019-11-29

### Fixed

- Restore support of empty prefix option ([#184](https://github.com/Level/level-js/issues/184)) ([**@achingbrain**](https://github.com/achingbrain)). This restores a previous behavior (of `level-js` < 3) that unknown to us, was provided by the since-removed `IDBWrapper`.

## [5.0.0] - 2019-10-04

_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._

### Changed

- **Breaking**: Drop support of key & value types other than string and Buffer ([#179](https://github.com/Level/level-js/issues/179)) ([**@vweevers**](https://github.com/vweevers))
- Replace mentions of `level-browserify` with `level` ([`58b3e07`](https://github.com/Level/level-js/commit/58b3e07)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `hallmark` devDependency from `^0.1.0` to `^2.0.0` ([#172](https://github.com/Level/level-js/issues/172), [#177](https://github.com/Level/level-js/issues/177)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `nyc` devDependency from `^13.1.0` to `^14.0.0` ([#169](https://github.com/Level/level-js/issues/169)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `standard` devDependency from `^12.0.1` to `^14.0.2` ([#171](https://github.com/Level/level-js/issues/171), [`aacb0ea`](https://github.com/Level/level-js/commit/aacb0ea)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))

### Added

- Add manifest ([Level/community#83](https://github.com/Level/community/issues/83)) ([#183](https://github.com/Level/level-js/issues/183)) ([**@vweevers**](https://github.com/vweevers))
- Support `clear()` ([Level/community#79](https://github.com/Level/community/issues/79)) ([#182](https://github.com/Level/level-js/issues/182)) ([**@vweevers**](https://github.com/vweevers))

## [4.0.1] - 2019-03-31

### Changed

- Apply common project tweaks ([#164](https://github.com/Level/level-js/issues/164), [#165](https://github.com/Level/level-js/issues/165)) ([**@vweevers**](https://github.com/vweevers))

### Removed

- Remove outdated sentence about nullish values from README ([#166](https://github.com/Level/level-js/issues/166)) ([**@vweevers**](https://github.com/vweevers))

## [4.0.0] - 2018-12-30

_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._

### Changed

- Upgrade `abstract-leveldown` from `~5.0.0` to `~6.0.1` ([#155](https://github.com/Level/level-js/issues/155), [#157](https://github.com/Level/level-js/issues/157)) ([**@vweevers**](https://github.com/vweevers))
- Don't serialize boolean or `NaN` keys, have IDB reject them ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Update test of `key cannot be an empty Array` error ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Change `iterator.db` to reference `level-js` instance, not IDB ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Handle `location` in constructor, as it was removed from `abstract-leveldown` ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Use `level-concat-iterator` and `testCommon.factory()` in custom tests ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Invoke abstract tests from single function ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `airtap` devDependency from `0.0.7` to `^2.0.0` ([`2b71337`](https://github.com/Level/level-js/commit/2b71337), [#161](https://github.com/Level/level-js/issues/161)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Upgrade `standard` devDependency from `^11.0.1` to `^12.0.1` ([#153](https://github.com/Level/level-js/issues/153)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Replace `remark-cli` devDependency with `hallmark` ([#151](https://github.com/Level/level-js/issues/151), [#153](https://github.com/Level/level-js/issues/153)) ([**@vweevers**](https://github.com/vweevers))

### Added

- Test and document native sort order ([#157](https://github.com/Level/level-js/issues/157)) ([**@vweevers**](https://github.com/vweevers))
- Add iPhone and Android `latest` to test matrix ([#162](https://github.com/Level/level-js/issues/162)) ([**@vweevers**](https://github.com/vweevers))
- Add `nyc` and `coveralls` devDependencies ([#150](https://github.com/Level/level-js/issues/150), [#153](https://github.com/Level/level-js/issues/153)) ([`eb1aead`](https://github.com/Level/level-js/commit/eb1aead)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Add Contributing section to README ([`c94a9a4`](https://github.com/Level/level-js/commit/c94a9a4)) ([**@ralphtheninja**](https://github.com/ralphtheninja))

### Removed

- Remove now irrelevant serialization of nullish values ([#155](https://github.com/Level/level-js/issues/155)) ([**@vweevers**](https://github.com/vweevers))
- Remove unused `IndexedDBShim` from tests ([#162](https://github.com/Level/level-js/issues/162)) ([**@vweevers**](https://github.com/vweevers))

## [3.0.0] - 2018-06-17

_If you are upgrading: please see [`UPGRADING.md`](UPGRADING.md)._

### Changed

- Destroy with `location` and `prefix` only ([#116](https://github.com/Level/level-js/issues/116)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Replace `util.inherits` with `inherits` module ([`8db16c1`](https://github.com/Level/level-js/commit/8db16c1)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Change copyright years to "2012-present" ([`7017edd`](https://github.com/Level/level-js/commit/7017edd)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Simplify license description ([#141](https://github.com/Level/level-js/issues/141)) ([**@vweevers**](https://github.com/vweevers))
- Update `package.json` description and keywords ([#141](https://github.com/Level/level-js/issues/141)) ([**@vweevers**](https://github.com/vweevers))

### Added

- Add `CHANGELOG.md` ([#107](https://github.com/Level/level-js/issues/107), [#115](https://github.com/Level/level-js/issues/115)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Add `UPGRADING.md` ([#143](https://github.com/Level/level-js/issues/143)) ([**@vweevers**](https://github.com/vweevers))
- Add `CONTRIBUTORS.md` (replaces `COLLABORATORS.md`) ([#141](https://github.com/Level/level-js/issues/141)) ([**@vweevers**](https://github.com/vweevers))
- Add `standard` ([#112](https://github.com/Level/level-js/issues/112)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Document constructor ([#119](https://github.com/Level/level-js/issues/119)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Document type support ([#125](https://github.com/Level/level-js/issues/125), [#143](https://github.com/Level/level-js/issues/143)) ([**@vweevers**](https://github.com/vweevers))
- Add `remark` tooling ([#141](https://github.com/Level/level-js/issues/141), [#143](https://github.com/Level/level-js/issues/143), [#147](https://github.com/Level/level-js/issues/147)) ([**@vweevers**](https://github.com/vweevers))
- Test default and custom prefix ([#124](https://github.com/Level/level-js/issues/124)) ([**@vweevers**](https://github.com/vweevers))
- Test all key types of IndexedDB Second Edition ([#130](https://github.com/Level/level-js/issues/130)) ([**@vweevers**](https://github.com/vweevers))
- Test illegal value types ([#118](https://github.com/Level/level-js/issues/118)) ([**@vweevers**](https://github.com/vweevers))
- Test illegal and stringified key types ([#139](https://github.com/Level/level-js/issues/139)) ([**@vweevers**](https://github.com/vweevers))
- Test `Buffer`, `ArrayBuffer` and `Uint8Array` values with `asBuffer` option ([#146](https://github.com/Level/level-js/issues/146)) ([**@vweevers**](https://github.com/vweevers))

### Fixed

- Add original copyright owner (Max Ogden) ([#141](https://github.com/Level/level-js/issues/141)) ([**@vweevers**](https://github.com/vweevers))
- Replace `level.js` in documentation to match npm name `level-js` ([#121](https://github.com/Level/level-js/issues/121)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Force airtap's browserify to use latest `buffer@5` ([#122](https://github.com/Level/level-js/issues/122)) ([**@vweevers**](https://github.com/vweevers))
- Don't stringify keys (except fallbacks, booleans and `NaN`) ([#130](https://github.com/Level/level-js/issues/130)) ([**@vweevers**](https://github.com/vweevers))
- Fix conversion of `ArrayBuffer` cursor key to `Buffer` ([#130](https://github.com/Level/level-js/issues/130)) ([**@vweevers**](https://github.com/vweevers))
- Catch IndexedDB key and value errors ([#139](https://github.com/Level/level-js/issues/139)) ([**@vweevers**](https://github.com/vweevers))
- Use `setImmediate` with callback in `_close()` ([#111](https://github.com/Level/level-js/issues/111)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Whitelist npm package files ([#126](https://github.com/Level/level-js/issues/126)) ([**@vweevers**](https://github.com/vweevers))
- Avoid `instanceof Date` for cross-realm support ([#129](https://github.com/Level/level-js/issues/129)) ([**@vweevers**](https://github.com/vweevers))
- Fix wrong release date for `3.0.0-rc1` ([`43a702b`](https://github.com/Level/level-js/commit/43a702b)) ([**@ralphtheninja**](https://github.com/ralphtheninja))

### Removed

- Remove `test/levelup-test.js` ([#134](https://github.com/Level/level-js/issues/134)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `levelup` from destroy tests ([#136](https://github.com/Level/level-js/issues/136)) ([**@ralphtheninja**](https://github.com/ralphtheninja))

## [3.0.0-rc1] - 2018-05-26

### Changed

- Upgrade `abstract-leveldown` from `0.12.0` to `5.0.0` ([**@vweevers**](https://github.com/vweevers))
- Upgrade `typedarray-to-buffer` from `1.0.0` to `3.1.5` ([**@vweevers**](https://github.com/vweevers))
- Upgrade `levelup` devDependency from `0.18.2` to `3.0.0` ([**@vweevers**](https://github.com/vweevers))
- Upgrade `browserify` devDependency from `4.1.2` to `16.2.2` ([**@vweevers**](https://github.com/vweevers))
- Switch license from BSD to MIT ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Replace `IDBWrapper` with straight IndexedDB code ([**@vweevers**](https://github.com/vweevers))
- Change default database prefix from `IDBWrapper-` to `level-js-` ([**@vweevers**](https://github.com/vweevers))
- Implement abstract `#_serializeKey` with support of all IndexedDB Second Edition types including binary keys (as Buffers) ([**@vweevers**](https://github.com/vweevers))
- Implement abstract `#_serializeValue` with support of all types of the structured clone algorithm except for `null` and `undefined` ([**@vweevers**](https://github.com/vweevers))
- Use `immediate` module for consistent microtask behavior ([**@vweevers**](https://github.com/vweevers))
- Replace `Buffer()` with `Buffer.from()` ([**@vweevers**](https://github.com/vweevers))
- Rename `Iterator#iterator` to `#transaction` ([**@vweevers**](https://github.com/vweevers))
- Replace `beefy` with `airtap --local` for local testing ([**@vweevers**](https://github.com/vweevers))
- Homogenize README title, description and headers ([**@vweevers**](https://github.com/vweevers))
- Make real `tape` tests out of `test-levelup.js` ([**@vweevers**](https://github.com/vweevers))
- Restructure custom tests to follow abstract test suite format ([**@vweevers**](https://github.com/vweevers))

### Added

- Add continuous browser tests with `airtap` and Sauce Labs ([**@vweevers**](https://github.com/vweevers))
- Add `prefix` and `version` options to constructor ([**@vweevers**](https://github.com/vweevers))
- Detect binary key support and fallback to `String(buffer)` ([**@vweevers**](https://github.com/vweevers))
- Detect array key support and fallback to `String(array)` ([**@vweevers**](https://github.com/vweevers))
- Test all value types of the structured clone algorithm ([**@vweevers**](https://github.com/vweevers))
- Catch `DataCloneError` if the environment does not support serializing the type of a key or value ([**@vweevers**](https://github.com/vweevers))
- Include Promise polyfill for `levelup` integration tests ([**@vweevers**](https://github.com/vweevers))
- Test that `Iterator` stringifies `Buffer.from()` argument ([**@vweevers**](https://github.com/vweevers))
- Add README badges, new goals and a code example with `levelup` ([**@vweevers**](https://github.com/vweevers))
- Add npm files to `.gitignore` ([**@vweevers**](https://github.com/vweevers))

### Fixed

- Start `Iterator` cursor immediately and fill an in-memory cache to fulfill `abstract-leveldown` snapshot guarantees ([**@vweevers**](https://github.com/vweevers))
- Stop advancing `Iterator` cursor when `options.limit` is reached ([**@vweevers**](https://github.com/vweevers))
- Rename public `#iterator` to private `#_iterator` ([**@vweevers**](https://github.com/vweevers))
- Fix `#_iterator({ limit: 0 })` to yield 0 entries ([**@vweevers**](https://github.com/vweevers))
- Handle transaction errors in `Iterator` ([**@vweevers**](https://github.com/vweevers))
- Fix constructor to call super ([**@vweevers**](https://github.com/vweevers))
- Make one request at a time in a batch transaction, saving CPU time ([**@vweevers**](https://github.com/vweevers))
- Properly close and destroy db's in custom tests ([**@vweevers**](https://github.com/vweevers))
- Update README links ([**@vweevers**](https://github.com/vweevers))

### Removed

- Remove support of `ArrayBuffer` values in favor of `Buffer` ([**@vweevers**](https://github.com/vweevers))
- Remove now unneeded `raw` option from `#_get()` and `#_iterator()` ([**@vweevers**](https://github.com/vweevers))
- Run tests without `IndexedDBShim` ([**@vweevers**](https://github.com/vweevers))
- Remove `Buffer` to `Uint8Array` conversion in `#_put()` and `#_batch()` ([**@vweevers**](https://github.com/vweevers))
- Remove obsolete `#_approximateSize` ([**@vweevers**](https://github.com/vweevers))
- Remove obsolete `#_isBuffer` ([**@vweevers**](https://github.com/vweevers))
- Remove obsolete `testBuffer` from abstract tests ([**@vweevers**](https://github.com/vweevers))
- Remove obsolete writestream test from `test-levelup.js` ([**@vweevers**](https://github.com/vweevers))
- Rely on `abstract-leveldown` defaults in `Iterator` constructor ([**@vweevers**](https://github.com/vweevers))
- Rely on `abstract-leveldown` callback defaults ([**@vweevers**](https://github.com/vweevers))
- Remove testling from `package.json` ([**@vweevers**](https://github.com/vweevers))
- Remove `level.js` logo ([**@vweevers**](https://github.com/vweevers))

## [2.2.4] - 2016-05-09

### Changed

- Use `toArrayBuffer()` only when present ([**@substack**](https://github.com/substack))

## [2.2.3] - 2015-12-10

### Changed

- Update `ltgt` to `^2.1.2` ([**@ryanramage**](https://github.com/ryanramage))

## [2.2.2] - 2015-09-12

_This release introduced `this._keyRangeError`._

### Added

- Add [**@nolanlawson**](https://github.com/nolanlawson) to collaborators ([**@maxogden**](https://github.com/maxogden))

### Fixed

- Fix iterator when start > end ([**@nolanlawson**](https://github.com/nolanlawson))

## [2.2.1] - 2015-07-05

### Changed

- Update collaborators ([**@maxogden**](https://github.com/maxogden))
- Roll back `abstract-leveldown` to `~0.12.0` ([**@maxogden**](https://github.com/maxogden))

## [2.2.0] - 2015-07-03

### Added

- Add `Collaborators` section to README ([**@maxogden**](https://github.com/maxogden))

### Changed

- Update syntax highlighting in README ([**@yoshuawuyts**](https://github.com/yoshuawuyts))
- Update `idb-wrapper` to `^1.5.0` ([**@JamesKyburz**](https://github.com/JamesKyburz))
- Update `abstract-leveldown` to `^2.4.0` ([**@maxogden**](https://github.com/maxogden))
- Update `tape` to `^4.0.0` ([**@maxogden**](https://github.com/maxogden))
- Move `tape` to devDependencies ([**@maxogden**](https://github.com/maxogden))
- Change license from BSD to BSD-2-Clause ([**@maxogden**](https://github.com/maxogden))

### Removed

- Remove Testling badge ([**@maxogden**](https://github.com/maxogden))

## [2.1.6] - 2014-06-15

### Fixed

- Avoid using keyword in `cursor.continue()` ([**@nolanlawson**](https://github.com/nolanlawson))

## [2.1.5] - 2014-05-29

### Changed

- Use `ltgt` module to handle ranges ([**@dominictarr**](https://github.com/dominictarr))

## [2.1.4] - 2014-05-13

### Changed

- Update `browserify` to `^4.1.2` ([**@maxogden**](https://github.com/maxogden))
- Move `browserify` to devDependencies ([**@maxogden**](https://github.com/maxogden))

## [2.1.3] - 2014-04-09

### Added

- Use `typedarray-to-buffer` to avoid copying to Buffer ([**@mafintosh**](https://github.com/mafintosh))

## [2.1.2] - 2014-04-05

### Added

- Add link to [**@brycebaril**](https://github.com/brycebaril)'s presentation to README ([**@maxogden**](https://github.com/maxogden))

### Changed

- Update browser configuration for Testling ([**@maxogden**](https://github.com/maxogden))

## [2.1.1] - 2014-03-12

_This was not published to npm. There's also a gap between `2.1.1` and `2.0.0` that is inconsistent. The `options.raw` property was introduced in this release._

### Changed

- Update browser configuration for Testling ([**@maxogden**](https://github.com/maxogden))
- Update `abstract-leveldown` to `~0.12.0` ([**@maxogden**](https://github.com/maxogden))
- Update `levelup` to `~0.18.2` ([**@maxogden**](https://github.com/maxogden))
- Make sure to store `Uint8Array` ([**@maxogden**](https://github.com/maxogden))
- Test storing native JS types with raw = true ([**@maxogden**](https://github.com/maxogden))

## [2.0.0] - 2014-03-09

_For some reason both `tape` and `browserify` were moved from devDependencies to dependencies. This release only had one commit._

### Changed

- Update `browserify` to `~3.32.0` ([**@maxogden**](https://github.com/maxogden))
- Update `tape` to `~2.10.2` ([**@maxogden**](https://github.com/maxogden))
- Change default encoding of values to strings to more closely match `leveldown` ([**@maxogden**](https://github.com/maxogden))

### Fixed

- Add missing `xtend` dependency ([**@maxogden**](https://github.com/maxogden))

## [1.2.0] - 2014-03-09

### Added

- Add `IndexedDBShim` to tests ([**@maxogden**](https://github.com/maxogden))
- Add `Level.destroy()` ([**@qs44**](https://github.com/qs44))
- Add prefix to pass `PouchDB` tests ([**@qs44**](https://github.com/qs44))
- Test `Level.destroy()` ([**@calvinmetcalf**](https://github.com/calvinmetcalf))

### Changed

- Update browser configuration for Testling ([**@maxogden**](https://github.com/maxogden))
- Pass through open options to idbwrapper ([**@maxogden**](https://github.com/maxogden))

### Fixed

- Don't use `indexedDB.webkitGetDatabasesNames()` in tests ([**@maxogden**](https://github.com/maxogden))

## [1.1.2] - 2014-02-02

### Removed

- Remove global leaks ([**@mcollina**](https://github.com/mcollina))

## [1.1.1] - 2014-02-02

### Changed

- Modify a copy of the batch array, not the original ([**@nrw**](https://github.com/nrw))

### Fixed

- Fix broken `package.json` ([**@maxogden**](https://github.com/maxogden))
- Fix testling path ([**@maxogden**](https://github.com/maxogden))

## [1.1.0] - 2014-01-30

_In this time period `bops` shows up and gets removed. Also, `._isBuffer()` uses `Buffer.isBuffer()` in favor of `is-buffer` module._

### Added

- Add Testling ([**@maxogden**](https://github.com/maxogden))
- Add npm badge ([**@maxogden**](https://github.com/maxogden))
- Test ranges ([**@rvagg**](https://github.com/rvagg), [**@maxogden**](https://github.com/maxogden))

### Changed

- Update README ([**@maxogden**](https://github.com/maxogden))
- Update `abstract-leveldown` to `~0.11.0` ([**@rvagg**](https://github.com/rvagg), [**@maxogden**](https://github.com/maxogden))
- Update to work with `abstract-leveldown@0.11.2` ([**@shama**](https://github.com/shama), [**@maxogden**](https://github.com/maxogden))
- Update iterator to pass all range tests ([**@shama**](https://github.com/shama), [**@maxogden**](https://github.com/maxogden))

### Fixed

- Fix incorrect version of `abstract-leveldown` ([**@maxogden**](https://github.com/maxogden))
- Pass error to callback in `approximateSize()` ([**@mcollina**](https://github.com/mcollina))

### Removed

- Remove unnecessary factor in tests ([**@rvagg**](https://github.com/rvagg), [**@maxogden**](https://github.com/maxogden))

## [1.0.8] - 2013-08-12

### Changed

- Move `levelup` to devDependencies ([**@juliangruber**](https://github.com/juliangruber))

### Removed

- Remove fn#bind from iterator ([**@juliangruber**](https://github.com/juliangruber))

## [1.0.7] - 2013-07-02

### Changed

- Implement full batch support ([**@mcollina**](https://github.com/mcollina))

### Fixed

- Fix git url to `abstract-leveldown` ([**@maxogden**](https://github.com/maxogden))

## [1.0.6] - 2013-05-31

### Changed

- Update `idb-wrapper` to `1.2.0` ([**@maxogden**](https://github.com/maxogden))
- Switch `abstract-leveldown#master` ([**@maxogden**](https://github.com/maxogden))
- Disable batch and chainable batch tests ([**@maxogden**](https://github.com/maxogden))

## [1.0.5] - 2013-05-30

### Changed

- Use upstream `idb-wrapper` ([**@maxogden**](https://github.com/maxogden))

## [1.0.4] - 2013-05-30

### Added

- Test batch and chainable batch ([**@rvagg**](https://github.com/rvagg))

### Changed

- Update `abstract-leveldown` to `~0.7.1` ([**@rvagg**](https://github.com/rvagg))
- Update `levelup` to `~0.9.0` ([**@brycebaril**](https://github.com/brycebaril))

## [1.0.3] - 2013-05-14

### Changed

- Use `is-buffer` ([**@juliangruber**](https://github.com/juliangruber))

## [1.0.2] - 2013-05-04

### Fixed

- Don't convert `ArrayBuffer` and typed arrays to strings ([**@maxogden**](https://github.com/maxogden))

## [1.0.1] - 2013-05-03

### Added

- Add optional options argument to `.open()` ([**@rvagg**](https://github.com/rvagg))
- Add `test-levelup.js` ([**@maxogden**](https://github.com/maxogden))

### Changed

- Update README ([**@maxogden**](https://github.com/maxogden))
- Use `npm test` instead of `npm start` ([**@shama**](https://github.com/shama))
- Properly delete test dbs ([**@maxogden**](https://github.com/maxogden))
- Inherit from `abstract-leveldown` ([**@rvagg**](https://github.com/rvagg))

## [1.0.0] - 2013-05-03

:seedling: Initial release.

[6.1.0]: https://github.com/Level/level-js/releases/tag/v6.1.0

[6.0.0]: https://github.com/Level/level-js/releases/tag/v6.0.0

[5.0.2]: https://github.com/Level/level-js/releases/tag/v5.0.2

[5.0.1]: https://github.com/Level/level-js/releases/tag/v5.0.1

[5.0.0]: https://github.com/Level/level-js/releases/tag/v5.0.0

[4.0.1]: https://github.com/Level/level-js/releases/tag/v4.0.1

[4.0.0]: https://github.com/Level/level-js/releases/tag/v4.0.0

[3.0.0]: https://github.com/Level/level-js/releases/tag/v3.0.0

[3.0.0-rc1]: https://github.com/Level/level-js/releases/tag/v3.0.0-rc1

[2.2.4]: https://github.com/Level/level-js/releases/tag/v2.2.4

[2.2.3]: https://github.com/Level/level-js/releases/tag/v2.2.3

[2.2.2]: https://github.com/Level/level-js/releases/tag/v2.2.2

[2.2.1]: https://github.com/Level/level-js/releases/tag/v2.2.1

[2.2.0]: https://github.com/Level/level-js/releases/tag/v2.2.0

[2.1.6]: https://github.com/Level/level-js/releases/tag/v2.1.6

[2.1.5]: https://github.com/Level/level-js/releases/tag/v2.1.5

[2.1.4]: https://github.com/Level/level-js/releases/tag/v2.1.4

[2.1.3]: https://github.com/Level/level-js/releases/tag/v2.1.3

[2.1.2]: https://github.com/Level/level-js/releases/tag/v2.1.2

[2.1.1]: https://github.com/Level/level-js/releases/tag/v2.1.1

[2.0.0]: https://github.com/Level/level-js/releases/tag/v2.0.0

[1.2.0]: https://github.com/Level/level-js/releases/tag/v1.2.0

[1.1.2]: https://github.com/Level/level-js/releases/tag/v1.1.2

[1.1.1]: https://github.com/Level/level-js/releases/tag/v1.1.1

[1.1.0]: https://github.com/Level/level-js/releases/tag/v1.1.0

[1.0.8]: https://github.com/Level/level-js/releases/tag/v1.0.8

[1.0.7]: https://github.com/Level/level-js/releases/tag/v1.0.7

[1.0.6]: https://github.com/Level/level-js/releases/tag/v1.0.6

[1.0.5]: https://github.com/Level/level-js/releases/tag/v1.0.5

[1.0.4]: https://github.com/Level/level-js/releases/tag/v1.0.4

[1.0.3]: https://github.com/Level/level-js/releases/tag/v1.0.3

[1.0.2]: https://github.com/Level/level-js/releases/tag/v1.0.2

[1.0.1]: https://github.com/Level/level-js/releases/tag/v1.0.1

[1.0.0]: https://github.com/Level/level-js/releases/tag/v1.0.0


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright © 2012 Max Ogden and the contributors to level-js.

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.


================================================
FILE: README.md
================================================
# level-js

**Superseded by [`browser-level`](https://github.com/Level/browser-level). Please see [Frequently Asked Questions](https://github.com/Level/community#faq).**

## Background

Here are the goals of `level-js`:

- Store large amounts of data in modern browsers
- Pass the full [`abstract-leveldown`][abstract-leveldown] test suite
- Support string and [`Buffer`][buffer] keys and values
- Be as fast as possible
- ~~Sync with [multilevel](https://github.com/juliangruber/multilevel) over ASCII or binary transports.~~

Being `abstract-leveldown` compliant means you can use many of the [Level modules][awesome] on top of this library.

## Example

**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md).

```js
const levelup = require('levelup')
const leveljs = require('level-js')
const db = levelup(leveljs('bigdata'))

db.put('hello', Buffer.from('world'), function (err) {
  if (err) throw err

  db.get('hello', function (err, value) {
    if (err) throw err

    console.log(value.toString()) // 'world'
  })
})
```

With `async/await`:

```js
const levelup = require('levelup')
const leveljs = require('level-js')
const db = levelup(leveljs('bigdata'))

await db.put('hello', Buffer.from('world'))
const value = await db.get('hello')
```

## Type Support

Keys and values can be a string or [`Buffer`][buffer]. Any other type will be irreversibly stringified. The only exceptions are `null` and `undefined`. Keys and values of that type are rejected.

In order to sort string and Buffer keys the same way, for compatibility with `leveldown` and the larger ecosystem, `level-js` internally converts keys and values to binary before passing them to IndexedDB.

If you desire non-destructive encoding (e.g. to store and retrieve numbers as-is), wrap `level-js` with [`encoding-down`][encoding-down]. Alternatively install [`level`][level] which conveniently bundles [`levelup`][levelup], `level-js` and `encoding-down`. Such an approach is also recommended if you want to achieve universal (isomorphic) behavior. For example, you could have [`leveldown`][leveldown] in a backend and `level-js` in the frontend. The `level` package does exactly that.

When getting or iterating keys and values, regardless of the type with which they were stored, keys and values will return as a Buffer unless the `asBuffer`, `keyAsBuffer` or `valueAsBuffer` options are set, in which case strings are returned. Setting these options is not needed when `level-js` is wrapped with `encoding-down`, which determines the optimal return type by the chosen encoding.

```js
db.get('key', { asBuffer: false })
db.iterator({ keyAsBuffer: false, valueAsBuffer: false })
```

## Install

With [npm](https://npmjs.org) do:

```bash
npm install level-js
```

Not to be confused with [leveljs](https://www.npmjs.com/package/leveljs).

This library is best used with [browserify](http://browserify.org).

## API

### `db = leveljs(location[, options])`

Returns a new `leveljs` instance. `location` is the string name of the [`IDBDatabase`](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase) to be opened, as well as the object store within that database. The database name will be prefixed with `options.prefix`.

#### `options`

The optional `options` argument may contain:

- `prefix` _(string, default: `'level-js-'`)_: Prefix for `IDBDatabase` name.
- `version` _(string | number, default: `1`)_: The version to open the database with.

See [`IDBFactory#open`](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory/open) for more details.

## Big Thanks

Cross-browser Testing Platform and Open Source ♥ Provided by [Sauce Labs](https://saucelabs.com).

[![Sauce Labs logo](./sauce-labs.svg)](https://saucelabs.com)

## Contributing

[`Level/level-js`](https://github.com/Level/level-js) is an **OPEN Open Source Project**. This means that:

> Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.

See the [Contribution Guide](https://github.com/Level/community/blob/master/CONTRIBUTING.md) for more details.

## Donate

Support us with a monthly donation on [Open Collective](https://opencollective.com/level) and help us continue our work.

## License

[MIT](LICENSE)

[indexeddb]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

[buffer]: https://nodejs.org/api/buffer.html

[awesome]: https://github.com/Level/awesome

[abstract-leveldown]: https://github.com/Level/abstract-leveldown

[levelup]: https://github.com/Level/levelup

[leveldown]: https://github.com/Level/leveldown

[level]: https://github.com/Level/level

[encoding-down]: https://github.com/Level/encoding-down


================================================
FILE: UPGRADING.md
================================================
# Upgrade Guide

This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the [changelog][changelog].

## 6.0.0

Legacy range options have been removed ([Level/community#86](https://github.com/Level/community/issues/86)). If you previously did:

```js
db.iterator({ start: 'a', end: 'z' })
```

An error would now be thrown and you must instead do:

```js
db.iterator({ gte: 'a', lte: 'z' })
```

This release also drops support of legacy runtime environments ([Level/community#98](https://github.com/Level/community/issues/98)):

- Internet Explorer 11
- Safari 9-11.

Lastly, and less likely to be a breaking change, the [`immediate`](https://github.com/calvinmetcalf/immediate) browser shim for `process.nextTick()` has been replaced with the smaller [`queue-microtask`](https://github.com/feross/queue-microtask).

## 5.0.0

Support of keys & values other than strings and Buffers has been dropped. Internally `level-js` now stores keys & values as binary which solves a number of compatibility issues ([Level/memdown#186](https://github.com/Level/memdown/issues/186)). If you pass in a key or value that isn't a string or Buffer, it will be irreversibly stringified.

Existing IndexedDB databases created with `level-js@4` can be read only if they used binary keys and string or binary values. Other types will come out stringified, and string keys will sort incorrectly. Use the included `upgrade()` utility to convert stored data to binary (in so far the environment supports it):

```js
var leveljs = require('level-js')
var db = leveljs('my-db')

db.open(function (err) {
  if (err) throw err

  db.upgrade(function (err) {
    if (err) throw err
  })
})
```

Or with (the upcoming release of) `level`:

```js
var level = require('level')
var reachdown = require('reachdown')
var db = level('my-db')

db.open(function (err) {
  if (err) throw err

  reachdown(db, 'level-js').upgrade(function (err) {
    if (err) throw err
  })
})
```

## 4.0.0

This is an upgrade to `abstract-leveldown@6` which solves long-standing issues around serialization and type support.

### Range options are now serialized

Previously, range options like `lt` were passed through as-is by `abstract-leveldown`, unlike keys. For `level-js` it means that Buffers and arrays, if not supported by the environment (e.g. Microsoft Edge), will be stringified.

### The rules for range options have been relaxed

Because `null`, `undefined`, zero-length strings and zero-length buffers are significant types in encodings like `bytewise` and `charwise`, they became valid as range options in `abstract-leveldown`. This means `db.iterator({ gt: undefined })` is not the same as `db.iterator({})`.

In the case of `level-js`, when used by itself, the aforementioned change means that `db.iterator({ gt: undefined })` will throw an error as `undefined` is not a valid IndexedDB key type. On the other hand `db.iterator({ gt: '' })` is valid and thus now supported. For details on sort order (which is richer than in `leveldown`) please see [the readme](README.md).

### Nullish values are rejected

In addition to rejecting `null` and `undefined` as _keys_, `abstract-leveldown` now also rejects these types as _values_, due to preexisting significance in streams and iterators.

### Zero-length array keys are rejected

Though this was already the case (both in IndexedDB and `abstract-leveldown`), `abstract-leveldown` has replaced the behavior with an explicit `Array.isArray()` check and a new error message.

### Boolean and `NaN` keys (as well as range options) are rejected

Previously, for compliance with `abstract-leveldown` tests that have since been removed, they were stringified. As of `level-js@4` they are rejected (by IndexedDB).

### Added mobile browser support

iPhone and Android `latest` are now officially supported. At the time of writing that's iPhone 12.0 and Android 7.1 (note that's Chrome for Android, not the old stock browser). Older versions (iPhone 10+ and Android 6+) did pass our tests but are not included in the test matrix going forward. Feel free to open an issue if you need/want these versions to be supported.

### The value of `iterator#db` has changed

Though this was undocumented and only for internal use, the `db` property on an iterator pointed to an `IDBDatabase`. To comply with `abstract-leveldown` the `db` property now points to the `level-js` instance that created that iterator.

## 3.0.0

This release brings `level-js` up to par with latest [`levelup`][levelup] (v2), [`abstract-leveldown`][abstract-leveldown] (v5) and IndexedDB Second Edition. It targets modern `browserify` preferring [`Buffer`][buffer] over `ArrayBuffer`. Lastly, [`IDBWrapper`][idbwrapper] has been replaced with straight IndexedDB code.

### Usage with [`levelup`][levelup]

Usage has changed to:

```js
const levelup = require('levelup')
const leveljs = require('leveljs')

const db = levelup(leveljs('mydb'))
```

From the old:

```js
const db = levelup('mydb', { db: leveljs })
```

Friendly reminder: encodings have moved from [`levelup`][levelup] to [`encoding-down`][encoding-down]. To get identical functionality to `levelup < 2` please use the [`level-browserify`][level-browserify] convenience package or wrap `level-js` with `encoding-down`:

```js
const encode = require('encoding-down')
const db = levelup(encode(leveljs('mydb')))
```

### New database prefix

The default prefix of the [`IDBDatabase`][idbdatabase] name has changed from `IDBWrapper-` to `level-js-`. To access databases created using `level-js < 3`, pass a custom prefix to the `level-js` constructor:

```js
const db = levelup(leveljs('mydb', { prefix: 'IDBWrapper-' }))
```

### Browser support

As a result of removing [`IDBWrapper`][idbwrapper], only modern browsers with a non-prefixed `window.indexedDB` are supported in this release. The current test matrix of `level-js` includes the latest versions of Chrome, Firefox, Safari, Edge and IE.

:fire: Internet Explorer 10 is no longer supported.

### Type support

All value types of the [structured clone algorithm][structured-clone-algorithm] and all key types of IndexedDB Second Edition are now supported. This means you can store almost any JavaScript type without the need for [`encoding-down`][encoding-down]. In addition, you can use [`Buffer`][buffer] for both keys and values. For details and caveats please see the [readme][readme].

### No backpressure

In `level-js`, iterators are powered by IndexedDB cursors. To fulfill [`abstract-leveldown`][abstract-leveldown] snapshot guarantees (reads not being affected by simultaneous writes) cursors are started immediately and continuously read from, filling an in-memory cache.

Though `level-js` now passes the full [`abstract-leveldown`][abstract-leveldown] test suite, fulfilling the snapshot guarantee means a loss of backpressure. Memory consumption might increase if an iterator is not consumed fast enough. A future release will have an option to favor backpressure over snapshot guarantees.

### Removed `raw` option

Because `level-js` no longer stringifies values, the `raw` option (which bypassed conversion) became unnecessary and has been removed. If you use [`level-browserify`][level-browserify] or [`levelup`][levelup] with [`encoding-down`][encoding-down], you can store and retrieve raw values (as returned by IndexedDB) using the `id` encoding. Please refer to the [readme][readme] for an example.

### New `destroy()` function signature

Previously, a `level-js` instance could be passed to `destroy()`:

```js
leveljs.destroy(db, callback)
```

This was useful to destroy a database that used a custom prefix. The new signature is `destroy(location[, prefix], callback)`.

### Strict `.batch(array)`

The upgrade to [`abstract-leveldown`][abstract-leveldown] comes with a [breaking change](https://github.com/Level/abstract-leveldown/commit/a2621ad70571f6ade9d2be42632ece042e068805) for the array version of `.batch()`. This change ensures all elements in the batch array are objects. If you previously passed arrays to `.batch()` that contained `undefined` or `null`, they would be silently ignored. Now this will produce an error.

[readme]: README.md

[changelog]: CHANGELOG.md

[buffer]: https://nodejs.org/api/buffer.html

[idbwrapper]: https://www.npmjs.com/package/idb-wrapper

[abstract-leveldown]: https://github.com/Level/abstract-leveldown

[levelup]: https://github.com/Level/levelup

[encoding-down]: https://github.com/Level/encoding-down

[level-browserify]: https://github.com/Level/level-browserify

[idbdatabase]: https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase

[structured-clone-algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm


================================================
FILE: index.js
================================================
/* global indexedDB */

'use strict'

module.exports = Level

const AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
const inherits = require('inherits')
const parallel = require('run-parallel-limit')
const Iterator = require('./iterator')
const serialize = require('./util/serialize')
const deserialize = require('./util/deserialize')
const support = require('./util/support')
const clear = require('./util/clear')
const createKeyRange = require('./util/key-range')

const DEFAULT_PREFIX = 'level-js-'

function Level (location, opts) {
  if (!(this instanceof Level)) return new Level(location, opts)

  AbstractLevelDOWN.call(this, {
    bufferKeys: support.bufferKeys(indexedDB),
    snapshots: true,
    permanence: true,
    clear: true,
    getMany: true
  })

  opts = opts || {}

  if (typeof location !== 'string') {
    throw new Error('constructor requires a location string argument')
  }

  this.location = location
  this.prefix = opts.prefix == null ? DEFAULT_PREFIX : opts.prefix
  this.version = parseInt(opts.version || 1, 10)
}

inherits(Level, AbstractLevelDOWN)

Level.prototype.type = 'level-js'

Level.prototype._open = function (options, callback) {
  const req = indexedDB.open(this.prefix + this.location, this.version)

  req.onerror = function () {
    callback(req.error || new Error('unknown error'))
  }

  req.onsuccess = () => {
    this.db = req.result
    callback()
  }

  req.onupgradeneeded = (ev) => {
    const db = ev.target.result

    if (!db.objectStoreNames.contains(this.location)) {
      db.createObjectStore(this.location)
    }
  }
}

Level.prototype.store = function (mode) {
  const transaction = this.db.transaction([this.location], mode)
  return transaction.objectStore(this.location)
}

Level.prototype.await = function (request, callback) {
  const transaction = request.transaction

  // Take advantage of the fact that a non-canceled request error aborts
  // the transaction. I.e. no need to listen for "request.onerror".
  transaction.onabort = function () {
    callback(transaction.error || new Error('aborted by user'))
  }

  transaction.oncomplete = function () {
    callback(null, request.result)
  }
}

Level.prototype._get = function (key, options, callback) {
  const store = this.store('readonly')
  let req

  try {
    req = store.get(key)
  } catch (err) {
    return this._nextTick(callback, err)
  }

  this.await(req, function (err, value) {
    if (err) return callback(err)

    if (value === undefined) {
      // 'NotFound' error, consistent with LevelDOWN API
      return callback(new Error('NotFound'))
    }

    callback(null, deserialize(value, options.asBuffer))
  })
}

Level.prototype._getMany = function (keys, options, callback) {
  const asBuffer = options.asBuffer
  const store = this.store('readonly')
  const tasks = keys.map((key) => (next) => {
    let request

    try {
      request = store.get(key)
    } catch (err) {
      return next(err)
    }

    request.onsuccess = () => {
      const value = request.result
      next(null, value === undefined ? value : deserialize(value, asBuffer))
    }

    request.onerror = (ev) => {
      ev.stopPropagation()
      next(request.error)
    }
  })

  parallel(tasks, 16, callback)
}

Level.prototype._del = function (key, options, callback) {
  const store = this.store('readwrite')
  let req

  try {
    req = store.delete(key)
  } catch (err) {
    return this._nextTick(callback, err)
  }

  this.await(req, callback)
}

Level.prototype._put = function (key, value, options, callback) {
  const store = this.store('readwrite')
  let req

  try {
    // Will throw a DataError or DataCloneError if the environment
    // does not support serializing the key or value respectively.
    req = store.put(value, key)
  } catch (err) {
    return this._nextTick(callback, err)
  }

  this.await(req, callback)
}

Level.prototype._serializeKey = function (key) {
  return serialize(key, this.supports.bufferKeys)
}

Level.prototype._serializeValue = function (value) {
  return serialize(value, true)
}

Level.prototype._iterator = function (options) {
  return new Iterator(this, this.location, options)
}

Level.prototype._batch = function (operations, options, callback) {
  if (operations.length === 0) return this._nextTick(callback)

  const store = this.store('readwrite')
  const transaction = store.transaction
  let index = 0
  let error

  transaction.onabort = function () {
    callback(error || transaction.error || new Error('aborted by user'))
  }

  transaction.oncomplete = function () {
    callback()
  }

  // Wait for a request to complete before making the next, saving CPU.
  function loop () {
    const op = operations[index++]
    const key = op.key

    let req

    try {
      req = op.type === 'del' ? store.delete(key) : store.put(op.value, key)
    } catch (err) {
      error = err
      transaction.abort()
      return
    }

    if (index < operations.length) {
      req.onsuccess = loop
    }
  }

  loop()
}

Level.prototype._clear = function (options, callback) {
  let keyRange
  let req

  try {
    keyRange = createKeyRange(options)
  } catch (e) {
    // The lower key is greater than the upper key.
    // IndexedDB throws an error, but we'll just do nothing.
    return this._nextTick(callback)
  }

  if (options.limit >= 0) {
    // IDBObjectStore#delete(range) doesn't have such an option.
    // Fall back to cursor-based implementation.
    return clear(this, this.location, keyRange, options, callback)
  }

  try {
    const store = this.store('readwrite')
    req = keyRange ? store.delete(keyRange) : store.clear()
  } catch (err) {
    return this._nextTick(callback, err)
  }

  this.await(req, callback)
}

Level.prototype._close = function (callback) {
  this.db.close()
  this._nextTick(callback)
}

// NOTE: remove in a next major release
Level.prototype.upgrade = function (callback) {
  if (this.status !== 'open') {
    return this._nextTick(callback, new Error('cannot upgrade() before open()'))
  }

  const it = this.iterator()
  const batchOptions = {}
  const self = this

  it._deserializeKey = it._deserializeValue = identity
  next()

  function next (err) {
    if (err) return finish(err)
    it.next(each)
  }

  function each (err, key, value) {
    if (err || key === undefined) {
      return finish(err)
    }

    const newKey = self._serializeKey(deserialize(key, true))
    const newValue = self._serializeValue(deserialize(value, true))

    // To bypass serialization on the old key, use _batch() instead of batch().
    // NOTE: if we disable snapshotting (#86) this could lead to a loop of
    // inserting and then iterating those same entries, because the new keys
    // possibly sort after the old keys.
    self._batch([
      { type: 'del', key: key },
      { type: 'put', key: newKey, value: newValue }
    ], batchOptions, next)
  }

  function finish (err) {
    it.end(function (err2) {
      callback(err || err2)
    })
  }

  function identity (data) {
    return data
  }
}

Level.destroy = function (location, prefix, callback) {
  if (typeof prefix === 'function') {
    callback = prefix
    prefix = DEFAULT_PREFIX
  }
  const request = indexedDB.deleteDatabase(prefix + location)
  request.onsuccess = function () {
    callback()
  }
  request.onerror = function (err) {
    callback(err)
  }
}


================================================
FILE: iterator.js
================================================
'use strict'

const inherits = require('inherits')
const AbstractIterator = require('abstract-leveldown').AbstractIterator
const createKeyRange = require('./util/key-range')
const deserialize = require('./util/deserialize')
const noop = function () {}

module.exports = Iterator

function Iterator (db, location, options) {
  AbstractIterator.call(this, db)

  this._limit = options.limit
  this._count = 0
  this._callback = null
  this._cache = []
  this._completed = false
  this._aborted = false
  this._error = null
  this._transaction = null

  this._keys = options.keys
  this._values = options.values
  this._keyAsBuffer = options.keyAsBuffer
  this._valueAsBuffer = options.valueAsBuffer

  if (this._limit === 0) {
    this._completed = true
    return
  }

  let keyRange

  try {
    keyRange = createKeyRange(options)
  } catch (e) {
    // The lower key is greater than the upper key.
    // IndexedDB throws an error, but we'll just return 0 results.
    this._completed = true
    return
  }

  this.createIterator(location, keyRange, options.reverse)
}

inherits(Iterator, AbstractIterator)

Iterator.prototype.createIterator = function (location, keyRange, reverse) {
  const transaction = this.db.db.transaction([location], 'readonly')
  const store = transaction.objectStore(location)
  const req = store.openCursor(keyRange, reverse ? 'prev' : 'next')

  req.onsuccess = (ev) => {
    const cursor = ev.target.result
    if (cursor) this.onItem(cursor)
  }

  this._transaction = transaction

  // If an error occurs (on the request), the transaction will abort.
  transaction.onabort = () => {
    this.onAbort(this._transaction.error || new Error('aborted by user'))
  }

  transaction.oncomplete = () => {
    this.onComplete()
  }
}

Iterator.prototype.onItem = function (cursor) {
  this._cache.push(cursor.key, cursor.value)

  if (this._limit <= 0 || ++this._count < this._limit) {
    cursor.continue()
  }

  this.maybeNext()
}

Iterator.prototype.onAbort = function (err) {
  this._aborted = true
  this._error = err
  this.maybeNext()
}

Iterator.prototype.onComplete = function () {
  this._completed = true
  this.maybeNext()
}

Iterator.prototype.maybeNext = function () {
  if (this._callback) {
    this._next(this._callback)
    this._callback = null
  }
}

Iterator.prototype._next = function (callback) {
  if (this._aborted) {
    // The error should be picked up by either next() or end().
    const err = this._error
    this._error = null
    this._nextTick(callback, err)
  } else if (this._cache.length > 0) {
    let key = this._cache.shift()
    let value = this._cache.shift()

    if (this._keys && key !== undefined) {
      key = this._deserializeKey(key, this._keyAsBuffer)
    } else {
      key = undefined
    }

    if (this._values && value !== undefined) {
      value = this._deserializeValue(value, this._valueAsBuffer)
    } else {
      value = undefined
    }

    this._nextTick(callback, null, key, value)
  } else if (this._completed) {
    this._nextTick(callback)
  } else {
    this._callback = callback
  }
}

// Exposed for the v4 to v5 upgrade utility
Iterator.prototype._deserializeKey = deserialize
Iterator.prototype._deserializeValue = deserialize

Iterator.prototype._end = function (callback) {
  if (this._aborted || this._completed) {
    return this._nextTick(callback, this._error)
  }

  // Don't advance the cursor anymore, and the transaction will complete
  // on its own in the next tick. This approach is much cleaner than calling
  // transaction.abort() with its unpredictable event order.
  this.onItem = noop
  this.onAbort = callback
  this.onComplete = callback
}


================================================
FILE: package.json
================================================
{
  "name": "level-js",
  "version": "6.1.0",
  "description": "An abstract-leveldown compliant store on top of IndexedDB",
  "author": "max ogden",
  "license": "MIT",
  "main": "index.js",
  "scripts": {
    "test": "standard && hallmark && airtap -p local --coverage test/index.js",
    "test-browsers": "standard && airtap --coverage test/index.js",
    "coverage": "nyc report -r lcovonly",
    "hallmark": "hallmark --fix",
    "dependency-check": "dependency-check --no-dev -i buffer .",
    "prepublishOnly": "npm run dependency-check"
  },
  "files": [
    "index.js",
    "iterator.js",
    "util",
    "CHANGELOG.md",
    "UPGRADING.md",
    "sauce-labs.svg"
  ],
  "dependencies": {
    "abstract-leveldown": "^7.2.0",
    "buffer": "^6.0.3",
    "inherits": "^2.0.3",
    "ltgt": "^2.1.2",
    "run-parallel-limit": "^1.1.0"
  },
  "devDependencies": {
    "airtap": "^4.0.1",
    "airtap-playwright": "^1.0.1",
    "airtap-sauce": "^1.1.0",
    "dependency-check": "^4.1.0",
    "hallmark": "^4.0.0",
    "level-concat-iterator": "^3.0.0",
    "nyc": "^15.0.0",
    "standard": "^16.0.3",
    "tape": "^5.0.0",
    "uuid": "^3.3.2"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/Level/level-js.git"
  },
  "homepage": "https://github.com/Level/level-js",
  "keywords": [
    "level",
    "leveldb",
    "indexeddb",
    "abstract-leveldown"
  ]
}


================================================
FILE: test/custom-test.js
================================================
'use strict'

const concat = require('level-concat-iterator')

module.exports = function (leveljs, test, testCommon) {
  test('setUp', testCommon.setUp)

  test('default prefix', function (t) {
    const db = testCommon.factory()

    t.ok(db.location, 'instance has location property')
    t.is(db.prefix, 'level-js-', 'instance has prefix property')

    db.open(function (err) {
      t.notOk(err, 'no open error')

      const idb = db.db
      const databaseName = idb.name
      const storeNames = idb.objectStoreNames

      t.is(databaseName, 'level-js-' + db.location, 'database name is prefixed')
      t.is(storeNames.length, 1, 'created 1 object store')
      t.is(storeNames.item(0), db.location, 'object store name equals location')

      db.close(t.end.bind(t))
    })
  })

  test('custom prefix', function (t) {
    const db = testCommon.factory({ prefix: 'custom-' })

    t.ok(db.location, 'instance has location property')
    t.is(db.prefix, 'custom-', 'instance has prefix property')

    db.open(function (err) {
      t.notOk(err, 'no open error')

      const idb = db.db
      const databaseName = idb.name
      const storeNames = idb.objectStoreNames

      t.is(databaseName, 'custom-' + db.location, 'database name is prefixed')
      t.is(storeNames.length, 1, 'created 1 object store')
      t.is(storeNames.item(0), db.location, 'object store name equals location')

      db.close(t.end.bind(t))
    })
  })

  test('empty prefix', function (t) {
    const db = testCommon.factory({ prefix: '' })

    t.ok(db.location, 'instance has location property')
    t.is(db.prefix, '', 'instance has prefix property')

    db.open(function (err) {
      t.notOk(err, 'no open error')

      const idb = db.db
      const databaseName = idb.name
      const storeNames = idb.objectStoreNames

      t.is(databaseName, db.location, 'database name is prefixed')
      t.is(storeNames.length, 1, 'created 1 object store')
      t.is(storeNames.item(0), db.location, 'object store name equals location')

      db.close(t.end.bind(t))
    })
  })

  test('put Buffer value, get Buffer value', function (t) {
    const level = testCommon.factory()
    level.open(function (err) {
      t.notOk(err, 'no error')
      level.put('key', Buffer.from('00ff', 'hex'), function (err) {
        t.notOk(err, 'no error')
        level.get('key', function (err, value) {
          t.notOk(err, 'no error')
          t.ok(Buffer.isBuffer(value), 'is buffer')
          t.same(value, Buffer.from('00ff', 'hex'))
          level.close(t.end.bind(t))
        })
      })
    })
  })

  test('put Buffer value, get string value', function (t) {
    const level = testCommon.factory()
    level.open(function (err) {
      t.notOk(err, 'no error')
      level.put('key', Buffer.from('abc'), function (err) {
        t.notOk(err, 'no error')
        level.get('key', { asBuffer: false }, function (err, value) {
          t.notOk(err, 'no error')
          t.is(value, 'abc')
          level.close(t.end.bind(t))
        })
      })
    })
  })

  test('put utf8 string, get utf8 string', function (t) {
    const level = testCommon.factory()
    level.open(function (err) {
      t.notOk(err, 'no error')
      level.put('💩', '💩', function (err) {
        t.notOk(err, 'no error')
        level.get('💩', { asBuffer: false }, function (err, value) {
          t.notOk(err, 'no error')
          t.is(value, '💩')
          level.close(t.end.bind(t))
        })
      })
    })
  })

  // This should be covered by abstract-leveldown tests, but that's
  // prevented by process.browser checks (Level/abstract-leveldown#121).
  // This test is adapted from memdown.
  test('buffer keys', function (t) {
    const db = testCommon.factory()

    if (!db.supports.bufferKeys) {
      t.fail('environment does not support buffer keys')
      return t.end()
    }

    db.open(function (err) {
      t.ifError(err, 'no open error')

      const one = Buffer.from('80', 'hex')
      const two = Buffer.from('c0', 'hex')

      t.ok(two.toString() === one.toString(), 'would be equal when not buffer-aware')
      t.ok(Buffer.compare(two, one) > 0, 'but greater when buffer-aware')

      db.put(one, 'one', function (err) {
        t.notOk(err, 'no error')

        db.get(one, { asBuffer: false }, function (err, value) {
          t.notOk(err, 'no error')
          t.equal(value, 'one', 'value one ok')

          db.put(two, 'two', function (err) {
            t.notOk(err, 'no error')

            db.get(one, { asBuffer: false }, function (err, value) {
              t.notOk(err, 'no error')
              t.equal(value, 'one', 'value one is the same')

              db.close(function (err) {
                t.ifError(err, 'no close error')
                t.end()
              })
            })
          })
        })
      })
    })
  })

  // This should be covered by abstract-leveldown tests, but that's
  // prevented by process.browser checks (Level/abstract-leveldown#121).
  test('iterator yields buffer keys', function (t) {
    const db = testCommon.factory()

    if (!db.supports.bufferKeys) {
      t.fail('environment does not support buffer keys')
      return t.end()
    }

    db.open(function (err) {
      t.ifError(err, 'no open error')

      db.batch([
        { type: 'put', key: Buffer.from([0]), value: '0' },
        { type: 'put', key: Buffer.from([1]), value: '1' }
      ], function (err) {
        t.ifError(err, 'no batch error')

        const it = db.iterator({ valueAsBuffer: false })
        concat(it, function (err, entries) {
          t.ifError(err, 'no iterator error')

          t.same(entries, [
            { key: Buffer.from([0]), value: '0' },
            { key: Buffer.from([1]), value: '1' }
          ], 'keys are Buffers')

          db.close(function (err) {
            t.ifError(err, 'no close error')
            t.end()
          })
        })
      })
    })
  })

  test('buffer range option', function (t) {
    const db = testCommon.factory()

    if (!db.supports.bufferKeys) {
      t.fail('environment does not support buffer keys')
      return t.end()
    }

    db.open(function (err) {
      t.ifError(err, 'no open error')

      const one = Buffer.from('80', 'hex')
      const two = Buffer.from('c0', 'hex')

      db.batch([
        { type: 'put', key: one, value: one },
        { type: 'put', key: two, value: two }
      ], function (err) {
        t.ifError(err, 'no batch error')

        concat(db.iterator({ gt: one }), function (err, entries) {
          t.ifError(err, 'no iterator error')
          t.same(entries, [{ key: two, value: two }])

          db.close(function (err) {
            t.ifError(err, 'no close error')
            t.end()
          })
        })
      })
    })
  })

  // Adapted from a memdown test.
  test('iterator stringifies buffer input', function (t) {
    t.plan(6)

    const db = testCommon.factory()

    db.open(function (err) {
      t.ifError(err, 'no open error')

      db.put(1, 2, function (err) {
        t.ifError(err, 'no put error')

        concat(db.iterator(), function (err, entries) {
          t.ifError(err, 'no iterator error')
          t.same(entries[0].key, Buffer.from('1'), 'key is stringified')
          t.same(entries[0].value, Buffer.from('2'), 'value is stringified')

          db.close(function (err) {
            t.ifError(err, 'no close error')
          })
        })
      })
    })
  })

  // NOTE: in chrome (at least) indexeddb gets buggy if you try and destroy a db,
  // then create it again, then try and destroy it again. these avoid doing that

  test('test .destroy', function (t) {
    const db = testCommon.factory()
    const location = db.location
    db.open(function (err) {
      t.notOk(err, 'no error')
      db.put('key', 'value', function (err) {
        t.notOk(err, 'no error')
        db.get('key', { asBuffer: false }, function (err, value) {
          t.notOk(err, 'no error')
          t.equal(value, 'value', 'should have value')
          db.close(function (err) {
            t.notOk(err, 'no error')
            leveljs.destroy(location, function (err) {
              t.notOk(err, 'no error')
              const db2 = leveljs(location)
              db2.open(function (err) {
                t.notOk(err, 'no error')
                db2.get('key', { asBuffer: false }, function (err, value) {
                  t.is(err.message, 'NotFound', 'key is not there')
                  db2.close(t.end.bind(t))
                })
              })
            })
          })
        })
      })
    })
  })

  test('test .destroy and custom prefix', function (t) {
    const prefix = 'custom-'
    const db = testCommon.factory({ prefix: prefix })
    const location = db.location

    db.open(function (err) {
      t.notOk(err, 'no error')
      db.put('key', 'value', function (err) {
        t.notOk(err, 'no error')
        db.get('key', { asBuffer: false }, function (err, value) {
          t.notOk(err, 'no error')
          t.equal(value, 'value', 'should have value')
          db.close(function (err) {
            t.notOk(err, 'no error')
            leveljs.destroy(location, prefix, function (err) {
              t.notOk(err, 'no error')
              const db2 = leveljs(location, { prefix: prefix })
              db2.open(function (err) {
                t.notOk(err, 'no error')
                db2.get('key', { asBuffer: false }, function (err, value) {
                  t.is(err.message, 'NotFound', 'key is not there')
                  db2.close(t.end.bind(t))
                })
              })
            })
          })
        })
      })
    })
  })

  // TODO: move to abstract-leveldown test suite (and add to iterator tests too)
  test('clear() with lower key greater than upper key', function (t) {
    const db = testCommon.factory()

    db.open(function (err) {
      t.ifError(err, 'no open error')

      db.put('a', 'a', function (err) {
        t.ifError(err, 'no put error')

        db.clear({ gt: 'b', lt: 'a' }, function (err) {
          t.ifError(err, 'no clear error')

          db.get('a', { asBuffer: false }, function (err, value) {
            t.ifError(err, 'no get error')
            t.is(value, 'a')

            db.close(t.end.bind(t))
          })
        })
      })
    })
  })

  test('teardown', testCommon.tearDown)
}


================================================
FILE: test/index.js
================================================
'use strict'

const test = require('tape')
const uuid = require('uuid/v4')
const suite = require('abstract-leveldown/test')
const leveljs = require('..')

// Test feature detection
require('./support-test')(leveljs, test)

const testCommon = suite.common({
  test: test,
  factory: function (opts) {
    return leveljs(uuid(), opts)
  },

  // Unsupported features
  createIfMissing: false,
  errorIfExists: false,
  seek: false,

  // Support of buffer keys depends on environment
  bufferKeys: leveljs(uuid()).supports.bufferKeys,

  // Opt-in to new tests
  clear: true,
  getMany: true
})

// Test abstract-leveldown compliance
suite(testCommon)

// Additional tests for this implementation
require('./custom-test')(leveljs, test, testCommon)
require('./upgrade-test')(leveljs, test, testCommon)


================================================
FILE: test/support-test.js
================================================
'use strict'

const support = require('../util/support')

const pos = function () { }
const neg = function () { throw new Error() }

module.exports = function (leveljs, test) {
  test('mock bufferKeys support', function (t) {
    t.ok(support.bufferKeys({ cmp: pos }))
    t.notOk(support.bufferKeys({ cmp: neg }))
    t.end()
  })
}


================================================
FILE: test/upgrade-test.js
================================================
'use strict'

const concat = require('level-concat-iterator')

module.exports = function (leveljs, test, testCommon) {
  test('upgrade', function (t) {
    const db = testCommon.factory()

    const input = [
      { key: -1, value: 'a' },
      { key: '0', value: ab('b') },
      { key: '1', value: 1 },
      { key: ab('2'), value: new Uint8Array(ab('2')) }
    ]

    const output = [
      { key: ab('-1'), value: new Uint8Array(ab('a')) },
      { key: ab('0'), value: new Uint8Array(ab('b')) },
      { key: ab('1'), value: new Uint8Array(ab('1')) },
      { key: ab('2'), value: new Uint8Array(ab('2')) }
    ]

    db.open(function (err) {
      t.ifError(err, 'no open error')

      // To bypass serialization, use _batch() instead of batch().
      db._batch(input.map(putOperation), {}, function (err) {
        t.ifError(err, 'no batch error')

        db.upgrade(function (err) {
          t.ifError(err, 'no upgrade error')

          concatRaw(function (err, entries) {
            t.ifError(err, 'no concat error')

            entries.forEach(function (entry) {
              t.ok(entry.key instanceof ArrayBuffer)
              t.ok(entry.value instanceof Uint8Array)
            })

            t.same(entries.map(bufferEntry), output.map(bufferEntry))
            t.end()
          })
        })
      })
    })

    function concatRaw (callback) {
      const it = db.iterator()
      it._deserializeKey = it._deserializeValue = identity
      concat(it, callback)
    }

    function identity (data) {
      return data
    }

    function ab (data) {
      return Buffer.from(data).buffer
    }

    function bufferEntry (entry) {
      return { key: Buffer.from(entry.key), value: Buffer.from(entry.value) }
    }

    function putOperation (entry) {
      return { type: 'put', key: entry.key, value: entry.value }
    }
  })
}


================================================
FILE: util/clear.js
================================================
'use strict'

module.exports = function clear (db, location, keyRange, options, callback) {
  if (options.limit === 0) return db._nextTick(callback)

  const transaction = db.db.transaction([location], 'readwrite')
  const store = transaction.objectStore(location)
  let count = 0

  transaction.oncomplete = function () {
    callback()
  }

  transaction.onabort = function () {
    callback(transaction.error || new Error('aborted by user'))
  }

  // A key cursor is faster (skips reading values) but not supported by IE
  const method = store.openKeyCursor ? 'openKeyCursor' : 'openCursor'
  const direction = options.reverse ? 'prev' : 'next'

  store[method](keyRange, direction).onsuccess = function (ev) {
    const cursor = ev.target.result

    if (cursor) {
      // Wait for a request to complete before continuing, saving CPU.
      store.delete(cursor.key).onsuccess = function () {
        if (options.limit <= 0 || ++count < options.limit) {
          cursor.continue()
        }
      }
    }
  }
}


================================================
FILE: util/deserialize.js
================================================
'use strict'

const Buffer = require('buffer').Buffer
const ta2str = (function () {
  if (global.TextDecoder) {
    const decoder = new TextDecoder('utf-8')
    return decoder.decode.bind(decoder)
  } else {
    return function ta2str (ta) {
      return ta2buf(ta).toString()
    }
  }
})()

const ab2str = (function () {
  if (global.TextDecoder) {
    const decoder = new TextDecoder('utf-8')
    return decoder.decode.bind(decoder)
  } else {
    return function ab2str (ab) {
      return Buffer.from(ab).toString()
    }
  }
})()

function ta2buf (ta) {
  const buf = Buffer.from(ta.buffer)

  if (ta.byteLength === ta.buffer.byteLength) {
    return buf
  } else {
    return buf.slice(ta.byteOffset, ta.byteOffset + ta.byteLength)
  }
}

module.exports = function (data, asBuffer) {
  if (data instanceof Uint8Array) {
    return asBuffer ? ta2buf(data) : ta2str(data)
  } else if (data instanceof ArrayBuffer) {
    return asBuffer ? Buffer.from(data) : ab2str(data)
  } else {
    return asBuffer ? Buffer.from(String(data)) : String(data)
  }
}


================================================
FILE: util/key-range.js
================================================
/* global IDBKeyRange */

'use strict'

const ltgt = require('ltgt')
const NONE = Symbol('none')

module.exports = function createKeyRange (options) {
  const lower = ltgt.lowerBound(options, NONE)
  const upper = ltgt.upperBound(options, NONE)
  const lowerOpen = ltgt.lowerBoundExclusive(options, NONE)
  const upperOpen = ltgt.upperBoundExclusive(options, NONE)

  if (lower !== NONE && upper !== NONE) {
    return IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen)
  } else if (lower !== NONE) {
    return IDBKeyRange.lowerBound(lower, lowerOpen)
  } else if (upper !== NONE) {
    return IDBKeyRange.upperBound(upper, upperOpen)
  } else {
    return null
  }
}


================================================
FILE: util/serialize.js
================================================
'use strict'

const Buffer = require('buffer').Buffer
// Returns either a Uint8Array or Buffer (doesn't matter to
// IndexedDB, because Buffer is a subclass of Uint8Array)
const str2bin = (function () {
  if (global.TextEncoder) {
    const encoder = new TextEncoder('utf-8')
    return encoder.encode.bind(encoder)
  } else {
    return Buffer.from
  }
})()

module.exports = function (data, asBuffer) {
  if (asBuffer) {
    return Buffer.isBuffer(data) ? data : str2bin(String(data))
  } else {
    return String(data)
  }
}


================================================
FILE: util/support.js
================================================
'use strict'

const Buffer = require('buffer').Buffer

exports.test = function (key) {
  return function test (impl) {
    try {
      impl.cmp(key, 0)
      return true
    } catch (err) {
      return false
    }
  }
}

// Detect binary key support (IndexedDB Second Edition)
exports.bufferKeys = exports.test(Buffer.alloc(0))
Download .txt
gitextract_dn_f2s6r/

├── .airtap.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── UPGRADING.md
├── index.js
├── iterator.js
├── package.json
├── test/
│   ├── custom-test.js
│   ├── index.js
│   ├── support-test.js
│   └── upgrade-test.js
└── util/
    ├── clear.js
    ├── deserialize.js
    ├── key-range.js
    ├── serialize.js
    └── support.js
Download .txt
SYMBOL INDEX (15 symbols across 5 files)

FILE: index.js
  constant DEFAULT_PREFIX (line 17) | const DEFAULT_PREFIX = 'level-js-'
  function Level (line 19) | function Level (location, opts) {
  function loop (line 190) | function loop () {
  function next (line 258) | function next (err) {
  function each (line 263) | function each (err, key, value) {
  function finish (line 281) | function finish (err) {
  function identity (line 287) | function identity (data) {

FILE: iterator.js
  function Iterator (line 11) | function Iterator (db, location, options) {

FILE: test/upgrade-test.js
  function concatRaw (line 48) | function concatRaw (callback) {
  function identity (line 54) | function identity (data) {
  function ab (line 58) | function ab (data) {
  function bufferEntry (line 62) | function bufferEntry (entry) {
  function putOperation (line 66) | function putOperation (entry) {

FILE: util/deserialize.js
  function ta2buf (line 26) | function ta2buf (ta) {

FILE: util/key-range.js
  constant NONE (line 6) | const NONE = Symbol('none')
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (76K chars).
[
  {
    "path": ".airtap.yml",
    "chars": 345,
    "preview": "providers:\n  - airtap-sauce\n\nbrowsers:\n  - name: chrome\n  - name: firefox\n  - name: safari\n    version: 12..latest\n  - n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 279,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: npm\n    directory: /\n    schedule:\n      interval: monthly\n    ignore:\n      "
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 357,
    "preview": "name: Release\non:\n  push:\n    tags: ['*']\npermissions:\n  contents: write\njobs:\n  release:\n    name: Release\n    runs-on:"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 895,
    "preview": "name: Test\non: push\nconcurrency: sauce-labs\njobs:\n  test:\n    runs-on: ubuntu-latest\n    name: Sauce Labs\n    steps:\n   "
  },
  {
    "path": ".gitignore",
    "chars": 68,
    "preview": "node_modules\n.DS_Store\nnpm-debug.log\npackage-lock.json\n.nyc_output/\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 26622,
    "preview": "# Changelog\n\n## [6.1.0] - 2021-09-28\n\n### Added\n\n- Add `db.getMany(keys)` ([#214](https://github.com/Level/level-js/issu"
  },
  {
    "path": "LICENSE",
    "chars": 1108,
    "preview": "The MIT License (MIT)\n\nCopyright © 2012 Max Ogden and the contributors to level-js.\n\nPermission is hereby granted, free "
  },
  {
    "path": "README.md",
    "chars": 4772,
    "preview": "# level-js\n\n**Superseded by [`browser-level`](https://github.com/Level/browser-level). Please see [Frequently Asked Ques"
  },
  {
    "path": "UPGRADING.md",
    "chars": 8827,
    "preview": "# Upgrade Guide\n\nThis document describes breaking changes and how to upgrade. For a complete list of changes including m"
  },
  {
    "path": "index.js",
    "chars": 7373,
    "preview": "/* global indexedDB */\n\n'use strict'\n\nmodule.exports = Level\n\nconst AbstractLevelDOWN = require('abstract-leveldown').Ab"
  },
  {
    "path": "iterator.js",
    "chars": 3659,
    "preview": "'use strict'\n\nconst inherits = require('inherits')\nconst AbstractIterator = require('abstract-leveldown').AbstractIterat"
  },
  {
    "path": "package.json",
    "chars": 1387,
    "preview": "{\n  \"name\": \"level-js\",\n  \"version\": \"6.1.0\",\n  \"description\": \"An abstract-leveldown compliant store on top of IndexedD"
  },
  {
    "path": "test/custom-test.js",
    "chars": 10367,
    "preview": "'use strict'\n\nconst concat = require('level-concat-iterator')\n\nmodule.exports = function (leveljs, test, testCommon) {\n "
  },
  {
    "path": "test/index.js",
    "chars": 800,
    "preview": "'use strict'\n\nconst test = require('tape')\nconst uuid = require('uuid/v4')\nconst suite = require('abstract-leveldown/tes"
  },
  {
    "path": "test/support-test.js",
    "chars": 334,
    "preview": "'use strict'\n\nconst support = require('../util/support')\n\nconst pos = function () { }\nconst neg = function () { throw ne"
  },
  {
    "path": "test/upgrade-test.js",
    "chars": 1855,
    "preview": "'use strict'\n\nconst concat = require('level-concat-iterator')\n\nmodule.exports = function (leveljs, test, testCommon) {\n "
  },
  {
    "path": "util/clear.js",
    "chars": 1017,
    "preview": "'use strict'\n\nmodule.exports = function clear (db, location, keyRange, options, callback) {\n  if (options.limit === 0) r"
  },
  {
    "path": "util/deserialize.js",
    "chars": 1056,
    "preview": "'use strict'\n\nconst Buffer = require('buffer').Buffer\nconst ta2str = (function () {\n  if (global.TextDecoder) {\n    cons"
  },
  {
    "path": "util/key-range.js",
    "chars": 672,
    "preview": "/* global IDBKeyRange */\n\n'use strict'\n\nconst ltgt = require('ltgt')\nconst NONE = Symbol('none')\n\nmodule.exports = funct"
  },
  {
    "path": "util/serialize.js",
    "chars": 528,
    "preview": "'use strict'\n\nconst Buffer = require('buffer').Buffer\n// Returns either a Uint8Array or Buffer (doesn't matter to\n// Ind"
  },
  {
    "path": "util/support.js",
    "chars": 329,
    "preview": "'use strict'\n\nconst Buffer = require('buffer').Buffer\n\nexports.test = function (key) {\n  return function test (impl) {\n "
  }
]

About this extraction

This page contains the full source code of the maxogden/level.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (70.9 KB), approximately 20.6k tokens, and a symbol index with 15 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!