diff --git a/src/block.ts b/src/block.ts index ae59ff13..3e2f9504 100644 --- a/src/block.ts +++ b/src/block.ts @@ -141,7 +141,7 @@ export async function encode ({ 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( @@ -168,7 +168,7 @@ export async function decode ({ 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 @@ -194,10 +194,10 @@ type CreateUnsafeInput ({ bytes, cid, value: maybeValue, codec }: CreateUnsafeInput): API.BlockView { - const value = maybeValue !== undefined +export async function createUnsafe ({ bytes, cid, value: maybeValue, codec }: CreateUnsafeInput): Promise> { + 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"') @@ -224,7 +224,7 @@ interface CreateInput ({ bytes, cid, hasher, codec }: CreateInput): Promise> { 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') diff --git a/src/codecs/interface.ts b/src/codecs/interface.ts index 8e5d9d1a..61b5394e 100644 --- a/src/codecs/interface.ts +++ b/src/codecs/interface.ts @@ -6,7 +6,7 @@ import type { ArrayBufferView, ByteView } from '../block/interface.js' export interface BlockEncoder { name: string code: Code - encode(data: T): ByteView + encode(data: T): ByteView | PromiseLike> } /** @@ -14,7 +14,7 @@ export interface BlockEncoder { */ export interface BlockDecoder { code: Code - decode(bytes: ByteView | ArrayBufferView): T + decode(bytes: ByteView | ArrayBufferView): T | PromiseLike } /** diff --git a/test/test-block.spec.ts b/test/test-block.spec.ts index 120be93c..30c07e8e 100644 --- a/test/test-block.spec.ts +++ b/test/test-block.spec.ts @@ -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(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 }) @@ -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) }) @@ -36,25 +50,29 @@ describe('block', () => { // @ts-expect-error - 'string' is not assignable to parameter of type 'ArrayLike' 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()) @@ -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, @@ -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' @@ -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 () => { diff --git a/test/test-multibase-spec.spec.ts b/test/test-multibase-spec.spec.ts index 1f7f2523..db5dbece 100644 --- a/test/test-multibase-spec.spec.ts +++ b/test/test-multibase-spec.spec.ts @@ -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`)