1 | # lucass (Lightweight Universal Content Addressable Storage Spec)
|
2 |
|
3 | [![Coverage Status](https://coveralls.io/repos/github/mikeal/lucass/badge.svg?branch=master)](https://coveralls.io/github/mikeal/lucass?branch=master)
|
4 | [![Build Status](https://travis-ci.org/mikeal/lucass.svg?branch=master)](https://travis-ci.org/mikeal/lucass)
|
5 | [![dependencies Status](https://david-dm.org/mikeal/lucass/status.svg)](https://david-dm.org/mikeal/lucass)
|
6 |
|
7 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
|
8 | [![Greenkeeper badge](https://badges.greenkeeper.io/mikeal/lucass.svg)](https://greenkeeper.io/)
|
9 | [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
|
10 | [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
|
11 |
|
12 | There are a bunch of content addressable stores out there, and even some abstract store specs. A few things that are different about lucass:
|
13 |
|
14 | * There is **NO** requirement that implementations use a specific hashing method, only that the method they use is consistent.
|
15 | * This means that there can be many more types of implementations but that they aren't compatible by default. Users of each implementation may need to configure the hashing methods.
|
16 | * Requires support for both Buffers and Streams as values.
|
17 |
|
18 | This module contains compliance tests and two reference implementations (filesystem and inmemory).
|
19 |
|
20 | ## Spec
|
21 |
|
22 | ```javascript
|
23 | class Store {
|
24 | async set (value, cb) {
|
25 | // value is either a Buffer or a Stream, both must be supported.
|
26 | // cb(Error, Hash)
|
27 | // Hash must be consistent. Data written with Buffer or Stream should
|
28 | // be identical.
|
29 | // Hash must be a String.
|
30 | }
|
31 | async get (hash, cb) {
|
32 | // Hash must be a String.
|
33 | // returns a buffer.
|
34 | }
|
35 | async hash (value, cb) {
|
36 | // Identical method signature to set but MUST NOT store the value.
|
37 | }
|
38 | }
|
39 | ```
|
40 |
|
41 | There are also optional APIs. These are not required as they may not be
|
42 | possible on top of certain storage but *may* be required by certain users
|
43 | of an implementation.
|
44 |
|
45 | ```javascript
|
46 | class Store {
|
47 | async set (value, ...args) {
|
48 | // Optional args are sent to the hashing function..
|
49 | }
|
50 | async hash (value, ...args) {
|
51 | // Optional args are sent to the hashing function.
|
52 | }
|
53 | async missing (hashes) {
|
54 | // Optional array of hashes. Missing hashes will be returned.
|
55 | }
|
56 | }
|
57 | ```
|
58 |
|
59 | ## In-Memory Implementation
|
60 |
|
61 | ```javascript
|
62 | let store = require('lucass/inmemory')()
|
63 | let hasher = await store.set(Buffer.from('asdf'))
|
64 | let value = await store.getBuffer(hash)
|
65 | console.log(value.toString()) // 'asdf'
|
66 | ```
|
67 |
|
68 | Additionally, all methods in the spec are implemented.
|
69 |
|
70 | ## Filesystem Implementation
|
71 |
|
72 | ```javascript
|
73 | let store = require('lucass/fs')('/var/custom-directory')
|
74 | let hasher = await store.set(Buffer.from('asdf'))
|
75 | let value = await store.getBuffer(hash)
|
76 | console.log(value.toString()) // 'asdf'
|
77 | ```
|
78 |
|
79 | Additionally, all methods in the spec are implemented.
|