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

feat: add typeScript support #3236

Merged
merged 21 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from 9 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
8 changes: 4 additions & 4 deletions docs/core-api/FILES.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ An optional object which may have the following keys:

| Name | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| chunker | `String` | `'size-262144` | chunking algorithm used to build ipfs DAGs |
| chunker | `String` | `'size-262144'` | chunking algorithm used to build ipfs DAGs |
| cidVersion | `Number` | `0` | the CID version to use when storing the data |
| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use |
| onlyHash | `boolean` | `false` | If true, will not add blocks to the blockstore |
Expand All @@ -178,7 +178,7 @@ An optional object which may have the following keys:

| Type | Description |
| -------- | -------- |
| `UnixFSEntry` | A object describing the added data |
| `Promise<UnixFSEntry>` | A object describing the added data |

Each yielded object is of the form:

Expand Down Expand Up @@ -226,7 +226,7 @@ Now [ipfs.io/ipfs/Qm..pg/myfile.txt](https://ipfs.io/ipfs/QmWXdjNC362aPDtwHPUE9o

| Name | Type | Description |
| ---- | ---- | ----------- |
| source | [FileStream<FileContent|FileObject>](#filestream) | Data to import (see below) |
| source | [FileStream<FileContent\|FileObject>](#filestream) | Data to import (see below) |

##### FileStream

Expand All @@ -242,7 +242,7 @@ An optional object which may have the following keys:

| Name | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| chunker | `String` | `'size-262144` | chunking algorithm used to build ipfs DAGs |
| chunker | `String` | `'size-262144'` | chunking algorithm used to build ipfs DAGs |
| cidVersion | `Number` | `0` | the CID version to use when storing the data |
| enableShardingExperiment | `boolean` | `false` | allows to create directories with an unlimited number of entries currently size of unixfs directories is limited by the maximum block size. Note that this is an experimental feature |
| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use |
Expand Down
3 changes: 2 additions & 1 deletion packages/ipfs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"tcme <hi@this-connect.me>",
"victorbjelkholm <victorbjelkholm@gmail.com>",
"Łukasz Magiera <magik6k@users.noreply.github.com>",
"Максим Ильин <negamaxi@gmail.com>"
"Максим Ильин <negamaxi@gmail.com>",
"Xmader <xmader@outlook.com>"
]
}
24 changes: 22 additions & 2 deletions packages/ipfs/src/core/api-manager.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
'use strict'

module.exports = class ApiManager {
/**
* @callback UndefFn
* @param {PropertyKey} prop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why to note add @return type here and do it on line 18 instead ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eslint valid-jsdoc requires an @return on line 18, and the default return type for @callback definition is any

*/

/**
* @template API
* @typedef {{ cancel(): any; api: API; }} Updated
*/

constructor () {
this._api = {}
/**
* @type {UndefFn}
* @returns {any}
*/
this._onUndef = () => undefined
this.api = new Proxy(this._api, {
get: (_, prop) => {
Expand All @@ -12,12 +26,18 @@ module.exports = class ApiManager {
})
}

/**
* @template A
* @param {A} nextApi
* @param {UndefFn} [onUndef]
* @returns {Updated<A>}
*/
update (nextApi, onUndef) {
const prevApi = { ...this._api }
const prevUndef = this._onUndef
Object.keys(this._api).forEach(k => { delete this._api[k] })
Object.assign(this._api, nextApi)
const api = Object.assign(this._api, nextApi)
if (onUndef) this._onUndef = onUndef
return { cancel: () => this.update(prevApi, prevUndef), api: this.api }
return { cancel: () => this.update(prevApi, prevUndef), api }
}
}
59 changes: 56 additions & 3 deletions packages/ipfs/src/core/components/add-all/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,64 @@
const importer = require('ipfs-unixfs-importer')
const normaliseAddInput = require('ipfs-core-utils/src/files/normalise-input')
const { parseChunkerString } = require('./utils')
const pipe = require('it-pipe')
const { pipe } = require('it-pipe')
const { withTimeoutOption } = require('../../utils')

/**
* @typedef {Uint8Array | Blob | String | Iterable<Uint8Array|Number> | AsyncIterable<Uint8Array> | ReadableStream<Uint8Array>} FileContent
Gozala marked this conversation as resolved.
Show resolved Hide resolved
*
* @typedef {object} FileObject
* - If no path is specified, then the item will be added to the root level and will be given a name according to it's CID.
* - If no content is passed, then the item is treated as an empty directory.
* - One of path or content must be passed.
* @property {string} [path] - The path you want to the file to be accessible at from the root CID _after_ it has been added
* @property {FileContent} [content] - The contents of the file
* @property {number | string} [mode] - File mode to store the entry with (see https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation)
* @property {UnixTime} [mtime] - The modification time of the entry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 If you want to be more precise (not asking you to, I have taken same shortcuts myself) FileObject would be:

type FileObject =
  | { path: string, mode?: Mode, mtime?: UnixTime } // Directory
  | { path?: string, content: FileContent, mtime?: UnixTime } // File

That is to say it must have path or a content or both.

*
* @typedef {FileContent | FileObject} Source
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I think it would be better to call this something like FileSource or FileImport so it's little bit more meaningful out of context.

* @typedef {Iterable<Source> | AsyncIterable<Source> | ReadableStream<Source>} FileStream
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@achingbrain now that I'm looking at it, I find FileStream to be misleading, as I expect stream of representing file contents not the stream of files. Can we rename to ImportStream or something along those lines instead ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'm all for making it more straightforward.

Input streams are largely called source throughout the codebase, though I see Source here is being used for the stream contents?

*
* @typedef {Date | UnixTimeObj | [number, number]} UnixTime - As an array of numbers, it must have two elements, as per the output of [`process.hrtime()`](https://nodejs.org/dist/latest/docs/api/process.html#process_process_hrtime_time).
*
* @typedef {object} UnixTimeObj
* @property {number} secs - the number of seconds since (positive) or before (negative) the Unix Epoch began
* @property {number} [nsecs] - the number of nanoseconds since the last full second.
*
* @typedef {object} UnixFSEntry
* @property {string} path
* @property {import('cids')} cid
* @property {number} mode
* @property {UnixTimeObj} mtime
* @property {number} size
*/

module.exports = ({ block, gcLock, preload, pin, options: constructorOptions }) => {
const isShardingEnabled = constructorOptions.EXPERIMENTAL && constructorOptions.EXPERIMENTAL.sharding

return withTimeoutOption(async function * addAll (source, options) {
/**
* Import multiple files and data into IPFS.
*
* @param {FileStream} source
*
* @param {object} [options]
* @param {string} [options.chunker] - chunking algorithm used to build ipfs DAGs (default: `'size-262144'`)
* @param {Number} [options.cidVersion] - the CID version to use when storing the data (default: `0`)
* @param {boolean} [options.enableShardingExperiment] - allows to create directories with an unlimited number of entries currently size of unixfs directories is limited by the maximum block size. Note that this is an experimental feature (default: `false`)
* @param {String} [options.hashAlg] - multihash hashing algorithm to use (default: `'sha2-256'`)
* @param {boolean} [options.onlyHash] - If true, will not add blocks to the blockstore (default: `false`)
* @param {boolean} [options.pin] - pin this object when adding (default: `true`)
* @param {function} [options.progress] - a function that will be called with the byte length of chunks as a file is added to ipfs (default: `undefined`)
* @param {boolean} [options.rawLeaves] - if true, DAG leaves will contain raw file data and not be wrapped in a protobuf (default: `false`)
* @param {Number} [options.shardSplitThreshold] - Directories with more than this number of files will be created as HAMT-sharded directories (default: `1000`)
* @param {boolean} [options.trickle] - if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation (default: `false`)
* @param {boolean} [options.wrapWithDirectory] - Adds a wrapping node around the content (default: `false`)
* @param {Number} [options.timeout] - A timeout in ms (default: `undefined`)
* @param {AbortSignal} [options.signal] - Can be used to cancel any long running requests started as a result of this call (default: `undefined`)

* @returns {AsyncIterable<UnixFSEntry>}
*/
async function * addAll (source, options) {
options = options || {}

const opts = {
Expand Down Expand Up @@ -58,7 +109,9 @@ module.exports = ({ block, gcLock, preload, pin, options: constructorOptions })
} finally {
releaseLock()
}
})
}

return withTimeoutOption(addAll)
}

function transformFile (opts) {
Expand Down
28 changes: 27 additions & 1 deletion packages/ipfs/src/core/components/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,34 @@

const last = require('it-last')

/**
* @typedef {import('./add-all').Source} Source
* @typedef {import('./add-all').UnixFSEntry} UnixFSEntry
*/

module.exports = ({ addAll }) => {
return async function add (source, options) { // eslint-disable-line require-await
/**
* Import a file or data into IPFS.
*
* @param {Source} source - Data to import
*
* @param {object} [options]
* @param {String} [options.chunker] - chunking algorithm used to build ipfs DAGs (default: `'size-262144'`)
* @param {Number} [options.cidVersion] - the CID version to use when storing the data (default: `0`)
* @param {String} [options.hashAlg] - multihash hashing algorithm to use (default: `'sha2-256'`)
* @param {boolean} [options.onlyHash] - If true, will not add blocks to the blockstore (default: `false`)
* @param {boolean} [options.pin] - pin this object when adding (default: `true`)
* @param {function} [options.progress] - a function that will be called with the byte length of chunks as a file is added to ipfs (default: `undefined`)
* @param {boolean} [options.rawLeaves] - if true, DAG leaves will contain raw file data and not be wrapped in a protobuf (default: `false`)
* @param {boolean} [options.trickle] - if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation (default: `false`)
* @param {boolean} [options.wrapWithDirectory] - Adds a wrapping node around the content (default: `false`)
* @param {Number} [options.timeout] - A timeout in ms (default: `undefined`)
* @param {AbortSignal} [options.signal] - Can be used to cancel any long running requests started as a result of this call (default: `undefined`)
*
* @returns {Promise<UnixFSEntry>}
*/
async function add (source, options) { // eslint-disable-line require-await
return last(addAll(source, options))
}
return add
}
2 changes: 1 addition & 1 deletion packages/ipfs/src/core/components/bitswap/stat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const Big = require('bignumber.js')
const Big = require('bignumber.js').default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary ? From their website this is how they suggest to import

const BigNumber = require('bignumber.js');

So I would much rather keep it as it was, unless absolutely necessary. Otherwise it's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the typings work, the export signature in its .d.ts file

export default BigNumber;
export declare class BigNumber ...

is either require('bignumber.js').default or require('bignumber.js').BigNumber in CommonJS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think when namespace and class name do collide in definitions TS does know to not require default, but I could be wrong and it might be behind some config flag. I think I'd still prefer const { BigNumber: Big } = require('bignumber.js') over current version, but I'm ok with current version too.

const CID = require('cids')
const { withTimeoutOption } = require('../../utils')

Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs/src/core/components/block/rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const CID = require('cids')
const errCode = require('err-code')
const { parallelMap, filter } = require('streaming-iterables')
const pipe = require('it-pipe')
const { pipe } = require('it-pipe')
const { PinTypes } = require('../pin/pin-manager')
const { cleanCid } = require('./utils')
const { withTimeoutOption } = require('../../utils')
Expand Down
3 changes: 1 addition & 2 deletions packages/ipfs/src/core/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ exports.pin = {
}
exports.ping = require('./ping')
exports.pubsub = require('./pubsub')
exports.refs = require('./refs')
exports.refs.local = require('./refs/local')
exports.refs = Object.assign({}, require('./refs'), { local: require('./refs/local') })
exports.repo = {
gc: require('./repo/gc'),
stat: require('./repo/stat'),
Expand Down
6 changes: 4 additions & 2 deletions packages/ipfs/src/core/components/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,14 @@ module.exports = ({
})

apiManager.update(api, () => { throw new NotStartedError() })

/** @type {typeof api} */
const initializedApi = apiManager.api
return initializedApi
} catch (err) {
cancel()
throw err
}

return apiManager.api
}

async function initNewRepo (repo, { privateKey, emptyRepo, algorithm, bits, profiles, config, pass, print }) {
Expand Down
20 changes: 15 additions & 5 deletions packages/ipfs/src/core/components/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,24 @@ module.exports = ({
})

apiManager.update(api, () => undefined)

/** @type {typeof api} */
const startedApi = apiManager.api
startPromise.resolve(startedApi)
return startedApi
} catch (err) {
cancel()
startPromise.reject(err)
throw err
}

startPromise.resolve(apiManager.api)
return apiManager.api
})

// eslint-disable-next-line valid-jsdoc
/**
* @template LIBP2P
* @template BlockAPI, DagAPI, FilesAPI, PinAPI
* @param {{ [x: string]: any; libp2p: LIBP2P; block: BlockAPI; dag: DagAPI; files: FilesAPI; pin: PinAPI; }} options
*/
function createApi ({
apiManager,
bitswap,
Expand Down Expand Up @@ -222,8 +230,10 @@ function createApi ({
resolve: Components.name.resolve({ dns, ipns, peerId, isOnline, options: constructorOptions })
}
const resolve = Components.resolve({ name, ipld })
const refs = Components.refs({ ipld, resolve, preload })
refs.local = Components.refs.local({ repo })
const refs = Object.assign({},
Components.refs({ ipld, resolve, preload }),
{ local: Components.refs.local({ repo }) }
)

const pubsubNotEnabled = async () => { // eslint-disable-line require-await
throw new NotEnabledError('pubsub not enabled')
Expand Down
8 changes: 5 additions & 3 deletions packages/ipfs/src/core/components/stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = ({
libp2p,
mfsPreload,
peerId,
pinManager,
pinManager = {},
preload,
print,
repo
Expand Down Expand Up @@ -115,8 +115,10 @@ function createApi ({

const addAll = Components.addAll({ block, preload, pin, gcLock, options: constructorOptions })
const resolve = Components.resolve({ ipld })
const refs = Components.refs({ ipld, resolve, preload })
refs.local = Components.refs.local({ repo })
const refs = Object.assign({},
Components.refs({ ipld, resolve, preload }),
{ local: Components.refs.local({ repo }) }
)

const notStarted = async () => { // eslint-disable-line require-await
throw new NotStartedError()
Expand Down
Loading