libp2p Error: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No “exports” main defined in …

Use dynamic import instead.

utils.ts

// To deal with ESM modules, we need to use dynamic imports
// Error: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in ...
const dynamicImport = async (packageName: string) => new Function(`return import('${packageName}')`)();

export async function initDynamicImports(libs: string[]) {
  return await Promise.all(libs.map((lib) => dynamicImport(lib)));
}

Examples

Import libp2p

import defaultsDeep from '@nodeutils/defaults-deep';
import { initDynamicImports } from '../libs/utils';
// import { createLibp2p as create } from 'libp2p';
// import { tcp } from '@libp2p/tcp';
// import { webSockets } from '@libp2p/websockets';
// import { noise } from '@chainsafe/libp2p-noise';
// import { tls } from '@libp2p/tls';
// import { yamux } from '@chainsafe/libp2p-yamux';
// import { gossipsub } from '@chainsafe/libp2p-gossipsub';
// import { bootstrap } from '@libp2p/bootstrap';
// import { mdns } from '@libp2p/mdns';
// import { SignaturePolicy } from '@libp2p/interface';
// import { identify } from '@libp2p/identify';

// https://docs.libp2p.io/guides/getting-started/javascript/
// https://github.com/libp2p/js-libp2p/blob/main/doc/CONFIGURATION.md
// https://github.com/libp2p/js-libp2p-examples/tree/main
export async function createLibp2p(_options) {
  const [
    libp2p,
    { tcp },
    { webSockets },
    { noise },
    { tls },
    { yamux },
    { gossipsub },
    { bootstrap },
    { mdns },
    { SignaturePolicy },
    { identify },
  ] = await initDynamicImports([
    'libp2p',
    '@libp2p/tcp',
    '@libp2p/websockets',
    '@chainsafe/libp2p-noise',
    '@libp2p/tls',
    '@chainsafe/libp2p-yamux',
    '@chainsafe/libp2p-gossipsub',
    '@libp2p/bootstrap',
    '@libp2p/mdns',
    '@libp2p/interface',
    '@libp2p/identify',
  ]);

  const defaults = {
    transports: [tcp(), webSockets()],
    streamMuxers: [yamux()],
    connectionEncrypters: [noise(), tls()],
    peerDiscovery: [mdns()],
  };
  return libp2p.createLibp2p(defaultsDeep(_options, defaults));
}

Stream

import { initDynamicImports } from '../libs/utils';
// import * as lp from 'it-length-prefixed';
// import map from 'it-map';
// import { pipe } from 'it-pipe';
// import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
// import { toString as uint8ArrayToString } from 'uint8arrays/to-string';

let lp, map: any, pipe, uint8ArrayFromString, uint8ArrayToString;
const initLibs = async () => {
  if (!lp) {
    [lp, map, { pipe }, uint8ArrayFromString, uint8ArrayToString] = await initDynamicImports([
      'it-length-prefixed',
      'it-map',
      'it-pipe',
      'uint8arrays/from-string',
      'uint8arrays/to-string',
    ]);
    map = map.default;
    uint8ArrayFromString = uint8ArrayFromString.fromString;
    uint8ArrayToString = uint8ArrayToString.toString;
  }
};

export async function stdinToStream(stream) {
  await initLibs();
  // Read utf-8 from stdin
  process.stdin.setEncoding('utf8');
  pipe(
    // Read from stdin (the source)
    process.stdin,
    // Turn strings into buffers
    (source) => map(source, (string) => uint8ArrayFromString(string)),
    // Encode with length prefix (so receiving side knows how much data is coming)
    (source) => lp.encode(source),
    // Write to the stream (the sink)
    stream.sink,
  );
}

export async function streamToConsole(stream) {
  await initLibs();
  pipe(
    // Read from the stream (the source)
    stream.source,
    // Decode length-prefixed data
    (source) => lp.decode(source),
    // Turn buffers into strings
    (source) => map(source, (buf) => uint8ArrayToString(buf.subarray())),
    // Sink function
    async function (source) {
      // For each chunk of data
      for await (const msg of source) {
        // Output the data as a utf8 string
        console.log('> ' + msg.toString().replace('\n', ''));
      }
    },
  );
}

Leave a Reply

Your email address will not be published.Required fields are marked *