-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Alan Shaw
committed
Apr 20, 2021
0 parents
commit 2b8c753
Showing
9 changed files
with
5,382 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
The MIT License (MIT) | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# ipfs-cluster | ||
|
||
A zero-dependency client to the [IPFS Cluster](https://cluster.ipfs.io/) HTTP API, built for the browser. | ||
|
||
## Install | ||
|
||
Import it from your favourite CDN (e.g. skypack.dev, unpkg.com, jsdelivr.com) or install directly from npm: | ||
|
||
```sh | ||
npm i @nftstorage/ipfs-cluster | ||
``` | ||
|
||
## Usage | ||
|
||
Example: | ||
|
||
```js | ||
import { Cluster } from 'https://cdn.skypack.dev/@nftstorage/ipfs-cluster' | ||
|
||
const cluster = new Cluster('https://your-cluster-domain.com', { auth: 'TOKEN' }) | ||
|
||
const file = new File(['foo'], 'foo.txt') | ||
const { Hash } = await cluster.add(file) | ||
``` | ||
|
||
### Using in Node.js | ||
|
||
This library is designed to run in the browser or in web workers but it can be run in Node.js if required web APIs are added to the global environment. For exmaple: | ||
|
||
```js | ||
import fetch from '@web-std/fetch' | ||
import { FormData } from '@web-std/form-data' | ||
import { File, Blob } from '@web-std/file' | ||
|
||
Object.assign(global, { fetch, File, Blob, FormData }) | ||
``` | ||
|
||
## API | ||
|
||
This library is **WIP** and not _all_ cluster HTTP API methods are available yet. | ||
|
||
### Constructor | ||
|
||
Create a new instance of the cluster client. | ||
|
||
```js | ||
import { Cluster } from '@nftstorage/ipfs-cluster' | ||
const cluster = new Cluster('https://your-cluster-domain.com', { auth: 'TOKEN' }) | ||
``` | ||
|
||
### `add` | ||
|
||
Import a file to the cluster. First argument must be a `File` or `Blob`. | ||
|
||
```js | ||
const file = new File(['foo'], 'foo.txt') | ||
const { cid } = await cluster.add(file) | ||
``` | ||
|
||
### `addDirectory` | ||
|
||
Imports multiple files to the cluster. First argument must be an array of `File` or `Blob`. | ||
|
||
```js | ||
const files = [ | ||
new File(['foo'], 'foo.txt'), | ||
new File(['bar'], 'bar.txt'), | ||
] | ||
const dir = await cluster.addDirectory(file) | ||
|
||
for (const entry of dir) { | ||
console.log(entry.cid) | ||
} | ||
``` | ||
|
||
### `pin` | ||
|
||
Tracks a CID with the given replication factor and a name for human-friendliness. | ||
|
||
```js | ||
const cid = 'bafybeigpsl667todjswabhelaxvwmk7amgg3txsv5tkcpbpj5rtrf6g7mu' | ||
const { cid } = await cluster.pin(cid) | ||
``` | ||
|
||
### `unpin` | ||
|
||
Untracks a CID from cluster. | ||
|
||
```js | ||
const cid = 'bafybeigpsl667todjswabhelaxvwmk7amgg3txsv5tkcpbpj5rtrf6g7mu' | ||
const { cid } = await cluster.pin(cid) | ||
``` | ||
|
||
### `status` | ||
|
||
Returns the current IPFS state for a given CID. | ||
|
||
```js | ||
const cid = 'bafybeigpsl667todjswabhelaxvwmk7amgg3txsv5tkcpbpj5rtrf6g7mu' | ||
const status = await cluster.status(cid) | ||
|
||
for (const [clusterPeerID, pinInfo] of Object.entries(status.peerMap)) { | ||
console.log(`${clusterPeerID}: ${pinInfo.status}`) | ||
} | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
export type AddResponse = { | ||
cid: string | ||
name?: string | ||
size?: number|string | ||
bytes?: number|string | ||
} | ||
|
||
export type AddDirectoryResponse = AddResponse[] | ||
|
||
export type PinOptions = { | ||
replicationFactorMin?: number | ||
replicationFactorMax?: number | ||
name?: string | ||
/** | ||
* 0 = recursive, 1 = direct | ||
*/ | ||
mode?: 0|1 | ||
shardSize?: number | ||
/** | ||
* The peers to which this pin should be allocated. | ||
*/ | ||
userAllocations?: string[] | ||
expireAt?: Date | ||
metadata?: Record<string, string> | ||
pinUpdate?: string | ||
} | ||
|
||
export enum PinType { | ||
/** | ||
* Bad type showing up anywhere indicates a bug | ||
*/ | ||
BAD = 1, | ||
/** | ||
* Data is a regular, non-sharded pin. It is pinned recursively. | ||
* It has no associated reference. | ||
*/ | ||
DATA = 2, | ||
/** | ||
* Meta tracks the original CID of a sharded DAG. Its Reference points to the | ||
* Cluster DAG CID. | ||
*/ | ||
META = 3, | ||
/** | ||
* ClusterDAG pins carry the CID of the root node that points to all the | ||
* shard-root-nodes of the shards in which a DAG has been divided. Its | ||
* Reference carries the MetaType CID. | ||
* ClusterDAGType pins are pinned directly everywhere. | ||
*/ | ||
CLUSTER_DAG = 4, | ||
/** | ||
* Shard pins carry the root CID of a shard, which points to individual blocks | ||
* on the original DAG that the user is adding, which has been sharded. They | ||
* carry a Reference to the previous shard. ShardTypes are pinned with | ||
* MaxDepth=1 (root and direct children only). | ||
*/ | ||
SHARD = 5 | ||
} | ||
|
||
export type PinResponse = { | ||
replicationFactorMin: number | ||
replicationFactorMax: number | ||
name: string | ||
mode: 0|1 | ||
shardSize: number | ||
/** | ||
* The peers to which this pin is allocated. | ||
*/ | ||
userAllocations?: string[] | ||
expireAt: Date | ||
metadata?: Record<string, string> | ||
pinUpdate?: string | ||
cid: string | ||
/** | ||
* Specifies which sort of Pin object we are dealing with. In practice, the | ||
* type decides how a Pin object is treated by the PinTracker. | ||
*/ | ||
type: PinType | ||
/** | ||
* The peers to which this pin is allocated. | ||
*/ | ||
allocations: string[] | ||
/** | ||
* Indicates how deep a pin should be pinned, with -1 meaning "to the bottom", | ||
* or "recursive". | ||
*/ | ||
maxDepth: number | ||
/** | ||
* We carry a reference CID to this pin. For ClusterDAGs, it is the MetaPin | ||
* CID. For the MetaPin it is the ClusterDAG CID. For Shards, it is the | ||
* previous shard CID. When not needed it is undefined. | ||
*/ | ||
reference?: string | ||
} | ||
|
||
export type StatusOptions = { | ||
local?: boolean | ||
} | ||
|
||
export type StatusResponse = { | ||
cid: string | ||
name: string | ||
peerMap: Record<string, PinInfo> | ||
} | ||
|
||
export type PinInfo = { | ||
peerName: string | ||
status: TrackerStatus | ||
timestamp: Date | ||
error: string | ||
} | ||
|
||
export enum TrackerStatus { | ||
/** | ||
* IPFSStatus should never take this value. When used as a filter. It means "all". | ||
*/ | ||
UNDEFINED = 'undefined', | ||
/** | ||
* The cluster node is offline or not responding. | ||
*/ | ||
CLUSTER_ERROR = 'cluster_error', | ||
/** | ||
* An error occurred pinning. | ||
*/ | ||
PIN_ERROR = 'pin_error', | ||
/** | ||
* An error occurred unpinning. | ||
*/ | ||
UNPIN_ERROR = 'unpin_error', | ||
/** | ||
* The IPFS daemon has pinned the item. | ||
*/ | ||
PINNED = 'pinned', | ||
/** | ||
* The IPFS daemon is currently pinning the item. | ||
*/ | ||
PINNING = 'pinning', | ||
/** | ||
* The IPFS daemon is currently unpinning the item. | ||
*/ | ||
UNPINNING = 'unpinning', | ||
/** | ||
* The IPFS daemon is not pinning the item. | ||
*/ | ||
UNPINNED = 'unpinned', | ||
/** | ||
* The IPFS daemon is not pinning the item but it is being tracked. | ||
*/ | ||
REMOTE = 'remote', | ||
/** | ||
* The item has been queued for pinning on the IPFS daemon. | ||
*/ | ||
PIN_QUEUED = 'queued', | ||
/** | ||
* The item has been queued for unpinning on the IPFS daemon. | ||
*/ | ||
UNPIN_QUEUED = 'unpin_queued', | ||
/** | ||
* The IPFS daemon is not pinning the item through this CID but it is tracked | ||
* in a cluster dag | ||
*/ | ||
SHARDED = 'sharded' | ||
} | ||
|
||
export class Cluster { | ||
constructor (url: URL|string, options?: { auth: string }) | ||
add (file: File|Blob, options: PinOptions): Promise<AddResponse> | ||
addDirectory (file: Iterable<File|Blob>, options: PinOptions): Promise<AddDirectoryResponse> | ||
pin (cid: string, options?: PinOptions): Promise<PinResponse> | ||
unpin (cid: string): Promise<PinResponse> | ||
status (cid: string, options?: StatusOptions): Promise<StatusResponse> | ||
} |
Oops, something went wrong.