diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index fceedd7b8..34cd39043 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -24,8 +24,8 @@ module.exports = { md.use(require('markdown-it-footnote')) md.use(require('markdown-it-task-lists')) md.use(require('markdown-it-deflist')), - md.use(require('markdown-it-imsize')), - md.use(require('markdown-it-image-lazy-loading')) + md.use(require('markdown-it-imsize')), + md.use(require('markdown-it-image-lazy-loading')) } }, themeConfig: { @@ -85,7 +85,8 @@ module.exports = { path: '/basics/', children: [ 'basics/desktop-app', - 'basics/command-line', + 'basics/go/command-line', + 'basics/js/js-ipfs', 'basics/ipfs-implementations' ] }, @@ -200,7 +201,7 @@ module.exports = { '/how-to/work-with-pinning-services', '/how-to/take-snapshot', '/how-to/store-play-videos', - '/how-to/host-git-style-repo', + '/how-to/host-git-repo', '/how-to/move-ipfs-installation/move-ipfs-installation' ] }, @@ -433,7 +434,8 @@ module.exports = { } ], 'vuepress-plugin-chunkload-redirect', - 'vuepress-plugin-ipfs' + 'vuepress-plugin-ipfs', + 'tabs' ], extraWatchFiles: ['.vuepress/nav/en.js'] } diff --git a/docs/.vuepress/theme/styles/index.styl b/docs/.vuepress/theme/styles/index.styl index facdaa4f1..08c64665d 100644 --- a/docs/.vuepress/theme/styles/index.styl +++ b/docs/.vuepress/theme/styles/index.styl @@ -6,6 +6,7 @@ @import 'video'; @import 'alert-panels'; @import 'ipfs'; +@require '~vuepress-plugin-tabs/dist/themes/default.styl' // apply scrolling by default excluding firefox due to trigger issues html.smooth-scroll { @@ -75,3 +76,12 @@ code { --code-bg-color: $codeBgColor; --highlight-color: $highlightColor; } + +section.tabs-component-panel::before { + content: ''; + display: block; + position: relative; + width: 0; + height: 10em; + margin-top: -10em; +} diff --git a/docs/basics/command-line.md b/docs/basics/go/command-line.md similarity index 97% rename from docs/basics/command-line.md rename to docs/basics/go/command-line.md index 043329fd1..925da4b68 100644 --- a/docs/basics/command-line.md +++ b/docs/basics/go/command-line.md @@ -1,11 +1,11 @@ --- -title: "Command-line" +title: IPFS in Golang description: "A simple walkthrough of how to perform basic IPFS operations using the Kubo command-line." --- # Basic CLI Operations -This short guide aims to walk you through the basics of using IPFS with the Kubo CLI. Kubo is [one of multiple IPFS implementations](ipfs-implementations.md). It is the oldest IPFS implementation and exposes a CLI (among other things). +This short guide aims to walk you through the **basics of using IPFS with the Kubo CLI**. Kubo is [one of multiple IPFS implementations](../ipfs-implementations.md). It is the oldest IPFS implementation and exposes a CLI (among other things). You will learn how to add, retrieve, read, and remove files within the CLI. If you are unsure about the meaning of some terms, you can check out the [glossary](../concepts/glossary.md). diff --git a/docs/basics/js/js-ipfs.md b/docs/basics/js/js-ipfs.md new file mode 100644 index 000000000..a31f859c3 --- /dev/null +++ b/docs/basics/js/js-ipfs.md @@ -0,0 +1,450 @@ +--- +title: IPFS in JavaScript +description: "A simple walkthrough of how to perform basic IPFS operations using the JavaScript implementation." +--- + +# IPFS in JavaScript + +This guide will walk you through the basics of using IPFS with JavaScript. JS-IPFS is one of multiple [IPFS implementations](../ipfs-implementations.md). You will learn how to install and spawn a node using the available libraries, and add, retrieve, read, and remove files. If you are unsure about the meaning of some terms, check out the [glossary](../concepts/glossary.md). + +::: tip Environment + +All instructions and examples shown here were performed and tested on an M1 Mac. However, the IPFS commands are the same on Linux, macOS, and Windows. You will to navigate your computer's directories from within the CLI. If you're unsure how to use the CLI, we recommend learning how before continuing with this guide. + +::: + +There are two ways to work with IPFS using JavaScript; the [JS-IPFS](../../reference/js/api/#js-ipfs) library or the [HTTP client](../../reference/js/api/#http-client). We'll show you how to use both in this guide. + +## Install JS-IPFS + +:::: tabs + +::: tab ipfs-cli id="install-ipfs-cli" + +### JS-IPFS module + +To use the CLI on your machine, globally install the `ipfs` Node.js package: + + ```bash + npm i --location=global ipfs + ``` + +Alternatively, you can build the project from the source. See the [JS-IPFS GitHub repository](https://github.com/ipfs/js-ipfs) for instructions. + +::: + +::: tab ipfs-core id="install-ipfs-core" + +### IPFS core API + +To use the IPFS core API, install the `ipfs-core` Node.js package: + + ```bash + npm i ipfs-core + ``` + +Alternatively, you can build the project from the source. See the [JS-IPFS GitHub repository](https://github.com/ipfs/js-ipfs) for instructions. + +::: + +:::: + +## Spawn a node + +:::: tabs + +::: tab ipfs-cli id="spawn-ipfs-cli" + +1. To spawn a node using the CLI, start the daemon: + + ```bash + jsipfs daemon + ``` + +2. You should see an output similar to: + + ```shell + Initializing IPFS daemon... + System version: arm64/darwin + Node.js version: 16.16.0 + Swarm listening on /ip4/127.0.0.1/tcp/4002/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + Swarm listening on /ip4/10.0.0.25/tcp/4002/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + Swarm listening on /ip4/10.2.0.2/tcp/4002/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + Swarm listening on /ip4/127.0.0.1/tcp/4003/ws/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + js-ipfs version: 0.15.4 + HTTP API listening on /ip4/127.0.0.1/tcp/5002/http + gRPC listening on /ip4/127.0.0.1/tcp/5003/ws + Gateway (read only) listening on /ip4/127.0.0.1/tcp/9090/http + Web UI available at http://127.0.0.1:5002/webui + Daemon is ready + ``` + +3. You should be able to point to the [webpage](http://127.0.0.1:5002/webui) using the address output by the terminal `http://127.0.0.1:5002/webui`: + + ![The JS-IPFS daemon showing the web-ui.](../../images/jsipfs-webui.png) + +4. If you are unable to connect to the API, ensure [cross-origin (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) requests are configured: + + ```bash + jsipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://127.0.0.1:5002", "http://localhost:3000", "http://127.0.0.1:5001", "https://webui.ipfs.io"]' + jsipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "POST"]' + ``` + +::: + +::: tab ipfs-core id="spawn-ipfs-core" + +Create a simple Node.js application to host the logic that will allow you to use the RPC API. You'll also use this Node.js application later on to add and remove files. + +1. Start by initiating a new project: + + ```bash + npm init -y + ``` + +1. If you have not already installed `ipfs-core`, add the `ipfs-core` module to your project: + + ```bash + npm i ipfs-core + ``` + +1. Create an `index.js` file for the application logic: + + ```bash + touch index.js + ``` + +1. Now, populate the `index.js` file by initiating an `async` function: + + ```js + const main = async () => { + // "await" logic to spawn a node + } + + main() + ``` + +1. To create an IPFS node, add: + + ```js{1,4} + import * as IPFS from 'ipfs-core'; + + async function main() { + const node = await IPFS.create(); + } + + main(); + ``` + + This imports IPFS as a dependency and uses the `create()` function to create a node instance. + +1. To spawn the node, run the application: + + ```bash + node index.js + ``` + +1. You should see an output similar to: + + ```shell + Swarm listening on /ip4/127.0.0.1/tcp/4002/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + Swarm listening on /ip4/10.0.0.25/tcp/4002/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + Swarm listening on /ip4/127.0.0.1/tcp/4003/ws/p2p/12D3KooWMZr34r6FArFH36QxyT25BM4HL4u2WF7jQzwNdg91awB6 + ``` + +::: + +:::: + +### Connect to IPFS + +The JS-IPFS implementation is split into several Node.js modules. The following section shows examples of using the HTTP client to connect to IPFS. For more information on the different modules, examine the [API Packages table](../../reference/js/api.md##packages) + +:::: tabs + +::: tab ipfs-http-client id="connect-ipfs-http-client" + +1. If you have not already installed the client library, add the `ipfs-http-client` module to your project: + + ```bash + npm i ipfs-http-client + ``` + +1. Populate your `index.js` file with the following to create an instance of the HTTP API client: + + ```js{1,3} + import { create } from 'ipfs-http-client' + + const client = create() // the default API address http://localhost:5001 + ``` + + This imports the client library and uses the `create()` function to connect to an IPFS API server. + +1. To connect to the API, run the application: + + ```bash + node index.js + ``` + +The library internally detects if your machine is running a local node. + +::: + +::: tab ipfs-client id="connect-ipfs-client" + +1. If you have not already installed the client library, add the `ipfs-client` module to your project: + + ```bash + npm i ipfs-client + ``` + +1. Populate your `index.js` file with the following to create an instance of the HTTP API client: + + ```js{1,3-5} + import { create } from 'ipfs-client' + + const client = create({ + grpc: '/ip4/127.0.0.1/tcp/5003/ws', + http: '/ip4/127.0.0.1/tcp/5002/http' + }) + + const id = await client.id() + ``` + + This imports the client library and uses the `create()` function to define the server endpoints. + +1. To connect to the endpoints, run the application: + + ```bash + node index.js + ``` + +The library internally detects if your machine is running a local node that leverages the specified connections. + +::: + +:::: + +## Add a file + +Now you can start to add files using JS-IPFS to the IPFS network. + +::: warning Section changes coming soon + +As the JS-IPFS implementation changes, some of these steps should be deemed conditional. Please reference the [source packages](https://github.com/ipfs/js-ipfs) for the latest updates. + +::: + +:::: tabs + +::: tab ipfs-cli id="add-ipfs-cli" + +1. In a new session, navigate to the directory from which you wish to add a file. You can also specify the file path when using the cli to add a file. +2. The daemon uses an `ADD` method to request data from IPFS; `jsipfs add`. We will use a test file called `test.txt` to add through the jsipfs daemon. + + ```bash + jsipfs add ./test.txt + ``` + +3. You should obtain a result that verifies the file was added and returns the CID: + + ```shell + added QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi test.txt + ``` + +4. The file has been added to the IPFS network and has given the file a CID. You can share this CID with anyone, and they can use it on their IPFS node to obtain the content you uploaded. +5. To view the file contents, navigate to the [webui](http://127.0.0.1:5002/webui) and provide the CID on the search bar. The UI will provide the file contents, similar to the following: + +![](../../images/jsipfs-add-webui.png) + +::: + +::: tab ipfs-core id="add-ipfs-core" + +1. To add a file using `ipfs-core`, you can create a test `.txt` file in your project directory or point to a local file on your machine that you would like to upload to IPFS. +1. Then, using `node.add`, add an `await` operator that includes a `path` and `content` field and an output message in the project's `index.js` file: + + ```js{6-9,11} + import * as IPFS from 'ipfs-core'; + + async function main() { + const node = await IPFS.create(); + + const fileAdded = await node.add({ + path: "test.txt", + content: "Hello IPFS!", + }); + + console.log("Added file:", fileAdded.path, fileAdded.cid); + } + + main(); + ``` + +1. You should obtain an output similar to: + + ```shell + Added file: test.txt CID(QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk) + ``` + +1. The file has been added to the IPFS network and has given the file a CID. You can share this CID with anyone, and they can use it on their IPFS node to obtain the content you uploaded. +1. If you take the CID and load it on the HTTP gateway, you will see the content `https://ipfs.io/ipfs/QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk`: + +![](../../images/jsipfs-add-gateway.png) + +::: + +:::: + +## Retrieve a file + +::::tabs + +::: tab ipfs-cli id="retrieve-ipfs-cli" + +1. Navigate to the directory where you wish to save the folder. IPFS will save the folder to whichever directory you are in. Here, we're going to save the file in the ~/Desktop directory: + + ```bash + cd ~/Desktop + ``` + +1. We must specify the CID to the jsipfs daemon to retrieve our desired content. The daemon uses a `GET` method to request data from IPFS; `jsipfs get`. We will use the CID from the previous section where we added the `test.txt` file: + + ```bash + jsipfs get QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +1 You should see an output similar to: + + ```bash + Saving file(s) to QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +1. You will notice a new file in your project directory that is labeled as the CID of the retrieved content. + +::: + +::: tab ipfs-core id="retrieve-ipfs-core" + +1. Continuing with the same Node.js application, retrieving a file from IPFS can be done by using a `cat` call. We will use the CID from the previous section when we added the `test.txt` file by passing `fileAdded.cid` as an argument to `node.cat`. However, you can use the same setup to retrieve any file by defining the CID. + + ```js{13-16,18} + import * as IPFS from 'ipfs-core'; + + async function main() { + const node = await IPFS.create(); + + const fileAdded = await node.add({ + path: "hello.txt", + content: "Hello World 101", + }); + + console.log("Added file:", fileAdded.path, fileAdded.cid); + + const chunks = []; + for await (const chunk of node.cat(fileAdded.cid)) { + chunks.push(chunk); + } + + console.log("Retrieved file contents:", chunks.toString()); + } + + main(); + ``` + +1. You should retrieve the file contents: + + ```shell + Retrieved file contents: Hello IPFS! + ``` + +:::: + +### Pin a file + +Pinning a file will save the file data save to the local IPFS node and ensure data is not lost. + +1. Using the `pin add` method on the daemon, you can pin a file by running: + + ```bash + jsipfs pin add QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +1. The result should be something like: + + ```shell + pinned QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +By default, objects that you retrieve over IPFS are not pinned to your node. If you wish to prevent the files from being garbage collected, you need to pin them. You will notice that the pin you just added is a recursive pin, meaning it is a directory containing other objects. Check out the [pinning content](../concepts/persistence/##pinning-in-context) to learn more about pinning. + +## Remove a file + +::: warning Removing a file from IPFS does not guarantee that it was completely removed from the network. + +There is no way to know if someone else has made a copy of the content from when it became available on the network. This caveat is also found in regular HTTP networks, as nothing stops users from addressing content and creating a copy once it is pushed to IPFS. + +::: + +Removing the content pin will remove a file from IPFS. In this section, we will remove the pinned `test.txt` file we pinned earlier. + +:::: tabs + +::: tab ipfs-cli id="remove-ipfs-cli" + +1. If you would like to remove a different piece of content, you can run `jsipfs pin ls` to view a list of pinned content on the local IPFS node: + + ```shell + QmRaaUwTNfwgFZpeUy8qrZwrp2dY4kCKmmB5xEqvH3vtD1 recursive + QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive + QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi recursive + QmXgZAUWd8yo4tvjBETqzUy3wLx5YRzuDwUQnBwRGrAmAo recursive + QmYt9ypyGsR1BKdaCGPdwdBgAiuXK5AYN2bGSNZov7YXuk recursive + QmSVcZ3G5SFZMMk9egqHBaMch4aKYpaaCnxBAJCQR25Am4 indirect + QmYCvbfNbCwFR45HiNP45rwJgvatpiW38D961L5qAhUM5Y indirect + QmegvLXxpVKiZ4b57Xs1syfBVRd8CbucVHAp7KpLQdGieC indirect + QmQN88TEidd3RY2u3dpib49fERTDfKtDpvxnvczATNsfKT indirect + QmY5heUM5qgRubMDD1og9fhCPA6QdkMp3QCwd4s7gJsyE7 indirect + QmdncfsVm2h5Kqq9hPmU7oAVX2zTSVP3L869tgTbPYnsha indirect + QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB indirect + QmQ5vhrL7uv6tuoN9KeVBwd4PwfQkXdVVmDLUZuTNxqgvm indirect + QmV4KrV1DBzTaA5xJWTYNx852YjRsrcTGGsaSR5a7gBzbr indirect + QmYE7xo6NxbHEVEHej1yzxijYaNY51BaeKxjXxn6Ssa6Bs indirect + ``` + +1. Using the daemon's `pin rm` method, unpin the file: + + ```bash + jsipfs pin rm QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +1. This will output something like: + + ```shell + unpinned QmWcYcWY5vdDzBcAoLo3rYXQ2tLkjzu57vEePCvyhuwZRi + ``` + +1. `test.txt` file is now unpinned, but it has not been removed from our node completely. To remove it completely, run the [garbage collection](../../concepts/persistence##garbage-collection). The command will remove everything from your node that does not have a pin: + + ```shell + jsipfs repo gc + ``` + +1. This will output something like: + + ```shell + removed bafybeif2ewg3nqa33mjokpxii36jj2ywfqjpy3urdh7v6vqyfjoocvgy3a + removed bafkreieceevgg2auxo4u3rjgeiqfr4ccxh6ylkgxt2ss6k2leuad5xckxe + removed bafkreiblcvcr7letdbp2k2thkbjyunznrwq3y6pyoylzaq4epawqcca2my + [...] + ``` + +2. The target file has now been removed from your IPFS node and other files that were not pinned. If the content that was just garbage collected was saved to your computer's local storage, it is still there. If you wish to remove the content from your computer's local storage, you will need to find where it is saved and delete it using the normal deletion method. + +::: tip + +Run `jsipfs pin ls` again to confirm that the CID you intended to remove is no longer pinned. + +::: + +:::: diff --git a/docs/how-to/host-git-style-repo.md b/docs/how-to/host-git-repo.md similarity index 87% rename from docs/how-to/host-git-style-repo.md rename to docs/how-to/host-git-repo.md index b7c7392ef..ea8bc69a2 100644 --- a/docs/how-to/host-git-style-repo.md +++ b/docs/how-to/host-git-repo.md @@ -1,9 +1,10 @@ --- title: Host a Git-style repo -description: Learn how to serve a static Git repository worldwide using IPFS, the InterPlanetary File System. +legacyUrl: https://docs.ipfs.io/guides/examples/git/ +description: Learn how to serve a static Git repository worldwide using IPFS. --- -# Host a Git-style repo +# Host a Git repo Have you ever said to yourself: "Man, my Git server isn't distributed enough" or "I wish I had an easy way to serve a static Git repository worldwide"? Well, wish no more. @@ -12,7 +13,7 @@ In this guide, we discuss how to serve a Git repository through the IPFS network To start, select a Git repository you want to host, and do a bare clone of it: ```bash -git clone --bare git@myhost.io/myrepo +git clone --mirror git@myhost.io/myrepo ``` For those who aren't super Git-savvy, a bare repository means that it doesn't have a working tree, and can be used as a server. They have a slightly different format than your normal Git repository. @@ -55,7 +56,7 @@ $ git clone http://QmX679gmfyaRkKMvPA4WGNWXj9PtpvKWGPgtXaF18etC95.ipfs.localhost Note: make sure to change out that hash for yours. -Now, you may be asking "Well, what good is a Git repository that I can't change anything on?" Here's one use case. Say you program in Go. For those who don't know, Go uses version control paths for its imports, i.e: +Now, you may be asking, "Well, what good is a Git repository that I can't change anything on?" Here's one use case. Say you program in Go. For those who don't know, Go uses version control paths for its imports, i.e: ```go import ( diff --git a/docs/images/jsipfs-add-gateway.png b/docs/images/jsipfs-add-gateway.png new file mode 100644 index 000000000..3b2b89456 Binary files /dev/null and b/docs/images/jsipfs-add-gateway.png differ diff --git a/docs/images/jsipfs-add-webui.png b/docs/images/jsipfs-add-webui.png new file mode 100644 index 000000000..473ace6c7 Binary files /dev/null and b/docs/images/jsipfs-add-webui.png differ diff --git a/docs/images/jsipfs-webui.png b/docs/images/jsipfs-webui.png new file mode 100644 index 000000000..17ac5add0 Binary files /dev/null and b/docs/images/jsipfs-webui.png differ diff --git a/docs/reference/js/api.md b/docs/reference/js/api.md index b66bea124..3e41ef7e1 100644 --- a/docs/reference/js/api.md +++ b/docs/reference/js/api.md @@ -5,38 +5,130 @@ description: Developer resources for working in JavaScript with IPFS, the InterP # IPFS in JavaScript -::: callout -[Explore js-ipfs through interactive coding challenges at ProtoSchool](https://proto.school/course/ipfs) +## JavaScript libraries + +There are two main JavaScript libraries for working with IPFS, `ipfs` and `ipfs-http-client`. Both work in Node.js and modern web browsers. JS-IPFS in Node.js is long-running and supports transports like TCP and UDP along with WebScoekts and WebRTC, while JS-IPFS in the browser is short-lived and limited to Web APIs available on a web page; it only supports WebSockets and WebRTC as transports. The browser is also resource constrained and does not support all of the interfaces found in the Node.js version. + +### JS-IPFS + +[JS-IPFS](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs) is a full implementation of IPFS, similar to [Kubo (Go-IPFS)](https://github.com/ipfs/kubo). You can use it either as a command-line application or as a library to start an IPFS node directly in your program, as JS implementation is available as two Node.js packages, `ipfs-core` and `ipfs`. + +- [ipfs-core](https://www.npmjs.com/package/ipfs-core) includes the core IPFS API and is intended to be used to run an IPFS node as part of your application without the need to start external processes or manage API ports and servers. + +::: tip IPFS Core API + +See the [JS core API reference →](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) + ::: -## JavaScript libraries +- [ipfs](https://www.npmjs.com/package/ipfs) is built on `ipfs-core` but also includes the CLI, an HTTP RPC API server and, other tools to run ipfs as a background process, so it is a larger install with more dependencies. -There are two main JavaScript libraries for working with IPFS. Both work in Node.js and in modern web browsers: +::: tip ipfs-core vs. ipfs -- [JS-IPFS](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs) is a full implementation of IPFS, similar to [Kubo (Go-IPFS)](https://github.com/ipfs/kubo). You can use it either as a command-line application or as a library to start an IPFS node directly in your program. -- The [JS-IPFS HTTP RPC API client library](https://www.npmjs.com/package/ipfs-http-client) is a smaller library that controls an IPFS node (Kubo or JS-IPFS) that is already running via its [RPC API](../kubo/rpc.md). - - JS-IPFS actually uses this library internally if it detects that another node is already running on your computer. You can also interact with the [RPC API](../kubo/rpc.md) directly using `fetch()` in a browser or a module like `request` in Node.js, but using this library can be much more convenient. - - When JS-IPFS is used as a backend, instead use the [ipfs-client](https://www.npmjs.com/package/ipfs-client) to leverage gRPC over websockets for some commands to achieve the bidirectional streaming necessary to have full duplex streams running in the browser. +If you are writing an application that needs to access the IPFS network, use `ipfs-core`. If you wish to use **js-ipfs** in a terminal window or run it as a server for use by multiple otherwise unrelated processes, use `ipfs`. +::: -All libraries have the same [interface for using all the major IPFS commands](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api). +### HTTP client -Whenever reasonable, we recommend the second method (interacting with a separate IPFS node via the RPC API). Keeping the IPFS node in a separate process (even if it’s one your program spawns) isolates you from any stability problems with the node. If a user already has IPFS installed, this also means you can take advantage of a single, common installation on their computer. It’s also less code to load in a browser. If you need to spawn a separate IPFS process, you might want to take a look at [`js-ipfsd-ctl`](https://github.com/ipfs/js-ipfsd-ctl), which uses the same interface to spawn a Kubo (Go-IPFS) node, a JS-IPFS node, or an in-process JS-IPFS node. +[JS-IPFS HTTP RPC API](https://www.npmjs.com/package/ipfs-http-client) is a client library that controls an active IPFS node (Kubo or JS-IPFS) running through its [RPC API](../kubo/rpc.md). + - JS-IPFS will internally use this library if it detects another node is running on your machine. You can also interact with the [RPC API](../kubo/rpc.md) directly using `fetch()` in a browser or a module like `request` in Node.js, but using this library can be much more convenient. + - When using JS-IPFS as a backend, use the [ipfs-client](https://www.npmjs.com/package/ipfs-client) instead to leverage gRPC connections over WebSockets to allow some commands to achieve the bidirectional streaming necessary to have full duplex streams running in the browser. -### Browsers +All the libraries have the [same interface](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) for using all the major IPFS commands. This client library implements the interface-ipfs-core enabling applications to change between an embedded js-ipfs node and any remote IPFS node without changing the code. In addition, this client library implements a set of utility functions. -Both the `js-ipfs` and `js-ipfs-http-client` libraries work in browsers, but each has some special considerations noted in their READMEs. +::: tip Interacting with IPFS -## JS API reference +We recommend the second method (interacting with a separate IPFS node via RPC API) whenever reasonable. Keeping the IPFS node in a separate process (even if it’s one of your program spawns) isolates you from any stability problems with the node. If a user already has IPFS installed, this also means that you can take advantage of a single, standard installation on their machine. It’s also less code to load in a browser. If you need to spawn a separate IPFS process, you might want to take a look at [`js-ipfsd-ctl`](https://github.com/ipfs/js-ipfsd-ctl), which uses the same interface to spawn a Kubo (Go-IPFS) node, a JS-IPFS node, or an in-process JS-IPFS node. -See the [JS core API reference →](https://github.com/ipfs/js-ipfs/tree/master/docs/core-api) +::: + +::: warning Browsers + +The `ipfs` and `ipfs-http-client` libraries work in browsers, but each has special considerations noted in their READMEs. + +::: + +The implementation is split into several modules. + +::: details Node modules + +* [`/packages/interface-ipfs-core`](./packages/interface-ipfs-core) Tests to ensure adherence of an implementation to the spec +* [`/packages/ipfs`](./packages/ipfs) An aggregator module that bundles the core implementation, the CLI, HTTP API server and daemon +* [`/packages/ipfs-cli`](./packages/ipfs-cli) A CLI to the core implementation +* [`/packages/ipfs-core`](./packages/ipfs-core) The core implementation +* [`/packages/ipfs-core-types`](./packages/ipfs-core-types) Typescript definitions for the core API +* [`/packages/ipfs-core-utils`](./packages/ipfs-core-utils) Helpers and utilities common to core and the HTTP RPC API client +* [`/packages/ipfs-daemon`](./packages/ipfs-daemon) Run js-IPFS as a background daemon +* [`/packages/ipfs-grpc-client`](./packages/ipfs-grpc-client) A gRPC client for js-IPFS +* [`/packages/ipfs-grpc-protocol`](./packages/ipfs-grpc-protocol) Shared module between the gRPC client and server +* [`/packages/ipfs-grpc-server`](./packages/ipfs-grpc-server) A gRPC-over-websockets server for js-IPFS +* [`/packages/ipfs-http-client`](./packages/ipfs-http-client) A client for the RPC-over-HTTP API presented by both js-ipfs and go-ipfs +* [`/packages/ipfs-http-server`](./packages/ipfs-http-server) JS implementation of the [Kubo RPC HTTP API](https://docs.ipfs.io/reference/kubo/rpc/) +* [`/packages/ipfs-http-gateway`](./packages/ipfs-http-gateway) JS implementation of the [IPFS HTTP Gateway](https://docs.ipfs.io/concepts/ipfs-gateway/) +* [`/packages/ipfs-http-response`](./packages/ipfs-http-response) Creates a HTTP response for a given IPFS Path +* [`/packages/ipfs-message-port-client`](./packages/ipfs-message-port-client) A client for the RPC-over-message-port API presented by js-ipfs running in a shared worker +* [`/packages/ipfs-message-port-protocol`](./packages/ipfs-message-port-protocol) Code shared by the message port client & server +* [`/packages/ipfs-message-port-server`](./packages/ipfs-message-port-server) The server that receives requests from ipfs-message-port-client -## RPC client library +::: -A [client library](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client) for the JS-IPFS RPC API, implemented in JavaScript. This client library implements the interface-ipfs-core enabling applications to change between an embedded js-ipfs node and any remote IPFS node without having to change the code. In addition, this client library implements a set of utility functions. +## Packages + +> This table is generated using the module [`package-table`](https://www.npmjs.com/package/package-table) with `package-table --data=package-list.json`. + +Listing of the main JS packages in the IPFS ecosystem: + +| Package | Version | Deps | CI/Travis | Coverage | Lead Maintainer | +| ---------|---------|---------|---------|---------|--------- | +| **Files** | +| [`ipfs-unixfs`](//github.com/ipfs/js-ipfs-unixfs) | [![npm](https://img.shields.io/npm/v/ipfs-unixfs.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs-unixfs/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-unixfs.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-unixfs) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs-unixfs/master)](https://travis-ci.com/ipfs/js-ipfs-unixfs) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-unixfs/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs-unixfs) | [Alex Potsides](mailto:alex.potsides@protocol.ai) | +| **Repo** | +| [`ipfs-repo`](//github.com/ipfs/js-ipfs-repo) | [![npm](https://img.shields.io/npm/v/ipfs-repo.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs-repo/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-repo.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-repo) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs-repo/master)](https://travis-ci.com/ipfs/js-ipfs-repo) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-repo/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs-repo) | [Alex Potsides](mailto:alex@achingbrain.net) | +| [`ipfs-repo-migrations`](//github.com/ipfs/js-ipfs-repo-migrations) | [![npm](https://img.shields.io/npm/v/ipfs-repo-migrations.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs-repo-migrations/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-repo-migrations.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-repo-migrations) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs-repo-migrations/master)](https://travis-ci.com/ipfs/js-ipfs-repo-migrations) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-repo-migrations/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs-repo-migrations) | N/A | +| **Exchange** | +| [`ipfs-bitswap`](//github.com/ipfs/js-ipfs-bitswap) | [![npm](https://img.shields.io/npm/v/ipfs-bitswap.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs-bitswap/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-bitswap.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-bitswap) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs-bitswap/master)](https://travis-ci.com/ipfs/js-ipfs-bitswap) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-bitswap/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs-bitswap) | [Dirk McCormick](mailto:dirk@protocol.ai) | +| **IPNS** | +| [`ipns`](//github.com/ipfs/js-ipns) | [![npm](https://img.shields.io/npm/v/ipns.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipns/releases) | [![Deps](https://david-dm.org/ipfs/js-ipns.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipns) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipns/master)](https://travis-ci.com/ipfs/js-ipns) | [![codecov](https://codecov.io/gh/ipfs/js-ipns/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipns) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| **Generics/Utils** | +| [`ipfs-utils`](//github.com/ipfs/js-ipfs) | [![npm](https://img.shields.io/npm/v/ipfs-utils.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs/master)](https://travis-ci.com/ipfs/js-ipfs) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs) | [Hugo Dias](mailto:hugomrdias@gmail.com) | +| [`ipfs-http-client`](//github.com/ipfs/js-ipfs) | [![npm](https://img.shields.io/npm/v/ipfs-http-client.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs/master)](https://travis-ci.com/ipfs/js-ipfs) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs) | [Alex Potsides](mailto:alex@achingbrain.net) | +| [`ipfs-http-response`](//github.com/ipfs/js-ipfs-http-response) | [![npm](https://img.shields.io/npm/v/ipfs-http-response.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfs-http-response/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfs-http-response.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-http-response) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfs-http-response/master)](https://travis-ci.com/ipfs/js-ipfs-http-response) | [![codecov](https://codecov.io/gh/ipfs/js-ipfs-http-response/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs-http-response) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`ipfsd-ctl`](//github.com/ipfs/js-ipfsd-ctl) | [![npm](https://img.shields.io/npm/v/ipfsd-ctl.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/js-ipfsd-ctl/releases) | [![Deps](https://david-dm.org/ipfs/js-ipfsd-ctl.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfsd-ctl) | [![Travis CI](https://flat.badgen.net/travis/ipfs/js-ipfsd-ctl/master)](https://travis-ci.com/ipfs/js-ipfsd-ctl) | [![codecov](https://codecov.io/gh/ipfs/js-ipfsd-ctl/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfsd-ctl) | [Hugo Dias](mailto:mail@hugodias.me) | +| [`is-ipfs`](//github.com/ipfs/is-ipfs) | [![npm](https://img.shields.io/npm/v/is-ipfs.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/is-ipfs/releases) | [![Deps](https://david-dm.org/ipfs/is-ipfs.svg?style=flat-square)](https://david-dm.org/ipfs/is-ipfs) | [![Travis CI](https://flat.badgen.net/travis/ipfs/is-ipfs/master)](https://travis-ci.com/ipfs/is-ipfs) | [![codecov](https://codecov.io/gh/ipfs/is-ipfs/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/is-ipfs) | [Marcin Rataj](mailto:lidel@lidel.org) | +| [`aegir`](//github.com/ipfs/aegir) | [![npm](https://img.shields.io/npm/v/aegir.svg?maxAge=86400&style=flat-square)](//github.com/ipfs/aegir/releases) | [![Deps](https://david-dm.org/ipfs/aegir.svg?style=flat-square)](https://david-dm.org/ipfs/aegir) | [![Travis CI](https://flat.badgen.net/travis/ipfs/aegir/master)](https://travis-ci.com/ipfs/aegir) | [![codecov](https://codecov.io/gh/ipfs/aegir/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipfs/aegir) | [Hugo Dias](mailto:hugomrdias@gmail.com) | +| **libp2p** | +| [`libp2p`](//github.com/libp2p/js-libp2p) | [![npm](https://img.shields.io/npm/v/libp2p.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p/master)](https://travis-ci.com/libp2p/js-libp2p) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`peer-id`](//github.com/libp2p/js-peer-id) | [![npm](https://img.shields.io/npm/v/peer-id.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-peer-id/releases) | [![Deps](https://david-dm.org/libp2p/js-peer-id.svg?style=flat-square)](https://david-dm.org/libp2p/js-peer-id) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-peer-id/master)](https://travis-ci.com/libp2p/js-peer-id) | [![codecov](https://codecov.io/gh/libp2p/js-peer-id/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-peer-id) | [Vasco Santos](mailto:santos.vasco10@gmail.com) | +| [`libp2p-crypto`](//github.com/libp2p/js-libp2p-crypto) | [![npm](https://img.shields.io/npm/v/libp2p-crypto.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-crypto/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-crypto.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-crypto) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-crypto/master)](https://travis-ci.com/libp2p/js-libp2p-crypto) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-crypto/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-crypto) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`libp2p-floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/libp2p-floodsub.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-floodsub.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-floodsub) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-floodsub/master)](https://travis-ci.com/libp2p/js-libp2p-floodsub) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`libp2p-gossipsub`](//github.com/ChainSafe/gossipsub-js) | [![npm](https://img.shields.io/npm/v/libp2p-gossipsub.svg?maxAge=86400&style=flat-square)](//github.com/ChainSafe/gossipsub-js/releases) | [![Deps](https://david-dm.org/ChainSafe/gossipsub-js.svg?style=flat-square)](https://david-dm.org/ChainSafe/gossipsub-js) | [![Travis CI](https://flat.badgen.net/travis/ChainSafe/gossipsub-js/master)](https://travis-ci.com/ChainSafe/gossipsub-js) | [![codecov](https://codecov.io/gh/ChainSafe/gossipsub-js/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/gossipsub-js) | [Cayman Nava](mailto:caymannava@gmail.com) | +| [`libp2p-kad-dht`](//github.com/libp2p/js-libp2p-kad-dht) | [![npm](https://img.shields.io/npm/v/libp2p-kad-dht.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-kad-dht/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-kad-dht.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-kad-dht) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-kad-dht/master)](https://travis-ci.com/libp2p/js-libp2p-kad-dht) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-kad-dht/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-kad-dht) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`libp2p-mdns`](//github.com/libp2p/js-libp2p-mdns) | [![npm](https://img.shields.io/npm/v/libp2p-mdns.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-mdns/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-mdns.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-mdns) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-mdns/master)](https://travis-ci.com/libp2p/js-libp2p-mdns) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-mdns/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-mdns) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`libp2p-bootstrap`](//github.com/libp2p/js-libp2p-bootstrap) | [![npm](https://img.shields.io/npm/v/libp2p-bootstrap.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-bootstrap/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-bootstrap.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-bootstrap) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-bootstrap/master)](https://travis-ci.com/libp2p/js-libp2p-bootstrap) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-bootstrap/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-bootstrap) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`@chainsafe/libp2p-noise`](//github.com/ChainSafe/js-libp2p-noise) | [![npm](https://img.shields.io/npm/v/libp2p-noise.svg?maxAge=86400&style=flat-square)](//github.com/ChainSafe/js-libp2p-noise/releases) | [![Deps](https://david-dm.org/ChainSafe/js-libp2p-noise.svg?style=flat-square)](https://david-dm.org/ChainSafe/js-libp2p-noise) | [![Travis CI](https://flat.badgen.net/travis/ChainSafe/js-libp2p-noise/master)](https://travis-ci.com/ChainSafe/js-libp2p-noise) | [![codecov](https://codecov.io/gh/ChainSafe/js-libp2p-noise/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/js-libp2p-noise) | N/A | +| [`libp2p-tcp`](//github.com/libp2p/js-libp2p-tcp) | [![npm](https://img.shields.io/npm/v/libp2p-tcp.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-tcp/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-tcp.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-tcp) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-tcp/master)](https://travis-ci.com/libp2p/js-libp2p-tcp) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-tcp/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-tcp) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`libp2p-webrtc-star`](//github.com/libp2p/js-libp2p-webrtc-star) | [![npm](https://img.shields.io/npm/v/libp2p-webrtc-star.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-webrtc-star/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-webrtc-star.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-webrtc-star) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-webrtc-star/master)](https://travis-ci.com/libp2p/js-libp2p-webrtc-star) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-webrtc-star/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-webrtc-star) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [![npm](https://img.shields.io/npm/v/libp2p-websockets.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-websockets/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-websockets/master)](https://travis-ci.com/libp2p/js-libp2p-websockets) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-websockets/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-websockets) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`libp2p-mplex`](//github.com/libp2p/js-libp2p-mplex) | [![npm](https://img.shields.io/npm/v/libp2p-mplex.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-mplex/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-mplex.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-mplex) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-mplex/master)](https://travis-ci.com/libp2p/js-libp2p-mplex) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-mplex/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-mplex) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`libp2p-delegated-content-routing`](//github.com/libp2p/js-libp2p-delegated-content-routing) | [![npm](https://img.shields.io/npm/v/libp2p-delegated-content-routing.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-delegated-content-routing/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-delegated-content-routing.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-delegated-content-routing) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-delegated-content-routing/master)](https://travis-ci.com/libp2p/js-libp2p-delegated-content-routing) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-delegated-content-routing/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-delegated-content-routing) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| [`libp2p-delegated-peer-routing`](//github.com/libp2p/js-libp2p-delegated-peer-routing) | [![npm](https://img.shields.io/npm/v/libp2p-delegated-peer-routing.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-delegated-peer-routing/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-delegated-peer-routing.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-delegated-peer-routing) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-delegated-peer-routing/master)](https://travis-ci.com/libp2p/js-libp2p-delegated-peer-routing) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-delegated-peer-routing/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-delegated-peer-routing) | [Jacob Heun](mailto:jacobheun@gmail.com) | +| **IPLD** | +| [`@ipld/dag-pb`](//github.com/ipld/js-dag-pb) | [![npm](https://img.shields.io/npm/v/@ipld/dag-pb.svg?maxAge=86400&style=flat-square)](//github.com/ipld/js-dag-pb/releases) | [![Deps](https://david-dm.org/ipld/js-dag-pb.svg?style=flat-square)](https://david-dm.org/ipld/js-dag-pb) | [![Travis CI](https://flat.badgen.net/travis/ipld/js-dag-pb/master)](https://travis-ci.com/ipld/js-dag-pb) | [![codecov](https://codecov.io/gh/ipld/js-dag-pb/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipld/js-dag-pb) | N/A | +| [`@ipld/dag-cbor`](//github.com/ipld/js-dag-cbor) | [![npm](https://img.shields.io/npm/v/@ipld/dag-cbor.svg?maxAge=86400&style=flat-square)](//github.com/ipld/js-dag-cbor/releases) | [![Deps](https://david-dm.org/ipld/js-dag-cbor.svg?style=flat-square)](https://david-dm.org/ipld/js-dag-cbor) | [![Travis CI](https://flat.badgen.net/travis/ipld/js-dag-cbor/master)](https://travis-ci.com/ipld/js-dag-cbor) | [![codecov](https://codecov.io/gh/ipld/js-dag-cbor/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ipld/js-dag-cbor) | N/A | +| **Multiformats** | +| [`multiformats`](//github.com/multiformats/js-multiformats) | [![npm](https://img.shields.io/npm/v/multiformats.svg?maxAge=86400&style=flat-square)](//github.com/multiformats/js-multiformats/releases) | [![Deps](https://david-dm.org/multiformats/js-multiformats.svg?style=flat-square)](https://david-dm.org/multiformats/js-multiformats) | [![Travis CI](https://flat.badgen.net/travis/multiformats/js-multiformats/master)](https://travis-ci.com/multiformats/js-multiformats) | [![codecov](https://codecov.io/gh/multiformats/js-multiformats/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-multiformats) | N/A | +| [`mafmt`](//github.com/multiformats/js-mafmt) | [![npm](https://img.shields.io/npm/v/mafmt.svg?maxAge=86400&style=flat-square)](//github.com/multiformats/js-mafmt/releases) | [![Deps](https://david-dm.org/multiformats/js-mafmt.svg?style=flat-square)](https://david-dm.org/multiformats/js-mafmt) | [![Travis CI](https://flat.badgen.net/travis/multiformats/js-mafmt/master)](https://travis-ci.com/multiformats/js-mafmt) | [![codecov](https://codecov.io/gh/multiformats/js-mafmt/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-mafmt) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | +| [`multiaddr`](//github.com/multiformats/js-multiaddr) | [![npm](https://img.shields.io/npm/v/multiaddr.svg?maxAge=86400&style=flat-square)](//github.com/multiformats/js-multiaddr/releases) | [![Deps](https://david-dm.org/multiformats/js-multiaddr.svg?style=flat-square)](https://david-dm.org/multiformats/js-multiaddr) | [![Travis CI](https://flat.badgen.net/travis/multiformats/js-multiaddr/master)](https://travis-ci.com/multiformats/js-multiaddr) | [![codecov](https://codecov.io/gh/multiformats/js-multiaddr/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-multiaddr) | [Jacob Heun](mailto:jacobheun@gmail.com) | ## Hands-on examples +::: callout + +**Explore js-ipfs through interactive coding challenges at [ProtoSchool](https://proto.school/course/ipfs).** + +::: + There are lots of JS-IPFS use-case examples in the [`ipfs/js-ipfs` GitHub repository](https://github.com/ipfs-examples/js-ipfs-examples). They're all self-contained projects that let your spin up and test environments quickly. [Check them out →](https://github.com/ipfs-examples/js-ipfs-examples/tree/master/examples) A good starting place is the [IPFS 101, spawn a node and add a file to the IPFS network](https://github.com/ipfs-examples/js-ipfs-examples/tree/master/examples/ipfs-101). diff --git a/package-lock.json b/package-lock.json index 95851455e..ee51d380a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,10 @@ "name": "ipfs-docs", "version": "2.0.0", "license": "MIT", + "dependencies": { + "vue-tabs-component": "^1.5.0", + "vuepress-plugin-tabs": "^0.3.0" + }, "devDependencies": { "@centerforopenscience/markdown-it-video": "^1.0.0", "@vuepress/plugin-active-header-links": "^1.9.7", @@ -498,7 +502,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -2311,7 +2314,6 @@ "version": "2.7.7", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.7.tgz", "integrity": "sha512-Ah8dIuo6ZVPHTq9+s4rBU/YpJu3vGSNyeOTCrPrVPQnkUfnT5Ig+IKBhePuQWFXguYb2TuEWrEfiiX9DZ3aJlA==", - "dev": true, "dependencies": { "@babel/parser": "^7.18.4", "postcss": "^8.4.14", @@ -2321,14 +2323,12 @@ "node_modules/@vue/compiler-sfc/node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/@vue/compiler-sfc/node_modules/postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6020,8 +6020,7 @@ "node_modules/csstype": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" }, "node_modules/cuint": { "version": "0.2.2", @@ -11247,7 +11246,6 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -14772,7 +14770,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -14781,7 +14778,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -16770,7 +16766,6 @@ "version": "2.7.7", "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.7.tgz", "integrity": "sha512-osfkncsGCWqtch+YWYxbqTNQ9hl/UQ6TFRkdmK/VqAjuMpxzr5QotFsYpmJ1AB1ez2LJeIKXDmtMkXUotMOTsA==", - "dev": true, "dependencies": { "@vue/compiler-sfc": "2.7.7", "csstype": "^3.1.0" @@ -16933,6 +16928,14 @@ "loader-utils": "^1.0.2" } }, + "node_modules/vue-tabs-component": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz", + "integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg==", + "peerDependencies": { + "vue": "^2.3.0" + } + }, "node_modules/vue-template-compiler": { "version": "2.7.7", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.7.tgz", @@ -17119,6 +17122,11 @@ "smoothscroll-polyfill": "^0.4.3" } }, + "node_modules/vuepress-plugin-tabs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-tabs/-/vuepress-plugin-tabs-0.3.0.tgz", + "integrity": "sha512-jooDlcMdBqhXgIaF1awFSaOTM56mleP6bbCiGxyQxTZexfvCfDvZhNLGpyXqMQA50ZmNGmvLrK82YYb63k1jfA==" + }, "node_modules/watchpack": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", @@ -19544,8 +19552,7 @@ "@babel/parser": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", - "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", - "dev": true + "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -20879,7 +20886,6 @@ "version": "2.7.7", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.7.tgz", "integrity": "sha512-Ah8dIuo6ZVPHTq9+s4rBU/YpJu3vGSNyeOTCrPrVPQnkUfnT5Ig+IKBhePuQWFXguYb2TuEWrEfiiX9DZ3aJlA==", - "dev": true, "requires": { "@babel/parser": "^7.18.4", "postcss": "^8.4.14", @@ -20889,14 +20895,12 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "dev": true, "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -23932,8 +23936,7 @@ "csstype": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" }, "cuint": { "version": "0.2.2", @@ -27978,8 +27981,7 @@ "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" }, "nanomatch": { "version": "1.2.13", @@ -30868,14 +30870,12 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-resolve": { "version": "0.5.3", @@ -32468,7 +32468,6 @@ "version": "2.7.7", "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.7.tgz", "integrity": "sha512-osfkncsGCWqtch+YWYxbqTNQ9hl/UQ6TFRkdmK/VqAjuMpxzr5QotFsYpmJ1AB1ez2LJeIKXDmtMkXUotMOTsA==", - "dev": true, "requires": { "@vue/compiler-sfc": "2.7.7", "csstype": "^3.1.0" @@ -32597,6 +32596,12 @@ "loader-utils": "^1.0.2" } }, + "vue-tabs-component": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz", + "integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg==", + "requires": {} + }, "vue-template-compiler": { "version": "2.7.7", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.7.tgz", @@ -32755,6 +32760,11 @@ "smoothscroll-polyfill": "^0.4.3" } }, + "vuepress-plugin-tabs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-tabs/-/vuepress-plugin-tabs-0.3.0.tgz", + "integrity": "sha512-jooDlcMdBqhXgIaF1awFSaOTM56mleP6bbCiGxyQxTZexfvCfDvZhNLGpyXqMQA50ZmNGmvLrK82YYb63k1jfA==" + }, "watchpack": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", diff --git a/package.json b/package.json index e7e4a520d..8c7932824 100644 --- a/package.json +++ b/package.json @@ -62,5 +62,9 @@ "format:styles": "stylus-supremacy format ./docs/.vuepress/**/*.styl --replace", "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" + }, + "dependencies": { + "vue-tabs-component": "^1.5.0", + "vuepress-plugin-tabs": "^0.3.0" } }