diff --git a/README.md b/README.md index 80fa390..f86ea6d 100644 --- a/README.md +++ b/README.md @@ -75,9 +75,9 @@ Try to subscribe a topic with Pubsub and receive the current local value if avai Arguments: -- `key` (Buffer): a key representing a unique identifier of the object to subscribe. +- `key` (Uint8Array): a key representing a unique identifier of the object to subscribe. -Returns `Promise` containing the most recent known record stored. +Returns `Promise` containing the most recent known record stored. #### Put @@ -89,8 +89,8 @@ Publishes a value through pubsub. Arguments: -- `key` (Buffer): a key representing a unique identifier of the object to publish. -- `val` (Buffer): value to be propagated. +- `key` (Uint8Array): a key representing a unique identifier of the object to publish. +- `val` (Uint8Array): value to be propagated. Returns `Promise` @@ -104,7 +104,7 @@ Unsubscribe a previously subscribe value. Arguments: -- `key` (Buffer): a key representing a unique identifier of the object to publish. +- `key` (Uint8Array): a key representing a unique identifier of the object to publish. Returns `Promise` diff --git a/package.json b/package.json index 8947bd3..11ef346 100644 --- a/package.json +++ b/package.json @@ -32,20 +32,18 @@ }, "homepage": "https://github.com/ipfs/js-datastore-pubsub#readme", "dependencies": { - "buffer": "^5.6.0", "debug": "^4.1.1", "err-code": "^2.0.3", - "interface-datastore": "^1.0.4", - "multibase": "^0.7.0" + "interface-datastore": "^2.0.0", + "multibase": "^2.0.0" }, "devDependencies": { "aegir": "^25.0.0", - "chai": "^4.2.0", "detect-node": "^2.0.4", - "dirty-chai": "^2.0.1", + "ipfs-utils": "^2.3.1", "it-pair": "^1.0.0", "libp2p-gossipsub": "^0.4.5", - "libp2p-record": "^0.7.3", + "libp2p-record": "^0.8.0", "p-wait-for": "^3.1.0", "peer-id": "^0.13.13", "sinon": "^9.0.2" diff --git a/src/index.js b/src/index.js index 7e58f35..3524914 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ 'use strict' -const { Buffer } = require('buffer') const { Key, Adapter } = require('interface-datastore') const { encodeBase32, keyToTopic, topicToKey } = require('./utils') @@ -54,20 +53,20 @@ class DatastorePubsub extends Adapter { /** * Publishes a value through pubsub. - * @param {Buffer} key identifier of the value to be published. - * @param {Buffer} val value to be propagated. + * @param {Uint8Array} key identifier of the value to be published. + * @param {Uint8Array} val value to be propagated. * @returns {Promise} */ async put (key, val) { // eslint-disable-line require-await - if (!Buffer.isBuffer(key)) { + if (!(key instanceof Uint8Array)) { const errMsg = 'datastore key does not have a valid format' log.error(errMsg) throw errcode(new Error(errMsg), 'ERR_INVALID_DATASTORE_KEY') } - if (!Buffer.isBuffer(val)) { - const errMsg = 'received value is not a buffer' + if (!(val instanceof Uint8Array)) { + const errMsg = 'received value is not a Uint8Array' log.error(errMsg) throw errcode(new Error(errMsg), 'ERR_INVALID_VALUE_RECEIVED') @@ -83,11 +82,11 @@ class DatastorePubsub extends Adapter { /** * Try to subscribe a topic with Pubsub and returns the local value if available. - * @param {Buffer} key identifier of the value to be subscribed. - * @returns {Promise} + * @param {Uint8Array} key identifier of the value to be subscribed. + * @returns {Promise} */ async get (key) { - if (!Buffer.isBuffer(key)) { + if (!(key instanceof Uint8Array)) { const errMsg = 'datastore key does not have a valid format' log.error(errMsg) @@ -118,7 +117,7 @@ class DatastorePubsub extends Adapter { /** * Unsubscribe topic. - * @param {Buffer} key identifier of the value to unsubscribe. + * @param {Uint8Array} key identifier of the value to unsubscribe. * @returns {void} */ unsubscribe (key) { @@ -148,7 +147,7 @@ class DatastorePubsub extends Adapter { throw errcode(new Error(errMsg), 'ERR_NOT_FOUND') } - if (!Buffer.isBuffer(dsVal)) { + if (!(dsVal instanceof Uint8Array)) { const errMsg = 'found record that we couldn\'t convert to a value' log.error(errMsg) @@ -210,7 +209,7 @@ class DatastorePubsub extends Adapter { } if (isBetter) { - await this._storeRecord(Buffer.from(key), data) + await this._storeRecord(key, data) } } @@ -251,7 +250,7 @@ class DatastorePubsub extends Adapter { let currentRecord try { - currentRecord = await this._getLocal(dsKey.toBuffer()) + currentRecord = await this._getLocal(dsKey.uint8Array()) } catch (err) { // if the old one is invalid, the new one is *always* better return true diff --git a/src/utils.js b/src/utils.js index 66b6727..08aa6bc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,6 +2,10 @@ const multibase = require('multibase') const errcode = require('err-code') +const TextEncoder = require('ipfs-utils/src/text-encoder') +const TextDecoder = require('ipfs-utils/src/text-decoder') +const utf8Encoder = new TextEncoder('utf8') +const utf8Decoder = new TextDecoder('utf8') const namespace = '/record/' const base64urlCode = 'u' // base64url code from multibase @@ -14,7 +18,11 @@ module.exports.encodeBase32 = (buf) => { module.exports.keyToTopic = (key) => { // Record-store keys are arbitrary binary. However, pubsub requires UTF-8 string topic IDs // Encodes to "/record/base64url(key)" - const b64url = multibase.encode('base64url', key).slice(1).toString() + if (typeof key === 'string' || key instanceof String) { + key = utf8Encoder.encode(key) + } + + const b64url = utf8Decoder.decode(multibase.encode('base64url', key).slice(1)) return `${namespace}${b64url}` } diff --git a/test/index.spec.js b/test/index.spec.js index fbb1a0b..d515168 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,14 +1,12 @@ /* eslint-env mocha */ 'use strict' -const { Buffer } = require('buffer') -const chai = require('chai') -const dirtyChai = require('dirty-chai') -const expect = chai.expect -chai.use(dirtyChai) +const { expect } = require('aegir/utils/chai') const sinon = require('sinon') const errcode = require('err-code') const isNode = require('detect-node') +const TextEncoder = require('ipfs-utils/src/text-encoder') +const utf8Encoder = new TextEncoder('utf8') const DatastorePubsub = require('../src') @@ -84,8 +82,8 @@ describe('datastore-pubsub', function () { // prepare Record beforeEach(() => { keyRef = `key${testCounter}` - key = (new Key(keyRef)).toBuffer() - record = new Record(key, Buffer.from(value)) + key = (new Key(keyRef)).uint8Array() + record = new Record(key, utf8Encoder.encode(value)) serializedRecord = record.serialize() }) @@ -110,13 +108,8 @@ describe('datastore-pubsub', function () { expect(subscribers).to.exist() expect(subscribers).to.not.include(subsTopic) // not subscribed key reference yet - const res = await dsPubsubA.get(key) - .then(() => expect.fail('Should have failed to fetch key'), (err) => { - // not locally stored record - expect(err.code).to.equal('ERR_NOT_FOUND') - }) - - expect(res).to.not.exist() + // not locally stored record + await expect(dsPubsubA.get(key)).to.eventually.be.rejected().with.property('code', 'ERR_NOT_FOUND') subscribers = await pubsubA.getTopics() @@ -327,7 +320,7 @@ describe('datastore-pubsub', function () { } const newValue = 'new value' - const record = new Record(key, Buffer.from(newValue)) + const record = new Record(key, utf8Encoder.encode(newValue)) const newSerializedRecord = record.serialize() const dsPubsubA = new DatastorePubsub(pubsubA, datastoreA, peerIdA, smoothValidator) @@ -377,7 +370,7 @@ describe('datastore-pubsub', function () { } const newValue = 'new value' - const record = new Record(key, Buffer.from(newValue)) + const record = new Record(key, utf8Encoder.encode(newValue)) const newSerializedRecord = record.serialize() const dsPubsubA = new DatastorePubsub(pubsubA, datastoreA, peerIdA, smoothValidator)