From 4b8021d389ac01f191d4fe87beead10088e53297 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Thu, 15 Oct 2020 21:12:07 -0700 Subject: [PATCH] feat: implement message-port ipfs.ls (#3322) --- packages/ipfs-message-port-client/src/core.js | 39 +++++++++++- .../test/interface-message-port-client.js | 4 -- packages/ipfs-message-port-server/src/core.js | 62 ++++++++++++++++--- packages/ipfs-message-port-server/src/ipfs.ts | 13 +++- 4 files changed, 102 insertions(+), 16 deletions(-) diff --git a/packages/ipfs-message-port-client/src/core.js b/packages/ipfs-message-port-client/src/core.js index 7144b6e928..388fde52d6 100644 --- a/packages/ipfs-message-port-client/src/core.js +++ b/packages/ipfs-message-port-client/src/core.js @@ -49,6 +49,8 @@ const iterateReadableStream = require('browser-readablestream-to-it') /** * @typedef {import('ipfs-message-port-server/src/core').CoreService} CoreService * @typedef {import('ipfs-message-port-server/src/core').AddedEntry} AddedEntry + * @typedef {import('ipfs-message-port-server/src/core').EncodedLsEntry} EncodedLsEntry + * @typedef {import('ipfs-message-port-server/src/core').LsEntry} LsEntry * @typedef {import('./client').ClientTransport} Transport */ @@ -61,7 +63,7 @@ class CoreClient extends Client { * @param {Transport} transport */ constructor (transport) { - super('core', ['add', 'addAll', 'cat'], transport) + super('core', ['add', 'addAll', 'cat', 'ls'], transport) } /** @@ -174,6 +176,24 @@ class CoreClient extends Client { const result = await this.remote.cat({ ...options, path: input }) yield * decodeIterable(result.data, identity) } + + /** + * Returns content addressed by a valid IPFS Path. + * + * @param {string|CID} inputPath + * @param {Object} [options] + * @param {boolean} [options.recursive] + * @param {boolean} [options.preload] + * @param {number} [options.timeout] + * @param {AbortSignal} [options.signal] + * @returns {AsyncIterable} + */ + async * ls (inputPath, options = {}) { + const input = CID.isCID(inputPath) ? encodeCID(inputPath) : inputPath + const result = await this.remote.ls({ ...options, path: input }) + + yield * decodeIterable(result.data, decodeLsEntry) + } } /** @@ -192,6 +212,21 @@ const decodeAddedData = ({ path, cid, mode, mtime, size }) => { } } +/** + * @param {EncodedLsEntry} encodedEntry + * @returns {LsEntry} + */ +const decodeLsEntry = ({ depth, name, path, size, cid, type, mode, mtime }) => ({ + cid: decodeCID(cid), + type, + name, + path, + mode, + mtime, + size, + depth +}) + /** * @template T * @param {T} v @@ -359,7 +394,7 @@ const encodeFileObject = ({ path, mode, mtime, content }, transfer) => { /** * - * @param {FileContent} [content] + * @param {FileContent|undefined} content * @param {Transferable[]} transfer * @returns {EncodedFileContent} */ diff --git a/packages/ipfs-message-port-client/test/interface-message-port-client.js b/packages/ipfs-message-port-client/test/interface-message-port-client.js index 225be17085..9381c955dd 100644 --- a/packages/ipfs-message-port-client/test/interface-message-port-client.js +++ b/packages/ipfs-message-port-client/test/interface-message-port-client.js @@ -74,10 +74,6 @@ describe('interface-ipfs-core tests', () => { name: 'get', reason: 'Not implemented' }, - { - name: 'ls', - reason: 'Not implemented' - }, { name: 'refs', reason: 'Not implemented' diff --git a/packages/ipfs-message-port-server/src/core.js b/packages/ipfs-message-port-server/src/core.js index b18a78ecef..da7952b415 100644 --- a/packages/ipfs-message-port-server/src/core.js +++ b/packages/ipfs-message-port-server/src/core.js @@ -21,6 +21,7 @@ const { decodeCID, encodeCID } = require('ipfs-message-port-protocol/src/cid') * @typedef {import('./ipfs').FileObject} FileObject * @typedef {import('./ipfs').FileContent} DecodedFileContent * @typedef {import('./ipfs').FileInput} DecodedFileInput + * @typedef {import('./ipfs').LsEntry} LsEntry */ /** @@ -95,17 +96,15 @@ const { decodeCID, encodeCID } = require('ipfs-message-port-protocol/src/cid') * @typedef {Object} LsQuery * @property {string} path * - * @typedef {RemoteIterable} LsResult - * - * @typedef {Object} LsEntry - * @property {number} depth + * @typedef {Object} EncodedLsEntry + * @property {EncodedCID} cid + * @property {FileType} type * @property {string} name * @property {string} path + * @property {number} depth * @property {number} size - * @property {EncodedCID} cid - * @property {FileType} type - * @property {Mode} mode - * @property {UnixFSTime} mtime + * @property {Mode} [mode] + * @property {UnixFSTime} [mtime] */ /** @@ -231,6 +230,26 @@ class CoreService { const content = this.ipfs.cat(location, { offset, length, timeout, signal }) return encodeCatResult(content) } + + /** + * @typedef {Object} LsResult + * @property {RemoteIterable} data + * @property {Transferable[]} transfer + * + * @param {Object} query + * @param {string|EncodedCID} query.path + * @param {boolean} [query.preload] + * @param {boolean} [query.recursive] + * @param {number} [query.timeout] + * @param {AbortSignal} [query.signal] + * @returns {LsResult} + */ + ls (query) { + const { path, recursive, preload, timeout, signal } = query + const location = typeof path === 'string' ? path : decodeCID(path) + const entries = this.ipfs.ls(location, { recursive, preload, timeout, signal }) + return encodeLsResult(entries) + } } // @returns {string|ArrayBufferView|ArrayBuffer|Blob|AsyncIterable|AsyncIterable|AsyncIterable|AsyncIterable|AsyncIterable} @@ -334,6 +353,33 @@ const encodeCatResult = content => { return { data: encodeIterable(content, moveBuffer, transfer), transfer } } +/** + * + * @param {AsyncIterable} entries + * @returns {LsResult} + */ +const encodeLsResult = entries => { + /** @type {Transferable[]} */ + const transfer = [] + return { data: encodeIterable(entries, encodeLsEntry, transfer), transfer } +} + +/** + * + * @param {LsEntry} entry + * @returns {EncodedLsEntry} + */ +const encodeLsEntry = ({ depth, name, path, size, cid, type, mode, mtime }) => ({ + cid: encodeCID(cid), + type, + name, + path, + mode, + mtime, + size, + depth +}) + /** * Adds underlying `ArrayBuffer` to the transfer list. * diff --git a/packages/ipfs-message-port-server/src/ipfs.ts b/packages/ipfs-message-port-server/src/ipfs.ts index ce62969bd6..f8538553a6 100644 --- a/packages/ipfs-message-port-server/src/ipfs.ts +++ b/packages/ipfs-message-port-server/src/ipfs.ts @@ -59,6 +59,8 @@ export interface Core { addAll(inputs: AddAllInput, options: AddOptions): AsyncIterable add(input: AddInput, options: AddOptions): Promise cat(ipfsPath: CID | string, options: CatOptions): AsyncIterable + + ls(ipfsPath: CID | string, options: CoreLsOptions): AsyncIterable } interface AddOptions extends AbortOptions { @@ -95,6 +97,11 @@ interface CatOptions extends AbortOptions { length?: number } +interface CoreLsOptions extends AbortOptions { + preload?: boolean + recursive?: boolean +} + export interface Files { chmod(path: string | CID, mode: Mode, options?: ChmodOptions): Promise @@ -120,13 +127,15 @@ interface LsOptions extends AbortOptions { sort?: boolean } -type LsEntry = { +export type LsEntry = { name: string + path: string type: FileType size: number + depth: number cid: CID mode: Mode - mtime: UnixFSTime + mtime?: UnixFSTime } interface StatOptions extends AbortOptions {