From 48819a968f81e08d6e7055a70128d03cba5457a0 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sat, 5 Sep 2015 21:02:33 +0100 Subject: [PATCH 01/22] Initial commit --- .gitignore | 27 +++++++++++++++++++++++++++ LICENSE | 22 ++++++++++++++++++++++ README.md | 2 ++ 3 files changed, 51 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..123ae94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git +node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..59a33ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 David Dias + +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. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..bcae663 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# abstract-record-store +A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. From 46f9cbebaa2ce35149e2fa3b7725e8fb1e3e0001 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 10:33:08 +0100 Subject: [PATCH 02/22] add badge --- README.md | 37 +++++++++++++++++++++++++++++++++++-- img/badge.png | Bin 0 -> 7315 bytes img/badge.sketch | Bin 0 -> 49152 bytes img/badge.svg | 18 ++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 img/badge.png create mode 100644 img/badge.sketch create mode 100644 img/badge.svg diff --git a/README.md b/README.md index bcae663..8ec1f4c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,35 @@ -# abstract-record-store -A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. +abstract-record-store +===================== + +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) + +> A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. + +The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`abstract-stream-muxer`](https://github.com/diasdavid/abstract-stream-muxer). + +Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. + +The API is presented with both Node.js and Go primitives, however, there is not actual limitations for it to be extended for any other language, pushing forward the cross compatibility and interop through diferent stacks. + +# Modules that implement the interface + +- [ipfs-distributed-record-store](https://github.com/diasdavid/node-ipfs-distributed-record-store) +- [ipfs-kad-record-store](https://github.com/diasdavid/node-ipfs-kad-record-store) + +# Badge + +Include this badge in your readme if you make a module that is compatible with the abstract-record-store API. You can validate this by running the tests. + + + +# How to use the battery of tests + +## Node.js + +## Go + +> WIP + +# API + + diff --git a/img/badge.png b/img/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1a460730c7332353e4ee236fa085b781a2bcd5 GIT binary patch literal 7315 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 t9wX?N-0sKTS7oWN<>nT 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 + + + badge + Created with Sketch. + + + + + Record Store + + + Compatibl + e + + + + \ No newline at end of file From 79589458c2b783d941ec020325237bcdc35e608e Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 12:19:07 +0100 Subject: [PATCH 03/22] add API interface and considerations --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ec1f4c..78fef94 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,61 @@ The API is presented with both Node.js and Go primitives, however, there is not Include this badge in your readme if you make a module that is compatible with the abstract-record-store API. You can validate this by running the tests. - +![](https://raw.githubusercontent.com/diasdavid/abstract-record-store/master/img/badge.png) # How to use the battery of tests ## Node.js +``` +var tape = require('tape') +var tests = require('abstract-stream-muxer/tests') +var YourRecordStore = require('../src') + +var common = { + setup: function (t, cb) { + cb(null, YourStreamMuxer) + }, + teardown: function (t, cb) { + cb() + } +} + +tests(tape, common) +``` + ## Go > WIP # API +A valid (read: that follows this abstraction) stream muxer, must implement the following API. +### Obtain a Record + +- `Node.js` rs.get(key, function (err, records) {}) + +This method returns an array of records, found in the Record Store. + +If `err` is passed, `records` will be a `undefined` value. + +`key` is a multihash value that represents any arbitraty random value, that may have records associated with it. + +### Store a Record + +- `Node.js` rs.put(key, recordSignatureMultiHash, function (err) {}) + +`recordSignatureMultihash` is multihash of the Record Signature MerkleDAG obj, as described by IPRS - InterPlanetary Record Spec + +if `err` is passed, means that the record wasn't stored properly or it was unvalid. + +### Implementation considerations + + +- the key is a multihash but not necessarily the hash of the record signature object. +- a DRS instance must have a mapping of key->[hash(recordSignature)] to know which records belong to a given key (provided value) +- DRS implements the abstract-record-store interface +- DRS may levarage other implementations of abstract-record-store to find records in the network or other storage mechanisms +- DRS should return every valid record it can find in a query +- all unvalid records detected in the process should be discarded/deleted From 9d56ac50e15a14fd805b6387654f7d85bfb987fd Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 12:39:19 +0100 Subject: [PATCH 04/22] add base test setup --- README.md | 2 +- package.json | 24 ++++++++++++++++++++++++ tests/base-test.js | 15 +++++++++++++++ tests/index.js | 6 ++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 package.json create mode 100644 tests/base-test.js create mode 100644 tests/index.js diff --git a/README.md b/README.md index 78fef94..c2cb169 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ abstract-record-store ===================== -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) > A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. diff --git a/package.json b/package.json new file mode 100644 index 0000000..8f8e331 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "abstract-record-store", + "version": "0.0.0", + "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/diasdavid/abstract-record-store.git" + }, + "keywords": [ + "IPFS" + ], + "author": "David Dias ", + "license": "MIT", + "bugs": { + "url": "https://github.com/diasdavid/abstract-record-store/issues" + }, + "homepage": "https://github.com/diasdavid/abstract-record-store", + "dependencies": { + "timed-tape": "^0.1.0" + } +} diff --git a/tests/base-test.js b/tests/base-test.js new file mode 100644 index 0000000..49ea253 --- /dev/null +++ b/tests/base-test.js @@ -0,0 +1,15 @@ +module.exports.all = function (test, common) { + + test('Store a valid record', function (t) { + common.setup(test, function (err, recordStore) { + t.ifError(err, 'Should not throw') + t.pass('woo') + }) + }) + + test('Store an unvalid record') + test('Store and retrieve a valid record') + test('Store a bunch of valid and unvalid records and check what gets retrieved') + test('Store a bunch of records with variable validity, wait for some to expire, check what gets retrieved') + +} diff --git a/tests/index.js b/tests/index.js new file mode 100644 index 0000000..b232406 --- /dev/null +++ b/tests/index.js @@ -0,0 +1,6 @@ +var timed = require('timed-tape') + +module.exports = function (test, common) { + test = timed(test) + require('./base-test.js').all(test, common) +} From c24e2852755a34b1410bba72aa836ac12a9a872a Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 14:26:21 +0100 Subject: [PATCH 05/22] remove muxer refs --- README.md | 4 +-- package.json | 3 ++ tests/base-test.js | 80 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c2cb169..6edefc5 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,12 @@ Include this badge in your readme if you make a module that is compatible with t ``` var tape = require('tape') -var tests = require('abstract-stream-muxer/tests') +var tests = require('abstract-record-store/tests') var YourRecordStore = require('../src') var common = { setup: function (t, cb) { - cb(null, YourStreamMuxer) + cb(null, YourRecordStore) }, teardown: function (t, cb) { cb() diff --git a/package.json b/package.json index 8f8e331..87a690f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,9 @@ }, "homepage": "https://github.com/diasdavid/abstract-record-store", "dependencies": { + "ecdsa": "^0.6.0", + "ipld": "^0.1.3", + "multihashing": "^0.1.3", "timed-tape": "^0.1.0" } } diff --git a/tests/base-test.js b/tests/base-test.js index 49ea253..75ccfd9 100644 --- a/tests/base-test.js +++ b/tests/base-test.js @@ -1,15 +1,85 @@ +var crypto = require('crypto') +var multihashing = require('multihashing') +var ipld = require('ipld') +var ecdsa = require('ecdsa') + module.exports.all = function (test, common) { test('Store a valid record', function (t) { common.setup(test, function (err, recordStore) { t.ifError(err, 'Should not throw') - t.pass('woo') + + var mdagStore = recordStore.mdagStore + + var ecdh = crypto.createECDH('secp256k1') + ecdh.generateKeys() + + var mdagObj_pubKey = { + '@context': ipld.context.merkleweb, + algorithm: { + mlink: 'secp256k1' + }, + encoding: { + mlink: 'raw' + }, + bytes: ecdh.getPublicKey() + } + + var mdagObj_pubKey_encoded = ipld.marshal(mdagObj_pubKey) + var mdagObj_pubKey_mh = multihashing(mdagObj_pubKey_encoded, 'sha2-256') + mdagStore.put(mdagObj_pubKey, mdagObj_pubKey_mh) + + var current = new Date() + + var mdagObj_record = { + '@context': ipld.context.merkleweb, + scheme: { + mlink: 'type-a' + }, + expires: (new Date()).setDate(current.getDate() + 1), + value: 'aaah the data!' + } + + var mdagObj_record_encoded = ipld.marshal(mdagObj_record) + var mdagObj_record_mh = multihashing(mdagObj_record_encoded, 'sha2-256') + mdagStore.put(mdagObj_record, mdagObj_record_mh) + + var mdagObj_record_encoded_hash = crypto.createHash('sha256').update(mdagObj_record_encoded).digest() + var record_signed = ecdsa.sign(mdagObj_record_encoded_hash, ecdh.getPrivateKey()) + + var mdagObj_record_signature = { + '@context': ipld.context.merkleweb, + pubKey: { + mlink: mdagObj_pubKey_mh + }, + algorithm: { + mlink: 'secp256k1' + }, + encoding: { + mlink: 'binary' + }, + signee: { + mlink: mdagObj_record_mh + }, + bytes: record_signed + } + + var mdagObj_record_signature_encoded = ipld.marshal(mdagObj_record_signature) + var mdagObj_record_signature_encoded_mh = multihashing(mdagObj_record_signature_encoded, 'sha2-256') + + mdagStore.put(mdagObj_record_signature, mdagObj_record_signature_encoded_mh) + + recordStore.put('bananas', mdagObj_record_signature, function (err) { + t.ifError(err, 'Should not throw') + t.pass('record was stored successfully') + t.end() + }) }) }) - test('Store an unvalid record') - test('Store and retrieve a valid record') - test('Store a bunch of valid and unvalid records and check what gets retrieved') - test('Store a bunch of records with variable validity, wait for some to expire, check what gets retrieved') + // test('Store an unvalid record') + // test('Store and retrieve a valid record') + // test('Store a bunch of valid and unvalid records and check what gets retrieved') + // test('Store a bunch of records with variable validity, wait for some to expire, check what gets retrieved') } From 987474b014a853a02bd678fe92ae4fe3b34d803d Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 14:38:38 +0100 Subject: [PATCH 06/22] it works --- tests/base-test.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/base-test.js b/tests/base-test.js index 75ccfd9..ba8d22c 100644 --- a/tests/base-test.js +++ b/tests/base-test.js @@ -71,8 +71,13 @@ module.exports.all = function (test, common) { recordStore.put('bananas', mdagObj_record_signature, function (err) { t.ifError(err, 'Should not throw') - t.pass('record was stored successfully') - t.end() + recordStore.get('bananas', function (err, records) { + t.ifError(err, 'Should not throw') + t.equal(records.length, 1) + t.pass('record was stored successfully') + t.end() + }) + }) }) }) From fc1e4d7c877c24e4cb809eba0d776c39b075dd91 Mon Sep 17 00:00:00 2001 From: David Dias Date: Sun, 6 Sep 2015 14:38:47 +0100 Subject: [PATCH 07/22] Release v0.1.0. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87a690f..09fd44f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "abstract-record-store", - "version": "0.0.0", + "version": "0.1.0", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 79532e01c6270e655a3ded41112f32f14b9b4a0e Mon Sep 17 00:00:00 2001 From: David Dias Date: Mon, 14 Sep 2015 11:19:22 +0100 Subject: [PATCH 08/22] update dependencies to work with nodev4 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 09fd44f..2b0d9db 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "keywords": [ "IPFS" ], + "engines" : { "node" : "^4.0.0" }, "author": "David Dias ", "license": "MIT", "bugs": { @@ -20,7 +21,7 @@ "homepage": "https://github.com/diasdavid/abstract-record-store", "dependencies": { "ecdsa": "^0.6.0", - "ipld": "^0.1.3", + "ipld": "^0.2.0", "multihashing": "^0.1.3", "timed-tape": "^0.1.0" } From 4a9eabb29320b6e52ec5a9b04b51a09c5a508e65 Mon Sep 17 00:00:00 2001 From: David Dias Date: Mon, 14 Sep 2015 11:20:19 +0100 Subject: [PATCH 09/22] Release v0.1.1. --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2b0d9db..3e3df62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "abstract-record-store", - "version": "0.1.0", + "version": "0.1.1", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -12,7 +12,9 @@ "keywords": [ "IPFS" ], - "engines" : { "node" : "^4.0.0" }, + "engines": { + "node": "^4.0.0" + }, "author": "David Dias ", "license": "MIT", "bugs": { From 894bb69f18015c48c46de0d8b7c3e7769b09f04a Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 11 Dec 2015 20:27:55 -0800 Subject: [PATCH 10/22] update name --- README.md | 14 +++++++------- package.json | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 6edefc5..6c27305 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -abstract-record-store +interface-record-store ===================== [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) > A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. -The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`abstract-stream-muxer`](https://github.com/diasdavid/abstract-stream-muxer). +The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/diasdavid/interface-stream-muxer). Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. @@ -18,9 +18,9 @@ The API is presented with both Node.js and Go primitives, however, there is not # Badge -Include this badge in your readme if you make a module that is compatible with the abstract-record-store API. You can validate this by running the tests. +Include this badge in your readme if you make a module that is compatible with the interface-record-store API. You can validate this by running the tests. -![](https://raw.githubusercontent.com/diasdavid/abstract-record-store/master/img/badge.png) +![](https://raw.githubusercontent.com/diasdavid/interface-record-store/master/img/badge.png) # How to use the battery of tests @@ -28,7 +28,7 @@ Include this badge in your readme if you make a module that is compatible with t ``` var tape = require('tape') -var tests = require('abstract-record-store/tests') +var tests = require('interface-record-store/tests') var YourRecordStore = require('../src') var common = { @@ -74,7 +74,7 @@ if `err` is passed, means that the record wasn't stored properly or it was unval - the key is a multihash but not necessarily the hash of the record signature object. - a DRS instance must have a mapping of key->[hash(recordSignature)] to know which records belong to a given key (provided value) -- DRS implements the abstract-record-store interface -- DRS may levarage other implementations of abstract-record-store to find records in the network or other storage mechanisms +- DRS implements the interface-record-store interface +- DRS may levarage other implementations of interface-record-store to find records in the network or other storage mechanisms - DRS should return every valid record it can find in a query - all unvalid records detected in the process should be discarded/deleted diff --git a/package.json b/package.json index 3e3df62..1d8aba7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "abstract-record-store", + "name": "interface-record-store", "version": "0.1.1", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", "scripts": { @@ -7,7 +7,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/diasdavid/abstract-record-store.git" + "url": "https://github.com/diasdavid/interface-record-store.git" }, "keywords": [ "IPFS" @@ -18,9 +18,9 @@ "author": "David Dias ", "license": "MIT", "bugs": { - "url": "https://github.com/diasdavid/abstract-record-store/issues" + "url": "https://github.com/diasdavid/interface-record-store/issues" }, - "homepage": "https://github.com/diasdavid/abstract-record-store", + "homepage": "https://github.com/diasdavid/interface-record-store", "dependencies": { "ecdsa": "^0.6.0", "ipld": "^0.2.0", From 00af5695fb1fba37c57173b2984a61e4cf336251 Mon Sep 17 00:00:00 2001 From: David Dias Date: Fri, 11 Dec 2015 20:28:06 -0800 Subject: [PATCH 11/22] Release v0.1.2. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d8aba7..d8eb994 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-record-store", - "version": "0.1.1", + "version": "0.1.2", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 45e143598c7da31d2ba782f55dfdffa4ce20f8e3 Mon Sep 17 00:00:00 2001 From: David Dias Date: Tue, 22 Mar 2016 14:26:42 +0000 Subject: [PATCH 12/22] update ipld dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8eb994..f470fbd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "homepage": "https://github.com/diasdavid/interface-record-store", "dependencies": { "ecdsa": "^0.6.0", - "ipld": "^0.2.0", + "ipld": "^0.4.0", "multihashing": "^0.1.3", "timed-tape": "^0.1.0" } From 39af5822fa993fa79d6c79de311332d1e8586a7d Mon Sep 17 00:00:00 2001 From: David Dias Date: Tue, 22 Mar 2016 14:26:52 +0000 Subject: [PATCH 13/22] Release v0.1.3. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f470fbd..f3d2b55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interface-record-store", - "version": "0.1.2", + "version": "0.1.3", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 811e27e75e598f49348c98f8adad4b28801a800c Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 4 Aug 2016 19:12:25 +0200 Subject: [PATCH 14/22] chore(package): update dependencies https://greenkeeper.io/ --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f3d2b55..99f0fba 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,9 @@ }, "homepage": "https://github.com/diasdavid/interface-record-store", "dependencies": { - "ecdsa": "^0.6.0", - "ipld": "^0.4.0", - "multihashing": "^0.1.3", + "ecdsa": "^0.7.0", + "ipld": "^0.6.0", + "multihashing": "^0.2.1", "timed-tape": "^0.1.0" } } From 2ef6c67834a7ea77500721dbf1ff84dd39a22134 Mon Sep 17 00:00:00 2001 From: Patrik Wallstrom Date: Tue, 27 Sep 2016 13:33:13 +0200 Subject: [PATCH 15/22] Working link to IPRS spec --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c27305..d2b6601 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ interface-record-store [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) -> A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. +> A test suite and interface you can use to implement a a [IPRS compliant](https://github.com/ipfs/specs/tree/master/iprs-interplanetary-record-system) Record Store. The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/diasdavid/interface-stream-muxer). From cf45d844429024b1054d10c2768d2e4dfea837ac Mon Sep 17 00:00:00 2001 From: Richard Littauer Date: Fri, 30 Sep 2016 14:42:28 -0400 Subject: [PATCH 16/22] Update README URLs based on HTTP redirects --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6c27305..027fd7e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ interface-record-store > A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store. -The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/diasdavid/interface-stream-muxer). +The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/libp2p/interface-stream-muxer). Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. @@ -13,8 +13,8 @@ The API is presented with both Node.js and Go primitives, however, there is not # Modules that implement the interface -- [ipfs-distributed-record-store](https://github.com/diasdavid/node-ipfs-distributed-record-store) -- [ipfs-kad-record-store](https://github.com/diasdavid/node-ipfs-kad-record-store) +- [ipfs-distributed-record-store](https://github.com/libp2p/js-libp2p-distributed-record-store) +- [ipfs-kad-record-store](https://github.com/libp2p/js-libp2p-kad-record-store) # Badge From 9bea979b085b4a4f2f13996d4db618c0c78e2246 Mon Sep 17 00:00:00 2001 From: David Dias Date: Thu, 9 Feb 2017 08:50:57 -0800 Subject: [PATCH 17/22] chore: ^ to ~ --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 99f0fba..f0f67c3 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/diasdavid/interface-record-store.git" + "url": "https://github.com/libp2p/interface-record-store.git" }, "keywords": [ "IPFS" @@ -18,13 +18,13 @@ "author": "David Dias ", "license": "MIT", "bugs": { - "url": "https://github.com/diasdavid/interface-record-store/issues" + "url": "https://github.com/libp2p/interface-record-store/issues" }, - "homepage": "https://github.com/diasdavid/interface-record-store", + "homepage": "https://github.com/libp2p/interface-record-store", "dependencies": { - "ecdsa": "^0.7.0", - "ipld": "^0.6.0", - "multihashing": "^0.2.1", - "timed-tape": "^0.1.0" + "ecdsa": "~0.7.0", + "ipld": "~0.6.0", + "multihashing": "~0.2.2", + "timed-tape": "~0.1.1" } } From b2b928b25a7d73164de2211438a98f737a47cae5 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 16 Mar 2017 15:54:23 +0100 Subject: [PATCH 18/22] chore(package): update multihashing to version 0.3.2 https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f0f67c3..d8de813 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dependencies": { "ecdsa": "~0.7.0", "ipld": "~0.6.0", - "multihashing": "~0.2.2", + "multihashing": "~0.3.2", "timed-tape": "~0.1.1" } } From 057c8d3e6cb5b6897ec32979310199264fa9e8fb Mon Sep 17 00:00:00 2001 From: Greg Zuro Date: Mon, 24 Jul 2017 13:07:55 -0700 Subject: [PATCH 19/22] fix iprs url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc46073..2c98a18 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ interface-record-store [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) -> A test suite and interface you can use to implement a a [IPRS compliant](https://github.com/ipfs/specs/tree/master/iprs-interplanetary-record-system) Record Store. +> A test suite and interface you can use to implement a a [IPRS compliant](https://github.com/ipfs/specs/tree/master/iprs) Record Store. The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/libp2p/interface-stream-muxer). From 305ec4eb4b514498dd1a705a648a3972f4990a5c Mon Sep 17 00:00:00 2001 From: James Ray <16969914+jamesray1@users.noreply.github.com> Date: Wed, 6 Jun 2018 18:05:18 +1000 Subject: [PATCH 20/22] Fix IPRS URL again --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c98a18..462d60e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ interface-record-store [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) -> A test suite and interface you can use to implement a a [IPRS compliant](https://github.com/ipfs/specs/tree/master/iprs) Record Store. +> A test suite and interface you can use to implement a a [IPRS compliant](/IPRS.md) Record Store. The primary goal of this module is to enable developers to pick and swap their Record Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by [`abstract-blob-store`](https://github.com/maxogden/abstract-blob-store) and [`interface-stream-muxer`](https://github.com/libp2p/interface-stream-muxer). From afc24e9137571d6b051e92f2cc5ce94708ca78ec Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 31 Oct 2018 13:49:01 +0000 Subject: [PATCH 21/22] docs: add lead-maintainer --- README.md | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 462d60e..dc86aa0 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Publishing a test suite as a module lets multiple modules all ensure compatibili The API is presented with both Node.js and Go primitives, however, there is not actual limitations for it to be extended for any other language, pushing forward the cross compatibility and interop through diferent stacks. +## Lead Maintainer + +[Vasco Santos](https://github.com/vasco-santos). + # Modules that implement the interface - [ipfs-distributed-record-store](https://github.com/libp2p/js-libp2p-distributed-record-store) diff --git a/package.json b/package.json index d8de813..8c1f85e 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "interface-record-store", "version": "0.1.3", "description": "A test suite and interface you can use to implement a a IPRS compliant(https://github.com/ipfs/specs/tree/master/records) Record Store", + "leadMaintainer": "Vasco Santos ", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, From a9c6842386ce66e10a951b35f9add14b2dd041e4 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Fri, 26 Apr 2019 14:04:21 +0100 Subject: [PATCH 22/22] chore: add discourse badge (#15) --- README.md | 5 ++++- package.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dc86aa0..26320a6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ interface-record-store ===================== -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) +[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai) +[![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) +[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) > A test suite and interface you can use to implement a a [IPRS compliant](/IPRS.md) Record Store. diff --git a/package.json b/package.json index 8c1f85e..c66ae37 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "homepage": "https://github.com/libp2p/interface-record-store", "dependencies": { "ecdsa": "~0.7.0", - "ipld": "~0.6.0", - "multihashing": "~0.3.2", + "ipld": "~0.22.0", + "multihashing": "~0.3.3", "timed-tape": "~0.1.1" } }