diff --git a/__tests__/lossless.ts b/__tests__/lossless.ts index b3a5286..fe9f861 100644 --- a/__tests__/lossless.ts +++ b/__tests__/lossless.ts @@ -1,5 +1,5 @@ -import {Delta, DeltaFilter} from '../src/delta'; -import {Lossless} from '../src/lossless'; +import {Delta, DeltaFilter} from '../src/delta.js'; +import {Lossless} from '../src/lossless.js'; describe('Lossless', () => { it('creates a lossless view of keanu as neo in the matrix', () => { diff --git a/__tests__/lossy.ts b/__tests__/lossy.ts index c37ccc6..fbe05ab 100644 --- a/__tests__/lossy.ts +++ b/__tests__/lossy.ts @@ -1,6 +1,6 @@ -import {Delta, PointerTarget} from "../src/delta"; -import {Lossless, LosslessViewMany} from "../src/lossless"; -import {Lossy, lastValueFromLosslessViewOne, valueFromCollapsedDelta, ResolvedViewMany} from "../src/lossy"; +import {Delta, PointerTarget} from "../src/delta.js"; +import {Lossless, LosslessViewMany} from "../src/lossless.js"; +import {Lossy, lastValueFromLosslessViewOne, valueFromCollapsedDelta } from "../src/lossy.js"; describe('Lossy', () => { describe('se a provided function to resolve entity views', () => { diff --git a/__tests__/peer-address.ts b/__tests__/peer-address.ts index 907efb3..38b7f99 100644 --- a/__tests__/peer-address.ts +++ b/__tests__/peer-address.ts @@ -1,4 +1,4 @@ -import {PeerAddress} from '../src/types'; +import {PeerAddress} from '../src/types.js'; describe('PeerAddress', () => { it('toString()', () => { diff --git a/__tests__/run/001-single-node.ts b/__tests__/run/001-single-node.ts index eef4ea1..50a9fbe 100644 --- a/__tests__/run/001-single-node.ts +++ b/__tests__/run/001-single-node.ts @@ -1,4 +1,4 @@ -import {App} from "../../util/app"; +import {App} from "../../util/app.js"; describe('Run', () => { let app: App; diff --git a/__tests__/run/002-two-nodes.ts b/__tests__/run/002-two-nodes.ts index cdb7631..9c62161 100644 --- a/__tests__/run/002-two-nodes.ts +++ b/__tests__/run/002-two-nodes.ts @@ -1,5 +1,5 @@ import Debug from 'debug'; -import {App} from '../../util/app'; +import {App} from '../../util/app.js'; const debug = Debug('test:two'); describe('Run', () => { @@ -13,6 +13,8 @@ describe('Run', () => { apps[1] = new App({ httpEnable: true, peerId: 'app1', + // Make the apps use the same pubsub topic so they can talk to each other + pubSubTopic: apps[0].config.pubSubTopic, }); apps[0].config.seedPeers.push(apps[1].myRequestAddr); apps[1].config.seedPeers.push(apps[0].myRequestAddr); diff --git a/examples/app.ts b/examples/app.ts index e6fcbe0..e9186e3 100644 --- a/examples/app.ts +++ b/examples/app.ts @@ -1,7 +1,7 @@ import Debug from 'debug'; -import {Collection} from "../src/collection"; -import {Entity} from "../src/entity"; -import {RhizomeNode} from "../src/node"; +import {Collection} from "../src/collection.js"; +import {Entity} from "../src/entity.js"; +import {RhizomeNode} from "../src/node.js"; const debug = Debug('example-app'); // As an app we want to be able to write and read data. diff --git a/package-lock.json b/package-lock.json index 19fe238..420e01b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,18 @@ "version": "0.1.0", "license": "Unlicense", "dependencies": { + "@chainsafe/libp2p-gossipsub": "^14.1.0", + "@chainsafe/libp2p-noise": "^16.0.0", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@libp2p/identify": "^3.0.14", + "@libp2p/mdns": "^11.0.16", + "@libp2p/ping": "^2.0.14", + "@libp2p/tcp": "^10.0.14", "debug": "^4.4.0", "express": "^4.21.2", "json-logic-js": "^2.0.5", "level": "^9.0.0", + "libp2p": "^2.4.2", "microtime": "^3.1.1", "object-hash": "^3.0.0", "showdown": "^2.1.0", @@ -34,6 +42,7 @@ "eslint-config-airbnb-base-typescript": "^1.1.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", + "tsc-alias": "^1.8.10", "typescript": "^5.7.2", "typescript-eslint": "^8.18.0" } @@ -598,6 +607,98 @@ "dev": true, "license": "MIT" }, + "node_modules/@chainsafe/as-chacha20poly1305": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz", + "integrity": "sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew==", + "license": "Apache-2.0" + }, + "node_modules/@chainsafe/as-sha256": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.4.2.tgz", + "integrity": "sha512-HJ8GZBRjLeWtRsAXf3EbNsNzmTGpzTFjfpSf4yHkLYC+E52DhT6hwz+7qpj6I/EmFzSUm5tYYvT9K8GZokLQCQ==", + "license": "Apache-2.0" + }, + "node_modules/@chainsafe/is-ip": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.0.2.tgz", + "integrity": "sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==", + "license": "MIT" + }, + "node_modules/@chainsafe/libp2p-gossipsub": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-14.1.0.tgz", + "integrity": "sha512-nzFBbHOoRFa/bXUSzmJaXOgHI+EttTldhLJ33yWcM0DxnWhLKychHkCDLoJO3THa1+dnzrDJoxj3N3/V0WoPVw==", + "license": "Apache-2.0", + "dependencies": { + "@libp2p/crypto": "^5.0.0", + "@libp2p/interface": "^2.0.0", + "@libp2p/interface-internal": "^2.0.0", + "@libp2p/peer-id": "^5.0.0", + "@libp2p/pubsub": "^10.0.0", + "@multiformats/multiaddr": "^12.1.14", + "denque": "^2.1.0", + "it-length-prefixed": "^9.0.4", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "multiformats": "^13.0.1", + "protons-runtime": "^5.5.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.0.1" + }, + "engines": { + "npm": ">=8.7.0" + } + }, + "node_modules/@chainsafe/libp2p-noise": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-noise/-/libp2p-noise-16.0.0.tgz", + "integrity": "sha512-8rqr8V1RD2/lVbfL0Bb//N8iPOFof11cUe8v8z8xJT7fUhCAbtCCSM4jbwI4HCnw0MvHLmcpmAfDCFRwcWzoeA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/as-chacha20poly1305": "^0.1.0", + "@chainsafe/as-sha256": "^0.4.1", + "@libp2p/crypto": "^5.0.0", + "@libp2p/interface": "^2.0.0", + "@libp2p/peer-id": "^5.0.0", + "@noble/ciphers": "^0.6.0", + "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", + "it-length-prefixed": "^9.0.1", + "it-length-prefixed-stream": "^1.0.0", + "it-pair": "^2.0.6", + "it-pipe": "^3.0.1", + "it-stream-types": "^2.0.1", + "protons-runtime": "^5.5.0", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^5.0.0", + "wherearewe": "^2.0.1" + } + }, + "node_modules/@chainsafe/libp2p-yamux": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@chainsafe/libp2p-yamux/-/libp2p-yamux-7.0.1.tgz", + "integrity": "sha512-949MI0Ll0AsYq1gUETZmL/MijwX0jilOQ1i4s8wDEXGiMhuPWWiMsPgEnX6n+VzFmTrfNYyGaaJj5/MqxV9y/g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.0.0", + "@libp2p/utils": "^6.0.0", + "get-iterator": "^2.0.1", + "it-foreach": "^2.0.6", + "it-pushable": "^3.2.3", + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/@chainsafe/netmask": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", + "integrity": "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==", + "license": "MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1" + } + }, "node_modules/@cypress/request": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", @@ -1322,6 +1423,367 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@libp2p/crypto": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-5.0.8.tgz", + "integrity": "sha512-3ZxuzqMvyLXhRnjT3sjvzCCW4zkO9UKgv75KfqExP3k1Yk/Zbb+oM2z7OgnDycvLGxnRZgGwizrgnWpZvXlDEA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@noble/curves": "^1.7.0", + "@noble/hashes": "^1.6.1", + "asn1js": "^3.0.5", + "multiformats": "^13.3.1", + "protons-runtime": "^5.5.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/identify": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@libp2p/identify/-/identify-3.0.14.tgz", + "integrity": "sha512-H80tdH8csD3W+wHoaltJEnjTAmZBJ22bYqFOPk5YKCF0k19Ox2MwRTkyCXuVDIdQfrYs94JE3HvLvUoN9X/JBQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/interface-internal": "^2.2.1", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/peer-record": "^8.0.13", + "@libp2p/utils": "^6.3.0", + "@multiformats/multiaddr": "^12.3.3", + "@multiformats/multiaddr-matcher": "^1.6.0", + "it-drain": "^3.0.7", + "it-parallel": "^3.0.8", + "it-protobuf-stream": "^1.1.5", + "protons-runtime": "^5.5.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0", + "wherearewe": "^2.0.1" + } + }, + "node_modules/@libp2p/interface": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-2.3.0.tgz", + "integrity": "sha512-lodc8jxw32fkY2m2bsS6yzzozua6EDr5rJvahJaJVC36jZWFW5sBmOW8jBoKfoZyRwgD6uoOXP39miWQhEaUcg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@multiformats/multiaddr": "^12.3.3", + "it-pushable": "^3.2.3", + "it-stream-types": "^2.0.2", + "multiformats": "^13.3.1", + "progress-events": "^1.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/@libp2p/interface-internal": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@libp2p/interface-internal/-/interface-internal-2.2.1.tgz", + "integrity": "sha512-GGxQnTgQ891bpOcHQAG9Dy/KXo1OoKnCaV2e02yWNhW8TkqlFJnwdny6tX8O6BN8Od56yuEIS89ZoNn2SK4F5g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@libp2p/peer-collections": "^6.0.13", + "@multiformats/multiaddr": "^12.3.3", + "progress-events": "^1.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/@libp2p/logger": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-5.1.5.tgz", + "integrity": "sha512-Qe8B/Mja0myaArPvuI5iKVi3o2Z55Rir+RDkkEU/m9TkKDkHVFmGKnPlWDzHehi18GALjLxOsTE9TJASxjDTCA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@multiformats/multiaddr": "^12.3.3", + "interface-datastore": "^8.3.1", + "multiformats": "^13.3.1", + "weald": "^1.0.4" + } + }, + "node_modules/@libp2p/mdns": { + "version": "11.0.16", + "resolved": "https://registry.npmjs.org/@libp2p/mdns/-/mdns-11.0.16.tgz", + "integrity": "sha512-FJLJywEFCm5r61b7IZ+KGvxUPEGuGx5VGXyTSE10y7lSxizn50ZUAmnN76OsBdLz/Uj3/iyzTOOmY17mzBjN3g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@libp2p/interface-internal": "^2.2.1", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/utils": "^6.3.0", + "@multiformats/multiaddr": "^12.3.3", + "@types/multicast-dns": "^7.2.4", + "dns-packet": "^5.6.1", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/@libp2p/multistream-select": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@libp2p/multistream-select/-/multistream-select-6.0.10.tgz", + "integrity": "sha512-u2sxsPk18cmJl1GLbfKgV+HXcFP2e873411PPwfQgMqTuNYXvJZheJWxV/nz7LjB3XelHxgYPpDVkMvK/kjMyw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "it-length-prefixed": "^9.1.0", + "it-length-prefixed-stream": "^1.2.0", + "it-stream-types": "^2.0.2", + "p-defer": "^4.0.1", + "race-signal": "^1.1.0", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-collections": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/@libp2p/peer-collections/-/peer-collections-6.0.13.tgz", + "integrity": "sha512-BjpXs3kWegnNay2CApntOkL9tPyzTxC2lKUt0Mj9qntmOp1BF/zWY982U1X4ScjCE/M9Nh9x/w4Z/GKCT+K5lQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/utils": "^6.3.0", + "multiformats": "^13.3.1" + } + }, + "node_modules/@libp2p/peer-id": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-5.0.9.tgz", + "integrity": "sha512-TgWOPbU7AcUdSiHomL2wcg9eJqjoMCvCmU5eq/3fyBygTaG4BiQA/tYKuTEfeB5YPMdG1cJLmxgpk/a+ZRkY1g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "multiformats": "^13.3.1", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-record": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-8.0.13.tgz", + "integrity": "sha512-4+jd3UvlF3sUoHpjPToy9AdW3ReF/ipvA9yBdl5axDKWxjJVOfyG8DvLRGJsTvm12gLdvb7vDgmEtpUPwWqjGQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/utils": "^6.3.0", + "@multiformats/multiaddr": "^12.3.3", + "multiformats": "^13.3.1", + "protons-runtime": "^5.5.0", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/peer-store": { + "version": "11.0.13", + "resolved": "https://registry.npmjs.org/@libp2p/peer-store/-/peer-store-11.0.13.tgz", + "integrity": "sha512-KieXSY8ysyC7ROJ7GI7dtQkowRFDuG2jk5HQedSXNUe74JurG0uI/HddFF8yij+HgY/kZiBwWUQbKrTC4Cewbw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/peer-record": "^8.0.13", + "@multiformats/multiaddr": "^12.3.3", + "interface-datastore": "^8.3.1", + "it-all": "^3.0.6", + "mortice": "^3.0.6", + "multiformats": "^13.3.1", + "protons-runtime": "^5.5.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/ping": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@libp2p/ping/-/ping-2.0.14.tgz", + "integrity": "sha512-+idRl+4T2bhP+FNDgwBFWHyHkFoOcjwzQmezLR00mG8hg2iH3BvDmzMd7cagZM21SaeDd4eiN8XyhQqyi1RcZA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/interface-internal": "^2.2.1", + "@multiformats/multiaddr": "^12.3.3", + "it-byte-stream": "^1.1.0", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/pubsub": { + "version": "10.0.14", + "resolved": "https://registry.npmjs.org/@libp2p/pubsub/-/pubsub-10.0.14.tgz", + "integrity": "sha512-fzHHpI6Smrvvlje1ySRfohjlxeifpoowNRcnJy6/ZFoziHvtufuPQdJ65jL/oobd6sTnbbShAlkkx/KVXBr5lw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/interface-internal": "^2.2.1", + "@libp2p/peer-collections": "^6.0.13", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/utils": "^6.3.0", + "it-length-prefixed": "^9.1.0", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "multiformats": "^13.3.1", + "p-queue": "^8.0.1", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@libp2p/tcp": { + "version": "10.0.14", + "resolved": "https://registry.npmjs.org/@libp2p/tcp/-/tcp-10.0.14.tgz", + "integrity": "sha512-HwYCvNnSqjVzoy3DQh6chy4EwWgmnII+ccT/LEpitKbV8QzHTv2HUeSaGtuGc42Z95rFMXqmJeqBkhbXcpeCRA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/interface": "^2.3.0", + "@libp2p/utils": "^6.3.0", + "@multiformats/mafmt": "^12.1.6", + "@multiformats/multiaddr": "^12.3.3", + "@types/sinon": "^17.0.3", + "p-defer": "^4.0.1", + "p-event": "^6.0.1", + "progress-events": "^1.0.1", + "race-event": "^1.3.0", + "stream-to-it": "^1.0.1" + } + }, + "node_modules/@libp2p/utils": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-6.3.0.tgz", + "integrity": "sha512-1zF9xwxtAjg7N54deR3l45d0awLsuO8cacfp9J4vE+4RjrtKSa40IxhunLOp52ctm9H17wixlXUhoP85Ki8F3w==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/logger": "^5.1.5", + "@multiformats/multiaddr": "^12.3.3", + "@sindresorhus/fnv1a": "^3.1.0", + "@types/murmurhash3js-revisited": "^3.0.3", + "any-signal": "^4.1.1", + "delay": "^6.0.0", + "get-iterator": "^2.0.1", + "is-loopback-addr": "^2.0.2", + "it-foreach": "^2.1.1", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "it-stream-types": "^2.0.2", + "murmurhash3js-revisited": "^3.0.0", + "netmask": "^2.0.2", + "p-defer": "^4.0.1", + "race-event": "^1.3.0", + "race-signal": "^1.1.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/@multiformats/dns": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@multiformats/dns/-/dns-1.0.6.tgz", + "integrity": "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@types/dns-packet": "^5.6.5", + "buffer": "^6.0.3", + "dns-packet": "^5.6.1", + "hashlru": "^2.3.0", + "p-queue": "^8.0.1", + "progress-events": "^1.0.0", + "uint8arrays": "^5.0.2" + } + }, + "node_modules/@multiformats/mafmt": { + "version": "12.1.6", + "resolved": "https://registry.npmjs.org/@multiformats/mafmt/-/mafmt-12.1.6.tgz", + "integrity": "sha512-tlJRfL21X+AKn9b5i5VnaTD6bNttpSpcqwKVmDmSHLwxoz97fAHaepqFOk/l1fIu94nImIXneNbhsJx/RQNIww==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@multiformats/multiaddr": "^12.0.0" + } + }, + "node_modules/@multiformats/multiaddr": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.3.4.tgz", + "integrity": "sha512-R4pEEUyWGrRo16TSflz80Yr6XNbPirix1pfPqDLXsDZ4aaIrhZ7cez9jnyRQgci6DuuqSyZAdJKV6SdxpZ7Oiw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@multiformats/dns": "^1.0.3", + "multiformats": "^13.0.0", + "uint8-varint": "^2.0.1", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/@multiformats/multiaddr-matcher": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.6.0.tgz", + "integrity": "sha512-E77lLvQR+50kTAfvjV3g4wr9qCu77Z+6yT0s1hgfh8B4sAXZ8u/YdQJGhjgstgW1kmGy7BXPppROKYijqQsesQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@multiformats/multiaddr": "^12.0.0", + "multiformats": "^13.0.0" + } + }, + "node_modules/@noble/ciphers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.6.0.tgz", + "integrity": "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1372,6 +1834,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/fnv1a": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz", + "integrity": "sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -1475,6 +1949,15 @@ "@types/ms": "*" } }, + "node_modules/@types/dns-packet": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.5.tgz", + "integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1606,11 +2089,26 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/multicast-dns": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.4.tgz", + "integrity": "sha512-ib5K4cIDR4Ro5SR3Sx/LROkMDa0BHz0OPaCBL/OSPDsAXEGZ3/KQeS6poBKYVN7BfjXDL9lWNwzyHVgt/wkyCw==", + "license": "MIT", + "dependencies": { + "@types/dns-packet": "*", + "@types/node": "*" + } + }, + "node_modules/@types/murmurhash3js-revisited": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.3.tgz", + "integrity": "sha512-QvlqvYtGBYIDeO8dFdY4djkRubcrc+yTJtBc7n8VZPlJDUS/00A+PssbvERM8f9bYRmcaSEHPZgZojeQj7kzAA==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "dev": true, "dependencies": { "undici-types": "~6.20.0" } @@ -1636,6 +2134,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "license": "MIT" + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -1666,6 +2170,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/sinon": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", + "license": "MIT", + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2381,6 +2900,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-signal": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-4.1.1.tgz", + "integrity": "sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==", + "license": "Apache-2.0 OR MIT", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2572,6 +3101,26 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/asn1js/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -2778,6 +3327,19 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -3067,6 +3629,44 @@ "node": ">=10" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -3369,6 +3969,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/datastore-core": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/datastore-core/-/datastore-core-10.0.2.tgz", + "integrity": "sha512-B3WXxI54VxJkpXxnYibiF17si3bLXE1XOjrJB7wM5co9fx2KOEkiePDGiCCEtnapFHTnmAnYCPdA7WZTIpdn/A==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@libp2p/logger": "^5.0.1", + "interface-datastore": "^8.0.0", + "interface-store": "^6.0.0", + "it-drain": "^3.0.7", + "it-filter": "^3.1.1", + "it-map": "^3.1.1", + "it-merge": "^3.0.5", + "it-pipe": "^3.0.1", + "it-pushable": "^3.2.3", + "it-sort": "^3.0.6", + "it-take": "^3.0.6" + } + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -3452,6 +4071,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delay": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", + "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3467,6 +4098,15 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "license": "MIT" }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3517,6 +4157,18 @@ "node": ">=8" } }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -4367,6 +5019,12 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -4888,6 +5546,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", + "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==", + "license": "MIT" + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -5133,6 +5797,12 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "license": "ISC" }, + "node_modules/hashlru": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", + "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==", + "license": "MIT" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -5295,6 +5965,22 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/interface-datastore": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.3.1.tgz", + "integrity": "sha512-3r0ETmHIi6HmvM5sc09QQiCD3gUfwtEM/AAChOyAd/UAKT69uk8LXfTSUBufbUIO/dU65Vj8nb9O6QjwW8vDSQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "interface-store": "^6.0.0", + "uint8arrays": "^5.1.0" + } + }, + "node_modules/interface-store": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-6.0.2.tgz", + "integrity": "sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==", + "license": "Apache-2.0 OR MIT" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -5378,6 +6064,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", @@ -5485,6 +6184,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==", + "license": "MIT" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5559,6 +6264,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-loopback-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", + "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==", + "license": "MIT" + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -5587,6 +6298,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5625,6 +6348,15 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -5902,6 +6634,203 @@ "node": ">=8" } }, + "node_modules/it-all": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-all/-/it-all-3.0.6.tgz", + "integrity": "sha512-HXZWbxCgQZJfrv5rXvaVeaayXED8nTKx9tj9fpBhmcUJcedVZshMMMqTj0RG2+scGypb9Ut1zd1ifbf3lA8L+Q==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/it-byte-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/it-byte-stream/-/it-byte-stream-1.1.0.tgz", + "integrity": "sha512-WWponBWdKEa6o2U3NX+wGMY8X1EkWXcQvpC+3CUqKb4ZzK30q3EPqiTjFxLf9tNVgdF/MNAtx/XclpVfgaz9KQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-queueless-pushable": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-drain": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.7.tgz", + "integrity": "sha512-vy6S1JKjjHSIFHgBpLpD1zhkCRl3z1zYWUxE14+kAYf+BL9ssWSFImJfhl361IIcwr0ofw8etzg11VqqB+ntUA==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/it-filter": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/it-filter/-/it-filter-3.1.1.tgz", + "integrity": "sha512-TOXmVuaSkxlLp2hXKoMTra0WMZMKVFxE3vSsbIA+PbADNCBAHhjJ/lM31vBOUTddHMO34Ku++vU8T9PLlBxQtg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-foreach": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/it-foreach/-/it-foreach-2.1.1.tgz", + "integrity": "sha512-ID4Gxnavk/LVQLQESAQ9hR6dR63Ih6X+8VdxEktX8rpz2dCGAbZpey/eljTNbMfV2UKXHiu6UsneoNBZuac97g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-length-prefixed": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-9.1.0.tgz", + "integrity": "sha512-kx2UTJuy7/lsT3QUzf50NjfxU1Z4P4wlvYp6YnR5Nc61P8XKfy+QtiJi1VLojA+Kea7vMbB4002rIij1Ol9hcw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-reader": "^6.0.1", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.1", + "uint8arraylist": "^2.0.0", + "uint8arrays": "^5.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-length-prefixed-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/it-length-prefixed-stream/-/it-length-prefixed-stream-1.2.0.tgz", + "integrity": "sha512-vX7dzSl/2UMYYsAr0FQdPNVR5xYEETaeboZ+eXxNBjgARuvxnWA6OedW8lC5/J3ebMTC98JhA3eH76eTijUOsA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-byte-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-map": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.1.1.tgz", + "integrity": "sha512-9bCSwKD1yN1wCOgJ9UOl+46NQtdatosPWzxxUk2NdTLwRPXLh+L7iwCC9QKsbgM60RQxT/nH8bKMqm3H/o8IHQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-peekable": "^3.0.0" + } + }, + "node_modules/it-merge": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-merge/-/it-merge-3.0.5.tgz", + "integrity": "sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-pushable": "^3.2.3" + } + }, + "node_modules/it-pair": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/it-pair/-/it-pair-2.0.6.tgz", + "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-stream-types": "^2.0.1", + "p-defer": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-parallel": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.8.tgz", + "integrity": "sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "p-defer": "^4.0.1" + } + }, + "node_modules/it-peekable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/it-peekable/-/it-peekable-3.0.5.tgz", + "integrity": "sha512-JWQOGMt6rKiPcY30zUVMR4g6YxkpueTwHVE7CMs/aGqCf4OydM6w+7ZM3PvmO1e0TocjuR4aL8xyZWR46cTqCQ==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/it-pipe": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-3.0.1.tgz", + "integrity": "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-merge": "^3.0.0", + "it-pushable": "^3.1.2", + "it-stream-types": "^2.0.1" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-protobuf-stream": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/it-protobuf-stream/-/it-protobuf-stream-1.1.5.tgz", + "integrity": "sha512-H70idW45As3cEbU4uSoZ9IYHUIV3YM69/2mmXYR7gOlPabWjuyNi3/abK11geiiq3la27Sos/mXr68JljjKtEQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-length-prefixed-stream": "^1.0.0", + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.4.8" + } + }, + "node_modules/it-pushable": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", + "integrity": "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "p-defer": "^4.0.0" + } + }, + "node_modules/it-queueless-pushable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/it-queueless-pushable/-/it-queueless-pushable-1.0.0.tgz", + "integrity": "sha512-HbcAbcuQj7a9EBxiRCZ+77FxWutgs/pY5ZvEyQnylWPGNFojCLAUwhcZjf5OuEQ9+y+vSa7w1GQBe8xJdmIn5A==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "p-defer": "^4.0.1", + "race-signal": "^1.0.2" + } + }, + "node_modules/it-reader": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/it-reader/-/it-reader-6.0.4.tgz", + "integrity": "sha512-XCWifEcNFFjjBHtor4Sfaj8rcpt+FkY0L6WdhD578SCDhV4VUm7fCkF3dv5a+fTcfQqvN9BsxBTvWbYO6iCjTg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-stream-types": "^2.0.1", + "uint8arraylist": "^2.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-sort": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-sort/-/it-sort-3.0.6.tgz", + "integrity": "sha512-aNrlZAXB8vWBd42tCpaXGL6CJVJNDW3OLczmdt6g0k/s9Z6evkTdgU2LjwW5SNNeX41sF+C8MjV+OcVf93PsPw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-all": "^3.0.0" + } + }, + "node_modules/it-stream-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.2.tgz", + "integrity": "sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/it-take": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.6.tgz", + "integrity": "sha512-uqw3MRzf9to1SOLxaureGa73lK8k8ZB/asOApTAkvrzUqCznGtKNgPFH7uYIWlt4UuWq/hU6I+U4Fm5xpjN8Vg==", + "license": "Apache-2.0 OR MIT" + }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -6737,6 +7666,42 @@ "node": ">= 0.8.0" } }, + "node_modules/libp2p": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.4.2.tgz", + "integrity": "sha512-8y+moEpzzkDjRbK7e+0k8zgtCnL4RkttFnjxrnzoVLQdk6ki3xf0SQkH3aD6FHyz8fdHlG48Av6BEOsT+F9TKg==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.2", + "@chainsafe/netmask": "^2.0.0", + "@libp2p/crypto": "^5.0.8", + "@libp2p/interface": "^2.3.0", + "@libp2p/interface-internal": "^2.2.1", + "@libp2p/logger": "^5.1.5", + "@libp2p/multistream-select": "^6.0.10", + "@libp2p/peer-collections": "^6.0.13", + "@libp2p/peer-id": "^5.0.9", + "@libp2p/peer-store": "^11.0.13", + "@libp2p/utils": "^6.3.0", + "@multiformats/dns": "^1.0.6", + "@multiformats/multiaddr": "^12.3.3", + "@multiformats/multiaddr-matcher": "^1.6.0", + "any-signal": "^4.1.1", + "datastore-core": "^10.0.2", + "interface-datastore": "^8.3.1", + "it-byte-stream": "^1.1.0", + "it-merge": "^3.0.5", + "it-parallel": "^3.0.8", + "merge-options": "^3.0.4", + "multiformats": "^13.3.1", + "p-defer": "^4.0.1", + "p-retry": "^6.2.1", + "progress-events": "^1.0.1", + "race-event": "^1.3.0", + "race-signal": "^1.1.0", + "uint8arrays": "^5.1.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -6885,6 +7850,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7052,12 +8029,65 @@ "node": ">=10" } }, + "node_modules/mortice": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.6.tgz", + "integrity": "sha512-xUjsTQreX8rO3pHuGYDZ3PY/sEiONIzqzjLeog5akdY4bz9TlDDuvYlU8fm+6qnm4rnpa6AFxLhsfSBThLijdA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "observable-webworkers": "^2.0.1", + "p-queue": "^8.0.1", + "p-timeout": "^6.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multiformats": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.3.1.tgz", + "integrity": "sha512-QxowxTNwJ3r5RMctoGA5p13w5RbRT2QDkoM+yFlqfLiioBp78nhDjnRLvmSBI9+KAqN4VdgOVWM9c0CHd86m3g==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/murmurhash3js-revisited": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", + "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, "node_modules/napi-macros": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", @@ -7079,6 +8109,15 @@ "node": ">= 0.6" } }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/node-addon-api": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz", @@ -7270,6 +8309,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/observable-webworkers": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/observable-webworkers/-/observable-webworkers-2.0.1.tgz", + "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", + "license": "Apache-2.0 OR MIT", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -7325,6 +8374,33 @@ "node": ">= 0.8.0" } }, + "node_modules/p-defer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", + "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-event": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.1.tgz", + "integrity": "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==", + "license": "MIT", + "dependencies": { + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7357,6 +8433,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.3.tgz", + "integrity": "sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -7562,6 +8683,19 @@ "node": ">=8" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -7617,6 +8751,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/progress-events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.1.tgz", + "integrity": "sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==", + "license": "Apache-2.0 OR MIT" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -7631,6 +8771,17 @@ "node": ">= 6" } }, + "node_modules/protons-runtime": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.5.0.tgz", + "integrity": "sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "uint8-varint": "^2.0.2", + "uint8arraylist": "^2.4.3", + "uint8arrays": "^5.0.1" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -7670,6 +8821,30 @@ ], "license": "MIT" }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvtsutils/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -7684,6 +8859,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7704,6 +8889,18 @@ ], "license": "MIT" }, + "node_modules/race-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/race-event/-/race-event-1.3.0.tgz", + "integrity": "sha512-kaLm7axfOnahIqD3jQ4l1e471FIFcEGebXEnhxyLscuUzV8C94xVHtWEqDDXxll7+yu/6lW0w1Ff4HbtvHvOHg==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/race-signal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.1.0.tgz", + "integrity": "sha512-VqsW1uzCXfKBd2DhA3K3NhQlqQr04+5WQ7+kHpf1HzT01Q+ePSFWZdQHXKZPuLmm2eXTZM1XLO76cq15ZRAaEA==", + "license": "Apache-2.0 OR MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7747,6 +8944,19 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", @@ -7861,6 +9071,15 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -8310,6 +9529,15 @@ "node": ">= 0.8" } }, + "node_modules/stream-to-it": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-to-it/-/stream-to-it-1.0.1.tgz", + "integrity": "sha512-AqHYAYPHcmvMrcLNgncE/q0Aj/ajP6A4qGhxP6EVn7K3YTNs0bJpJyk57wc2Heb7MUL64jurvmnmui8D9kjZgA==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "it-stream-types": "^2.0.1" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -8529,6 +9757,12 @@ "license": "MIT", "peer": true }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, "node_modules/tldts": { "version": "6.1.69", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.69.tgz", @@ -8673,6 +9907,24 @@ "node": ">=10" } }, + "node_modules/tsc-alias": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", + "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -8895,6 +10147,34 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/uint8-varint": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", + "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "uint8arraylist": "^2.0.0", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/uint8arraylist": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", + "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "uint8arrays": "^5.0.1" + } + }, + "node_modules/uint8arrays": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", + "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "multiformats": "^13.0.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -8915,8 +10195,7 @@ "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/universalify": { "version": "2.0.1", @@ -9083,6 +10362,50 @@ "makeerror": "1.0.12" } }, + "node_modules/weald": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/weald/-/weald-1.0.4.tgz", + "integrity": "sha512-+kYTuHonJBwmFhP1Z4YQK/dGi3jAnJGCYhyODFpHK73rbxnp9lnZQj7a2m+WVgn8fXr5bJaxUpF6l8qZpPeNWQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "ms": "^3.0.0-canary.1", + "supports-color": "^9.4.0" + } + }, + "node_modules/weald/node_modules/ms": { + "version": "3.0.0-canary.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.1.tgz", + "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", + "license": "MIT", + "engines": { + "node": ">=12.13" + } + }, + "node_modules/weald/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/wherearewe": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", + "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "is-electron": "^2.2.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 14d6637..57b9ea1 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "name": "rhizome-node", "version": "0.1.0", "description": "Rhizomatic database engine node", + "type": "module", "scripts": { "build": "tsc", "build:watch": "tsc --watch", "lint": "eslint", - "test": "jest", + "test": "node --experimental-vm-modules node_modules/.bin/jest", "coverage": "./scripts/coverage.sh", "example-app": "node dist/examples/app.js" }, @@ -18,15 +19,38 @@ ], "testMatch": [ "**/__tests__/**/*" - ] + ], + "verbose": true, + "transform": { + "^.+\\.ts?$": [ + "ts-jest", + { + "useESM": true + } + ] + }, + "extensionsToTreatAsEsm": [ + ".ts" + ], + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + } }, "author": "Taliesin (Ladd) ", "license": "Unlicense", "dependencies": { + "@chainsafe/libp2p-gossipsub": "^14.1.0", + "@chainsafe/libp2p-noise": "^16.0.0", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@libp2p/identify": "^3.0.14", + "@libp2p/mdns": "^11.0.16", + "@libp2p/ping": "^2.0.14", + "@libp2p/tcp": "^10.0.14", "debug": "^4.4.0", "express": "^4.21.2", "json-logic-js": "^2.0.5", "level": "^9.0.0", + "libp2p": "^2.4.2", "microtime": "^3.1.1", "object-hash": "^3.0.0", "showdown": "^2.1.0", @@ -34,20 +58,21 @@ "zeromq": "^6.1.2" }, "devDependencies": { + "@eslint/js": "^9.17.0", "@types/bluebird": "^3.5.42", "@types/debug": "^4.1.12", - "@types/json-logic-js": "^2.0.8", - "@types/microtime": "^2.1.2", - "@types/object-hash": "^3.0.6", - "@eslint/js": "^9.17.0", "@types/express": "^5.0.0", "@types/jest": "^29.5.14", + "@types/json-logic-js": "^2.0.8", + "@types/microtime": "^2.1.2", "@types/node": "^22.10.2", + "@types/object-hash": "^3.0.6", "@types/showdown": "^2.0.6", "eslint": "^9.17.0", "eslint-config-airbnb-base-typescript": "^1.1.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", + "tsc-alias": "^1.8.10", "typescript": "^5.7.2", "typescript-eslint": "^8.18.0" } diff --git a/src/collection.ts b/src/collection.ts index 6beb83d..c40c174 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -6,11 +6,11 @@ import Debug from 'debug'; import {randomUUID} from "node:crypto"; import EventEmitter from "node:events"; -import {Delta, DeltaFilter} from "./delta"; -import {Entity, EntityProperties} from "./entity"; -import {Lossy, ResolvedViewOne, Resolver} from "./lossy"; -import {RhizomeNode} from "./node"; -import {DomainEntityID} from "./types"; +import {Delta, DeltaFilter} from "./delta.js"; +import {Entity, EntityProperties} from "./entity.js"; +import {Lossy, ResolvedViewOne, Resolver} from "./lossy.js"; +import {RhizomeNode} from "./node.js"; +import {DomainEntityID} from "./types.js"; const debug = Debug('collection'); export class Collection { @@ -214,9 +214,10 @@ export class Collection { resolver?: Resolver, deltaFilter?: DeltaFilter ): T | undefined { - if (!this.rhizomeNode) return undefined; + if (!this.rhizomeNode) throw new Error('collection not connected to rhizome'); + if (!this.lossy) throw new Error('lossy view not initialized'); - const res = this.lossy?.resolve(resolver, [id], deltaFilter) || {}; + const res = this.lossy.resolve(resolver, [id], deltaFilter) || {}; return res[id] as T; } diff --git a/src/config.ts b/src/config.ts index 24cf79b..9e179d2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,5 @@ import {randomUUID} from "crypto"; -import {PeerAddress} from "./types"; +import {PeerAddress} from "./types.js"; // _HOST refers to the address from an external perspective // _ADDR refers to the interface address from the service's perspective @@ -20,3 +20,5 @@ export const HTTP_API_ENABLE = process.env.RHIZOME_HTTP_API_ENABLE === 'true'; export const SEED_PEERS: PeerAddress[] = (process.env.RHIZOME_SEED_PEERS || '').split(',') .filter(x => !!x) .map((peer: string) => PeerAddress.fromString(peer)); + +export const PUB_SUB_TOPIC = process.env.RHIZOME_PUB_SUB_TOPIC || `deltas-${randomUUID()}`; diff --git a/src/delta.ts b/src/delta.ts index 6c8612f..10a33e4 100644 --- a/src/delta.ts +++ b/src/delta.ts @@ -1,6 +1,6 @@ import {randomUUID} from "crypto"; import microtime from 'microtime'; -import {CreatorID, HostID, PeerAddress, Timestamp, TransactionID} from "./types"; +import {CreatorID, HostID, PeerAddress, Timestamp, TransactionID} from "./types.js"; export type DeltaID = string; diff --git a/src/deltas.ts b/src/deltas.ts index d15341d..0b823cc 100644 --- a/src/deltas.ts +++ b/src/deltas.ts @@ -1,8 +1,8 @@ import Debug from 'debug'; import EventEmitter from 'node:events'; import objectHash from 'object-hash'; -import {Delta, DeltaNetworkImage} from './delta'; -import {RhizomeNode} from './node'; +import {Delta, DeltaNetworkImage} from './delta.js'; +import {RhizomeNode} from './node.js'; const debug = Debug('deltas'); enum Decision { @@ -87,7 +87,10 @@ export class DeltaStream { async publishDelta(delta: Delta) { debug(`Publishing delta: ${JSON.stringify(delta)}`); - await this.rhizomeNode.pubSub.publish("deltas", this.serializeDelta(delta)); + await this.rhizomeNode.pubSub.publish( + this.rhizomeNode.config.pubSubTopic, + this.serializeDelta(delta) + ); } serializeDelta(delta: Delta): string { diff --git a/src/entity.ts b/src/entity.ts index 616da1b..7dd7fc1 100644 --- a/src/entity.ts +++ b/src/entity.ts @@ -7,8 +7,8 @@ // - As typescript interfaces? // - As typescript classes? -import {Collection} from "./collection"; -import {PropertyTypes} from "./types"; +import {Collection} from "./collection.js"; +import {PropertyTypes} from "./types.js"; export type EntityProperties = { [key: string]: PropertyTypes; diff --git a/src/filter/index.ts b/src/filter/index.ts index 38ad0d5..c6d347a 100644 --- a/src/filter/index.ts +++ b/src/filter/index.ts @@ -1,5 +1,5 @@ import { add_operation, apply } from 'json-logic-js'; -import { Delta } from '../delta'; +import { Delta } from '../delta.js'; type DeltaContext = Delta & { creatorAddress: string; diff --git a/src/filter/known.ts b/src/filter/known.ts index 819d7a7..3ee0f57 100644 --- a/src/filter/known.ts +++ b/src/filter/known.ts @@ -1,4 +1,4 @@ -import { FilterExpr } from "../types"; +import { FilterExpr } from "../types.js"; // import { map } from 'radash'; // A creator as seen by a host @@ -30,4 +30,4 @@ export function generateFilter(): FilterExpr { return { 'in': ['$creatorAddress', addresses] }; -}; \ No newline at end of file +}; diff --git a/src/http/api.ts b/src/http/api.ts index 0412e81..4861f30 100644 --- a/src/http/api.ts +++ b/src/http/api.ts @@ -30,24 +30,25 @@ export class HttpApi { // Get the list of peers seen by this node (including itself) this.router.get("/peers", (_req: express.Request, res: express.Response) => { - res.json(this.rhizomeNode.peers.peers.map(({reqAddr, publishAddr, isSelf, isSeedPeer}) => { - const deltasAcceptedCount = this.rhizomeNode.deltaStream.deltasAccepted - .filter((delta: Delta) => { - return delta.receivedFrom?.addr == reqAddr.addr && - delta.receivedFrom?.port == reqAddr.port; - }) - .length; - const peerInfo = { - reqAddr: reqAddr.toAddrString(), - publishAddr: publishAddr?.toAddrString(), - isSelf, - isSeedPeer, - deltaCount: { - accepted: deltasAcceptedCount - } - }; - return peerInfo; - })); + res.json(this.rhizomeNode.peers.peers.map( + ({reqAddr, publishAddr, isSelf, isSeedPeer}) => { + const deltasAcceptedCount = this.rhizomeNode.deltaStream.deltasAccepted + .filter((delta: Delta) => { + return delta.receivedFrom?.addr == reqAddr.addr && + delta.receivedFrom?.port == reqAddr.port; + }) + .length; + const peerInfo = { + reqAddr: reqAddr.toAddrString(), + publishAddr: publishAddr?.toAddrString(), + isSelf, + isSeedPeer, + deltaCount: { + accepted: deltasAcceptedCount + } + }; + return peerInfo; + })); }); // Get the number of peers seen by this node (including itself) diff --git a/src/http/html.ts b/src/http/html.ts index 577af62..a16bc6b 100644 --- a/src/http/html.ts +++ b/src/http/html.ts @@ -1,5 +1,5 @@ import express, {Router} from "express"; -import {htmlDocFromMarkdown, MDFiles} from "../util/md-files"; +import {htmlDocFromMarkdown, MDFiles} from "../util/md-files.js"; export class HttpHtml { router = Router(); diff --git a/src/http/index.ts b/src/http/index.ts index 676daaa..c064040 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -1,9 +1,9 @@ import Debug from "debug"; import express from "express"; import {Server} from "http"; -import {RhizomeNode} from "../node"; -import {HttpApi} from "./api"; -import {HttpHtml} from "./html"; +import {RhizomeNode} from "../node.js"; +import {HttpApi} from "./api.js"; +import {HttpHtml} from "./html.js"; const debug = Debug('http-api'); export class HttpServer { diff --git a/src/lossless.ts b/src/lossless.ts index 38d1d49..e32d5e7 100644 --- a/src/lossless.ts +++ b/src/lossless.ts @@ -3,9 +3,9 @@ import Debug from 'debug'; import EventEmitter from 'events'; -import {Delta, DeltaFilter, DeltaNetworkImage} from './delta'; -import {Transactions} from './transactions'; -import {DomainEntityID, PropertyID, PropertyTypes, TransactionID, ViewMany} from "./types"; +import {Delta, DeltaFilter, DeltaNetworkImage} from './delta.js'; +import {Transactions} from './transactions.js'; +import {DomainEntityID, PropertyID, PropertyTypes, TransactionID, ViewMany} from "./types.js"; const debug = Debug('lossless'); export type CollapsedPointer = {[key: PropertyID]: PropertyTypes}; @@ -141,6 +141,7 @@ export class Lossless { if (delta.transactionId) { if (!this.transactions.isComplete(delta.transactionId)) { // TODO: Test this condition + debug(`excluding delta ${delta.id} because transaction ${delta.transactionId} is not completed`); continue; } } diff --git a/src/lossy.ts b/src/lossy.ts index 05db4e1..203bc5d 100644 --- a/src/lossy.ts +++ b/src/lossy.ts @@ -6,9 +6,9 @@ // Fields in the output can be described as transformations import Debug from 'debug'; -import {DeltaFilter} from "./delta"; -import {CollapsedDelta, Lossless, LosslessViewMany, LosslessViewOne} from "./lossless"; -import {DomainEntityID, PropertyID, PropertyTypes, Timestamp, ViewMany} from "./types"; +import {DeltaFilter} from "./delta.js"; +import {CollapsedDelta, Lossless, LosslessViewMany, LosslessViewOne} from "./lossless.js"; +import {DomainEntityID, PropertyID, PropertyTypes, Timestamp, ViewMany} from "./types.js"; const debug = Debug('lossy'); type TimestampedProperty = { @@ -77,14 +77,14 @@ export function lastValueFromLosslessViewOne( function defaultResolver(losslessView: LosslessViewMany): ResolvedViewMany { const resolved: ResolvedViewMany = {}; - // debug('default resolver, lossless view', JSON.stringify(losslessView)); + debug('default resolver, lossless view', JSON.stringify(losslessView)); for (const [id, ent] of Object.entries(losslessView)) { resolved[id] = {id, properties: {}}; for (const key of Object.keys(ent.properties)) { const {value} = lastValueFromLosslessViewOne(ent, key) || {}; - // debug(`[ ${key} ] = ${value}`); + debug(`[ ${key} ] = ${value}`); resolved[id].properties[key] = value; } } diff --git a/src/node.ts b/src/node.ts index 9ea3a06..31b1540 100644 --- a/src/node.ts +++ b/src/node.ts @@ -1,12 +1,12 @@ import Debug from 'debug'; -import {CREATOR, HTTP_API_ADDR, HTTP_API_ENABLE, HTTP_API_PORT, PEER_ID, PUBLISH_BIND_ADDR, PUBLISH_BIND_HOST, PUBLISH_BIND_PORT, REQUEST_BIND_ADDR, REQUEST_BIND_HOST, REQUEST_BIND_PORT, SEED_PEERS} from './config'; -import {DeltaStream} from './deltas'; -import {HttpServer} from './http'; -import {Lossless} from './lossless'; -import {Peers} from './peers'; -import {PubSub} from './pub-sub'; -import {RequestReply} from './request-reply'; -import {PeerAddress} from './types'; +import {CREATOR, HTTP_API_ADDR, HTTP_API_ENABLE, HTTP_API_PORT, PEER_ID, PUB_SUB_TOPIC, PUBLISH_BIND_ADDR, PUBLISH_BIND_HOST, PUBLISH_BIND_PORT, REQUEST_BIND_ADDR, REQUEST_BIND_HOST, REQUEST_BIND_PORT, SEED_PEERS} from './config.js'; +import {DeltaStream} from './deltas.js'; +import {HttpServer} from './http/index.js'; +import {Lossless} from './lossless.js'; +import {Peers} from './peers.js'; +import {PubSub} from './pub-sub.js'; +import {RequestReply} from './request-reply.js'; +import {PeerAddress} from './types.js'; const debug = Debug('rhizome-node'); export type RhizomeNodeConfig = { @@ -22,6 +22,7 @@ export type RhizomeNodeConfig = { seedPeers: PeerAddress[]; peerId: string; creator: string; // TODO each host should be able to support multiple users + pubSubTopic: string; }; // So that we can run more than one instance in the same process (for testing) @@ -50,6 +51,7 @@ export class RhizomeNode { seedPeers: SEED_PEERS, peerId: PEER_ID, creator: CREATOR, + pubSubTopic: PUB_SUB_TOPIC, ...config }; debug('config', this.config); @@ -74,7 +76,7 @@ export class RhizomeNode { this.deltaStream.subscribeDeltas((delta) => this.lossless.ingestDelta(delta)); // Start ZeroMQ publish and reply sockets - this.pubSub.start(); + await this.pubSub.start(); this.requestReply.start(); // Start HTTP server @@ -82,6 +84,9 @@ export class RhizomeNode { this.httpServer.start(); } + // Start libp2p subscription + this.peers.start(); + // Wait a short time for sockets to initialize await new Promise((resolve) => setTimeout(resolve, 500)); diff --git a/src/peers.ts b/src/peers.ts index 3307076..2712b87 100644 --- a/src/peers.ts +++ b/src/peers.ts @@ -1,11 +1,11 @@ import Debug from 'debug'; import {Message} from 'zeromq'; -import {SEED_PEERS} from "./config"; -import {Delta} from "./delta"; -import {RhizomeNode} from "./node"; -import {Subscription} from './pub-sub'; -import {PeerRequest, RequestSocket, ResponseSocket} from "./request-reply"; -import {PeerAddress} from "./types"; +import {SEED_PEERS} from "./config.js"; +import {Delta} from "./delta.js"; +import {RhizomeNode} from "./node.js"; +import {Subscription} from './pub-sub.js'; +import {PeerRequest, RequestSocket, ResponseSocket} from "./request-reply.js"; +import {PeerAddress} from "./types.js"; const debug = Debug('peers'); export enum RequestMethods { @@ -46,9 +46,9 @@ class Peer { this.subscription = this.rhizomeNode.pubSub.subscribe( this.publishAddr, - "deltas", + this.rhizomeNode.config.pubSubTopic, (sender, msg) => { - const delta = this.rhizomeNode.deltaStream.deserializeDelta(msg.toString()); + const delta = this.rhizomeNode.deltaStream.deserializeDelta(msg); delta.receivedFrom = sender; debug(`Received delta: ${JSON.stringify(delta)}`); this.rhizomeNode.deltaStream.ingestDelta(delta); @@ -99,7 +99,18 @@ export class Peers { } } }); + } + start() { + this.rhizomeNode.pubSub.subscribeTopic( + this.rhizomeNode.config.pubSubTopic, + (sender, msg) => { + const delta = this.rhizomeNode.deltaStream.deserializeDelta(msg); + delta.receivedFrom = sender; + debug(`Received delta: ${JSON.stringify(delta)}`); + this.rhizomeNode.deltaStream.ingestDelta(delta); + } + ); } addPeer(addr: PeerAddress): Peer { diff --git a/src/pub-sub.ts b/src/pub-sub.ts index 5286255..c34ccaa 100644 --- a/src/pub-sub.ts +++ b/src/pub-sub.ts @@ -1,10 +1,18 @@ +import {GossipSub, gossipsub} from '@chainsafe/libp2p-gossipsub'; +import {noise} from '@chainsafe/libp2p-noise'; +import {yamux} from '@chainsafe/libp2p-yamux'; +import {identify} from '@libp2p/identify'; +import {mdns} from '@libp2p/mdns'; +import {ping} from '@libp2p/ping'; +import {tcp} from '@libp2p/tcp'; import Debug from 'debug'; -import {Message, Publisher, Subscriber} from 'zeromq'; -import {RhizomeNode} from './node'; -import {PeerAddress} from './types'; +import {Libp2p, createLibp2p} from 'libp2p'; +import {Publisher, Subscriber} from 'zeromq'; +import {RhizomeNode} from './node.js'; +import {PeerAddress} from './types.js'; const debug = Debug('pub-sub'); -export type SubscribedMessageHandler = (sender: PeerAddress, msg: Message) => void; +export type SubscribedMessageHandler = (sender: PeerAddress, msg: string) => void; // TODO: Allow subscribing to multiple topics on one socket export class Subscription { @@ -13,22 +21,33 @@ export class Subscription { publishAddr: PeerAddress; publishAddrStr: string; cb: SubscribedMessageHandler; + libp2p?: Libp2p; - constructor(publishAddr: PeerAddress, topic: string, cb: SubscribedMessageHandler) { + constructor( + publishAddr: PeerAddress, + topic: string, + cb: SubscribedMessageHandler, + libp2p?: Libp2p + ) { this.cb = cb; this.topic = topic; this.publishAddr = publishAddr; this.publishAddrStr = `tcp://${this.publishAddr.toAddrString()}`; + this.libp2p = libp2p; } async start() { this.sock.connect(this.publishAddrStr); this.sock.subscribe(this.topic); - debug(`Subscribing to ${this.topic} topic on ${this.publishAddrStr}`); + debug(`Subscribing to ${this.topic} topic on ZeroMQ ${this.publishAddrStr}`); + // Wait for ZeroMQ messages. + // This will block indefinitely. for await (const [, sender, msg] of this.sock) { - const senderAddr = PeerAddress.fromString(sender.toString()); - this.cb(senderAddr, msg); + const senderStr = PeerAddress.fromString(sender.toString()); + const msgStr = msg.toString(); + debug(`ZeroMQ subscribtion received msg: ${msgStr}`); + this.cb(senderStr, msgStr); } } } @@ -38,6 +57,7 @@ export class PubSub { publishSock: Publisher; publishAddrStr: string; subscriptions: Subscription[] = []; + libp2p?: Libp2p; constructor(rhizomeNode: RhizomeNode) { this.rhizomeNode = rhizomeNode; @@ -49,19 +69,82 @@ export class PubSub { async start() { await this.publishSock.bind(this.publishAddrStr); - debug(`Publishing socket bound to ${this.publishAddrStr}`); + debug(`ZeroMQ publishing socket bound to ${this.publishAddrStr}`); + + this.libp2p = await createLibp2p({ + addresses: { + // TODO: Config + listen: ['/ip4/127.0.0.1/tcp/0'] + }, + transports: [tcp()], + connectionEncrypters: [noise()], + streamMuxers: [yamux()], + peerDiscovery: [mdns()], + services: { + pubsub: gossipsub(), + identify: identify(), + ping: ping(), + } + }); + + this.libp2p.addEventListener("peer:discovery", (event) => { + debug(`found peer: ${JSON.stringify(event.detail, null, 2)}`); + this.libp2p?.dial(event.detail.multiaddrs); + }); + + this.libp2p.addEventListener("peer:connect", (event) => { + debug(`connected to peer: ${JSON.stringify(event.detail, null, 2)}`); + // TODO: Subscribe + }); } async publish(topic: string, msg: string) { + debug(`publishing to ZeroMQ, msg: ${msg}`); await this.publishSock.send([ topic, this.rhizomeNode.myRequestAddr.toAddrString(), msg ]); + + if (this.libp2p) { + const pubsub = this.libp2p.services.pubsub as GossipSub; + debug(`publishing to Libp2p, msg: ${msg}`); + try { + await pubsub.publish(topic, Buffer.from(msg)); + } catch (e: unknown) { + debug('Libp2p publish:', (e as Error).message); + } + } } - subscribe(publishAddr: PeerAddress, topic: string, cb: SubscribedMessageHandler): Subscription { - const subscription = new Subscription(publishAddr, topic, cb); + subscribedTopics = new Set(); + + subscribeTopic(topic: string, cb: SubscribedMessageHandler) { + if (!this.libp2p) throw new Error('libp2p not initialized'); + const pubsub = this.libp2p.services.pubsub as GossipSub; + + // TODO: If we subscribe to multiple topics this callback will be duplicated + pubsub.addEventListener("message", (event) => { + const msg = Buffer.from(event.detail.data).toString(); + debug(`Libp2p subscribtion received msg: ${msg}`); + cb(new PeerAddress('libp2p', 0), msg); + }); + + // Add to our list of subscribed topics so we can unsubscribe later. + // Also has the effect of not calling subscribe more than once per topic. + if (!this.subscribedTopics.has(topic)) { + pubsub.subscribe(topic); + this.subscribedTopics.add(topic); + debug('subscribed topics:', Array.from(this.subscribedTopics.keys())); + } + } + + subscribe( + publishAddr: PeerAddress, + topic: string, + cb: SubscribedMessageHandler + ): Subscription { + const subscription = new Subscription(publishAddr, topic, cb, this.libp2p); this.subscriptions.push(subscription); return subscription; } @@ -73,7 +156,23 @@ export class PubSub { for (const subscription of this.subscriptions) { subscription.sock.close(); - debug('subscription socket is closed?', subscription.sock.closed); + } + + if (this.libp2p) { + const pubsub = this.libp2p.services.pubsub as GossipSub; + + pubsub.removeEventListener("message"); + + for (const topic of this.subscribedTopics) { + debug(`unsubscribing Libp2p topic ${topic}`); + pubsub.unsubscribe(topic) + } + + debug('stopping gossipsub'); + + await pubsub.stop(); + + await this.libp2p.stop(); } } } diff --git a/src/request-reply.ts b/src/request-reply.ts index 9ea0d5c..93a0ad3 100644 --- a/src/request-reply.ts +++ b/src/request-reply.ts @@ -1,9 +1,9 @@ -import {Request, Reply, Message} from 'zeromq'; -import {EventEmitter} from 'node:events'; -import {RequestMethods} from './peers'; import Debug from 'debug'; -import {RhizomeNode} from './node'; -import {PeerAddress} from './types'; +import {EventEmitter} from 'node:events'; +import {Message, Reply, Request} from 'zeromq'; +import {RhizomeNode} from './node.js'; +import {RequestMethods} from './peers.js'; +import {PeerAddress} from './types.js'; const debug = Debug('request-reply'); export type PeerRequest = { diff --git a/src/store.ts b/src/store.ts index ff76820..f8244b5 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,5 +1,5 @@ import { Level } from 'level'; -import { LEVEL_DB_DIR } from './config'; +import { LEVEL_DB_DIR } from './config.js'; import path from 'path'; function newStore(name: string): Level { @@ -8,4 +8,4 @@ function newStore(name: string): Level { export const queryResultStore = newStore('query-results'); -export const deltasAcceptedStore = newStore('deltas-accepted'); \ No newline at end of file +export const deltasAcceptedStore = newStore('deltas-accepted'); diff --git a/src/transactions.ts b/src/transactions.ts index 5c8ece5..4b7a4a8 100644 --- a/src/transactions.ts +++ b/src/transactions.ts @@ -1,7 +1,7 @@ import Debug from "debug"; import EventEmitter from "events"; -import {Delta, DeltaID} from "./delta"; -import {DomainEntityID, TransactionID} from "./types"; +import {Delta, DeltaID} from "./delta.js"; +import {DomainEntityID, TransactionID} from "./types.js"; const debug = Debug("transactions"); function getDeltaTransactionId(delta: Delta): TransactionID | undefined { diff --git a/src/util/md-files.ts b/src/util/md-files.ts index f7e53fc..f6ee014 100644 --- a/src/util/md-files.ts +++ b/src/util/md-files.ts @@ -1,7 +1,8 @@ import Debug from "debug"; import {FSWatcher, readdirSync, readFileSync, watch} from "fs"; import path, {join} from "path"; -import {Converter} from "showdown"; +import showdown from "showdown"; +const {Converter} = showdown; const debug = Debug('md-files'); const docConverter = new Converter({ diff --git a/tsconfig.json b/tsconfig.json index a148e62..49cade1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,17 @@ { "compilerOptions": { - "target": "ES6", - "module": "CommonJS", + "target": "ESNext", + "module": "ESNext", "esModuleInterop": true, - "moduleResolution": "Node", + "moduleResolution": "bundler", "sourceMap": false, + "isolatedModules": true, + /* "allowImportingTsExtensions": true, */ + /* "noEmit": true, */ "baseUrl": ".", "outDir": "dist", + "lib": ["ESNext"], + "types": ["node", "jest"], "importsNotUsedAsValues": "remove", "strict": true, "skipLibCheck": true, @@ -21,5 +26,8 @@ ], "exclude": [ "node_modules" - ] + ], + "tsc-alias": { + "resolveFullPaths": true + } } diff --git a/util/app.ts b/util/app.ts index c1515bd..c7f8c37 100644 --- a/util/app.ts +++ b/util/app.ts @@ -1,5 +1,6 @@ -import {RhizomeNode, RhizomeNodeConfig} from "../src/node"; -import {Collection} from "../src/collection"; +import {RhizomeNode, RhizomeNodeConfig} from "../src/node.js"; +import {Collection} from "../src/collection.js"; +import {randomUUID} from "crypto"; const start = 5000; const range = 5000; @@ -14,6 +15,7 @@ export class App extends RhizomeNode { publishBindPort: getRandomPort(), requestBindPort: getRandomPort(), httpPort: getRandomPort(), + pubSubTopic: config?.pubSubTopic || `deltas-${randomUUID()}`, ...config, });