Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

feat: Add pin.add to ipfs-message-port #3497

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions packages/ipfs-message-port-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
"dependencies": {
"browser-readablestream-to-it": "^1.0.1",
"ipfs-core-types": "^0.3.0",
"ipfs-message-port-protocol": "^0.6.0"
"ipfs-message-port-protocol": "file:../ipfs-message-port-protocol"
},
"devDependencies": {
"aegir": "^30.3.0",
"interface-ipfs-core": "^0.144.1",
"ipfs": "^0.54.2",
"ipfs-core": "^0.5.2",
"ipfs-message-port-server": "^0.6.1",
"ipfs-message-port-server": "file:../ipfs-message-port-server",
"rimraf": "^3.0.2"
},
"engines": {
Expand Down
4 changes: 3 additions & 1 deletion packages/ipfs-message-port-client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const BlockClient = require('./block')
const DAGClient = require('./dag')
const CoreClient = require('./core')
const FilesClient = require('./files')
const PinClient = require('./pin')

/**
* @typedef {Object} ClientOptions
Expand All @@ -19,9 +20,10 @@ class IPFSClient extends CoreClient {
constructor (transport) {
super(transport)
this.transport = transport
this.block = new BlockClient(this.transport)
this.dag = new DAGClient(this.transport)
this.files = new FilesClient(this.transport)
this.block = new BlockClient(this.transport)
this.pin = new PinClient(this.transport)
}

/**
Expand Down
127 changes: 127 additions & 0 deletions packages/ipfs-message-port-client/src/pin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
'use strict'

/* eslint-env browser */
const Client = require('./client')
const { decodeCID, encodeCID, CID } = require('ipfs-message-port-protocol/src/cid')
const { decodeIterable, encodeIterable } = require('ipfs-message-port-protocol/src/core')

/**
* @typedef {import('ipfs-message-port-protocol/src/pin').EncodedPin} EncodedPin
* @typedef {import('ipfs-message-port-protocol/src/pin').LsEntry} LsEntry
* @typedef {import('ipfs-message-port-protocol/src/pin').LsOptions} LsOptions
* @typedef {import('ipfs-message-port-protocol/src/pin').Pin} Pin
* @typedef {import('ipfs-message-port-protocol/src/pin').Source} Source
* @typedef {import('ipfs-message-port-server/src/pin').EncodedCID} EncodedCID
* @typedef {import('ipfs-message-port-server/src/pin').EncodedLsEntry} EncodedLsEntry
* @typedef {import('ipfs-message-port-server/src/pin').PinService} PinService
* @typedef {import('./client').MessageTransport} MessageTransport
*/

/**
* @class
* @extends {Client<PinService>}
*/
class PinClient extends Client {
/**
* @param {MessageTransport} transport
*/
constructor (transport) {
super('pin', ['add', 'ls', 'rmAll'], transport)
}

/**
* @param {string|CID} pathOrCID
* @param {Object} [options]
* @property {boolean} [recursive=true]
* @property {number} [timeout]
* @property {AbortSignal} [signal]
*
* @returns {Promise<CID>}
*/
async add (pathOrCID, options = {}) {
const { recursive, timeout, signal } = options
const { cid } = await this.remote.add({
path: encodePathOrCID(pathOrCID),
recursive,
timeout,
signal
})
return decodeCID(cid)
}

/**
* @param {LsOptions} [options]
* @returns {AsyncIterable<LsEntry>}
*/
async * ls (options = {}) {
let paths = options.paths
let encodedPaths

if (paths === undefined) {
encodedPaths = paths
} else if (Array.isArray(paths)) {
encodedPaths = paths.map(path => encodePathOrCID(path))
} else {
encodedPaths = encodePathOrCID(paths)
}

const result = await this.remote.ls({ ...options, paths: encodedPaths })

yield * decodeIterable(result.data, decodeLsEntry)
}

/**
* @typedef {Object} RmAllOptions
* @property {AbortSignal} [signal]
* @property {number} [timeout]
*
* @param {Source} source
* @param {RmAllOptions} [options]
* @returns {AsyncIterable<CID>}
*/
async * rmAll (source, options = {}) {
const transfer = []
const encodedSource = source[Symbol.asyncIterator]
? encodeIterable(/** @type {AsyncIterable<Pin>} */(source), encodePin, transfer)
: encodePin(/** @type {Pin} */(source))

const result = await this.remote.rmAll({ ...options, source: encodedSource, transfer })

yield * decodeIterable(result.data, decodeCID)
}
}
module.exports = PinClient

/**
*
* @param {string|CID} pathOrCID
* @returns {string|EncodedCID}
*/
const encodePathOrCID = pathOrCID =>
CID.isCID(pathOrCID) ? encodeCID(pathOrCID) : pathOrCID

/**
*
* @param {Pin} pin
* @returns {EncodedPin}
*/
const encodePin = pin => ({
...pin, path: typeof pin.path === "string" ? pin.path : encodeCID(pin.path)
})

/**
* @param {EncodedLsEntry} encodedEntry
* @returns {LsEntry}
*/
const decodeLsEntry = ({ cid, metadata, type }) => {
const entry = {
cid: decodeCID(cid),
type
}

if (metadata) {
entry.metadata = metadata
}

return entry
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,6 @@ describe('interface-ipfs-core tests', () => {
name: 'should remove by CID in buffer',
reason: 'Passing CID as Buffer is not supported'
},
{
name: 'should error when removing pinned blocks',
reason: 'ipfs.pin.add is not implemented'
},

{
name: 'should remove multiple CIDs',
reason: 'times out'
Expand All @@ -167,4 +162,59 @@ describe('interface-ipfs-core tests', () => {
}
]
})

tests.pin(factory, {
skip: [
// pin.addAll
{
name: 'should add an array of CIDs',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should add a generator of CIDs',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should add an async generator of CIDs',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should add an array of pins with options',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should add a generator of pins with options',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should add an async generator of pins with options',
reason: 'ipfs.pin.addAll is not implemented'
},
{
name: 'should respect timeout option when pinning a block',
reason: 'ipfs.pin.addAll is not implemented'
},
// pin.rm
{
name: 'should respect timeout option when unpinning a block',
reason: 'ipfs.pin.rm is not implemented'
},
{
name: 'should remove a recursive pin',
reason: 'ipfs.pin.rm is not implemented'
},
{
name: 'should remove a direct pin',
reason: 'ipfs.pin.rm is not implemented'
},
{
name: 'should fail to remove an indirect pin',
reason: 'ipfs.pin.rm is not implemented'
},
{
name: 'should fail when an item is not pinned',
reason: 'ipfs.pin.rm is not implemented'
},
]
})
})
5 changes: 3 additions & 2 deletions packages/ipfs-message-port-protocol/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ipfs-message-port-protocol",
"version": "0.6.0",
"version": "0.7.0",
"description": "IPFS client/server protocol over message port",
"keywords": [
"ipfs"
Expand Down Expand Up @@ -41,7 +41,8 @@
},
"dependencies": {
"cids": "^1.1.5",
"ipld-block": "^0.11.0"
"ipld-block": "^0.11.0",
"ipfs-core-types": "^0.3.0"
},
"devDependencies": {
"aegir": "^30.3.0",
Expand Down
54 changes: 54 additions & 0 deletions packages/ipfs-message-port-protocol/src/pin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'

/* eslint-env browser */

/**
* @typedef {import('ipfs-core-types').AbortOptions} AbortOptions
* @typedef {import('./cid').CID} CID
* @typedef {import('./cid').EncodedCID} EncodedCID
*/

/**
* @template T
* @typedef {import('./core').RemoteIterable<T>} RemoteIterable
*/

/**
* @typedef {'direct'|'recursive'|'indirect'} PinType
* @typedef {PinType|'all'} PinQueryType
*
* @typedef {Object} Pin
* @property {string|CID} path
* @property {boolean} [recursive]
* @property {any} [metadata]
*
* @typedef {Object} EncodedPin
* @property {string|EncodedCID} path
* @property {boolean} [recursive]
* @property {any} [metadata]
*
* @typedef {Pin|AsyncIterable<Pin>} Source
* @typedef {EncodedPin|RemoteIterable<EncodedPin>} EncodedSource
*/

/**
* @typedef {LsSettings & AbortOptions} LsOptions
*
* @typedef {Object} LsSettings
* @property {Array<string|CID>|string|CID} [paths]
* @property {number} [timeout]
* @property {PinType} [type]
*
* @typedef {Object} LsEntry
* @property {CID} cid
* @property {PinType} type
* @property {any} [metadata]
*
* @typedef {Object} EncodedLsEntry
* @property {EncodedCID} cid
* @property {PinType} type
* @property {any} [metadata]
*/

// trigger type exports
exports.default = {}
2 changes: 1 addition & 1 deletion packages/ipfs-message-port-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"dep-check": "aegir dep-check -i rimraf"
},
"dependencies": {
"ipfs-message-port-protocol": "^0.6.0",
"ipfs-message-port-protocol": "file:../ipfs-message-port-protocol",
"it-all": "^1.0.4"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions packages/ipfs-message-port-server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ exports.BlockService = BlockService
const { IPFSService } = require('./service')
exports.IPFSService = IPFSService

const { PinService } = require('./pin')
exports.PinService = PinService

const { Server } = require('./server')
exports.Server = Server
12 changes: 12 additions & 0 deletions packages/ipfs-message-port-server/src/ipfs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DAGNode } from 'ipfs-message-port-protocol/src/dag'
import * as pin from 'ipfs-message-port-protocol/src/pin'
import CID from 'cids'
import {
FileType,
Expand All @@ -14,6 +15,7 @@ export interface IPFS extends Core {
dag: DAG
files: Files
block: BlockService
pin: PinService
}

export interface IPFSFactory {
Expand Down Expand Up @@ -62,6 +64,12 @@ export interface Core {
ls: (ipfsPath: CID | string, options: CoreLsOptions) => AsyncIterable<LsEntry>
}

export interface PinService {
add(path: string | CID, options?: AddPinOptions): Promise<CID>
ls(options: pin.LsOptions): AsyncIterable<pin.LsEntry>
rmAll(source: pin.Source, options?: AbortOptions): AsyncIterable<CID>
}

export interface AddOptions extends AbortOptions {
chunker?: string
cidVersion?: number
Expand All @@ -76,6 +84,10 @@ export interface AddOptions extends AbortOptions {
wrapWithDirectory?: boolean
}

export interface AddPinOptions extends AbortOptions {
recursive?: boolean
}

export interface FileInput {
path?: string
content?: FileContent
Expand Down
Loading