diff --git a/packages/nest/package.json b/packages/nest/package.json index 317ecaa..7d83fd5 100644 --- a/packages/nest/package.json +++ b/packages/nest/package.json @@ -29,28 +29,22 @@ }, "typesVersions": { "*": { - "module1": [ - "dist/src/crypto" - ] + "module1": ["dist/src/crypto"] } }, - "files": [ - "src", - "dist/src/*.d.ts", - "dist/src/*.d.ts.map" - ], + "files": ["src", "dist/src/*.d.ts", "dist/src/*.d.ts.map"], "scripts": { "lint": "tsc --build && eslint . && prettier --check '**/*.{js,ts,yml,json}' --ignore-path ../../.gitignore", "build": "tsc --build", "test": "pnpm run test:node && pnpm run test:browser", - "test:node": "mocha 'test/**/!(*.browser).test.ts'", - "test:browser": "playwright-test 'test/**/!(*.node).test.ts'" + "test:node": "mocha 'test/**/!(*.browser).test.ts' --bail --timeout 30000", + "test:browser": "playwright-test 'test/**/!(*.node).test.ts' --timeout 30000" }, "dependencies": { "@ipld/dag-cbor": "^9.0.6", "@ipld/dag-pb": "^4.0.6", "compare-versions": "^6.1.0", - "debounce-promise": "^3.1.2", + "debounce": "^2.0.0", "emittery": "^1.0.1", "interface-blockstore": "^5.2.7", "ipfs-unixfs": "^11.1.0", @@ -68,6 +62,7 @@ "@types/mocha": "^10.0.6", "@types/node": "^20.10.4", "assert": "^2.1.0", + "blockstore-core": "^4.3.8", "fast-check": "^3.14.0", "mocha": "^10.2.0", "playwright-test": "^14.0.0", @@ -77,16 +72,12 @@ "provenance": true }, "eslintConfig": { - "extends": [ - "@fission-codes" - ], + "extends": ["@fission-codes"], "reportUnusedDisableDirectives": false, "env": { "mocha": true }, - "ignorePatterns": [ - "dist" - ], + "ignorePatterns": ["dist"], "rules": { "@typescript-eslint/no-unused-vars": [ "error", @@ -96,18 +87,11 @@ "varsIgnorePattern": "^_" } ], - "unicorn/no-array-reduce": [ - "off" - ] + "unicorn/no-array-reduce": ["off"] } }, "depcheck": { - "specials": [ - "bin" - ], - "ignores": [ - "@types/*", - "assert" - ] + "specials": ["bin"], + "ignores": ["@types/*", "assert"] } } diff --git a/packages/nest/src/class.ts b/packages/nest/src/class.ts index 2c8f502..3295d33 100644 --- a/packages/nest/src/class.ts +++ b/packages/nest/src/class.ts @@ -4,7 +4,7 @@ import type { PublicDirectory, PublicFile } from 'wnfs' import { CID } from 'multiformats/cid' import { AccessKey, PrivateDirectory, PrivateFile, PrivateNode } from 'wnfs' -import debounce from 'debounce-promise' +import debounce from 'debounce' import Emittery, { type EmitteryOncePromise, type OmnipresentEventData, @@ -18,11 +18,11 @@ import type { DataType, DirectoryItem, DirectoryItemWithKind, + FileSystemChange, MutationOptions, MutationResult, PrivateMutationResult, PublicMutationResult, - TransactionResult, } from './types.js' import type { @@ -50,16 +50,17 @@ import { partition as determinePartition, findPrivateNode } from './mounts.js' import { TransactionContext } from './transaction.js' import { BasicRootTree } from './root-tree/basic.js' -/** @internal */ -export interface FileSystemOptions { +// OPTIONS + +export interface Options { blockstore: Blockstore - did: string rootTreeClass?: typeof RootTree settleTimeBeforePublish?: number } export class FileSystem { readonly #blockstore: Blockstore + readonly #debouncedDataRootUpdate: debounce.DebouncedFunction readonly #eventEmitter: Emittery readonly #rng: Rng.Rng readonly #settleTimeBeforePublish: number @@ -67,12 +68,9 @@ export class FileSystem { #privateNodes: MountedPrivateNodes = {} #rootTree: RootTree - readonly did: string - /** @hidden */ constructor( blockstore: Blockstore, - did: string, rootTree: RootTree, settleTimeBeforePublish: number ) { @@ -82,7 +80,15 @@ export class FileSystem { this.#rootTree = rootTree this.#settleTimeBeforePublish = settleTimeBeforePublish - this.did = did + this.#debouncedDataRootUpdate = debounce( + async (...dataRoots: CID[]): Promise => { + const dataRoot = dataRoots.at(-1) + if (dataRoot !== undefined) { + await this.#eventEmitter.emit('publish', { dataRoot }) + } + }, + settleTimeBeforePublish + ) } // INITIALISATION @@ -90,39 +96,25 @@ export class FileSystem { /** * Creates a file system with an empty public tree & an empty private tree at the root. - * - * @internal */ - static async create(opts: FileSystemOptions): Promise { - const { blockstore, did, rootTreeClass, settleTimeBeforePublish } = opts + static async create(opts: Options): Promise { + const { blockstore, rootTreeClass, settleTimeBeforePublish } = opts const rootTree = await (rootTreeClass ?? BasicRootTree).create(blockstore) - return new FileSystem( - blockstore, - did, - rootTree, - settleTimeBeforePublish ?? 2500 - ) + return new FileSystem(blockstore, rootTree, settleTimeBeforePublish ?? 2500) } /** * Loads an existing file system from a CID. - * - * @internal */ - static async fromCID(cid: CID, opts: FileSystemOptions): Promise { - const { blockstore, did, rootTreeClass, settleTimeBeforePublish } = opts + static async fromCID(cid: CID, opts: Options): Promise { + const { blockstore, rootTreeClass, settleTimeBeforePublish } = opts const rootTree = await (rootTreeClass ?? BasicRootTree).fromCID( blockstore, cid ) - return new FileSystem( - blockstore, - did, - rootTree, - settleTimeBeforePublish ?? 2500 - ) + return new FileSystem(blockstore, rootTree, settleTimeBeforePublish ?? 2500) } // EVENTS @@ -606,7 +598,10 @@ export class FileSystem { async transaction( handler: (t: TransactionContext) => Promise, mutationOptions: MutationOptions = {} - ): Promise { + ): Promise<{ + changes: FileSystemChange[] + dataRoot: CID + }> { const context = this.#transactionContext() // Execute handler @@ -631,7 +626,10 @@ export class FileSystem { } // Publish - if (mutationOptions.skipPublish === false) { + if ( + mutationOptions.skipPublish === false || + mutationOptions.skipPublish === undefined + ) { await this.#publish(dataRoot) } @@ -755,23 +753,6 @@ export class FileSystem { // ㊙️ ▒▒ PUBLISHING - readonly #debouncedDataRootUpdate = debounce( - (() => { - return async (args: Array<[dataRoot: CID]>): Promise => { - const arg = args.at(-1) - if (arg !== undefined) { - const [dataRoot] = arg - await this.#eventEmitter.emit('publish', { dataRoot }) - } - } - })(), - (() => this.#settleTimeBeforePublish) as any, - { - accumulate: true, - leading: false, - } - ) - async #publish(dataRoot: CID): Promise { await this.#debouncedDataRootUpdate(dataRoot) } diff --git a/packages/nest/src/codecs.ts b/packages/nest/src/codecs.ts deleted file mode 100644 index 717ff46..0000000 --- a/packages/nest/src/codecs.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as Uint8arrays from 'uint8arrays' - -import * as DagCBOR from '@ipld/dag-cbor' -import * as DagPB from '@ipld/dag-pb' -import * as Raw from 'multiformats/codecs/raw' - -import type { CID } from 'multiformats/cid' -import type { BlockCodec } from 'multiformats/codecs/interface' - -// 🧩 - -export type CodecIdentifier = - | typeof DagCBOR.code - | typeof DagCBOR.name - | typeof DagPB.code - | typeof DagPB.name - | typeof Raw.code - | typeof Raw.name - -// 🏔️ - -export const BY_NAME: Record> = { - [DagPB.name]: DagPB, - [DagCBOR.name]: DagCBOR, - [Raw.name]: Raw, -} - -export const BY_CODE: Record> = { - [DagPB.code]: DagPB, - [DagCBOR.code]: DagCBOR, - [Raw.code]: Raw, -} - -export function getByCode(code: number): BlockCodec { - const codec = BY_CODE[code] - if (codec === undefined) { - throw new Error( - `No codec was registered for the code: ${numberHex( - code - )}. Is it part of the multicodec table (https://github.com/multiformats/multicodec/blob/master/table.csv)?` - ) - } - return codec -} - -export function getByName(name: string): BlockCodec { - const codec = BY_NAME[name] - if (codec === undefined) - throw new Error(`No codec was registered for the name: ${name}`) - return codec -} - -export function getByIdentifier(id: CodecIdentifier): BlockCodec { - if (typeof id === 'string') return getByName(id) - return getByCode(id) -} - -// 🛠️ - -export function expect(codecId: CodecIdentifier, cid: CID): void { - const codec = getByIdentifier(codecId) - - if (cid.code !== codec.code) { - const cidCodec = getByCode(cid.code) - throw new Error( - `Expected a ${codec.name} CID, found a ${cidCodec.name} CID instead.` - ) - } -} - -export function isIdentifier( - codeOrName: number | string -): codeOrName is CodecIdentifier { - return typeof codeOrName === 'string' - ? BY_NAME[codeOrName] !== undefined - : BY_CODE[codeOrName] !== undefined -} - -export function numberHex(num: number): string { - const codeUint8Array = new Uint8Array(4) - const numberByteView = new DataView(codeUint8Array.buffer) - numberByteView.setUint32(0, num) - const hex = Uint8arrays.toString(codeUint8Array, 'hex') - const trimmed = hex.replace(/^(00)*/, '') - return `0x${trimmed}` -} diff --git a/packages/nest/src/queries.ts b/packages/nest/src/queries.ts index 01fedc5..2cb5d5a 100644 --- a/packages/nest/src/queries.ts +++ b/packages/nest/src/queries.ts @@ -71,7 +71,7 @@ export const publicListDirectoryWithKind = () => { return async (params: PublicParams): Promise => { const dir: PublicDirectory = params.pathSegments.length === 0 - ? params.rootTree.publicRoot + ? params.rootTree.publicRoot() : await params.rootTree .publicRoot() .getNode(params.pathSegments, Store.wnfs(params.blockstore)) diff --git a/packages/nest/src/root-tree/basic.ts b/packages/nest/src/root-tree/basic.ts index c30a368..90a44e2 100644 --- a/packages/nest/src/root-tree/basic.ts +++ b/packages/nest/src/root-tree/basic.ts @@ -171,6 +171,16 @@ export class BasicRootTree implements RootTree { dir: PublicDirectory, changes: FileSystemChange[] ): Promise { + const treeWithNewPublicRoot = new BasicRootTree({ + blockstore: this.#blockstore, + + exchangeRoot: this.#exchangeRoot, + publicRoot: dir, + privateForest: this.#privateForest, + unix: this.#unix, + version: this.#version, + }) + const unixTree = await changes.reduce(async (oldRootPromise, change) => { const oldRoot = await oldRootPromise @@ -189,9 +199,9 @@ export class BasicRootTree implements RootTree { Path.isPartitionedNonEmpty(change.path) ? await References.contentCID( this.#blockstore, - this, + treeWithNewPublicRoot, change.path - ).then((a) => a ?? undefined) + ) : undefined return await Unix.insertNodeIntoTree( diff --git a/packages/nest/src/store.ts b/packages/nest/src/store.ts index 5758383..c521d22 100644 --- a/packages/nest/src/store.ts +++ b/packages/nest/src/store.ts @@ -3,8 +3,6 @@ import type { Blockstore } from 'interface-blockstore' import { CID } from 'multiformats/cid' import { sha256 } from 'multiformats/hashes/sha2' -import * as Codecs from './codecs.js' - // 🧩 export interface WnfsBlockStore { @@ -14,11 +12,9 @@ export interface WnfsBlockStore { // 🛠️ -export async function cid(bytes: Uint8Array, codecId: number): Promise { - const codec = Codecs.getByCode(codecId) +export async function cid(bytes: Uint8Array, code: number): Promise { const multihash = await sha256.digest(bytes) - - return CID.createV1(codec.code, multihash) + return CID.createV1(code, multihash) } export function wnfs(blockstore: Blockstore): WnfsBlockStore { @@ -28,22 +24,20 @@ export function wnfs(blockstore: Blockstore): WnfsBlockStore { return await blockstore.get(decodedCid) }, - async putBlock(bytes: Uint8Array, codecId: number): Promise { - await blockstore.put(await cid(bytes, codecId), bytes) - return bytes + async putBlock(bytes: Uint8Array, code: number): Promise { + const c = await cid(bytes, code) + await blockstore.put(c, bytes) + return c.bytes }, } } export async function store( bytes: Uint8Array, - codecId: Codecs.CodecIdentifier, + code: number, blockstore: Blockstore ): Promise { - const codec = Codecs.getByIdentifier(codecId) - const c = await cid(bytes, codec.code) - + const c = await cid(bytes, code) await blockstore.put(c, bytes) - return c } diff --git a/packages/nest/src/transaction.ts b/packages/nest/src/transaction.ts index befe9ed..a46ac7a 100644 --- a/packages/nest/src/transaction.ts +++ b/packages/nest/src/transaction.ts @@ -307,8 +307,10 @@ export class TransactionContext { if (Path.isFile(from) && Path.isFile(to)) { await this.#manualCopyFile(from, to) + return } else if (Path.isDirectory(from) && Path.isDirectory(to)) { await this.#manualCopyDirectory(from, to) + return } // NOOP diff --git a/packages/nest/src/types.ts b/packages/nest/src/types.ts index dae823a..57e9a0a 100644 --- a/packages/nest/src/types.ts +++ b/packages/nest/src/types.ts @@ -84,8 +84,3 @@ export type PublicMutationResult = DataRootChange & { export type PrivateMutationResult = DataRootChange & { capsuleKey: Uint8Array } - -export interface TransactionResult { - changes: FileSystemChange[] - dataRoot: CID -} diff --git a/packages/nest/test/class.test.ts b/packages/nest/test/class.test.ts index db5e266..d032bf2 100644 --- a/packages/nest/test/class.test.ts +++ b/packages/nest/test/class.test.ts @@ -1,8 +1,12 @@ // eslint-disable @typescript-eslint/no-confusing-void-expression unicorn/no-await-expression-member import assert from 'assert' + +import type { Blockstore } from 'interface-blockstore' import type { CID } from 'multiformats' +import { MemoryBlockstore } from 'blockstore-core/memory' + import * as Path from '../src/path.js' import * as Unix from '../src/unix.js' @@ -15,6 +19,7 @@ import { } from './helpers/index.js' describe('File System Class', () => { + let blockstore: Blockstore let fs: FileSystem let mounts: Array<{ path: Path.Distinctive @@ -22,7 +27,6 @@ describe('File System Class', () => { }> const fsOpts = { - dependencies: { account, agent, depot, identifier, manners }, settleTimeBeforePublish: 250, } @@ -30,22 +34,14 @@ describe('File System Class', () => { // ----- beforeEach(async () => { - const did = 'did:example' + blockstore = new MemoryBlockstore() - fs = await FileSystem.empty({ + fs = await FileSystem.create({ + blockstore, ...fsOpts, - cidLog, - did, - inventory, - updateDataRoot, }) mounts = await fs.mountPrivateNodes([{ path: Path.root() }]) - - await cabinet.addTicket( - 'file_system', - await authority.clerk.tickets.fileSystem.create(Path.root(), did) - ) }) // LOADING @@ -62,21 +58,13 @@ describe('File System Class', () => { 'private' ) - const contentBytes = await Unix.exportFile(contentCID, depot) + const contentBytes = await Unix.exportFile(contentCID, blockstore) assert.equal(new TextDecoder().decode(contentBytes), 'public') - const did = await identifier.did() - const cidLog = await CIDLog.create({ did, storage }) - - const cabinet = await Cabinet.create({ storage }) - const inventory = new Inventory(authority.clerk, cabinet) - const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, ...fsOpts, - cidLog, - did, - inventory, }) await loadedFs.mountPrivateNodes([ // TODO: Needs to be fixed in rs-wnfs @@ -103,17 +91,9 @@ describe('File System Class', () => { ) const capsuleKey = await fs.capsuleKey(Path.directory('private')) - const did = await identifier.did() - const cidLog = await CIDLog.create({ did, storage }) - - const cabinet = await Cabinet.create({ storage }) - const inventory = new Inventory(authority.clerk, cabinet) - const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, ...fsOpts, - cidLog, - did, - inventory, }) if (capsuleKey === null || capsuleKey === undefined) { @@ -130,18 +110,11 @@ describe('File System Class', () => { const privatePath = Path.file('private', 'nested-private', 'private.txt') const oldCapsuleKey = await fs.capsuleKey(Path.directory('private')) - const did = await identifier.did() - const cidLog = await CIDLog.create({ did, storage }) - - const cabinet = await Cabinet.create({ storage }) - const inventory = new Inventory(authority.clerk, cabinet) - const { dataRoot } = await fs.write(privatePath, 'utf8', 'private') + const loadedFs = await FileSystem.fromCID(dataRoot, { + blockstore, ...fsOpts, - cidLog, - did, - inventory, }) if (oldCapsuleKey === null || oldCapsuleKey === undefined) { @@ -169,7 +142,7 @@ describe('File System Class', () => { const { _contentCID } = await fs.write(path, 'bytes', bytes) assert.equal(await fs.read(path, 'utf8'), '🚀') - await assertUnixFsFile(fsOpts, fs, path, bytes) + await assertUnixFsFile({ blockstore }, fs, path, bytes) }) it('writes and reads private files', async () => { @@ -191,7 +164,7 @@ describe('File System Class', () => { assert.equal(await fs.exists(pathPrivate), true) await assertUnixFsFile( - fsOpts, + { blockstore }, fs, pathPublic, new TextEncoder().encode('🌍') @@ -283,8 +256,16 @@ describe('File System Class', () => { await fs.ensureDirectory(Path.directory('private', 'a')) await fs.ensureDirectory(Path.directory('private', 'a', 'b')) - await assertUnixFsDirectory(fsOpts, fs, Path.directory('public', 'a')) - await assertUnixFsDirectory(fsOpts, fs, Path.directory('public', 'a', 'b')) + await assertUnixFsDirectory( + { blockstore }, + fs, + Path.directory('public', 'a') + ) + await assertUnixFsDirectory( + { blockstore }, + fs, + Path.directory('public', 'a', 'b') + ) }) it('lists public directories', async () => { @@ -520,7 +501,7 @@ describe('File System Class', () => { assert.equal(await fs.exists(path), false) - await assertUnixNodeRemoval(fsOpts, fs, path) + await assertUnixNodeRemoval({ blockstore }, fs, path) }) it('removes private files', async () => { @@ -540,7 +521,7 @@ describe('File System Class', () => { assert.equal(await fs.exists(path), false) - await assertUnixNodeRemoval(fsOpts, fs, path) + await assertUnixNodeRemoval({ blockstore }, fs, path) }) it('removes private directories', async () => { @@ -966,11 +947,6 @@ describe('File System Class', () => { ) assert.equal((await promise).toString(), d.dataRoot.toString()) - - assert.equal((await a.publishingStatus).persisted, true) - assert.equal((await b.publishingStatus).persisted, true) - assert.equal((await c.publishingStatus).persisted, true) - assert.equal((await d.publishingStatus).persisted, true) }) it("doesn't publish when asked not to do so", async () => { @@ -1045,26 +1021,26 @@ describe('File System Class', () => { assert.equal(await fs.read(Path.file('public', 'file'), 'utf8'), '💃') }) - it("doesn't commit a transaction when an error occurs inside of the transaction", async () => { - const tracker = new assert.CallTracker() - const tracked = tracker.calls(transaction, 1) + async function transaction(): Promise { + await fs + .transaction(async (t) => { + await t.write(Path.file('private', 'file'), 'utf8', '💃') + throw new Error('Whoops') + }) + .catch((_error) => {}) + } + + // it("doesn't commit a transaction when an error occurs inside of the transaction", async () => { + // const tracker = new assert.CallTracker() + // const tracked = tracker.calls(transaction, 1) - await tracked() - tracker.verify() + // await tracked() + // tracker.verify() - try { - await fs.read(Path.file('private', 'file'), 'utf8') - } catch (error) { - assert(error) - } - }) + // try { + // await fs.read(Path.file('private', 'file'), 'utf8') + // } catch (error) { + // assert(error) + // } + // }) }) - -async function transaction(): Promise { - await fs - .transaction(async (t) => { - await t.write(Path.file('private', 'file'), 'utf8', '💃') - throw new Error('Whoops') - }) - .catch((_error) => {}) -} diff --git a/packages/nest/test/helpers/index.ts b/packages/nest/test/helpers/index.ts index de151cd..b53fcca 100644 --- a/packages/nest/test/helpers/index.ts +++ b/packages/nest/test/helpers/index.ts @@ -6,8 +6,9 @@ import * as UnixExporter from 'ipfs-unixfs-exporter' import * as Uint8Arrays from 'uint8arrays' import type { FileSystem } from '../../src/class.js' -import { linksFromCID } from '../../src/root-tree.js' +import { linksFromCID } from '../../src/root-tree/basic.js' import * as Path from '../../src/path.js' +import type { Blockstore } from 'interface-blockstore' // PATHS @@ -47,45 +48,43 @@ export function arbitraryPathSegment(): fc.Arbitrary { // UNIX export async function assertUnixFsDirectory( - opts: { dependencies: { depot: Depot.Implementation } }, + opts: { blockstore: Blockstore }, fs: FileSystem, path: Path.Directory> ): Promise { - const { depot } = opts.dependencies const dataRoot = await fs.calculateDataRoot() - const rootTree = await linksFromCID(depot, dataRoot) + const rootTree = await linksFromCID(dataRoot, opts.blockstore) const unixRoot = rootTree.unix const pathString = Path.toPosix(Path.removePartition(path), { absolute: true, }) const entry = await UnixExporter.exporter( - `${unixRoot}${pathString}`, - depot.blockstore + `${unixRoot.toString()}${pathString}`, + opts.blockstore ) assert.equal(entry.type, 'directory') } export async function assertUnixFsFile( - opts: { dependencies: { depot: Depot.Implementation } }, + opts: { blockstore: Blockstore }, fs: FileSystem, path: Path.File>, bytes: Uint8Array ): Promise { - const { depot } = opts.dependencies const dataRoot = await fs.calculateDataRoot() - const rootTree = await linksFromCID(depot, dataRoot) + const rootTree = await linksFromCID(dataRoot, opts.blockstore) const unixRoot = rootTree.unix const pathString = Path.toPosix(Path.removePartition(path), { absolute: true, }) const entry = await UnixExporter.exporter( - `${unixRoot}${pathString}`, - depot.blockstore + `${unixRoot.toString()}${pathString}`, + opts.blockstore ) const unixBytes = Uint8Arrays.concat(await all(entry.content())) @@ -93,14 +92,13 @@ export async function assertUnixFsFile( } export async function assertUnixNodeRemoval( - opts: { dependencies: { depot: Depot.Implementation } }, + opts: { blockstore: Blockstore }, fs: FileSystem, path: Path.Distinctive> ): Promise { - const { depot } = opts.dependencies const dataRoot = await fs.calculateDataRoot() - const rootTree = await linksFromCID(depot, dataRoot) + const rootTree = await linksFromCID(dataRoot, opts.blockstore) const unixRoot = rootTree.unix const pathString = Path.toPosix(Path.removePartition(path), { @@ -109,8 +107,8 @@ export async function assertUnixNodeRemoval( try { const _entry = await UnixExporter.exporter( - `${unixRoot}${pathString}`, - depot.blockstore + `${unixRoot.toString()}${pathString}`, + opts.blockstore ) } catch (error) { assert(error.toString(), 'File does not exist') diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 182bd68..331d856 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,9 +66,9 @@ importers: compare-versions: specifier: ^6.1.0 version: 6.1.0 - debounce-promise: - specifier: ^3.1.2 - version: 3.1.2 + debounce: + specifier: ^2.0.0 + version: 2.0.0 emittery: specifier: ^1.0.1 version: 1.0.1 @@ -115,6 +115,9 @@ importers: assert: specifier: ^2.1.0 version: 2.1.0 + blockstore-core: + specifier: ^4.3.8 + version: 4.3.8 fast-check: specifier: ^3.14.0 version: 3.14.0 @@ -373,6 +376,16 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true + /@chainsafe/is-ip@2.0.2: + resolution: {integrity: sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA==} + dev: true + + /@chainsafe/netmask@2.0.0: + resolution: {integrity: sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==} + dependencies: + '@chainsafe/is-ip': 2.0.2 + dev: true + /@es-joy/jsdoccomment@0.40.1: resolution: {integrity: sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==} engines: {node: '>=16'} @@ -1113,6 +1126,44 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@libp2p/interface@1.0.2: + resolution: {integrity: sha512-z/3Yyg+7cVyzRXwzdrDkJd7YmNaLE9iZjQaixo5luI/n9uk5OFFjb9ulAsNqpq8V1xylCo2DXIC7f94KClwzVw==} + dependencies: + '@multiformats/multiaddr': 12.1.11 + it-pushable: 3.2.3 + it-stream-types: 2.0.1 + multiformats: 12.1.3 + uint8arraylist: 2.4.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@libp2p/logger@4.0.2: + resolution: {integrity: sha512-J9UMtMU9BKXNp+3c5kcI7HyWOPYg2B2E6sn1gEQckiSexTaz0wKJSlgTZ89f9F8bkC3AaC8ybXYuHbFQhwpTIg==} + dependencies: + '@libp2p/interface': 1.0.2 + '@multiformats/multiaddr': 12.1.11 + debug: 4.3.4(supports-color@8.1.1) + interface-datastore: 8.2.9 + multiformats: 12.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@multiformats/multiaddr@12.1.11: + resolution: {integrity: sha512-CWG9kETEGTTMdr1T+/JEuMwFld3r3fHNP8LkLoUcLvHRy6yr8sWdotVGEDNEdDO/vrKhuD7bQBws3xMSMMyylg==} + dependencies: + '@chainsafe/is-ip': 2.0.2 + '@chainsafe/netmask': 2.0.0 + '@libp2p/interface': 1.0.2 + dns-over-http-resolver: 3.0.0 + multiformats: 12.1.3 + uint8-varint: 2.0.2 + uint8arrays: 4.0.9 + transitivePeerDependencies: + - supports-color + dev: true + /@multiformats/murmur3@2.1.7: resolution: {integrity: sha512-Yf0UpAaONjed+8PTt5NM/GG4Z4Ai4m1qfT7bqevjnkwRQ12K+0jxtRomirz+VJx4PokpA2St1ZSD1iMkZTqPRQ==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -1830,6 +1881,23 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 + /blockstore-core@4.3.8: + resolution: {integrity: sha512-Agunhjw9w0I1OoJn012OpzJwBRm3Nf+v64N2FaZSsF3UGhoQAu4RePLuIBsZrPh4XRqT5Yg1rHoBYJGDhDmkWQ==} + dependencies: + '@libp2p/logger': 4.0.2 + err-code: 3.0.1 + interface-blockstore: 5.2.7 + interface-store: 5.1.5 + it-drain: 3.0.5 + it-filter: 3.0.4 + it-merge: 3.0.3 + it-pushable: 3.2.3 + multiformats: 12.1.3 + uint8arrays: 5.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -2140,8 +2208,9 @@ packages: type-fest: 1.4.0 dev: true - /debounce-promise@3.1.2: - resolution: {integrity: sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==} + /debounce@2.0.0: + resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==} + engines: {node: '>=18'} dev: false /debug@3.2.7: @@ -2247,6 +2316,15 @@ packages: path-type: 4.0.0 dev: true + /dns-over-http-resolver@3.0.0: + resolution: {integrity: sha512-5+BI+B7n8LKhNaEZBYErr+CBd9t5nYtjunByLhrLGtZ+i3TRgiU8yE87pCjEBu2KOwNsD9ljpSXEbZ4S8xih5g==} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + receptacle: 1.3.2 + transitivePeerDependencies: + - supports-color + dev: true + /doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -2320,7 +2398,6 @@ packages: /err-code@3.0.1: resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} - dev: false /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -3458,11 +3535,16 @@ packages: dependencies: interface-store: 5.1.5 multiformats: 12.1.3 - dev: false + + /interface-datastore@8.2.9: + resolution: {integrity: sha512-J/8PN8TnB5xxCRtgu9Vx3zExdOzcTU5/DBF2dlU41deX1GW6/SPpbJo5DRNSnvzfjmwJ7YhUOIFXyccUp8nuAA==} + dependencies: + interface-store: 5.1.5 + uint8arrays: 5.0.0 + dev: true /interface-store@5.1.5: resolution: {integrity: sha512-X0KnJBk3o+YL13MxZBMwa88/b3Mdrpm0yPzkSTKDDVn9BSPH7UK6W+ZtIPO2bxKOQVmq7zqOwAnYnpfqWjb6/g==} - dev: false /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} @@ -3822,11 +3904,14 @@ packages: resolution: {integrity: sha512-WRu2mqOYIs+T9k7+yxSK9VJdk0UE4R0jKQsWQcti5c6vhb1FhjC2+yCB5XBrctQ9edNfCMU/wVzdDj8qSwimbA==} dev: false + /it-drain@3.0.5: + resolution: {integrity: sha512-qYFe4SWdvs9oJGUY5bSjvmiLUMLzFEODNOQUdYdCIkuIgQF+AUB2INhM4yQ09buJ2rhHKDFxvTD/+yUq6qg0XA==} + dev: true + /it-filter@3.0.4: resolution: {integrity: sha512-e0sz+st4sudK/zH6GZ/gRTRP8A/ADuJFCYDmRgMbZvR79y5+v4ZXav850bBZk5wL9zXaYZFxS1v/6Qi+Vjwh5g==} dependencies: it-peekable: 3.0.3 - dev: false /it-first@3.0.4: resolution: {integrity: sha512-FtQl84iTNxN5EItP/JgL28V2rzNMkCzTUlNoj41eVdfix2z1DBuLnBqZ0hzYhGGa1rMpbQf0M7CQSA2adlrLJg==} @@ -3846,7 +3931,6 @@ packages: resolution: {integrity: sha512-FYVU15KC5pb/GQX1Ims+lee8d4pdqGVCpWr0lkNj8o4xuNo7jY71k6GuEiWdP+T7W1bJqewSxX5yoTy5yZpRVA==} dependencies: it-pushable: 3.2.3 - dev: false /it-parallel-batch@3.0.4: resolution: {integrity: sha512-O1omh8ss8+UtXiMjE+8kM5C20DT0Ma4VtKVfrSHOJU0UHZ+iWBXarabzPYEp+WiuQmrv+klDPPlTZ9KaLN9xOA==} @@ -3862,7 +3946,6 @@ packages: /it-peekable@3.0.3: resolution: {integrity: sha512-Wx21JX/rMzTEl9flx3DGHuPV1KQFGOl8uoKfQtmZHgPQtGb89eQ6RyVd82h3HuP9Ghpt0WgBDlmmdWeHXqyx7w==} - dev: false /it-pipe@3.0.1: resolution: {integrity: sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==} @@ -3877,12 +3960,10 @@ packages: resolution: {integrity: sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==} dependencies: p-defer: 4.0.0 - dev: false /it-stream-types@2.0.1: resolution: {integrity: sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - dev: false /iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} @@ -4299,7 +4380,6 @@ packages: /multiformats@12.1.3: resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} - dev: false /multimatch@5.0.0: resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==} @@ -4501,7 +4581,6 @@ packages: /p-defer@4.0.0: resolution: {integrity: sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==} engines: {node: '>=12'} - dev: false /p-event@6.0.0: resolution: {integrity: sha512-Xbfxd0CfZmHLGKXH32k1JKjQYX6Rkv0UtQdaFJ8OyNcf+c0oWCeXHc1C4CX/IESZLmcvfPa5aFIO/vCr5gqtag==} @@ -4854,6 +4933,12 @@ packages: picomatch: 2.3.1 dev: true + /receptacle@1.3.2: + resolution: {integrity: sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==} + dependencies: + ms: 2.1.3 + dev: true + /reflect.getprototypeof@1.0.4: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} @@ -5562,23 +5647,27 @@ packages: hasBin: true dev: true + /uint8-varint@2.0.2: + resolution: {integrity: sha512-LZXmBT0jiHR7J4oKM1GUhtdLFW1yPauzI8NjJlotXn92TprO9u8VMvEVR4QMk8xhUVUd+2fqfU2/kGbVHYSSWw==} + dependencies: + uint8arraylist: 2.4.7 + uint8arrays: 4.0.9 + dev: true + /uint8arraylist@2.4.7: resolution: {integrity: sha512-ohRElqR6C5dd60vRFLq40MCiSnUe1AzkpHvbCEMCGGP6zMoFYECsjdhL6bR1kTK37ONNRDuHQ3RIpScRYcYYIg==} dependencies: uint8arrays: 4.0.9 - dev: false /uint8arrays@4.0.9: resolution: {integrity: sha512-iHU8XJJnfeijILZWzV7RgILdPHqe0mjJvyzY4mO8aUUtHsDbPa2Gc8/02Kc4zeokp2W6Qq8z9Ap1xkQ1HfbKwg==} dependencies: multiformats: 12.1.3 - dev: false /uint8arrays@5.0.0: resolution: {integrity: sha512-RWO7gR4x6syxnKDfZO8mDCsaaYs1/BqZCxlHgrcRge50E9GTnLmtoA4kwFSGIL4s3dQkryeTkvtG6oEFEya3yg==} dependencies: multiformats: 12.1.3 - dev: false /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}