Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
120 lines (104 sloc)
2.87 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict' | |
| const dirBuilder = require('./dir') | |
| const fileBuilder = require('./file') | |
| const errCode = require('err-code') | |
| /** | |
| * @typedef {import('../types').File} File | |
| * @typedef {import('../types').Directory} Directory | |
| * @typedef {import('../types').DAGBuilder} DAGBuilder | |
| * @typedef {import('../types').Chunker} Chunker | |
| * @typedef {import('../types').ChunkValidator} ChunkValidator | |
| */ | |
| /** | |
| * @param {any} thing | |
| * @returns {thing is Iterable<any>} | |
| */ | |
| function isIterable (thing) { | |
| return Symbol.iterator in thing | |
| } | |
| /** | |
| * @param {any} thing | |
| * @returns {thing is AsyncIterable<any>} | |
| */ | |
| function isAsyncIterable (thing) { | |
| return Symbol.asyncIterator in thing | |
| } | |
| /** | |
| * @param {Uint8Array | AsyncIterable<Uint8Array> | Iterable<Uint8Array>} content | |
| * @returns {AsyncIterable<Uint8Array>} | |
| */ | |
| function contentAsAsyncIterable (content) { | |
| try { | |
| if (content instanceof Uint8Array) { | |
| return (async function * () { | |
| yield content | |
| }()) | |
| } else if (isIterable(content)) { | |
| return (async function * () { | |
| yield * content | |
| }()) | |
| } else if (isAsyncIterable(content)) { | |
| return content | |
| } | |
| } catch { | |
| throw errCode(new Error('Content was invalid'), 'ERR_INVALID_CONTENT') | |
| } | |
| throw errCode(new Error('Content was invalid'), 'ERR_INVALID_CONTENT') | |
| } | |
| /** | |
| * @type {DAGBuilder} | |
| */ | |
| async function * dagBuilder (source, blockstore, options) { | |
| for await (const entry of source) { | |
| if (entry.path) { | |
| if (entry.path.substring(0, 2) === './') { | |
| options.wrapWithDirectory = true | |
| } | |
| entry.path = entry.path | |
| .split('/') | |
| .filter(path => path && path !== '.') | |
| .join('/') | |
| } | |
| if (entry.content) { | |
| /** | |
| * @type {Chunker} | |
| */ | |
| let chunker | |
| if (typeof options.chunker === 'function') { | |
| chunker = options.chunker | |
| } else if (options.chunker === 'rabin') { | |
| chunker = require('../chunker/rabin') | |
| } else { | |
| chunker = require('../chunker/fixed-size') | |
| } | |
| /** | |
| * @type {ChunkValidator} | |
| */ | |
| let chunkValidator | |
| if (typeof options.chunkValidator === 'function') { | |
| chunkValidator = options.chunkValidator | |
| } else { | |
| chunkValidator = require('./validate-chunks') | |
| } | |
| /** @type {File} */ | |
| const file = { | |
| path: entry.path, | |
| mtime: entry.mtime, | |
| mode: entry.mode, | |
| content: chunker(chunkValidator(contentAsAsyncIterable(entry.content), options), options) | |
| } | |
| yield () => fileBuilder(file, blockstore, options) | |
| } else if (entry.path) { | |
| /** @type {Directory} */ | |
| const dir = { | |
| path: entry.path, | |
| mtime: entry.mtime, | |
| mode: entry.mode | |
| } | |
| yield () => dirBuilder(dir, blockstore, options) | |
| } else { | |
| throw new Error('Import candidate must have content or path or both') | |
| } | |
| } | |
| } | |
| module.exports = dagBuilder |