├── .airtap.yml
├── .github
├── dependabot.yml
└── workflows
│ └── test.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTORS.md
├── LICENSE.md
├── README.md
├── UPGRADING.md
├── index.js
├── lib
└── encodings.js
├── package.json
└── test
├── as-buffer.js
├── batch.js
├── codec.js
├── decoder.js
├── kv.js
└── ltgt.js
/.airtap.yml:
--------------------------------------------------------------------------------
1 | providers:
2 | - airtap-playwright
3 |
4 | browsers:
5 | - name: chromium
6 | - name: firefox
7 | - name: webkit
8 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: /
5 | schedule:
6 | interval: monthly
7 | ignore:
8 | - dependency-name: dependency-check
9 | - dependency-name: standard
10 | - dependency-name: hallmark
11 | - package-ecosystem: github-actions
12 | directory: /
13 | schedule:
14 | interval: monthly
15 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on: [push, pull_request]
3 | jobs:
4 | test:
5 | runs-on: ubuntu-latest
6 | strategy:
7 | matrix:
8 | node: [10, 12, 14]
9 | name: Node ${{ matrix.node }}
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v4
13 | - name: Use node ${{ matrix.node }}
14 | uses: actions/setup-node@v3
15 | with:
16 | node-version: ${{ matrix.node }}
17 | - name: Install
18 | run: npm install
19 | - name: Test
20 | run: npm test
21 | - name: Coverage
22 | run: npm run coverage
23 | - name: Codecov
24 | uses: codecov/codecov-action@v3
25 | with:
26 | file: coverage/lcov.info
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .nyc_output/
3 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | _**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md)._
4 |
5 | ## [10.0.0] - 2021-04-09
6 |
7 | ### Changed
8 |
9 | - **Breaking:** remove legacy range options ([Level/community#86](https://github.com/Level/community/issues/86)) ([`73b19b4`](https://github.com/Level/codec/commit/73b19b4)) (Vincent Weevers)
10 | - **Breaking:** drop node 6 and 8 ([`38dc04c`](https://github.com/Level/codec/commit/38dc04c)) ([Level/community#98](https://github.com/Level/community/issues/98)) (Vincent Weevers)
11 | - **Breaking:** modernize syntax & bump `standard` to 16.x ([`874956f`](https://github.com/Level/codec/commit/874956f), [`e3ed6e4`](https://github.com/Level/codec/commit/e3ed6e4)) ([Level/community#98](https://github.com/Level/community/issues/98)) (Vincent Weevers).
12 | - **Breaking:** bump `buffer` from 15.x to 16.x ([#62](https://github.com/Level/codec/issues/62)) ([Level/community#98](https://github.com/Level/community/issues/98)) ([`78d2ea0`](https://github.com/Level/codec/commit/78d2ea0)) (Alex Potsides).
13 |
14 | ## [9.0.2] - 2020-06-26
15 |
16 | ### Changed
17 |
18 | - Upgrade `hallmark` devDependency from `^0.1.0` to `^2.0.0` ([#53](https://github.com/Level/codec/issues/53), [#56](https://github.com/Level/codec/issues/56)) ([**@vweevers**](https://github.com/vweevers))
19 | - Upgrade `standard` devDependency from `^12.0.0` to `^14.0.0` ([#52](https://github.com/Level/codec/issues/52), [#55](https://github.com/Level/codec/issues/55)) ([**@vweevers**](https://github.com/vweevers))
20 | - Upgrade `nyc` devDependency from `^13.2.0` to `^14.0.0` ([#50](https://github.com/Level/codec/issues/50)) ([**@vweevers**](https://github.com/vweevers))
21 |
22 | ### Fixed
23 |
24 | - Add `buffer` dependency for browsers ([#58](https://github.com/Level/codec/issues/58)) ([**@hugomrdias**](https://github.com/hugomrdias))
25 |
26 | ## [9.0.1] - 2019-04-01
27 |
28 | ### Changed
29 |
30 | - Upgrade `standard` devDependency from `^11.0.1` to `^12.0.0` ([#38](https://github.com/Level/codec/issues/38)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
31 | - Update description in README and `package.json` ([#47](https://github.com/Level/codec/issues/47)) ([**@vweevers**](https://github.com/vweevers))
32 | - Apply common project tweaks ([#39](https://github.com/Level/codec/issues/39), [#40](https://github.com/Level/codec/issues/40), [#41](https://github.com/Level/codec/issues/41)) ([**@vweevers**](https://github.com/vweevers))
33 | - Tweak copyright year for less maintenance ([`79d2d02`](https://github.com/Level/codec/commit/79d2d02)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
34 |
35 | ### Added
36 |
37 | - Add `nyc` and `coveralls` ([#36](https://github.com/Level/codec/issues/36), [#44](https://github.com/Level/codec/issues/44)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
38 | - Add `CHANGELOG.md` and `UPGRADING.md` ([#47](https://github.com/Level/codec/issues/47)) ([**@vweevers**](https://github.com/vweevers))
39 |
40 | ### Removed
41 |
42 | - Remove node 9 from travis ([`ffe3f92`](https://github.com/Level/codec/commit/ffe3f92)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
43 | - Remove experimental typings ([`1cfd23f`](https://github.com/Level/codec/commit/1cfd23f)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
44 |
45 | ### Fixed
46 |
47 | - Fix subtests by adding `t.plan()` ([#46](https://github.com/Level/codec/issues/46)) ([**@vweevers**](https://github.com/vweevers))
48 |
49 | ## [9.0.0] - 2018-05-12
50 |
51 | ### Changed
52 |
53 | - Update README ([#31](https://github.com/Level/codec/issues/31)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
54 |
55 | ### Added
56 |
57 | - Add `standard` ([#29](https://github.com/Level/codec/issues/29)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
58 | - Add node 9 and 10 ([`9476e58`](https://github.com/Level/codec/commit/9476e58)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
59 |
60 | ### Removed
61 |
62 | - Drop node 0.12, 4, 5 and 7 ([`9476e58`](https://github.com/Level/codec/commit/9476e58), [#32](https://github.com/Level/codec/issues/32)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
63 |
64 | ### Fixed
65 |
66 | - Fix constructor to work without `new` ([#30](https://github.com/Level/codec/issues/30)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
67 |
68 | ## [8.0.0] - 2017-10-21
69 |
70 | ### Changed
71 |
72 | - Revert "fix utf-8 encoding returning buffers" ([#23](https://github.com/Level/codec/issues/23)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
73 |
74 | ### Added
75 |
76 | - Add badges to `README` and stylize "levelup" ([#22](https://github.com/Level/codec/issues/22)) ([**@vweevers**](https://github.com/vweevers))
77 | - Document encodings and their format in greater detail ([#22](https://github.com/Level/codec/issues/22)) ([**@vweevers**](https://github.com/vweevers))
78 |
79 | ## [7.1.0] - 2017-09-12
80 |
81 | ### Changed
82 |
83 | - Update copyright year from 2015 to 2017 ([`aceb6ff`](https://github.com/Level/codec/commit/aceb6ff)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
84 |
85 | ### Added
86 |
87 | - Add basic typings ([#18](https://github.com/Level/codec/issues/18)) ([**@MeirionHughes**](https://github.com/MeirionHughes))
88 | - Add node 4, 5, 6, 7 and 8 ([`5c00a1c`](https://github.com/Level/codec/commit/5c00a1c)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
89 |
90 | ### Removed
91 |
92 | - Drop node 0.10 and iojs ([`5c00a1c`](https://github.com/Level/codec/commit/5c00a1c)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
93 |
94 | ## [7.0.1] - 2017-08-14
95 |
96 | ### Added
97 |
98 | - Add Greenkeeper ([#17](https://github.com/Level/codec/issues/17)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
99 |
100 | ### Fixed
101 |
102 | - Use `identity` function consistently ([#14](https://github.com/Level/codec/issues/14)) ([**@dcousens**](https://github.com/dcousens))
103 |
104 | ## [7.0.0] - 2017-01-26
105 |
106 | ### Fixed
107 |
108 | - Fix utf-8 encoding returning buffers ([#12](https://github.com/Level/codec/issues/12)) ([**@juliangruber**](https://github.com/juliangruber))
109 |
110 | ## [6.2.0] - 2016-02-24
111 |
112 | ### Changed
113 |
114 | - Rename "id" encoding to "none", add "id" alias ([#10](https://github.com/Level/codec/issues/10)) ([**@juliangruber**](https://github.com/juliangruber))
115 | - Upgrade `tape` devDependency ([#9](https://github.com/Level/codec/issues/9)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
116 |
117 | ### Added
118 |
119 | - Document available encodings ([#10](https://github.com/Level/codec/issues/10)) ([**@juliangruber**](https://github.com/juliangruber))
120 |
121 | ## [6.1.0] - 2015-10-21
122 |
123 | ### Added
124 |
125 | - Fallback to legacy `encoding` option if `valueEncoding` is not provided ([#8](https://github.com/Level/codec/issues/8)) ([**@dominictarr**](https://github.com/dominictarr))
126 |
127 | ## [6.0.0] - 2015-05-04
128 |
129 | ### Changed
130 |
131 | - Replace `createDecodeStream()` with `createStreamDecoder()` ([#6](https://github.com/Level/codec/issues/6)) ([**@juliangruber**](https://github.com/juliangruber))
132 |
133 | ## [5.5.0] - 2015-04-17
134 |
135 | ### Added
136 |
137 | - Add `createDecodeStream()` ([#5](https://github.com/Level/codec/issues/5)) ([**@juliangruber**](https://github.com/juliangruber))
138 |
139 | ## [5.4.0] - 2015-04-17
140 |
141 | ### Changed
142 |
143 | - Simplify `encodeLtgt()` ([`24f3817`](https://github.com/Level/codec/commit/24f3817)) ([**@juliangruber**](https://github.com/juliangruber))
144 |
145 | ## [5.3.0] - 2015-04-17
146 |
147 | ### Added
148 |
149 | - Add `encodeLtgt()` ([#4](https://github.com/Level/codec/issues/4)) ([**@juliangruber**](https://github.com/juliangruber))
150 |
151 | ## [5.2.0] - 2015-03-24
152 |
153 | ### Changed
154 |
155 | - Make all options optional ([`4f942eb`](https://github.com/Level/codec/commit/4f942eb)) ([**@juliangruber**](https://github.com/juliangruber))
156 |
157 | ## [5.1.0] - 2015-03-24
158 |
159 | ### Changed
160 |
161 | - Make member options optional ([`0c98ccb`](https://github.com/Level/codec/commit/0c98ccb)) ([**@juliangruber**](https://github.com/juliangruber))
162 |
163 | ## [5.0.0] - 2015-03-24
164 |
165 | **Historical Note** 4.3.0 was meant to be a major release.
166 |
167 | ## [4.3.0] - 2015-03-24
168 |
169 | ### Changed
170 |
171 | - Rewrite ([`37f103e`](https://github.com/Level/codec/commit/37f103e), [`054fb3f`](https://github.com/Level/codec/commit/054fb3f), [`f510a90`](https://github.com/Level/codec/commit/f510a90)) ([**@juliangruber**](https://github.com/juliangruber))
172 |
173 | ### Added
174 |
175 | - Add [**@ralphtheninja**](https://github.com/ralphtheninja) to contributors ([`dd2b9a0`](https://github.com/Level/codec/commit/dd2b9a0)) ([**@juliangruber**](https://github.com/juliangruber))
176 | - Add travis and licensing ([#1](https://github.com/Level/codec/issues/1)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
177 |
178 | ## [4.2.0] - 2015-03-19
179 |
180 | ### Fixed
181 |
182 | - Keep batch `.prefix` for `level-sublevel` ([`f706482`](https://github.com/Level/codec/commit/f706482)) ([**@juliangruber**](https://github.com/juliangruber))
183 |
184 | ## [4.1.0] - 2015-03-19
185 |
186 | ### Fixed
187 |
188 | - Set `batch` encodings to binary if `{key,value}AsBuffer` is true ([`bcf6feb`](https://github.com/Level/codec/commit/bcf6feb)) ([**@juliangruber**](https://github.com/juliangruber))
189 |
190 | ## [4.0.1] - 2015-03-19
191 |
192 | ### Fixed
193 |
194 | - Skip falsy objects in `walk` ([`270ea17`](https://github.com/Level/codec/commit/270ea17)) ([**@juliangruber**](https://github.com/juliangruber))
195 |
196 | ## [4.0.0] - 2015-03-19
197 |
198 | ### Removed
199 |
200 | - Remove default encoding ([`28a63b2`](https://github.com/Level/codec/commit/28a63b2)) ([**@juliangruber**](https://github.com/juliangruber))
201 |
202 | ## [3.1.0] - 2015-03-19
203 |
204 | ### Added
205 |
206 | - Add experimental `Codec` class ([`8a189f4`](https://github.com/Level/codec/commit/8a189f4)) ([**@juliangruber**](https://github.com/juliangruber))
207 |
208 | ## [3.0.0] - 2015-03-18
209 |
210 | ### Removed
211 |
212 | - Remove `encoding` option in favor of `keyEncoding` and `valueEncoding` ([`9fed84d`](https://github.com/Level/codec/commit/9fed84d)) ([**@juliangruber**](https://github.com/juliangruber))
213 |
214 | ## [2.0.1] - 2015-03-18
215 |
216 | ### Fixed
217 |
218 | - Fix `encoding` option to only be an alias for `valueEncoding` ([`b4de4d1`](https://github.com/Level/codec/commit/b4de4d1)) ([**@juliangruber**](https://github.com/juliangruber))
219 |
220 | ## [2.0.0] - 2015-03-18
221 |
222 | ### Changed
223 |
224 | - Remove side effects from `batch()` ([`bedaa26`](https://github.com/Level/codec/commit/bedaa26), [`6f5b373`](https://github.com/Level/codec/commit/6f5b373), [`abef01b`](https://github.com/Level/codec/commit/abef01b)) ([**@juliangruber**](https://github.com/juliangruber))
225 |
226 | ## [1.2.1] - 2015-03-18
227 |
228 | ### Fixed
229 |
230 | - Fix `require` statements for `{key,value}AsBuffer()` ([`71bf7a5`](https://github.com/Level/codec/commit/71bf7a5)) ([**@juliangruber**](https://github.com/juliangruber))
231 |
232 | ## [1.2.0] - 2015-03-18
233 |
234 | ### Added
235 |
236 | - Add `{key,value}AsBuffer()` ([`796a540`](https://github.com/Level/codec/commit/796a540)) ([**@juliangruber**](https://github.com/juliangruber))
237 |
238 | ## [1.1.0] - 2015-03-18
239 |
240 | ### Added
241 |
242 | - Add `decode{Key,Value}` ([`029fbd7`](https://github.com/Level/codec/commit/029fbd7)) ([**@juliangruber**](https://github.com/juliangruber))
243 |
244 | ## 1.0.1 - 2015-03-18
245 |
246 | :seedling: Initial release.
247 |
248 | [10.0.0]: https://github.com/Level/codec/compare/v9.0.2...v10.0.0
249 |
250 | [9.0.2]: https://github.com/Level/codec/compare/v9.0.1...v9.0.2
251 |
252 | [9.0.1]: https://github.com/Level/codec/compare/v9.0.0...v9.0.1
253 |
254 | [9.0.0]: https://github.com/Level/codec/compare/v8.0.0...v9.0.0
255 |
256 | [8.0.0]: https://github.com/Level/codec/compare/v7.1.0...v8.0.0
257 |
258 | [7.1.0]: https://github.com/Level/codec/compare/v7.0.1...v7.1.0
259 |
260 | [7.0.1]: https://github.com/Level/codec/compare/v7.0.0...v7.0.1
261 |
262 | [7.0.0]: https://github.com/Level/codec/compare/v6.2.0...v7.0.0
263 |
264 | [6.2.0]: https://github.com/Level/codec/compare/v6.1.0...v6.2.0
265 |
266 | [6.1.0]: https://github.com/Level/codec/compare/v6.0.0...v6.1.0
267 |
268 | [6.0.0]: https://github.com/Level/codec/compare/v5.5.0...v6.0.0
269 |
270 | [5.5.0]: https://github.com/Level/codec/compare/v5.4.0...v5.5.0
271 |
272 | [5.4.0]: https://github.com/Level/codec/compare/v5.3.0...v5.4.0
273 |
274 | [5.3.0]: https://github.com/Level/codec/compare/v5.2.0...v5.3.0
275 |
276 | [5.2.0]: https://github.com/Level/codec/compare/v5.1.0...v5.2.0
277 |
278 | [5.1.0]: https://github.com/Level/codec/compare/v5.0.0...v5.1.0
279 |
280 | [5.0.0]: https://github.com/Level/codec/compare/v4.3.0...v5.0.0
281 |
282 | [4.3.0]: https://github.com/Level/codec/compare/v4.2.0...v4.3.0
283 |
284 | [4.2.0]: https://github.com/Level/codec/compare/v4.1.0...v4.2.0
285 |
286 | [4.1.0]: https://github.com/Level/codec/compare/v4.0.1...v4.1.0
287 |
288 | [4.0.1]: https://github.com/Level/codec/compare/v4.0.0...v4.0.1
289 |
290 | [4.0.0]: https://github.com/Level/codec/compare/v3.1.0...v4.0.0
291 |
292 | [3.1.0]: https://github.com/Level/codec/compare/v3.0.0...v3.1.0
293 |
294 | [3.0.0]: https://github.com/Level/codec/compare/v2.0.1...v3.0.0
295 |
296 | [2.0.1]: https://github.com/Level/codec/compare/v2.0.0...v2.0.1
297 |
298 | [2.0.0]: https://github.com/Level/codec/compare/v1.2.1...v2.0.0
299 |
300 | [1.2.1]: https://github.com/Level/codec/compare/v1.2.0...v1.2.1
301 |
302 | [1.2.0]: https://github.com/Level/codec/compare/v1.1.0...v1.2.0
303 |
304 | [1.1.0]: https://github.com/Level/codec/compare/v1.0.1...v1.1.0
305 |
--------------------------------------------------------------------------------
/CONTRIBUTORS.md:
--------------------------------------------------------------------------------
1 | # Contributors
2 |
3 | | Name | GitHub | Social |
4 | | :------------------- | :----------------------------------------------------------- | :------------------------------------------------------------ |
5 | | **Julian Gruber** | [**@juliangruber**](https://github.com/juliangruber) | [**@juliangruber@twitter**](https://twitter.com/juliangruber) |
6 | | **Vincent Weevers** | [**@vweevers**](https://github.com/vweevers) | [**@vweevers@twitter**](https://twitter.com/vweevers) |
7 | | **Lars-Magnus Skog** | [**@ralphtheninja**](https://github.com/ralphtheninja) | [**@ralph@social.weho.st**](https://social.weho.st/@ralph) |
8 | | **Dominic Tarr** | [**@dominictarr**](https://github.com/dominictarr) | [**@dominictarr@twitter**](https://twitter.com/dominictarr) |
9 | | **Alex Potsides** | | |
10 | | **Daniel Cousens** | [**@dcousens**](https://github.com/dcousens) | |
11 | | **Hugo Dias** | | |
12 | | **Meirion Hughes** | [**@MeirionHughes**](https://github.com/MeirionHughes) | |
13 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | **Copyright © 2012-present [Contributors](CONTRIBUTORS.md).**
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # level-codec
2 |
3 | **Superseded by [`level-transcoder`](https://github.com/Level/transcoder). Please see [Frequently Asked Questions](https://github.com/Level/community#faq).**
4 |
5 | ## Usage
6 |
7 | **If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md).
8 |
9 | ```js
10 | const Codec = require('level-codec')
11 | const codec = Codec({ keyEncoding: 'json' })
12 | const key = codec.encodeKey({ foo: 'bar' })
13 | console.log(key) // -> '{"foo":"bar"}'
14 | console.log(codec.decodeKey(key)) // -> { foo: 'bar' }
15 | ```
16 |
17 | ## API
18 |
19 | ### `codec = Codec([opts])`
20 |
21 | Create a new codec, with a global options object.
22 |
23 | ### `codec.encodeKey(key[, opts])`
24 |
25 | Encode `key` with given `opts`.
26 |
27 | ### `codec.encodeValue(value[, opts])`
28 |
29 | Encode `value` with given `opts`.
30 |
31 | ### `codec.encodeBatch(batch[, opts])`
32 |
33 | Encode `batch` ops with given `opts`.
34 |
35 | ### `codec.encodeLtgt(ltgt)`
36 |
37 | Encode the ltgt values of option object `ltgt`.
38 |
39 | ### `codec.decodeKey(key[, opts])`
40 |
41 | Decode `key` with given `opts`.
42 |
43 | ### `codec.decodeValue(value[, opts])`
44 |
45 | Decode `value` with given `opts`.
46 |
47 | ### `codec.createStreamDecoder([opts])`
48 |
49 | Create a function with signature `(key, value)`, that for each key-value pair returned from a levelup read stream returns the decoded value to be emitted.
50 |
51 | ### `codec.keyAsBuffer([opts])`
52 |
53 | Check whether `opts` and the global `opts` call for a binary key encoding.
54 |
55 | ### `codec.valueAsBuffer([opts])`
56 |
57 | Check whether `opts` and the global `opts` call for a binary value encoding.
58 |
59 | ### `codec.encodings`
60 |
61 | The builtin encodings as object of form
62 |
63 | ```js
64 | {
65 | [type]: encoding
66 | }
67 | ```
68 |
69 | See below for a list and the format of `encoding`.
70 |
71 | ## Builtin Encodings
72 |
73 | | Type | Input | Stored as | Output |
74 | | :---------------------------------------------------------------- | :--------------------------- | :--------------- | :-------- |
75 | | `utf8` | String or Buffer | String or Buffer | String |
76 | | `json` | Any JSON type | JSON string | Input |
77 | | `binary` | Buffer, string or byte array | Buffer | As stored |
78 | | `hex`
`ascii`
`base64`
`ucs2`
`utf16le`
`utf-16le` | String or Buffer | Buffer | String |
79 | | `none` a.k.a. `id` | Any type (bypass encoding) | Input\* | As stored |
80 |
81 | \* Stores may have their own type coercion. Whether type information is preserved depends on the [`abstract-leveldown`] implementation as well as the underlying storage (`LevelDB`, `IndexedDB`, etc).
82 |
83 | ## Encoding Format
84 |
85 | An encoding is an object of the form:
86 |
87 | ```js
88 | {
89 | encode: function (data) {
90 | return data
91 | },
92 | decode: function (data) {
93 | return data
94 | },
95 | buffer: Boolean,
96 | type: 'example'
97 | }
98 | ```
99 |
100 | All of these properties are required.
101 |
102 | The `buffer` boolean tells consumers whether to fetch data as a Buffer, before calling your `decode()` function on that data. If `buffer` is true, it is assumed that `decode()` takes a Buffer. If false, it is assumed that `decode` takes any other type (usually a string).
103 |
104 | To explain this in the grand scheme of things, consider a store like [`leveldown`] which has the ability to return either a Buffer or string, both sourced from the same byte array. Wrap this store with [`encoding-down`] and it'll select the most optimal data type based on the `buffer` property of the active encoding. If your `decode()` function needs a string (and the data can legitimately become a UTF8 string), you should set `buffer` to `false`. This avoids the cost of having to convert a Buffer to a string.
105 |
106 | The `type` string should be a unique name.
107 |
108 | ## Contributing
109 |
110 | [`Level/codec`](https://github.com/Level/codec) is an **OPEN Open Source Project**. This means that:
111 |
112 | > 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.
113 |
114 | See the [Contribution Guide](https://github.com/Level/community/blob/master/CONTRIBUTING.md) for more details.
115 |
116 | ## License
117 |
118 | [MIT](LICENSE.md) © 2012-present [Contributors](CONTRIBUTORS.md).
119 |
120 | [`encoding-down`]: https://github.com/Level/encoding-down
121 |
122 | [`abstract-leveldown`]: https://github.com/Level/abstract-leveldown
123 |
124 | [`leveldown`]: https://github.com/Level/leveldown
125 |
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrade Guide
2 |
3 | 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.md).
4 |
5 | ## 10.0.0
6 |
7 | Legacy range options have been removed ([Level/community#86](https://github.com/Level/community/issues/86)). If you previously did:
8 |
9 | ```js
10 | codec.encodeLtgt({ start: 'a', end: 'z' })
11 | ```
12 |
13 | An error would now be thrown and you must instead do:
14 |
15 | ```js
16 | codec.encodeLtgt({ gte: 'a', lte: 'z' })
17 | ```
18 |
19 | This release also drops support of legacy runtime environments ([Level/community#98](https://github.com/Level/community/issues/98)):
20 |
21 | - Node.js 6 and 8
22 | - Internet Explorer 11
23 | - Safari 9-11
24 | - Stock Android browser (AOSP).
25 |
26 | ## 9.0.0
27 |
28 | Dropped node 0.12, 4, 5 and 7.
29 |
30 | ## 8.0.0
31 |
32 | Previously the "utf8" decoder always returned a string. This was a workaround for `encoding-down` that is no longer needed. The return type now depends on the `asBuffer` option, which is more optimal.
33 |
34 | ## 7.0.0
35 |
36 | Dropped node 0.10 and iojs.
37 |
38 | ## 6.0.0
39 |
40 | The `createDecodeStream()` method (introduced in the last 5.x version) has been replaced with `createStreamDecoder()`.
41 |
42 | ## 5.0.0
43 |
44 | This is a rewrite of both internals and the public API. Please see the README for details.
45 |
46 | ## 4.0.0
47 |
48 | Removed default encoding ("utf8"). If you relied on this behavior you must now define it yourself.
49 |
50 | ## 3.0.0
51 |
52 | Removed the `encoding` option in favor of `keyEncoding` and `valueEncoding`. Note: it was partially restored in v6.1.0.
53 |
54 | ## 2.0.0
55 |
56 | The function signature of `batch()` has changed from `batch(ops, batchOptions, dbOptions)` to `batch(ops, optionObjects)`.
57 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const encodings = require('./lib/encodings')
4 | const rangeOptions = new Set(['lt', 'gt', 'lte', 'gte'])
5 |
6 | module.exports = Codec
7 |
8 | function Codec (opts) {
9 | if (!(this instanceof Codec)) {
10 | return new Codec(opts)
11 | }
12 | this.opts = opts || {}
13 | this.encodings = encodings
14 | }
15 |
16 | Codec.prototype._encoding = function (encoding) {
17 | if (typeof encoding === 'string') encoding = encodings[encoding]
18 | if (!encoding) encoding = encodings.id
19 | return encoding
20 | }
21 |
22 | Codec.prototype._keyEncoding = function (opts, batchOpts) {
23 | return this._encoding((batchOpts && batchOpts.keyEncoding) ||
24 | (opts && opts.keyEncoding) ||
25 | this.opts.keyEncoding)
26 | }
27 |
28 | Codec.prototype._valueEncoding = function (opts, batchOpts) {
29 | return this._encoding((batchOpts && (batchOpts.valueEncoding || batchOpts.encoding)) ||
30 | (opts && (opts.valueEncoding || opts.encoding)) ||
31 | (this.opts.valueEncoding || this.opts.encoding))
32 | }
33 |
34 | Codec.prototype.encodeKey = function (key, opts, batchOpts) {
35 | return this._keyEncoding(opts, batchOpts).encode(key)
36 | }
37 |
38 | Codec.prototype.encodeValue = function (value, opts, batchOpts) {
39 | return this._valueEncoding(opts, batchOpts).encode(value)
40 | }
41 |
42 | Codec.prototype.decodeKey = function (key, opts) {
43 | return this._keyEncoding(opts).decode(key)
44 | }
45 |
46 | Codec.prototype.decodeValue = function (value, opts) {
47 | return this._valueEncoding(opts).decode(value)
48 | }
49 |
50 | Codec.prototype.encodeBatch = function (ops, opts) {
51 | return ops.map((_op) => {
52 | const op = {
53 | type: _op.type,
54 | key: this.encodeKey(_op.key, opts, _op)
55 | }
56 | if (this.keyAsBuffer(opts, _op)) op.keyEncoding = 'binary'
57 | if (_op.prefix) op.prefix = _op.prefix
58 | if ('value' in _op) {
59 | op.value = this.encodeValue(_op.value, opts, _op)
60 | if (this.valueAsBuffer(opts, _op)) op.valueEncoding = 'binary'
61 | }
62 | return op
63 | })
64 | }
65 |
66 | Codec.prototype.encodeLtgt = function (ltgt) {
67 | const ret = {}
68 |
69 | for (const key of Object.keys(ltgt)) {
70 | if (key === 'start' || key === 'end') {
71 | throw new Error('Legacy range options ("start" and "end") have been removed')
72 | }
73 |
74 | ret[key] = rangeOptions.has(key)
75 | ? this.encodeKey(ltgt[key], ltgt)
76 | : ltgt[key]
77 | }
78 |
79 | return ret
80 | }
81 |
82 | Codec.prototype.createStreamDecoder = function (opts) {
83 | if (opts.keys && opts.values) {
84 | return (key, value) => {
85 | return {
86 | key: this.decodeKey(key, opts),
87 | value: this.decodeValue(value, opts)
88 | }
89 | }
90 | } else if (opts.keys) {
91 | return (key) => {
92 | return this.decodeKey(key, opts)
93 | }
94 | } else if (opts.values) {
95 | return (_, value) => {
96 | return this.decodeValue(value, opts)
97 | }
98 | } else {
99 | return function () {}
100 | }
101 | }
102 |
103 | Codec.prototype.keyAsBuffer = function (opts) {
104 | return this._keyEncoding(opts).buffer
105 | }
106 |
107 | Codec.prototype.valueAsBuffer = function (opts) {
108 | return this._valueEncoding(opts).buffer
109 | }
110 |
--------------------------------------------------------------------------------
/lib/encodings.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const { Buffer } = require('buffer')
4 |
5 | exports.utf8 = exports['utf-8'] = {
6 | encode: function (data) {
7 | return isBinary(data) ? data : String(data)
8 | },
9 | decode: identity,
10 | buffer: false,
11 | type: 'utf8'
12 | }
13 |
14 | exports.json = {
15 | encode: JSON.stringify,
16 | decode: JSON.parse,
17 | buffer: false,
18 | type: 'json'
19 | }
20 |
21 | exports.binary = {
22 | encode: function (data) {
23 | return isBinary(data) ? data : Buffer.from(data)
24 | },
25 | decode: identity,
26 | buffer: true,
27 | type: 'binary'
28 | }
29 |
30 | exports.none = {
31 | encode: identity,
32 | decode: identity,
33 | buffer: false,
34 | type: 'id'
35 | }
36 |
37 | exports.id = exports.none
38 |
39 | const bufferEncodings = [
40 | 'hex',
41 | 'ascii',
42 | 'base64',
43 | 'ucs2',
44 | 'ucs-2',
45 | 'utf16le',
46 | 'utf-16le'
47 | ]
48 |
49 | for (const type of bufferEncodings) {
50 | exports[type] = {
51 | encode: function (data) {
52 | return isBinary(data) ? data : Buffer.from(data, type)
53 | },
54 | decode: function (buffer) {
55 | return buffer.toString(type)
56 | },
57 | buffer: true,
58 | type: type
59 | }
60 | }
61 |
62 | function identity (value) {
63 | return value
64 | }
65 |
66 | function isBinary (data) {
67 | return data === undefined || data === null || Buffer.isBuffer(data)
68 | }
69 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "level-codec",
3 | "version": "10.0.0",
4 | "description": "Encode keys, values and range options, with built-in or custom encodings",
5 | "license": "MIT",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "standard && hallmark && nyc tape test/*.js",
9 | "test-browsers-local": "airtap --coverage --verbose test/*.js",
10 | "coverage": "nyc report -r lcovonly",
11 | "hallmark": "hallmark --fix",
12 | "dependency-check": "dependency-check . test/*.js",
13 | "prepublishOnly": "npm run dependency-check"
14 | },
15 | "files": [
16 | "lib",
17 | "index.js",
18 | "CHANGELOG.md",
19 | "CONTRIBUTORS.md",
20 | "LICENSE.md",
21 | "UPGRADING.md"
22 | ],
23 | "dependencies": {
24 | "buffer": "^6.0.3"
25 | },
26 | "devDependencies": {
27 | "airtap": "^4.0.3",
28 | "airtap-playwright": "^1.0.1",
29 | "dependency-check": "^3.3.0",
30 | "hallmark": "^3.1.0",
31 | "level-community": "^3.0.0",
32 | "nyc": "^15.1.0",
33 | "standard": "^17.0.0",
34 | "tape": "^5.0.1"
35 | },
36 | "hallmark": {
37 | "community": "level-community"
38 | },
39 | "repository": "Level/codec",
40 | "homepage": "https://github.com/Level/codec",
41 | "keywords": [
42 | "level"
43 | ],
44 | "engines": {
45 | "node": ">=10"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/test/as-buffer.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('key as buffer', function (t) {
5 | const codec = new Codec({ keyEncoding: 'hex' })
6 | t.ok(codec.keyAsBuffer({}))
7 | t.ok(codec.keyAsBuffer())
8 | t.notOk(codec.keyAsBuffer({ keyEncoding: 'utf8' }))
9 | t.end()
10 | })
11 |
12 | test('value as buffer', function (t) {
13 | const codec = new Codec({ valueEncoding: 'hex' })
14 | t.ok(codec.valueAsBuffer({}))
15 | t.ok(codec.valueAsBuffer())
16 | t.notOk(codec.valueAsBuffer({ valueEncoding: 'utf8' }))
17 | t.end()
18 | })
19 |
--------------------------------------------------------------------------------
/test/batch.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('batch', function (t) {
5 | const codec = new Codec({})
6 | const ops = [
7 | { type: 'put', key: 'string', value: 'string', valueEncoding: 'utf8' },
8 | { type: 'put', key: 'json', value: {} }
9 | ]
10 | const opsSerialized = JSON.stringify(ops)
11 |
12 | let encoded = codec.encodeBatch(ops, { valueEncoding: 'json' })
13 |
14 | t.equal(opsSerialized, JSON.stringify(ops), 'ops not changed')
15 |
16 | t.deepEqual(encoded, [
17 | { type: 'put', key: 'string', value: 'string' },
18 | { type: 'put', key: 'json', value: '{}' }
19 | ])
20 |
21 | encoded = codec.encodeBatch(ops)
22 | t.deepEqual(encoded, [
23 | { type: 'put', key: 'string', value: 'string' },
24 | { type: 'put', key: 'json', value: {} }
25 | ])
26 |
27 | t.end()
28 | })
29 |
30 | test('batch - legacy', function (t) {
31 | const codec = new Codec({})
32 | const ops = [
33 | { type: 'put', key: 'string', value: 'string', encoding: 'utf8' },
34 | { type: 'put', key: 'json', value: {} }
35 | ]
36 | const opsSerialized = JSON.stringify(ops)
37 |
38 | let encoded = codec.encodeBatch(ops, { encoding: 'json' })
39 |
40 | t.equal(opsSerialized, JSON.stringify(ops), 'ops not changed')
41 |
42 | t.deepEqual(encoded, [
43 | { type: 'put', key: 'string', value: 'string' },
44 | { type: 'put', key: 'json', value: '{}' }
45 | ])
46 |
47 | encoded = codec.encodeBatch(ops)
48 | t.deepEqual(encoded, [
49 | { type: 'put', key: 'string', value: 'string' },
50 | { type: 'put', key: 'json', value: {} }
51 | ])
52 |
53 | t.end()
54 | })
55 |
--------------------------------------------------------------------------------
/test/codec.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('codec', function (t) {
5 | let codec = new Codec({ keyEncoding: 'hex' })
6 | t.ok(codec.keyAsBuffer())
7 | codec = new Codec()
8 | t.notOk(codec.keyAsBuffer())
9 | t.end()
10 | })
11 |
12 | test('codec, new not needed', function (t) {
13 | let codec = Codec({ keyEncoding: 'hex' })
14 | t.ok(codec.keyAsBuffer())
15 | codec = Codec()
16 | t.notOk(codec.keyAsBuffer())
17 | t.end()
18 | })
19 |
--------------------------------------------------------------------------------
/test/decoder.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('createStreamDecoder', function (t) {
5 | const codec = new Codec({ keyEncoding: 'hex' })
6 |
7 | t.plan(3)
8 |
9 | t.test('keys and values', function (t) {
10 | const decoder = codec.createStreamDecoder({
11 | valueEncoding: 'json',
12 | keys: true,
13 | values: true
14 | })
15 | t.deepEqual(decoder(Buffer.from('hey'), '"you"'), {
16 | key: '686579',
17 | value: 'you'
18 | })
19 | t.end()
20 | })
21 |
22 | t.test('keys', function (t) {
23 | const decoder = codec.createStreamDecoder({
24 | keys: true
25 | })
26 | t.equal(decoder(Buffer.from('hey')), '686579')
27 | t.end()
28 | })
29 |
30 | t.test('values', function (t) {
31 | const decoder = codec.createStreamDecoder({
32 | valueEncoding: 'hex',
33 | values: true
34 | })
35 | t.equal(decoder(null, Buffer.from('hey')), '686579')
36 | t.end()
37 | })
38 | })
39 |
40 | test('createStreamDecoder - legacy', function (t) {
41 | const codec = new Codec({ keyEncoding: 'hex' })
42 |
43 | t.plan(3)
44 |
45 | t.test('keys and values', function (t) {
46 | const decoder = codec.createStreamDecoder({
47 | encoding: 'json',
48 | keys: true,
49 | values: true
50 | })
51 | t.deepEqual(decoder(Buffer.from('hey'), '"you"'), {
52 | key: '686579',
53 | value: 'you'
54 | })
55 | t.end()
56 | })
57 |
58 | t.test('keys', function (t) {
59 | const decoder = codec.createStreamDecoder({
60 | keys: true
61 | })
62 | t.equal(decoder(Buffer.from('hey')), '686579')
63 | t.end()
64 | })
65 |
66 | t.test('values', function (t) {
67 | const decoder = codec.createStreamDecoder({
68 | encoding: 'hex',
69 | values: true
70 | })
71 | t.equal(decoder(null, Buffer.from('hey')), '686579')
72 | t.end()
73 | })
74 | })
75 |
--------------------------------------------------------------------------------
/test/kv.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('encode key', function (t) {
5 | const codec = new Codec({ keyEncoding: 'hex' })
6 |
7 | let buf = codec.encodeKey('686579', {})
8 | t.equal(buf.toString(), 'hey')
9 |
10 | buf = codec.encodeKey('686579')
11 | t.equal(buf.toString(), 'hey')
12 |
13 | buf = codec.encodeKey('686579', {
14 | keyEncoding: 'binary'
15 | })
16 | t.equal(buf.toString(), '686579')
17 |
18 | buf = codec.encodeKey({ foo: 'bar' }, {
19 | keyEncoding: 'none'
20 | })
21 | t.deepEqual(buf, { foo: 'bar' })
22 |
23 | t.end()
24 | })
25 |
26 | test('encode value', function (t) {
27 | const codec = new Codec({ valueEncoding: 'hex' })
28 |
29 | let buf = codec.encodeValue('686579', {})
30 | t.equal(buf.toString(), 'hey')
31 |
32 | buf = codec.encodeValue('686579')
33 | t.equal(buf.toString(), 'hey')
34 |
35 | buf = codec.encodeValue('686579', {
36 | valueEncoding: 'binary'
37 | })
38 | t.equal(buf.toString(), '686579')
39 |
40 | t.end()
41 | })
42 |
43 | test('decode key', function (t) {
44 | const codec = new Codec({ keyEncoding: 'hex' })
45 |
46 | let buf = codec.decodeKey(Buffer.from('hey'), {})
47 | t.equal(buf, '686579')
48 |
49 | buf = codec.decodeKey(Buffer.from('hey'))
50 | t.equal(buf, '686579')
51 |
52 | buf = codec.decodeKey(Buffer.from('hey'), {
53 | keyEncoding: 'binary'
54 | })
55 | t.equal(buf.toString(), 'hey')
56 |
57 | t.end()
58 | })
59 |
60 | test('decode value', function (t) {
61 | const codec = new Codec({ valueEncoding: 'hex' })
62 |
63 | let buf = codec.decodeValue(Buffer.from('hey'), {})
64 | t.equal(buf, '686579')
65 |
66 | buf = codec.decodeValue(Buffer.from('hey'))
67 | t.equal(buf, '686579')
68 |
69 | buf = codec.decodeValue(Buffer.from('hey'), {
70 | valueEncoding: 'binary'
71 | })
72 | t.equal(buf.toString(), 'hey')
73 |
74 | t.end()
75 | })
76 |
77 | test('encode value - legacy', function (t) {
78 | const codec = new Codec({ encoding: 'hex' })
79 |
80 | let buf = codec.encodeValue('686579', {})
81 | t.equal(buf.toString(), 'hey')
82 |
83 | buf = codec.encodeValue('686579')
84 | t.equal(buf.toString(), 'hey')
85 |
86 | buf = codec.encodeValue('686579', {
87 | encoding: 'binary'
88 | })
89 | t.equal(buf.toString(), '686579')
90 |
91 | t.end()
92 | })
93 |
94 | test('decode value - legacy', function (t) {
95 | const codec = new Codec({ encoding: 'hex' })
96 |
97 | let buf = codec.decodeValue(Buffer.from('hey'), {})
98 | t.equal(buf, '686579')
99 |
100 | buf = codec.decodeValue(Buffer.from('hey'))
101 | t.equal(buf, '686579')
102 |
103 | buf = codec.decodeValue(Buffer.from('hey'), {
104 | encoding: 'binary'
105 | })
106 | t.equal(buf.toString(), 'hey')
107 |
108 | t.end()
109 | })
110 |
--------------------------------------------------------------------------------
/test/ltgt.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const Codec = require('..')
3 |
4 | test('encode ltgt', function (t) {
5 | const codec = new Codec({ keyEncoding: 'hex' })
6 |
7 | let ltgt = {
8 | gte: '686579',
9 | lte: '686579'
10 | }
11 | let encoded = codec.encodeLtgt(ltgt)
12 | t.equal(encoded.gte.toString(), 'hey')
13 | t.equal(encoded.lte.toString(), 'hey')
14 |
15 | ltgt = {
16 | gte: '686579',
17 | lte: '686579',
18 | keyEncoding: 'json'
19 | }
20 | encoded = codec.encodeLtgt(ltgt)
21 | t.equal(encoded.gte, '"686579"')
22 | t.equal(encoded.lte, '"686579"')
23 |
24 | t.end()
25 | })
26 |
27 | test('rejects legacy range options', function (t) {
28 | t.plan(2)
29 |
30 | const codec = new Codec()
31 |
32 | for (const k of ['start', 'end']) {
33 | try {
34 | codec.encodeLtgt({ [k]: 123 })
35 | } catch (err) {
36 | t.is(err.message, 'Legacy range options ("start" and "end") have been removed')
37 | }
38 | }
39 | })
40 |
--------------------------------------------------------------------------------