Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@
"aegir": "^43.0.1",
"buffer": "^6.0.3",
"cids": "^1.1.9",
"crypto-hash": "^3.0.0"
"crypto-hash": "^3.0.0",
"mocha": "^10.7.0"
},
"aegir": {
"test": {
Expand Down
12 changes: 6 additions & 6 deletions src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export async function encode <T, Code extends number, Alg extends number> ({ val
if (typeof value === 'undefined') throw new Error('Missing required argument "value"')
if (codec == null || hasher == null) throw new Error('Missing required argument: codec or hasher')

const bytes = codec.encode(value)
const bytes = await Promise.resolve(codec.encode(value))
const hash = await hasher.digest(bytes)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const cid = CID.create(
Expand All @@ -168,7 +168,7 @@ export async function decode <T, Code extends number, Alg extends number> ({ byt
if (bytes == null) throw new Error('Missing required argument "bytes"')
if (codec == null || hasher == null) throw new Error('Missing required argument: codec or hasher')

const value = codec.decode(bytes)
const value = await Promise.resolve(codec.decode(bytes))
const hash = await hasher.digest(bytes)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const cid = CID.create(1, codec.code, hash) as CID<T, Code, Alg, 1>
Expand All @@ -194,10 +194,10 @@ type CreateUnsafeInput <T, Code extends number, Alg extends number, V extends AP
* @template Alg - multicodec code corresponding to the hashing algorithm used in CID creation.
* @template V - CID version
*/
export function createUnsafe <T, Code extends number, Alg extends number, V extends API.Version> ({ bytes, cid, value: maybeValue, codec }: CreateUnsafeInput<T, Code, Alg, V>): API.BlockView<T, Code, Alg, V> {
const value = maybeValue !== undefined
export async function createUnsafe <T, Code extends number, Alg extends number, V extends API.Version> ({ bytes, cid, value: maybeValue, codec }: CreateUnsafeInput<T, Code, Alg, V>): Promise<API.BlockView<T, Code, Alg, V>> {
const value = await Promise.resolve(maybeValue !== undefined
? maybeValue
: (codec?.decode(bytes))
: (codec?.decode(bytes)))

if (value === undefined) throw new Error('Missing required argument, must either provide "value" or "codec"')

Expand All @@ -224,7 +224,7 @@ interface CreateInput <T, Code extends number, Alg extends number, V extends API
export async function create <T, Code extends number, Alg extends number, V extends API.Version> ({ bytes, cid, hasher, codec }: CreateInput<T, Code, Alg, V>): Promise<API.BlockView<T, Code, Alg, V>> {
if (bytes == null) throw new Error('Missing required argument "bytes"')
if (hasher == null) throw new Error('Missing required argument "hasher"')
const value = codec.decode(bytes)
const value = await Promise.resolve(codec.decode(bytes))
const hash = await hasher.digest(bytes)
if (!binary.equals(cid.multihash.bytes, hash.bytes)) {
throw new Error('CID hash does not match bytes')
Expand Down
4 changes: 2 additions & 2 deletions src/codecs/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import type { ArrayBufferView, ByteView } from '../block/interface.js'
export interface BlockEncoder<Code extends number, T> {
name: string
code: Code
encode(data: T): ByteView<T>
encode(data: T): ByteView<T> | PromiseLike<ByteView<T>>
}

/**
* IPLD decoder part of the codec.
*/
export interface BlockDecoder<Code extends number, T> {
code: Code
decode(bytes: ByteView<T> | ArrayBufferView<T>): T
decode(bytes: ByteView<T> | ArrayBufferView<T>): T | PromiseLike<T>
}

/**
Expand Down
47 changes: 35 additions & 12 deletions test/test-block.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ const fixture = { hello: 'world' }
const link = CID.parse('bafyreidykglsfhoixmivffc5uwhcgshx4j465xwqntbmu43nb2dzqwfvae')
const buff = bytes.fromString('sadf')

describe('promise-resolve-semantics', () => {
it('should resolve to the value', async () => {
const value = await Promise.resolve('hello')
assert.equal(value, 'hello')
})
it('should resolve to the promise value', async () => {
// eslint-disable-next-line promise/param-names
const value = await Promise.resolve(new Promise<string>(function (rs: (value: string) => void) {
setTimeout(function () { rs('hello') }, 10)
}))
assert.equal(value, 'hello')
})
})

describe('block', () => {
it('basic encode/decode roundtrip', async () => {
const block = await main.encode({ value: fixture, codec, hasher })
Expand All @@ -23,7 +37,7 @@ describe('block', () => {

it('createUnsafe', async () => {
const block = await main.encode({ value: fixture, codec, hasher })
const block2 = main.createUnsafe({ bytes: block.bytes, cid: block.cid, codec })
const block2 = await main.createUnsafe({ bytes: block.bytes, cid: block.cid, codec })
assert.deepStrictEqual(block.cid.equals(block2.cid), true)
})

Expand All @@ -36,25 +50,29 @@ describe('block', () => {
// @ts-expect-error - 'string' is not assignable to parameter of type 'ArrayLike<number>'
bytes: Uint8Array.from('1234')
}
// @ts-expect-error - 'boolean' is not assignable to type 'CID'
const block = main.createUnsafe({ value, codec, hasher, cid: true, bytes: true })

it('links', () => {
it('links', async () => {
const expected = ['link', 'arr/0']
// @ts-expect-error - 'boolean' is not assignable to type 'CID'
const block = await main.createUnsafe({ value, codec, hasher, cid: true, bytes: true })
for (const [path, cid] of block.links()) {
assert.deepStrictEqual(path, expected.shift())
assert.deepStrictEqual(cid.toString(), link.toString())
}
})

it('tree', () => {
it('tree', async () => {
const expected = ['link', 'nope', 'arr', 'arr/0', 'obj', 'obj/arr', 'obj/arr/0', 'obj/arr/0/obj', 'bytes']
// @ts-expect-error - 'boolean' is not assignable to type 'CID'
const block = await main.createUnsafe({ value, codec, hasher, cid: true, bytes: true })
for (const path of block.tree()) {
assert.deepStrictEqual(path, expected.shift())
}
})

it('get', () => {
it('get', async () => {
// @ts-expect-error - 'boolean' is not assignable to type 'CID'
const block = await main.createUnsafe({ value, codec, hasher, cid: true, bytes: true })
let ret = block.get('link/test')
assert.deepStrictEqual(ret.remaining, 'test')
assert.deepStrictEqual(String(ret.value), link.toString())
Expand All @@ -63,8 +81,8 @@ describe('block', () => {
assert.deepStrictEqual(ret, { value: 'skip' })
})

it('null links/tree', () => {
const block = main.createUnsafe({
it('null links/tree', async () => {
const block = await main.createUnsafe({
value: null,
codec,
hasher,
Expand Down Expand Up @@ -95,9 +113,9 @@ describe('block', () => {
assert.equal(links[0][1].toString(), link.toString())
})

it('kitchen sink', () => {
it('kitchen sink', async () => {
const sink = { one: { two: { arr: [true, false, null], three: 3, buff, link } } }
const block = main.createUnsafe({
const block = await main.createUnsafe({
value: sink,
codec,
// @ts-expect-error - 'boolean' is not assignable to type 'ByteView<unknown>'
Expand Down Expand Up @@ -132,8 +150,13 @@ describe('block', () => {
})

it('createUnsafe', async () => {
// @ts-expect-error testing invalid usage
assert.throws(() => main.createUnsafe({}), 'Missing required argument, must either provide "value" or "codec"')
try {
// @ts-expect-error testing invalid usage
await main.createUnsafe({})
assert(false, 'Missing required argument, must either provide "value" or "codec"')
} catch (/** @type {Error} */ err) {
/* c8 ignore next */
}
})

it('create', async () => {
Expand Down
6 changes: 4 additions & 2 deletions test/test-multibase-spec.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,11 @@ describe('spec test', () => {
}

for (const base of Object.values(bases)) {
it('should fail decode with invalid char', function () {
// eslint-disable-next-line @typescript-eslint/method-signature-style
it('should fail decode with invalid char', function (this: { skip: () => void }) {
if (base.name === 'identity') {
return this.skip()
this.skip()
return
}

assert.throws(() => base.decode(base.prefix + '^!@$%!#$%@#y'), `Non-${base.name} character`)
Expand Down