diff --git a/package.json b/package.json index 85697a8..ff4f2e4 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,8 @@ "license": "MIT", "dependencies": { "buffer": "^5.2.1", + "err-code": "^2.0.0", + "is-blob": "^2.0.1", "is-buffer": "^2.0.3", "is-electron": "^2.2.0", "is-pull-stream": "0.0.0", diff --git a/src/files/add-input-validation.js b/src/files/add-input-validation.js index cbfb952..ce00da2 100644 --- a/src/files/add-input-validation.js +++ b/src/files/add-input-validation.js @@ -1,13 +1,11 @@ 'use strict' -const kindOf = require('kind-of') -const isStream = require('is-stream') -const { isSource } = require('is-pull-stream') -const isBuffer = require('is-buffer') +const isBlob = require('is-blob') +const errcode = require('err-code') const validateAddInput = (input) => { - // Buffer|ReadableStream|PullStream|File - const isPrimitive = obj => isBuffer(obj) || isStream.readable(obj) || isSource(obj) || kindOf(obj) === 'file' + // AsyncIterator|Blob|Iterator + const isPrimitive = (obj) => obj[Symbol.asyncIterator] || isBlob(obj) || obj[Symbol.iterator] // An object like { content?, path? }, where content isBufferOrStream and path isString const isContentObject = obj => { @@ -18,13 +16,13 @@ const validateAddInput = (input) => { return Boolean(obj.path) && typeof obj.path === 'string' } - // An input atom: a buffer, stream or content object + // An input atom: an async iterable, an iterable, a blob or a content object const isInput = obj => isPrimitive(obj) || isContentObject(obj) if (isInput(input) || (Array.isArray(input) && input.every(isInput))) { return true } else { - throw new Error(`Input not supported. Expected Buffer|ReadableStream|PullStream|File|Array got ${kindOf(input)}. Check the documentation for more info https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add`) + throw errcode(new Error(`Input not supported. Expected AsyncIterator|Blob|Iterator|{path, content}|Iterator<{path, content}>|AsyncIterator<{path, content}> got ${typeof input}. Check the documentation for more info https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add`), 'ERR_UNSUPPORTED_INPUT') } } diff --git a/test/files/add-input-validation.spec.js b/test/files/add-input-validation.spec.js index f4ba1a7..a8f864a 100644 --- a/test/files/add-input-validation.spec.js +++ b/test/files/add-input-validation.spec.js @@ -7,16 +7,25 @@ const validate = require('../../src/files/add-input-validation') const { supportsFileReader } = require('../../src/supports') const { Buffer } = require('buffer') const { Readable } = require('readable-stream') -const empty = require('pull-stream/sources/empty') chai.use(dirtyChai) const expect = chai.expect describe('add-input-validation', function () { it('validates correct primitive input types', function () { + expect(validate('Hello world')).to.be.true() + expect(validate([0, 1, 2, 3])).to.be.true() expect(validate(Buffer.from(('test')))).to.be.true() expect(validate(new Readable())).to.be.true() - expect(validate(empty())).to.be.true() + expect(validate(async function * () {}())).to.be.true() + expect(validate({ + [Symbol.asyncIterator]: () => {}, + next: () => {} + })).to.be.true() + expect(validate({ + [Symbol.iterator]: () => {}, + next: () => {} + })).to.be.true() if (supportsFileReader) { const file = new self.File(['test'], 'test.txt', { type: 'text/plain' }) @@ -27,7 +36,15 @@ describe('add-input-validation', function () { it('validates correct array of primitive input types', function () { expect(validate([Buffer.from('test'), Buffer.from('test')])).to.be.true() expect(validate([new Readable(), new Readable()])).to.be.true() - expect(validate([empty(), empty()])).to.be.true() + expect(validate([(async function * () {}())])).to.be.true() + expect(validate([{ + [Symbol.asyncIterator]: () => {}, + next: () => {} + }])).to.be.true() + expect(validate([{ + [Symbol.iterator]: () => {}, + next: () => {} + }])).to.be.true() if (supportsFileReader) { const file = new self.File(['test'], 'test.txt', { type: 'text/plain' }) @@ -39,7 +56,35 @@ describe('add-input-validation', function () { expect(validate({ path: '/path' })).to.be.true() expect(validate({ path: '/path', content: Buffer.from('test') })).to.be.true() expect(validate({ content: new Readable() })).to.be.true() - expect(validate({ content: empty() })).to.be.true() + expect(validate({ content: (async function * () {}()) })).to.be.true() + expect(validate({ content: { + [Symbol.asyncIterator]: () => {}, + next: () => {} + } })).to.be.true() + expect(validate({ content: { + [Symbol.iterator]: () => {}, + next: () => {} + } })).to.be.true() + + if (supportsFileReader) { + expect(validate({ content: new Readable() })).to.be.true() + } + }) + + it('validates correct form array of of object input', function () { + expect(validate([{ path: '/path' }])).to.be.true() + expect(validate([{ path: '/path', content: Buffer.from('test') }])).to.be.true() + expect(validate([{ content: new Readable() }])).to.be.true() + expect(validate([{ content: (async function * () {}()) }])).to.be.true() + expect(validate([{ content: { + [Symbol.asyncIterator]: () => {}, + next: () => {} + } }])).to.be.true() + expect(validate([{ content: { + [Symbol.iterator]: () => {}, + next: () => {} + } }])).to.be.true() + if (supportsFileReader) { expect(validate({ content: new Readable() })).to.be.true() } @@ -47,10 +92,8 @@ describe('add-input-validation', function () { it('should throw with bad input', function () { const regex = /Input not supported/ - expect(() => validate('test')).throw(regex) expect(() => validate(2)).throw(regex) expect(() => validate({ path: 3 })).throw(regex) - expect(() => validate({ path: 'path', content: 'test' })).throw(regex) expect(() => validate({ path: 'path', content: 2 })).throw(regex) expect(() => validate({})).throw(regex) })