├── test ├── fixtures │ ├── empty-obj.js │ ├── empty-array.js │ ├── foo.cbor │ ├── README.md │ ├── obj-no-link.js │ ├── empty-obj.cbor │ ├── array-link.cbor │ ├── empty-array.cbor │ ├── obj-no-link.cbor │ ├── obj-with-link.cbor │ ├── array-link.js │ ├── obj-with-link.js │ ├── foo.js │ └── expected.js ├── mod.spec.js ├── resolver.spec.js ├── interop.spec.js └── util.spec.js ├── tsconfig.json ├── src ├── index.js ├── resolver.js └── util.js ├── .npmignore ├── .gitignore ├── .travis.yml ├── LICENSE ├── package.json ├── README.md └── CHANGELOG.md /test/fixtures/empty-obj.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = {} 4 | -------------------------------------------------------------------------------- /test/fixtures/empty-array.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = [] 4 | -------------------------------------------------------------------------------- /test/fixtures/foo.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/foo.cbor -------------------------------------------------------------------------------- /test/fixtures/README.md: -------------------------------------------------------------------------------- 1 | Extracted from: https://github.com/ipfs/go-ipld-cbor/tree/master/test_objects 2 | -------------------------------------------------------------------------------- /test/fixtures/obj-no-link.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | sassafras: 'and cats' 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/empty-obj.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/empty-obj.cbor -------------------------------------------------------------------------------- /test/fixtures/array-link.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/array-link.cbor -------------------------------------------------------------------------------- /test/fixtures/empty-array.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/empty-array.cbor -------------------------------------------------------------------------------- /test/fixtures/obj-no-link.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/obj-no-link.cbor -------------------------------------------------------------------------------- /test/fixtures/obj-with-link.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipld/js-ipld-dag-cbor/HEAD/test/fixtures/obj-with-link.cbor -------------------------------------------------------------------------------- /test/fixtures/array-link.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const CID = require('cids') 4 | 5 | module.exports = [ 6 | new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL') 7 | ] 8 | -------------------------------------------------------------------------------- /test/fixtures/obj-with-link.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const CID = require('cids') 4 | 5 | module.exports = { 6 | foo: new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL') 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "aegir/src/config/tsconfig.aegir.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "include": [ 7 | "src", 8 | "test" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const util = require('./util.js') 4 | const resolver = require('./resolver.js') 5 | 6 | /** 7 | * @typedef {import('interface-ipld-format').Format} ObjectFormat 8 | */ 9 | 10 | /** 11 | * @type {ObjectFormat} 12 | */ 13 | module.exports = { 14 | util, 15 | resolver, 16 | codec: util.codec, 17 | defaultHashAlg: util.defaultHashAlg 18 | } 19 | -------------------------------------------------------------------------------- /test/fixtures/foo.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const CID = require('cids') 4 | 5 | module.exports = { 6 | foo: 'bar', 7 | cats: [ 8 | new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL'), 9 | { 10 | something: 'interesting' 11 | }, 12 | [ 13 | 'fish', 14 | new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL'), 15 | 9 16 | ] 17 | ], 18 | other: new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL') 19 | } 20 | -------------------------------------------------------------------------------- /test/mod.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { expect } = require('aegir/utils/chai') 5 | const multicodec = require('multicodec') 6 | const mod = require('../src') 7 | 8 | describe('IPLD Format', () => { 9 | it('codec is dag-cbor', () => { 10 | expect(mod.codec).to.equal(multicodec.DAG_CBOR) 11 | }) 12 | 13 | it('defaultHashAlg is sha2-256', () => { 14 | expect(mod.defaultHashAlg).to.equal(multicodec.SHA2_256) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/fixtures/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const CID = require('cids') 4 | 5 | module.exports = { 6 | arrayLink: new CID('zdpuAsZ8roJvCazJFXUnSULspbXfxrLkUkNxy6SToaiDpEiap'), 7 | emptyArray: new CID('zdpuAtQy7GSHNcZxdBfmtowdL1d2WAFjJBwb6WAEfFJ6T4Gbi'), 8 | emptyObj: new CID('zdpuAyTBnYSugBZhqJuLsNpzjmAjSmxDqBbtAqXMtsvxiN2v3'), 9 | foo: new CID('zdpuApbZ3Kmyxwa5rZ3mKHtQKkdHLKwHCXHTLbDSfEDfwkmen'), 10 | objWithLink: new CID('zdpuAp1WRqfq8w953Dep9pz7nNYUbQPKX9duW71G5C4doiPFK'), 11 | objNoLink: new CID('zdpuAtHFXfzgXBSoq5GSn3NTrK2ToYwj4tRZiMTfe2mVApYLa') 12 | } 13 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs 2 | package-lock.json 3 | yarn.lock 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 30 | node_modules 31 | 32 | dist 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: npm 3 | stages: 4 | - check 5 | - test 6 | - cov 7 | 8 | node_js: 9 | - 'lts/*' 10 | - 'node' 11 | 12 | os: 13 | - linux 14 | - osx 15 | - windows 16 | 17 | script: npx nyc -s npm run test:node -- --bail 18 | after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov 19 | 20 | jobs: 21 | include: 22 | - stage: check 23 | script: 24 | - npx aegir dep-check 25 | - npm run lint 26 | 27 | - stage: test 28 | name: chrome 29 | addons: 30 | chrome: stable 31 | script: npx aegir test -t browser -t webworker 32 | 33 | - stage: test 34 | name: firefox 35 | addons: 36 | firefox: latest 37 | script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless 38 | 39 | notifications: 40 | email: false 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 David Dias 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 | 23 | -------------------------------------------------------------------------------- /src/resolver.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const CID = require('cids') 4 | const util = require('./util') 5 | 6 | /** 7 | * Resolves a path within a CBOR block. 8 | * 9 | * Returns the value or a link and the partial mising path. This way the 10 | * IPLD Resolver can fetch the link and continue to resolve. 11 | * 12 | * @param {Uint8Array} binaryBlob - Binary representation of a CBOR block 13 | * @param {string} [path='/'] - Path that should be resolved 14 | */ 15 | exports.resolve = (binaryBlob, path = '') => { 16 | let node = util.deserialize(binaryBlob) 17 | 18 | const parts = path.split('/').filter(Boolean) 19 | while (parts.length) { 20 | const key = parts.shift() 21 | if (!key || !(key in node)) { 22 | throw new Error(`Object has no property '${key}'`) 23 | } 24 | 25 | node = node[key] 26 | if (CID.isCID(node)) { 27 | return { 28 | value: node, 29 | remainderPath: parts.join('/') 30 | } 31 | } 32 | } 33 | 34 | return { 35 | value: node, 36 | remainderPath: '' 37 | } 38 | } 39 | 40 | /** 41 | * @param {any} node 42 | * @param {string} [path] 43 | * @returns {Generator} 44 | */ 45 | const traverse = function * (node, path) { 46 | // Traverse only objects and arrays 47 | if (node instanceof Uint8Array || CID.isCID(node) || typeof node === 'string' || node === null) { 48 | return 49 | } 50 | 51 | for (const item of Object.keys(node)) { 52 | const nextpath = path === undefined ? item : path + '/' + item 53 | yield nextpath 54 | yield * traverse(node[item], nextpath) 55 | } 56 | 57 | // to stop eslint and tsc fighting 58 | return undefined 59 | } 60 | 61 | /** 62 | * Return all available paths of a block. 63 | * 64 | * @generator 65 | * @param {Uint8Array} binaryBlob - Binary representation of a CBOR block 66 | * @yields {string} - A single path 67 | */ 68 | exports.tree = function * (binaryBlob) { 69 | const node = util.deserialize(binaryBlob) 70 | 71 | yield * traverse(node) 72 | } 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ipld-dag-cbor", 3 | "version": "1.0.1", 4 | "description": "JavaScript implementation of the IPLD (InterpPlanetary Linked Data)", 5 | "leadMaintainer": "Volker Mische ", 6 | "main": "src/index.js", 7 | "types": "./dist/src/index.d.ts", 8 | "scripts": { 9 | "prepare": "aegir build", 10 | "test": "aegir test", 11 | "test:browser": "aegir test --target browser", 12 | "test:node": "aegir test --target node", 13 | "lint": "aegir lint", 14 | "release": "aegir release", 15 | "release-minor": "aegir release --type minor", 16 | "release-major": "aegir release --type major", 17 | "build": "aegir build" 18 | }, 19 | "pre-push": [ 20 | "lint", 21 | "test" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/ipld/js-ipld-dag-cbor.git" 26 | }, 27 | "keywords": [ 28 | "IPFS" 29 | ], 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/ipld/js-ipld-dag-cbor/issues" 33 | }, 34 | "engines": { 35 | "node": ">=6.0.0", 36 | "npm": ">=3.0.0" 37 | }, 38 | "homepage": "https://github.com/ipld/js-ipld-dag-cbor", 39 | "dependencies": { 40 | "borc": "^3.0.0", 41 | "cids": "^1.0.0", 42 | "interface-ipld-format": "^1.0.0", 43 | "is-circular": "^1.0.2", 44 | "multicodec": "^3.0.1", 45 | "multihashing-async": "^2.0.0", 46 | "uint8arrays": "^2.1.3" 47 | }, 48 | "devDependencies": { 49 | "@types/detect-node": "^2.0.0", 50 | "aegir": "^33.1.1", 51 | "detect-node": "^2.0.4", 52 | "garbage": "0.0.0", 53 | "multihashes": "^4.0.1" 54 | }, 55 | "contributors": [ 56 | "David Dias ", 57 | "Volker Mische ", 58 | "dignifiedquire ", 59 | "achingbrain ", 60 | "Richard Schneider ", 61 | "wanderer ", 62 | "Rod Vagg ", 63 | "Linus Unnebäck ", 64 | "Richard Littauer ", 65 | "Alan Shaw ", 66 | "Hugo Dias ", 67 | "ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ ", 68 | "Brandon Westcott ", 69 | "Irakli Gozalishvili ", 70 | "Joel Gustafson ", 71 | "Jonah Weissman ", 72 | "Mikeal Rogers ", 73 | "Yusef Napora " 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /test/resolver.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | /* eslint max-nested-callbacks: ["error", 5] */ 3 | 'use strict' 4 | 5 | const { expect } = require('aegir/utils/chai') 6 | const CID = require('cids') 7 | const dagCBOR = require('../src') 8 | const resolver = dagCBOR.resolver 9 | 10 | describe('IPLD format resolver (local)', () => { 11 | const emptyNode = {} 12 | const node = { 13 | name: 'I am a node', 14 | someLink: new CID('QmaNh5d3hFiqJAGjHmvxihSnWDGqYZCn7H2XHpbttYjCNE'), 15 | nest: { 16 | foo: { 17 | bar: 'baz' 18 | } 19 | }, 20 | array: [ 21 | { a: 'b' }, 22 | 2 23 | ], 24 | nullValue: null, 25 | boolValue: true 26 | } 27 | 28 | const emptyNodeBlob = dagCBOR.util.serialize(emptyNode) 29 | const nodeBlob = dagCBOR.util.serialize(node) 30 | 31 | describe('empty node', () => { 32 | describe('resolver.resolve', () => { 33 | it('root', () => { 34 | const result = resolver.resolve(emptyNodeBlob, '/') 35 | expect(result.value).to.be.eql({}) 36 | }) 37 | }) 38 | 39 | it('resolver.tree', () => { 40 | const paths = resolver.tree(emptyNodeBlob).next() 41 | expect(paths.value).to.be.undefined() 42 | expect(paths.done).to.be.true() 43 | }) 44 | }) 45 | 46 | describe('node', () => { 47 | it('resolver.tree', () => { 48 | const tree = resolver.tree(nodeBlob) 49 | const paths = [...tree] 50 | expect(paths).to.have.members([ 51 | 'name', 52 | 'nest', 53 | 'nest/foo', 54 | 'nest/foo/bar', 55 | 'array', 56 | 'array/0', 57 | 'array/0/a', 58 | 'array/1', 59 | 'someLink', 60 | 'boolValue', 61 | 'nullValue' 62 | ]) 63 | }) 64 | 65 | describe('resolver.resolve', () => { 66 | it('path within scope', () => { 67 | const result = resolver.resolve(nodeBlob, 'name') 68 | expect(result.value).to.equal('I am a node') 69 | }) 70 | 71 | it('path within scope, but nested', () => { 72 | const result = resolver.resolve(nodeBlob, 'nest/foo/bar') 73 | expect(result.value).to.equal('baz') 74 | }) 75 | 76 | it('should resolve falsy values for path within scope', () => { 77 | /** @type {{ [key: string]: any }} */ 78 | const falsyNode = { 79 | nu11: null, 80 | f4lse: false, 81 | empty: '', 82 | zero: 0 83 | } 84 | 85 | const falsyNodeBlob = dagCBOR.util.serialize(falsyNode) 86 | 87 | Object.keys(falsyNode).forEach((key) => { 88 | const result = resolver.resolve(falsyNodeBlob, key) 89 | expect(result.value).to.equal(falsyNode[key]) 90 | }) 91 | }) 92 | 93 | it('path out of scope', () => { 94 | const result = resolver.resolve(nodeBlob, 'someLink/a/b/c') 95 | expect(result.value.equals( 96 | new CID('QmaNh5d3hFiqJAGjHmvxihSnWDGqYZCn7H2XHpbttYjCNE')) 97 | ).to.be.true() 98 | expect(result.remainderPath).to.equal('a/b/c') 99 | }) 100 | }) 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /test/interop.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { expect } = require('aegir/utils/chai') 5 | const dagCBOR = require('../src') 6 | const loadFixture = require('aegir/utils/fixtures') 7 | const isNode = require('detect-node') 8 | 9 | const arrayLinkCBOR = loadFixture('test/fixtures/array-link.cbor') 10 | const arrayLinkJS = require('./fixtures/array-link') 11 | 12 | const emptyArrayCBOR = loadFixture('test/fixtures/empty-array.cbor') 13 | const emptyArrayJS = require('./fixtures/empty-array') 14 | 15 | const emptyObjCBOR = loadFixture('test/fixtures/empty-obj.cbor') 16 | const emptyObjJS = require('./fixtures/empty-obj') 17 | 18 | const fooCBOR = loadFixture('test/fixtures/foo.cbor') 19 | const fooJS = require('./fixtures/foo') 20 | 21 | const objNoLinkCBOR = loadFixture('test/fixtures/obj-no-link.cbor') 22 | const objNoLinkJS = require('./fixtures/obj-no-link') 23 | 24 | const objWithLinkCBOR = loadFixture('test/fixtures/obj-with-link.cbor') 25 | const objWithLinkJS = require('./fixtures/obj-with-link') 26 | 27 | const expectedCIDs = require('./fixtures/expected') 28 | 29 | describe('dag-cbor interop tests', () => { 30 | // the fixtures feature needs to be fixed 31 | if (!isNode) { return } 32 | 33 | describe('deserialize and compare', () => { 34 | it('array-link', async () => { 35 | const node = dagCBOR.util.deserialize(arrayLinkCBOR) 36 | expect(node).to.eql(arrayLinkJS) 37 | 38 | const cid = await dagCBOR.util.cid(arrayLinkCBOR) 39 | expect(cid.equals(expectedCIDs.arrayLink)).to.be.true() 40 | }) 41 | 42 | it('empty-array', async () => { 43 | const node = dagCBOR.util.deserialize(emptyArrayCBOR) 44 | expect(node).to.eql(emptyArrayJS) 45 | 46 | const cid = await dagCBOR.util.cid(emptyArrayCBOR) 47 | expect(cid.equals(expectedCIDs.emptyArray)).to.be.true() 48 | }) 49 | 50 | it('empty-obj', async () => { 51 | const node = dagCBOR.util.deserialize(emptyObjCBOR) 52 | expect(node).to.eql(emptyObjJS) 53 | 54 | const cid = await dagCBOR.util.cid(emptyObjCBOR) 55 | expect(cid.equals(expectedCIDs.emptyObj)).to.be.true() 56 | }) 57 | 58 | it('foo', async () => { 59 | const node = dagCBOR.util.deserialize(fooCBOR) 60 | expect(node).to.eql(fooJS) 61 | 62 | const cid = await dagCBOR.util.cid(fooCBOR) 63 | expect(cid.equals(expectedCIDs.foo)).to.be.true() 64 | }) 65 | 66 | it('obj-no-link', async () => { 67 | const node = dagCBOR.util.deserialize(objNoLinkCBOR) 68 | expect(node).to.eql(objNoLinkJS) 69 | 70 | const cid = await dagCBOR.util.cid(objNoLinkCBOR) 71 | expect(cid.equals(expectedCIDs.objNoLink)).to.be.true() 72 | }) 73 | 74 | it('obj-with-link', async () => { 75 | if (!isNode) { return } 76 | 77 | const cid = await dagCBOR.util.cid(objWithLinkCBOR) 78 | expect(cid.equals(expectedCIDs.objWithLink)).to.be.true() 79 | }) 80 | }) 81 | 82 | describe('serialise and compare', () => { 83 | it('array-link', () => { 84 | const serialized = dagCBOR.util.serialize(arrayLinkJS) 85 | expect(serialized).to.eql(arrayLinkCBOR) 86 | }) 87 | 88 | it('empty-array', () => { 89 | const serialized = dagCBOR.util.serialize(emptyArrayJS) 90 | expect(serialized).to.eql(emptyArrayCBOR) 91 | }) 92 | 93 | it('empty-obj', () => { 94 | const serialized = dagCBOR.util.serialize(emptyObjJS) 95 | expect(serialized).to.eql(emptyObjCBOR) 96 | }) 97 | 98 | it('foo', () => { 99 | const serialized = dagCBOR.util.serialize(fooJS) 100 | expect(serialized).to.eql(fooCBOR) 101 | }) 102 | 103 | it('obj-no-link', () => { 104 | const serialized = dagCBOR.util.serialize(objNoLinkJS) 105 | expect(serialized).to.eql(objNoLinkCBOR) 106 | }) 107 | 108 | it('obj-with-link', () => { 109 | const serialized = dagCBOR.util.serialize(objWithLinkJS) 110 | expect(serialized).to.eql(objWithLinkCBOR) 111 | }) 112 | }) 113 | }) 114 | -------------------------------------------------------------------------------- /test/util.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { expect } = require('aegir/utils/chai') 5 | // @ts-ignore 6 | const garbage = require('garbage') 7 | const dagCBOR = require('../src') 8 | const multihash = require('multihashes') 9 | const CID = require('cids') 10 | const uint8ArrayFromString = require('uint8arrays/from-string') 11 | const uint8ArrayToString = require('uint8arrays/to-string') 12 | const uint8ArrayConcat = require('uint8arrays/concat') 13 | const { 14 | configureDecoder 15 | } = require('../src/util') 16 | 17 | describe('util', () => { 18 | const obj = { 19 | someKey: 'someValue', 20 | link: new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL'), 21 | links: [ 22 | new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL'), 23 | new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL') 24 | ], 25 | nested: { 26 | hello: 'world', 27 | link: new CID('QmRgutAxd8t7oGkSm4wmeuByG6M51wcTso6cubDdQtuEfL') 28 | } 29 | } 30 | const serializedObj = dagCBOR.util.serialize(obj) 31 | 32 | it('.serialize and .deserialize', () => { 33 | expect(serializedObj).to.be.a('Uint8Array') 34 | 35 | // Check for the tag 42 36 | // d8 = tag, 2a = 42 37 | expect( 38 | uint8ArrayToString(serializedObj, 'base16').match(/d82a/g) 39 | ).to.have.length(4) 40 | 41 | const deserializedObj = dagCBOR.util.deserialize(serializedObj) 42 | expect(obj).to.eql(deserializedObj) 43 | }) 44 | 45 | it('.serialize and .deserialize large objects', () => { 46 | // larger than the default borc heap size, should auto-grow the heap 47 | const dataSize = 128 * 1024 48 | const largeObj = { someKey: [].slice.call(new Uint8Array(dataSize)) } 49 | 50 | const serialized = dagCBOR.util.serialize(largeObj) 51 | expect(serialized).to.be.a('Uint8Array') 52 | 53 | const deserialized = dagCBOR.util.deserialize(serialized) 54 | expect(largeObj).to.eql(deserialized) 55 | // reset decoder to default 56 | configureDecoder() 57 | }) 58 | 59 | it('.deserialize fail on large objects beyond maxSize', () => { 60 | // larger than the default borc heap size, should bust the heap if we turn off auto-grow 61 | const dataSize = (128 * 1024) + 1 62 | const largeObj = { someKey: [].slice.call(new Uint8Array(dataSize)) } 63 | 64 | configureDecoder({ size: 64 * 1024, maxSize: 128 * 1024 }) // 64 Kb start, 128 Kb max 65 | const serialized = dagCBOR.util.serialize(largeObj) 66 | expect(serialized).to.be.a('Uint8Array') 67 | 68 | expect(() => dagCBOR.util.deserialize(serialized)).to.throw( 69 | 'Data is too large to deserialize with current decoder') 70 | // reset decoder to default 71 | configureDecoder() 72 | }) 73 | 74 | it('.serialize and .deserialize object with slash as property', () => { 75 | const slashObject = { '/': true } 76 | const serialized = dagCBOR.util.serialize(slashObject) 77 | const deserialized = dagCBOR.util.deserialize(serialized) 78 | expect(deserialized).to.eql(slashObject) 79 | }) 80 | 81 | it('error catching', () => { 82 | const circlarObj = {} 83 | circlarObj.a = circlarObj 84 | expect(() => dagCBOR.util.serialize(circlarObj)).to.throw( 85 | 'The object passed has circular reference') 86 | }) 87 | 88 | it('.cid', async () => { 89 | const cid = await dagCBOR.util.cid(serializedObj) 90 | expect(cid.version).to.equal(1) 91 | expect(cid.codec).to.equal('dag-cbor') 92 | expect(cid.multihash).to.exist() 93 | const mh = multihash.decode(cid.multihash) 94 | expect(mh.name).to.equal('sha2-256') 95 | }) 96 | 97 | it('.cid with hashAlg', async () => { 98 | const cid = await dagCBOR.util.cid(serializedObj, { hashAlg: multihash.names['sha2-512'] }) 99 | expect(cid.version).to.equal(1) 100 | expect(cid.codec).to.equal('dag-cbor') 101 | expect(cid.multihash).to.exist() 102 | const mh = multihash.decode(cid.multihash) 103 | expect(mh.name).to.equal('sha2-512') 104 | expect(mh.length).to.equal(64) 105 | }) 106 | 107 | it('fuzz serialize and deserialize with garbage', () => { 108 | for (let ii = 0; ii < 1000; ii++) { 109 | const original = { in: garbage(100) } 110 | const encoded = dagCBOR.util.serialize(original) 111 | const decoded = dagCBOR.util.deserialize(encoded) 112 | expect(decoded).to.eql(original) 113 | } 114 | }) 115 | 116 | it('.serialize and .deserialize object with Uint8Array field', () => { 117 | const buffer = uint8ArrayFromString('some data') 118 | const bytes = Uint8Array.from(buffer) 119 | 120 | const s1 = dagCBOR.util.serialize({ data: buffer }) 121 | const s2 = dagCBOR.util.serialize({ data: bytes }) 122 | 123 | expect(s1).to.be.eql(s2) 124 | 125 | expect(dagCBOR.util.deserialize(s1)).to.be.eql({ data: bytes }) 126 | expect(dagCBOR.util.deserialize(s2)).to.be.eql({ data: bytes }) 127 | }) 128 | 129 | it('reject extraneous, but valid CBOR data after initial top-level object', () => { 130 | expect(() => 131 | // two top-level CBOR objects, the original and a single uint=0, valid if using 132 | // CBOR in streaming mode, not valid here 133 | dagCBOR.util.deserialize(uint8ArrayConcat([serializedObj, new Uint8Array(1)])) 134 | ).to.throw(Error, 'Extraneous CBOR data found beyond initial top-level object') 135 | }) 136 | }) 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⛔️ DEPRECATED: This module has been superseded by [@ipld/dag-cbor](https://github.com/ipld/js-dag-cbor) and [multiformats](https://github.com/multiformats/js-multiformats) 2 | ====== 3 | 4 | # js-ipld-dag-cbor 5 | 6 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) 7 | [![](https://img.shields.io/badge/project-IPLD-blue.svg?style=flat-square)](http://github.com/ipld/ipld) 8 | [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) 9 | [![Travis CI](https://flat.badgen.net/travis/ipld/js-ipld-dag-cbor)](https://travis-ci.com/ipld/js-ipld-dag-cbor) 10 | [![Coverage](https://coveralls.io/repos/github/ipld/js-ipld-dag-cbor/badge.svg?branch=master)](https://coveralls.io/github/ipld/js-ipld-dag-cbor?branch=master) 11 | [![](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) 12 | [![](https://david-dm.org/ipld/js-ipld-dag-cbor.svg?style=flat-square)](https://david-dm.org/ipld/js-ipld-dag-cbor) 13 | [![](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) 14 | [![Greenkeeper badge](https://badges.greenkeeper.io/ipld/js-ipld-dag-cbor.svg)](https://greenkeeper.io/) 15 | ![](https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square) 16 | ![](https://img.shields.io/badge/Node.js-%3E%3D6.0.0-orange.svg?style=flat-square) 17 | 18 | > JavaScript implementation of the [IPLD spec](https://github.com/ipfs/specs/tree/master/ipld). 19 | 20 | ## Lead Maintainer 21 | 22 | [Volker Mische](https://github.com/vmx) 23 | 24 | ## Table of Contents 25 | 26 | - [Install](#install) 27 | - [npm](#npm) 28 | - [Use in Node.js](#use-in-nodejs) 29 | - [Use in a browser with browserify, webpack or any other bundler](#use-in-a-browser-with-browserify-webpack-or-any-other-bundler) 30 | - [Use in a browser Using a script tag](#use-in-a-browser-using-a-script-tag) 31 | - [Usage](#usage) 32 | - [API](#api) 33 | - [`dagCBOR.util.serialize(obj)`](#dagcborutilserializeobj) 34 | - [`dagCBOR.util.deserialize(serialized)`](#dagcborutildeserializeserialized) 35 | - [`dagCBOR.util.configureDecoder([options])`](#dagcborutilconfiguredecoderoptions) 36 | - [`dagCBOR.util.cid(obj[, options,])`](#dagcborutilcidobj-options) 37 | - [Contribute](#contribute) 38 | - [License](#license) 39 | 40 | ## Install 41 | 42 | ### npm 43 | 44 | ```sh 45 | > npm install ipld-dag-cbor 46 | ``` 47 | 48 | ### Use in Node.js 49 | 50 | ```JavaScript 51 | const dagCBOR = require('ipld-dag-cbor') 52 | ``` 53 | 54 | ### Use in a browser with browserify, webpack or any other bundler 55 | 56 | The code published to npm that gets loaded on require is in fact a ES5 transpiled version with the right shims added. This means that you can require it and use with your favourite bundler without having to adjust asset management process. 57 | 58 | ```JavaScript 59 | var dagCBOR = require('ipld-dag-cbor') 60 | ``` 61 | 62 | ### Use in a browser Using a script tag 63 | 64 | Loading this module through a script tag will make the `IpldDagCbor` obj available in the global namespace. 65 | 66 | ```html 67 | 68 | 69 | 70 | ``` 71 | 72 | ## Usage 73 | 74 | ```JavaScript 75 | const dagCBOR = require('ipld-dag-cbor') 76 | 77 | const file = { 78 | name: 'hello.txt', 79 | size: 11 80 | } 81 | 82 | const serialized = dagCBOR.util.serialize(file) 83 | console.log(`Encoded as a ${serialized.length} byte Uint8Array`) 84 | 85 | const node = dagCBOR.util.deserialize(serialized) 86 | console.log('Decoded as:', node) 87 | require('assert').deepEqual(node, file) // should match 88 | 89 | // → Encoded as a 22 byte Uint8Array 90 | // → Decoded as: { name: 'hello.txt', size: 11 } 91 | ``` 92 | 93 | ## API 94 | 95 | ### `dagCBOR.util.serialize(obj)` 96 | 97 | Encodes an object into IPLD CBOR form, replacing any CIDs found within the object to CBOR tags (with an id of `42`). 98 | 99 | - `obj` (any): any object able to be serialized as CBOR 100 | 101 | Returns the serialized node. 102 | 103 | ### `dagCBOR.util.deserialize(serialized)` 104 | 105 | Decodes an IPLD CBOR encoded representation, restoring any CBOR tags (id `42`) to CIDs. 106 | 107 | - `serialized` (`Uint8Array` or `String`): a binary blob representing an IPLD CBOR encoded object. 108 | 109 | Returns the deserialized object. 110 | 111 | ### `dagCBOR.util.configureDecoder([options])` 112 | 113 | Configure the underlying CBOR decoder. 114 | 115 | Possible values in the `options` argument are: 116 | 117 | - `size` (`Number`, optional): the current heap size used in CBOR parsing, this may grow automatically as larger blocks are encountered up to `maxSize`. Default: `65536` (64Kb). 118 | - `maxSize` (`Number`, optional): the maximum size the CBOR parsing heap is allowed to grow to before `dagCBOR.util.deserialize()` returns an error. Default: `67108864` (64Mb). 119 | - `tags` (`Object`, optional): an object whose keys are CBOR tag numbers and values are transform functions that accept a `value` and return a decoded representation of that `value`. 120 | 121 | The CBOR decoder uses a heap size that is a power of two. Setting `size` to a number other than a power of two will result in a heap using the next-largest power of two. 122 | 123 | Calling `dagCBOR.util.configureDecoder()` with no arguments will reset to the default decoder `size`, `maxSize` and `tags`. 124 | 125 | ### `dagCBOR.util.cid(obj[, options,])` 126 | 127 | Create a [CID](https://github.com/multiformats/js-cid) for the given unserialized object. 128 | 129 | - `obj` (any): any object able to be serialized as CBOR 130 | - `options` (`Object`): 131 | * `hashAlg` (`String`): a [registered multicodec](https://github.com/multiformats/multicodec/blob/master/table.csv) hash algorithm. 132 | * `hashLen` (`String`): an optional hash length 133 | * `version` (`Number`): CID version number, defaults to `1` 134 | 135 | Returns a Promise with the created CID. 136 | 137 | ## Contribute 138 | 139 | Feel free to join in. All welcome. Open an [issue](https://github.com/ipld/js-ipld-dag-cbor/issues)! 140 | 141 | Check out our [contributing document](https://github.com/ipld/ipld/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to IPLD are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). 142 | 143 | Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. 144 | 145 | ## License 146 | 147 | [MIT](LICENSE) © 2015 David Dias 148 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // @ts-ignore TODO: switch to cborg 4 | const cbor = require('borc') 5 | const multicodec = require('multicodec') 6 | const multihashing = require('multihashing-async') 7 | const { multihash } = multihashing 8 | const CID = require('cids') 9 | // @ts-ignore 10 | const isCircular = require('is-circular') 11 | const uint8ArrayConcat = require('uint8arrays/concat') 12 | const uint8ArrayFromString = require('uint8arrays/from-string') 13 | 14 | /** 15 | * @typedef {import('cids').CIDVersion} CIDVersion 16 | * @typedef {import('multihashing-async').multihash.HashCode} HashCode 17 | */ 18 | 19 | // https://github.com/ipfs/go-ipfs/issues/3570#issuecomment-273931692 20 | const CID_CBOR_TAG = 42 21 | 22 | /** 23 | * @param {CID | string} cid 24 | */ 25 | function tagCID (cid) { 26 | let buf 27 | 28 | if (typeof cid === 'string') { 29 | buf = new CID(cid).bytes 30 | } else if (CID.isCID(cid)) { 31 | buf = cid.bytes 32 | } else { 33 | throw new Error('Could not tag CID - was not string or CID') 34 | } 35 | 36 | return new cbor.Tagged(CID_CBOR_TAG, uint8ArrayConcat([ 37 | uint8ArrayFromString('00', 'base16'), // thanks jdag 38 | buf 39 | ], 1 + buf.length)) 40 | } 41 | 42 | /** 43 | * @param {any} dagNode 44 | */ 45 | function replaceCIDbyTAG (dagNode) { 46 | let circular 47 | try { 48 | circular = isCircular(dagNode) 49 | } catch (e) { 50 | circular = false 51 | } 52 | if (circular) { 53 | throw new Error('The object passed has circular references') 54 | } 55 | 56 | /** 57 | * @param {any} obj 58 | * @returns {any} 59 | */ 60 | function transform (obj) { 61 | if (!obj || obj instanceof Uint8Array || typeof obj === 'string') { 62 | return obj 63 | } 64 | 65 | if (Array.isArray(obj)) { 66 | return obj.map(transform) 67 | } 68 | 69 | if (CID.isCID(obj)) { 70 | return tagCID(obj) 71 | } 72 | 73 | const keys = Object.keys(obj) 74 | 75 | if (keys.length > 0) { 76 | // Recursive transform 77 | /** @type {Record} */ 78 | const out = {} 79 | keys.forEach((key) => { 80 | if (typeof obj[key] === 'object') { 81 | out[key] = transform(obj[key]) 82 | } else { 83 | out[key] = obj[key] 84 | } 85 | }) 86 | return out 87 | } else { 88 | return obj 89 | } 90 | } 91 | 92 | return transform(dagNode) 93 | } 94 | 95 | const codec = multicodec.DAG_CBOR 96 | const defaultHashAlg = multihash.names['sha2-256'] 97 | 98 | const defaultTags = { 99 | /** 100 | * @param {Uint8Array} val 101 | */ 102 | [CID_CBOR_TAG]: (val) => { 103 | // remove that 0 104 | val = val.slice(1) 105 | return new CID(val) 106 | } 107 | } 108 | const defaultSize = 64 * 1024 // current decoder heap size, 64 Kb 109 | let currentSize = defaultSize 110 | const defaultMaxSize = 64 * 1024 * 1024 // max heap size when auto-growing, 64 Mb 111 | let maxSize = defaultMaxSize 112 | /** @type {cbor.Decoder} */ 113 | let decoder 114 | 115 | /** 116 | * Configure the underlying CBOR decoder. 117 | * 118 | * @param {Object} [options] - The options the decoder takes. The decoder will reset to the defaul values if no options are given. 119 | * @param {number} [options.size=65536] - The current heap size used in CBOR parsing, this may grow automatically as larger blocks are encountered up to `maxSize` 120 | * @param {number} [options.maxSize=67108864] - The maximum size the CBOR parsing heap is allowed to grow to before `dagCBOR.util.deserialize()` returns an error 121 | * @param {Object} [options.tags] - An object whose keys are CBOR tag numbers and values are transform functions that accept a `value` and return a decoded representation of that `value` 122 | */ 123 | function configureDecoder (options) { 124 | let tags = defaultTags 125 | 126 | if (options) { 127 | if (typeof options.size === 'number') { 128 | currentSize = options.size 129 | } 130 | if (typeof options.maxSize === 'number') { 131 | maxSize = options.maxSize 132 | } 133 | if (options.tags) { 134 | tags = Object.assign({}, defaultTags, options && options.tags) 135 | } 136 | } else { 137 | // no options, reset to defaults 138 | currentSize = defaultSize 139 | maxSize = defaultMaxSize 140 | } 141 | 142 | const decoderOptions = { 143 | tags, 144 | size: currentSize 145 | } 146 | 147 | decoder = new cbor.Decoder(decoderOptions) 148 | // borc edits opts.size in-place so we can capture _actual_ size 149 | currentSize = decoderOptions.size 150 | } 151 | 152 | configureDecoder() // Setup default cbor.Decoder 153 | 154 | /** 155 | * Serialize internal representation into a binary CBOR block. 156 | * 157 | * @param {Object} node - Internal representation of a CBOR block 158 | * @returns {Uint8Array} - The encoded binary representation 159 | */ 160 | function serialize (node) { 161 | const nodeTagged = replaceCIDbyTAG(node) 162 | const serialized = cbor.encode(nodeTagged) 163 | 164 | return serialized 165 | } 166 | 167 | /** 168 | * Deserialize CBOR block into the internal representation. 169 | * 170 | * @param {Uint8Array} data - Binary representation of a CBOR block 171 | * @returns {any} - An object that conforms to the IPLD Data Model 172 | */ 173 | function deserialize (data) { 174 | if (data.length > currentSize && data.length <= maxSize) { 175 | configureDecoder({ size: data.length }) 176 | } 177 | 178 | if (data.length > currentSize) { 179 | throw new Error('Data is too large to deserialize with current decoder') 180 | } 181 | 182 | // borc will decode back-to-back objects into an implicit top-level array, we 183 | // strictly want to only see a single explicit top-level object 184 | const all = decoder.decodeAll(data) 185 | if (all.length !== 1) { 186 | throw new Error('Extraneous CBOR data found beyond initial top-level object') 187 | } 188 | 189 | return all[0] 190 | } 191 | 192 | /** 193 | * Calculate the CID of the binary blob. 194 | * 195 | * @param {Uint8Array} binaryBlob - Encoded IPLD Node 196 | * @param {Object} [userOptions] - Options to create the CID 197 | * @param {CIDVersion} [userOptions.cidVersion=1] - CID version number 198 | * @param {HashCode} [userOptions.hashAlg=multihash.names['sha2-256']] - Defaults to the defaultHashAlg of the format 199 | */ 200 | async function cid (binaryBlob, userOptions = {}) { 201 | const options = { 202 | cidVersion: userOptions.cidVersion == null ? 1 : userOptions.cidVersion, 203 | hashAlg: userOptions.hashAlg == null ? module.exports.defaultHashAlg : userOptions.hashAlg 204 | } 205 | 206 | const hashName = multihash.codes[options.hashAlg] 207 | const hash = await multihashing(binaryBlob, hashName) 208 | const codecName = multicodec.getNameFromCode(module.exports.codec) 209 | const cid = new CID(options.cidVersion, codecName, hash) 210 | 211 | return cid 212 | } 213 | 214 | module.exports = { 215 | codec, 216 | defaultHashAlg, 217 | configureDecoder, 218 | serialize, 219 | deserialize, 220 | cid 221 | } 222 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v1.0.0...v1.0.1) (2021-08-11) 2 | 3 | 4 | 5 | # [1.0.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.18.0...v1.0.0) (2021-04-27) 6 | 7 | 8 | ### chore 9 | 10 | * update deps ([#140](https://github.com/ipld/js-ipld-dag-cbor/issues/140)) ([5d13035](https://github.com/ipld/js-ipld-dag-cbor/commit/5d13035533a00fba12d4a0e9544347cce51e1350)) 11 | 12 | 13 | ### BREAKING CHANGES 14 | 15 | * `buffer@6.x.x` has dropped support for IE and Safari < 10 16 | 17 | 18 | 19 | # [0.18.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.17.1...v0.18.0) (2021-03-11) 20 | 21 | 22 | 23 | ## [0.17.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.17.0...v0.17.1) (2021-03-03) 24 | 25 | 26 | 27 | 28 | # [0.17.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.16.0...v0.17.0) (2020-08-04) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * replace node buffers with uint8arrays ([#134](https://github.com/ipld/js-ipld-dag-cbor/issues/134)) ([41587e7](https://github.com/ipld/js-ipld-dag-cbor/commit/41587e7)) 34 | 35 | 36 | ### BREAKING CHANGES 37 | 38 | * - `util.serialize` now returns a Uint8Array 39 | 40 | 41 | 42 | 43 | # [0.16.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.15.3...v0.16.0) (2020-07-10) 44 | 45 | 46 | ### Bug Fixes 47 | 48 | * reject CBOR data with extraneous back-to-back encoded data ([8176c13](https://github.com/ipld/js-ipld-dag-cbor/commit/8176c13)), closes [/github.com/dignifiedquire/borc/issues/47#issuecomment-642432759](https://github.com//github.com/dignifiedquire/borc/issues/47/issues/issuecomment-642432759) 49 | 50 | 51 | 52 | 53 | ## [0.15.3](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.15.2...v0.15.3) (2020-06-10) 54 | 55 | 56 | ### Features 57 | 58 | * serialize Uint8Array as binary (like Buffer) ([95f6bda](https://github.com/ipld/js-ipld-dag-cbor/commit/95f6bda)) 59 | 60 | 61 | 62 | 63 | ## [0.15.2](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.15.1...v0.15.2) (2020-03-27) 64 | 65 | 66 | ### Bug Fixes 67 | 68 | * remove node globals ([#124](https://github.com/ipld/js-ipld-dag-cbor/issues/124)) ([7acfeae](https://github.com/ipld/js-ipld-dag-cbor/commit/7acfeae)) 69 | * **package:** update cids to version 0.8.0 ([bc6ac54](https://github.com/ipld/js-ipld-dag-cbor/commit/bc6ac54)) 70 | 71 | 72 | 73 | 74 | ## [0.15.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.15.0...v0.15.1) (2020-01-13) 75 | 76 | 77 | ### Bug Fixes 78 | 79 | * **package:** update multicodec to version 1.0.0 ([d1d78a0](https://github.com/ipld/js-ipld-dag-cbor/commit/d1d78a0)) 80 | * **package:** update multihashing-async to version 0.8.0 ([b8d4a55](https://github.com/ipld/js-ipld-dag-cbor/commit/b8d4a55)) 81 | 82 | 83 | 84 | 85 | # [0.15.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.14.0...v0.15.0) (2019-05-10) 86 | 87 | 88 | ### Bug Fixes 89 | 90 | * **package:** update cids to version 0.7.0 ([2dc3378](https://github.com/ipld/js-ipld-dag-cbor/commit/2dc3378)) 91 | 92 | 93 | ### BREAKING CHANGES 94 | 95 | * **package:** Returned v1 CIDs now default to base32 encoding 96 | 97 | Previous versions returned a base58 encoded string when `toString()`/ 98 | `toBaseEncodedString()` was called on a CIDv1. It now returns a base32 99 | encoded string. 100 | 101 | 102 | 103 | 104 | # [0.14.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.13.1...v0.14.0) (2019-05-08) 105 | 106 | 107 | ### Bug Fixes 108 | 109 | * make cbor Decoder configurable ([#90](https://github.com/ipld/js-ipld-dag-cbor/issues/90)) ([dfb9137](https://github.com/ipld/js-ipld-dag-cbor/commit/dfb9137)) 110 | * remove console.log statement ([a413cb2](https://github.com/ipld/js-ipld-dag-cbor/commit/a413cb2)) 111 | * typo in travis badge ([94122f0](https://github.com/ipld/js-ipld-dag-cbor/commit/94122f0)) 112 | * **package:** update cids to version 0.6.0 ([1d507f7](https://github.com/ipld/js-ipld-dag-cbor/commit/1d507f7)) 113 | * **package:** update multihashing-async to version 0.6.0 ([b328072](https://github.com/ipld/js-ipld-dag-cbor/commit/b328072)) 114 | 115 | 116 | ### Features 117 | 118 | * allow decoder heap to grow dynamically ([1f7b7f1](https://github.com/ipld/js-ipld-dag-cbor/commit/1f7b7f1)), closes [#73](https://github.com/ipld/js-ipld-dag-cbor/issues/73) 119 | * new IPLD Format API ([cfc8519](https://github.com/ipld/js-ipld-dag-cbor/commit/cfc8519)) 120 | 121 | 122 | ### BREAKING CHANGES 123 | 124 | * The API is now async/await based 125 | 126 | There are numerous changes, the most significant one is that the API 127 | is no longer callback based, but it using async/await. 128 | 129 | For the full new API please see the [IPLD Formats spec]. 130 | 131 | [IPLD Formats spec]: https://github.com/ipld/interface-ipld-format 132 | 133 | 134 | 135 | 136 | ## [0.13.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.13.0...v0.13.1) (2019-01-08) 137 | 138 | 139 | ### Bug Fixes 140 | 141 | * reduce bundle size ([#87](https://github.com/ipld/js-ipld-dag-cbor/issues/87)) ([ab637f3](https://github.com/ipld/js-ipld-dag-cbor/commit/ab637f3)) 142 | 143 | 144 | ### Features 145 | 146 | * support the hashLen option of multihashing ([#83](https://github.com/ipld/js-ipld-dag-cbor/issues/83)) ([9ffb5e2](https://github.com/ipld/js-ipld-dag-cbor/commit/9ffb5e2)) 147 | 148 | 149 | 150 | 151 | # [0.13.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.12.1...v0.13.0) (2018-10-01) 152 | 153 | 154 | ### Bug Fixes 155 | 156 | * resolve falsy values ([0a49705](https://github.com/ipld/js-ipld-dag-cbor/commit/0a49705)) 157 | 158 | 159 | ### Features 160 | 161 | * serialize and de-serialize CID instances ([8585d65](https://github.com/ipld/js-ipld-dag-cbor/commit/8585d65)) 162 | 163 | 164 | ### BREAKING CHANGES 165 | 166 | * return values from de-serializer are now CID instances. 167 | Serializer still supports old link objects. 168 | 169 | 170 | 171 | 172 | ## [0.12.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.12.0...v0.12.1) (2018-06-29) 173 | 174 | 175 | ### Bug Fixes 176 | 177 | * pass serialized blob to util.cid ([#67](https://github.com/ipld/js-ipld-dag-cbor/issues/67)) ([1ec7744](https://github.com/ipld/js-ipld-dag-cbor/commit/1ec7744)) 178 | 179 | 180 | ### Features 181 | 182 | * add defaultHashAlg ([#65](https://github.com/ipld/js-ipld-dag-cbor/issues/65)) ([e095ef5](https://github.com/ipld/js-ipld-dag-cbor/commit/e095ef5)) 183 | * add util.cid options ([#66](https://github.com/ipld/js-ipld-dag-cbor/issues/66)) ([1aed60e](https://github.com/ipld/js-ipld-dag-cbor/commit/1aed60e)) 184 | 185 | 186 | ### BREAKING CHANGES 187 | 188 | * the first argument is now the serialized output NOT the dag node. 189 | See https://github.com/ipld/interface-ipld-format/issues/32 190 | 191 | 192 | 193 | 194 | # [0.12.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.11.2...v0.12.0) (2018-02-12) 195 | 196 | 197 | ### Bug Fixes 198 | 199 | * use binary blobs directly ([5321d6a](https://github.com/ipld/js-ipld-dag-cbor/commit/5321d6a)) 200 | 201 | 202 | ### BREAKING CHANGES 203 | 204 | * Everyone calling the functions of `resolve` need to 205 | pass in the binary data instead of an IPFS block. 206 | 207 | So if your input is an IPFS block, the code changes from 208 | 209 | resolver.resolve(block, path, (err, result) => {…} 210 | 211 | to 212 | 213 | resolver.resolve(block.data, path, (err, result) => {…} 214 | 215 | 216 | 217 | 218 | # [0.12.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.11.2...v0.12.0) (2018-02-12) 219 | 220 | 221 | ### Bug Fixes 222 | 223 | * use binary blobs directly ([5321d6a](https://github.com/ipld/js-ipld-dag-cbor/commit/5321d6a)) 224 | 225 | 226 | ### BREAKING CHANGES 227 | 228 | * Everyone calling the functions of `resolve` need to 229 | pass in the binary data instead of an IPFS block. 230 | 231 | So if your input is an IPFS block, the code changes from 232 | 233 | resolver.resolve(block, path, (err, result) => {…} 234 | 235 | to 236 | 237 | resolver.resolve(block.data, path, (err, result) => {…} 238 | 239 | 240 | 241 | 242 | ## [0.11.2](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.11.1...v0.11.2) (2017-11-07) 243 | 244 | 245 | ### Features 246 | 247 | * next Aegir (fix tests in the middle) ([#53](https://github.com/ipld/js-ipld-dag-cbor/issues/53)) ([02940a0](https://github.com/ipld/js-ipld-dag-cbor/commit/02940a0)) 248 | 249 | 250 | 251 | 252 | ## [0.11.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.11.0...v0.11.1) (2017-04-04) 253 | 254 | 255 | 256 | 257 | # [0.11.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.10.1...v0.11.0) (2017-03-21) 258 | 259 | 260 | ### Features 261 | 262 | * use new block api ([4ec9228](https://github.com/ipld/js-ipld-dag-cbor/commit/4ec9228)) 263 | 264 | 265 | 266 | 267 | ## [0.10.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.10.0...v0.10.1) (2017-03-16) 268 | 269 | 270 | 271 | 272 | # [0.10.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.9.1...v0.10.0) (2017-03-13) 273 | 274 | 275 | 276 | 277 | ## [0.9.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.9.0...v0.9.1) (2017-02-09) 278 | 279 | 280 | 281 | 282 | # [0.9.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.6...v0.9.0) (2017-02-02) 283 | 284 | 285 | 286 | 287 | ## [0.8.6](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.5...v0.8.6) (2017-01-31) 288 | 289 | 290 | ### Features 291 | 292 | * CBOR TAG ([#38](https://github.com/ipld/js-ipld-dag-cbor/issues/38)) ([13323a2](https://github.com/ipld/js-ipld-dag-cbor/commit/13323a2)) 293 | 294 | 295 | 296 | 297 | ## [0.8.5](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.4...v0.8.5) (2017-01-29) 298 | 299 | 300 | 301 | 302 | ## [0.8.4](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.3...v0.8.4) (2017-01-29) 303 | 304 | 305 | 306 | 307 | ## [0.8.3](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.2...v0.8.3) (2016-12-11) 308 | 309 | 310 | ### Features 311 | 312 | * switch to borc ([#31](https://github.com/ipld/js-ipld-dag-cbor/issues/31)) ([3164a81](https://github.com/ipld/js-ipld-dag-cbor/commit/3164a81)), closes [#23](https://github.com/ipld/js-ipld-dag-cbor/issues/23) 313 | 314 | 315 | 316 | 317 | ## [0.8.2](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.1...v0.8.2) (2016-12-01) 318 | 319 | 320 | 321 | 322 | ## [0.8.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.8.0...v0.8.1) (2016-11-21) 323 | 324 | 325 | 326 | 327 | # [0.8.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.7.1...v0.8.0) (2016-11-03) 328 | 329 | 330 | 331 | 332 | ## [0.7.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.7.0...v0.7.1) (2016-10-30) 333 | 334 | 335 | 336 | 337 | # [0.7.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.6.0...v0.7.0) (2016-10-26) 338 | 339 | 340 | ### Bug Fixes 341 | 342 | * add array handling to .tree ([656ad84](https://github.com/ipld/js-ipld-dag-cbor/commit/656ad84)) 343 | * complete migration to async API ([2e91d7c](https://github.com/ipld/js-ipld-dag-cbor/commit/2e91d7c)) 344 | * out of scope traversal for 2 or more levels deep ([b7a565b](https://github.com/ipld/js-ipld-dag-cbor/commit/b7a565b)) 345 | 346 | 347 | ### Features 348 | 349 | * add util.serialize, util.deserialize and util.cid ([fcc2ab5](https://github.com/ipld/js-ipld-dag-cbor/commit/fcc2ab5)) 350 | * resolve out of scope ([bea41ea](https://github.com/ipld/js-ipld-dag-cbor/commit/bea41ea)) 351 | * resolver.resolve within scope ([1158fa4](https://github.com/ipld/js-ipld-dag-cbor/commit/1158fa4)) 352 | * resolver.tree and resolver.multicodec ([21ddefc](https://github.com/ipld/js-ipld-dag-cbor/commit/21ddefc)) 353 | * use async interfaces ([48eb863](https://github.com/ipld/js-ipld-dag-cbor/commit/48eb863)) 354 | 355 | 356 | 357 | 358 | # [0.6.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.4.0...v0.6.0) (2016-05-22) 359 | 360 | 361 | ### Bug Fixes 362 | 363 | * **cbor:** Typo in lodash.clonedeep ([2f617b0](https://github.com/ipld/js-ipld-dag-cbor/commit/2f617b0)) 364 | * Add missing babel-runtime dep ([5c11ce8](https://github.com/ipld/js-ipld-dag-cbor/commit/5c11ce8)) 365 | * correct references in package.json ([12f18ab](https://github.com/ipld/js-ipld-dag-cbor/commit/12f18ab)) 366 | * Ensure inputs are not modified ([b20f90b](https://github.com/ipld/js-ipld-dag-cbor/commit/b20f90b)) 367 | 368 | 369 | ### Features 370 | 371 | * upgrade to latest spec ([7375f99](https://github.com/ipld/js-ipld-dag-cbor/commit/7375f99)) 372 | 373 | 374 | 375 | 376 | # [0.4.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.3.1...v0.4.0) (2016-03-22) 377 | 378 | 379 | 380 | 381 | ## [0.3.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.3.0...v0.3.1) (2015-11-13) 382 | 383 | 384 | 385 | 386 | # [0.3.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.2.1...v0.3.0) (2015-11-13) 387 | 388 | 389 | 390 | 391 | ## [0.2.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.2.0...v0.2.1) (2015-10-29) 392 | 393 | 394 | 395 | 396 | # [0.2.0](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.1.3...v0.2.0) (2015-09-14) 397 | 398 | 399 | 400 | 401 | ## [0.1.3](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.1.2...v0.1.3) (2015-09-04) 402 | 403 | 404 | 405 | 406 | ## [0.1.2](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.1.1...v0.1.2) (2015-09-04) 407 | 408 | 409 | 410 | 411 | ## [0.1.1](https://github.com/ipld/js-ipld-dag-cbor/compare/v0.1.0...v0.1.1) (2015-09-01) 412 | 413 | 414 | 415 | 416 | # 0.1.0 (2015-09-01) 417 | 418 | 419 | 420 | --------------------------------------------------------------------------------