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

Latest commit

 

History

History
167 lines (109 loc) · 6.28 KB

v0.62-v0.63.md

File metadata and controls

167 lines (109 loc) · 6.28 KB

Migrating to ipfs@0.63 and ipfs-core@0.15

A migration guide for refactoring your application code from ipfs@0.62.x to ipfs@0.63.x

Table of Contents

ESM

The biggest change to ipfs@0.63.x is that the module is now ESM-only.

ESM is the module system for JavaScript. It allows us to structure our code in separate files without polluting a global namespace.

Other systems have tried to fill this gap, notably CommonJS, AMD, RequireJS and others, but ESM is the official standard format to package JavaScript code for reuse.

If you see errors similar to Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in node_modules/ipfs/package.json you are likely trying to load ESM code from a CJS environment via require. This is not possible, instead it must be loaded using import.

If your application is not yet ESM or you are not ready to port it to ESM, you can use the dynamic import function to load ipfs at runtime from a CJS module:

async function loadIpfs () {
  const { create } = await import('ipfs-core')

  const node = await create({
    // ... config here
  })

  return node
}

TypeScript and ESM

When authoring typescript it can often look like you are writing ESM:

import { create } from 'ipfs-core'

create()

When this is transpiled to JavaScript the default settings will emit CJS which will fail at runtime:

"use strict";
exports.__esModule = true;
var ipfs_core_1 = require("ipfs-core");
(0, ipfs_core_1.create)();

You may also see errors about private identifiers:

node_modules/@libp2p/interfaces/dist/src/events.d.ts:19:5 - error TS18028: Private identifiers are only available when targeting ECMAScript 2015 and higher.

19     #private;
       ~~~~~~~~

To build correctly with ESM as a target, update your tsconfig.json to include the following:

{
  "module": "es2020", // ensures output is ESM
  "target": "es2020", // support modern features like private identifiers
  // other settings
}

They must both be set to es2020 at least, more recent versions will also work.

If in doubt, examine the JavaScript files tsc emits and ensure that any ipfs modules are being loaded with import and not require.

libp2p@0.37.x

ipfs@0.63.x upgrades to libp2p@0.37.x. This is a significant refactor that ports the entire stack to TypeScript and publishes all modules as ESM-only code.

Please see the libp2p 0.37.x upgrade guide for how this may affect your application.

PeerIds

The core libp2p module and all supporting modules have now been ported to TypeScript in a complete ground-up rewrite. We took this opportunity to solve a few long-standing problems with some of the data types, particularly in how they relate to use in the browser.

One problem we have solved is that the PeerId objects used internally expose some cryptographic operations that require heavyweight libraries to be included in browser bundles due to there being no native web-crypto implementation of the algorithms used in those operations.

With libp2p@0.37.x those operations have been encapsulated in the @libp2p/crypto module which means PeerId objects become a lot more lightweight and can now be exposed/accepted as core-api types so we can use them to differentiate between different data types instead of having to treat everything as strings.

The affected methods are:

// `peerId` must now be a `PeerId`, previously it was a `string`
ipfs.bitswap.wantlistForPeer(peerId, options)

// Bitswp peers are now returned as `PeerId[]` instead of `string[]`
ipfs.bitswap.stat(options)

// `peerId` must now be a `PeerId`
ipfs.dht.findPeer(peerId, options)

// `peerIdOrCid` must now be a `PeerId` or a `CID`, previously it was a `string` or a `CID`
ipfs.dht.query(peerIdOrCid, options)

// the following DHT events have their `from` field as `PeerId`, previously it was a `string`
PeerResponseEvent
ValueEvent
DialingPeerEvent

// the following DHT events have had their `from` property removed because it is not exposed by go-ipfs so causes incompatibilities
QueryErrorEvent
FinalPeerEvent

// the folloing DHT events have had their `to` property removed because it is not exposed by go-ipfs so causes incompatibilities
SendingQueryEvent

// the `providers` and `closer` properties (where applicable) of the following events have the `peerId` property specified as a `PeerId`, previously it was a `string`
PeerResponseEvent
PeerResponseEvent

// `value` can now be a string or a `PeerId`.  If a string is passed it will be interpreted as a DNS address.
ipfs.name.resolve(value, options)

// The return type of this method is now `Promise<PeerId[]>`, previously it was a `Promise<string[]>`
ipfs.pubsub.peers(topic, options)

// `peerId` must now be a `PeerId`, previously it was a `string`
ipfs.ping(peerId, options)

// the `peer` property of `options` must now be a `PeerId` when specified, previously it was a `string`
ipfs.stats.bw(options)

// `multiaddrOrPeerId` must be a `Multiaddr` or `PeerId`, previously it was a `Multiaddr` or `string`
ipfs.swarm.connect(multiaddrOrPeerId, options)

// `multiaddrOrPeerId` must be a `Multiaddr` or `PeerId`, previously it was a `Multiaddr` or `string`
ipfs.swarm.disconnect(multiaddrOrPeerId, options)

PeerIds can be created from strings using the @libp2p/peer-id module:

import { peerIdFromString } from '@libp2p/peer-id'

const peerId = peerIdFromString('Qmfoo')

They can also be created using the @libp2p/peer-id-factory module:

import { createEd25519PeerId } from '@libp2p/peer-id-factory'

const peerId = await createEd25519PeerId()

multiaddrs

The multiaddr module has been ported to TypeScript and is now published as ESM-only.

It has been renamed to @multiformats/multiaddr so please update your dependencies and replace usage in your code.

The API otherwise is compatible.