UNPKG

@fireproof/database

Version:
1,842 lines (1,700 loc) 1.39 MB
console.log("Browser ESM build"); function writeQueue(worker, payload = Infinity) { const queue = []; let isProcessing = false; async function process() { if (isProcessing || queue.length === 0) return; isProcessing = true; const tasksToProcess = queue.splice(0, payload); const updates = tasksToProcess.map(item => item.task); const result = await worker(updates); tasksToProcess.forEach(task => task.resolve(result)); isProcessing = false; void process(); } return { push(task) { return new Promise((resolve) => { queue.push({ task, resolve }); void process(); }); } }; } var encode_1$2 = encode$a; var MSB$3 = 0x80 , REST$3 = 0x7F , MSBALL$2 = ~REST$3 , INT$2 = Math.pow(2, 31); function encode$a(num, out, offset) { out = out || []; offset = offset || 0; var oldOffset = offset; while(num >= INT$2) { out[offset++] = (num & 0xFF) | MSB$3; num /= 128; } while(num & MSBALL$2) { out[offset++] = (num & 0xFF) | MSB$3; num >>>= 7; } out[offset] = num | 0; encode$a.bytes = offset - oldOffset + 1; return out } var decode$e = read$3; var MSB$1$2 = 0x80 , REST$1$2 = 0x7F; function read$3(buf, offset) { var res = 0 , offset = offset || 0 , shift = 0 , counter = offset , b , l = buf.length; do { if (counter >= l) { read$3.bytes = 0; throw new RangeError('Could not decode varint') } b = buf[counter++]; res += shift < 28 ? (b & REST$1$2) << shift : (b & REST$1$2) * Math.pow(2, shift); shift += 7; } while (b >= MSB$1$2) read$3.bytes = counter - offset; return res } var N1$2 = Math.pow(2, 7); var N2$2 = Math.pow(2, 14); var N3$2 = Math.pow(2, 21); var N4$2 = Math.pow(2, 28); var N5$2 = Math.pow(2, 35); var N6$2 = Math.pow(2, 42); var N7$2 = Math.pow(2, 49); var N8$2 = Math.pow(2, 56); var N9$2 = Math.pow(2, 63); var length$2 = function (value) { return ( value < N1$2 ? 1 : value < N2$2 ? 2 : value < N3$2 ? 3 : value < N4$2 ? 4 : value < N5$2 ? 5 : value < N6$2 ? 6 : value < N7$2 ? 7 : value < N8$2 ? 8 : value < N9$2 ? 9 : 10 ) }; var varint$3 = { encode: encode_1$2 , decode: decode$e , encodingLength: length$2 }; var _brrp_varint$1 = varint$3; /** * @param {Uint8Array} data * @param {number} [offset=0] * @returns {[number, number]} */ const decode$d = (data, offset = 0) => { const code = _brrp_varint$1.decode(data, offset); return [code, _brrp_varint$1.decode.bytes] }; /** * @param {number} int * @param {Uint8Array} target * @param {number} [offset=0] */ const encodeTo$1 = (int, target, offset = 0) => { _brrp_varint$1.encode(int, target, offset); return target }; /** * @param {number} int * @returns {number} */ const encodingLength$1 = (int) => { return _brrp_varint$1.encodingLength(int) }; /** * @param {Uint8Array} aa * @param {Uint8Array} bb */ const equals$3 = (aa, bb) => { if (aa === bb) return true if (aa.byteLength !== bb.byteLength) { return false } for (let ii = 0; ii < aa.byteLength; ii++) { if (aa[ii] !== bb[ii]) { return false } } return true }; /** * @param {ArrayBufferView|ArrayBuffer|Uint8Array} o * @returns {Uint8Array} */ const coerce$1 = o => { if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') return o if (o instanceof ArrayBuffer) return new Uint8Array(o) if (ArrayBuffer.isView(o)) { return new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } throw new Error('Unknown type, must be binary type') }; /** * Creates a multihash digest. * * @template {number} Code * @param {Code} code * @param {Uint8Array} digest */ const create$6 = (code, digest) => { const size = digest.byteLength; const sizeOffset = encodingLength$1(code); const digestOffset = sizeOffset + encodingLength$1(size); const bytes = new Uint8Array(digestOffset + size); encodeTo$1(code, bytes, 0); encodeTo$1(size, bytes, sizeOffset); bytes.set(digest, digestOffset); return new Digest$1(code, size, digest, bytes) }; /** * Turns bytes representation of multihash digest into an instance. * * @param {Uint8Array} multihash * @returns {MultihashDigest} */ const decode$c = (multihash) => { const bytes = coerce$1(multihash); const [code, sizeOffset] = decode$d(bytes); const [size, digestOffset] = decode$d(bytes.subarray(sizeOffset)); const digest = bytes.subarray(sizeOffset + digestOffset); if (digest.byteLength !== size) { throw new Error('Incorrect length') } return new Digest$1(code, size, digest, bytes) }; /** * @param {MultihashDigest} a * @param {unknown} b * @returns {b is MultihashDigest} */ const equals$2 = (a, b) => { if (a === b) { return true } else { const data = /** @type {{code?:unknown, size?:unknown, bytes?:unknown}} */(b); return ( a.code === data.code && a.size === data.size && data.bytes instanceof Uint8Array && equals$3(a.bytes, data.bytes) ) } }; /** * @typedef {import('./interface.js').MultihashDigest} MultihashDigest */ /** * Represents a multihash digest which carries information about the * hashing algorithm and an actual hash digest. * * @template {number} Code * @template {number} Size * @class * @implements {MultihashDigest} */ let Digest$1 = class Digest { /** * Creates a multihash digest. * * @param {Code} code * @param {Size} size * @param {Uint8Array} digest * @param {Uint8Array} bytes */ constructor (code, size, digest, bytes) { this.code = code; this.size = size; this.digest = digest; this.bytes = bytes; } }; // base-x encoding / decoding // Copyright (c) 2018 base-x contributors // Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp) // Distributed under the MIT software license, see the accompanying // file LICENSE or http://www.opensource.org/licenses/mit-license.php. function base$3 (ALPHABET, name) { if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') } var BASE_MAP = new Uint8Array(256); for (var j = 0; j < BASE_MAP.length; j++) { BASE_MAP[j] = 255; } for (var i = 0; i < ALPHABET.length; i++) { var x = ALPHABET.charAt(i); var xc = x.charCodeAt(0); if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') } BASE_MAP[xc] = i; } var BASE = ALPHABET.length; var LEADER = ALPHABET.charAt(0); var FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up var iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up function encode (source) { if (source instanceof Uint8Array) ; else if (ArrayBuffer.isView(source)) { source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength); } else if (Array.isArray(source)) { source = Uint8Array.from(source); } if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') } if (source.length === 0) { return '' } // Skip & count leading zeroes. var zeroes = 0; var length = 0; var pbegin = 0; var pend = source.length; while (pbegin !== pend && source[pbegin] === 0) { pbegin++; zeroes++; } // Allocate enough space in big-endian base58 representation. var size = ((pend - pbegin) * iFACTOR + 1) >>> 0; var b58 = new Uint8Array(size); // Process the bytes. while (pbegin !== pend) { var carry = source[pbegin]; // Apply "b58 = b58 * 256 + ch". var i = 0; for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) { carry += (256 * b58[it1]) >>> 0; b58[it1] = (carry % BASE) >>> 0; carry = (carry / BASE) >>> 0; } if (carry !== 0) { throw new Error('Non-zero carry') } length = i; pbegin++; } // Skip leading zeroes in base58 result. var it2 = size - length; while (it2 !== size && b58[it2] === 0) { it2++; } // Translate the result into a string. var str = LEADER.repeat(zeroes); for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]); } return str } function decodeUnsafe (source) { if (typeof source !== 'string') { throw new TypeError('Expected String') } if (source.length === 0) { return new Uint8Array() } var psz = 0; // Skip leading spaces. if (source[psz] === ' ') { return } // Skip and count leading '1's. var zeroes = 0; var length = 0; while (source[psz] === LEADER) { zeroes++; psz++; } // Allocate enough space in big-endian base256 representation. var size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up. var b256 = new Uint8Array(size); // Process the characters. while (source[psz]) { // Decode character var carry = BASE_MAP[source.charCodeAt(psz)]; // Invalid character if (carry === 255) { return } var i = 0; for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) { carry += (BASE * b256[it3]) >>> 0; b256[it3] = (carry % 256) >>> 0; carry = (carry / 256) >>> 0; } if (carry !== 0) { throw new Error('Non-zero carry') } length = i; psz++; } // Skip trailing spaces. if (source[psz] === ' ') { return } // Skip leading zeroes in b256. var it4 = size - length; while (it4 !== size && b256[it4] === 0) { it4++; } var vch = new Uint8Array(zeroes + (size - it4)); var j = zeroes; while (it4 !== size) { vch[j++] = b256[it4++]; } return vch } function decode (string) { var buffer = decodeUnsafe(string); if (buffer) { return buffer } throw new Error(`Non-${name} character`) } return { encode: encode, decodeUnsafe: decodeUnsafe, decode: decode } } var src$1 = base$3; var _brrp__multiformats_scope_baseX$1 = src$1; /** * Class represents both BaseEncoder and MultibaseEncoder meaning it * can be used to encode to multibase or base encode without multibase * prefix. * * @class * @template {string} Base * @template {string} Prefix * @implements {API.MultibaseEncoder<Prefix>} * @implements {API.BaseEncoder} */ let Encoder$1 = class Encoder { /** * @param {Base} name * @param {Prefix} prefix * @param {(bytes:Uint8Array) => string} baseEncode */ constructor (name, prefix, baseEncode) { this.name = name; this.prefix = prefix; this.baseEncode = baseEncode; } /** * @param {Uint8Array} bytes * @returns {API.Multibase<Prefix>} */ encode (bytes) { if (bytes instanceof Uint8Array) { return `${this.prefix}${this.baseEncode(bytes)}` } else { throw Error('Unknown type, must be binary type') } } }; /** * @template {string} Prefix */ /** * Class represents both BaseDecoder and MultibaseDecoder so it could be used * to decode multibases (with matching prefix) or just base decode strings * with corresponding base encoding. * * @class * @template {string} Base * @template {string} Prefix * @implements {API.MultibaseDecoder<Prefix>} * @implements {API.UnibaseDecoder<Prefix>} * @implements {API.BaseDecoder} */ let Decoder$1 = class Decoder { /** * @param {Base} name * @param {Prefix} prefix * @param {(text:string) => Uint8Array} baseDecode */ constructor (name, prefix, baseDecode) { this.name = name; this.prefix = prefix; /* c8 ignore next 3 */ if (prefix.codePointAt(0) === undefined) { throw new Error('Invalid prefix character') } /** @private */ this.prefixCodePoint = /** @type {number} */ (prefix.codePointAt(0)); this.baseDecode = baseDecode; } /** * @param {string} text */ decode (text) { if (typeof text === 'string') { if (text.codePointAt(0) !== this.prefixCodePoint) { throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`) } return this.baseDecode(text.slice(this.prefix.length)) } else { throw Error('Can only multibase decode strings') } } /** * @template {string} OtherPrefix * @param {API.UnibaseDecoder<OtherPrefix>|ComposedDecoder<OtherPrefix>} decoder * @returns {ComposedDecoder<Prefix|OtherPrefix>} */ or (decoder) { return or$1(this, decoder) } }; /** * @template {string} Prefix * @typedef {Record<Prefix, API.UnibaseDecoder<Prefix>>} Decoders */ /** * @template {string} Prefix * @implements {API.MultibaseDecoder<Prefix>} * @implements {API.CombobaseDecoder<Prefix>} */ let ComposedDecoder$1 = class ComposedDecoder { /** * @param {Decoders<Prefix>} decoders */ constructor (decoders) { this.decoders = decoders; } /** * @template {string} OtherPrefix * @param {API.UnibaseDecoder<OtherPrefix>|ComposedDecoder<OtherPrefix>} decoder * @returns {ComposedDecoder<Prefix|OtherPrefix>} */ or (decoder) { return or$1(this, decoder) } /** * @param {string} input * @returns {Uint8Array} */ decode (input) { const prefix = /** @type {Prefix} */ (input[0]); const decoder = this.decoders[prefix]; if (decoder) { return decoder.decode(input) } else { throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`) } } }; /** * @template {string} L * @template {string} R * @param {API.UnibaseDecoder<L>|API.CombobaseDecoder<L>} left * @param {API.UnibaseDecoder<R>|API.CombobaseDecoder<R>} right * @returns {ComposedDecoder<L|R>} */ const or$1 = (left, right) => new ComposedDecoder$1(/** @type {Decoders<L|R>} */({ ...(left.decoders || { [/** @type API.UnibaseDecoder<L> */(left).prefix]: left }), ...(right.decoders || { [/** @type API.UnibaseDecoder<R> */(right).prefix]: right }) })); /** * @class * @template {string} Base * @template {string} Prefix * @implements {API.MultibaseCodec<Prefix>} * @implements {API.MultibaseEncoder<Prefix>} * @implements {API.MultibaseDecoder<Prefix>} * @implements {API.BaseCodec} * @implements {API.BaseEncoder} * @implements {API.BaseDecoder} */ let Codec$1 = class Codec { /** * @param {Base} name * @param {Prefix} prefix * @param {(bytes:Uint8Array) => string} baseEncode * @param {(text:string) => Uint8Array} baseDecode */ constructor (name, prefix, baseEncode, baseDecode) { this.name = name; this.prefix = prefix; this.baseEncode = baseEncode; this.baseDecode = baseDecode; this.encoder = new Encoder$1(name, prefix, baseEncode); this.decoder = new Decoder$1(name, prefix, baseDecode); } /** * @param {Uint8Array} input */ encode (input) { return this.encoder.encode(input) } /** * @param {string} input */ decode (input) { return this.decoder.decode(input) } }; /** * @template {string} Base * @template {string} Prefix * @param {object} options * @param {Base} options.name * @param {Prefix} options.prefix * @param {(bytes:Uint8Array) => string} options.encode * @param {(input:string) => Uint8Array} options.decode * @returns {Codec<Base, Prefix>} */ const from$4 = ({ name, prefix, encode, decode }) => new Codec$1(name, prefix, encode, decode); /** * @template {string} Base * @template {string} Prefix * @param {object} options * @param {Base} options.name * @param {Prefix} options.prefix * @param {string} options.alphabet * @returns {Codec<Base, Prefix>} */ const baseX$1 = ({ prefix, name, alphabet }) => { const { encode, decode } = _brrp__multiformats_scope_baseX$1(alphabet, name); return from$4({ prefix, name, encode, /** * @param {string} text */ decode: text => coerce$1(decode(text)) }) }; /** * @param {string} string * @param {string} alphabet * @param {number} bitsPerChar * @param {string} name * @returns {Uint8Array} */ const decode$b = (string, alphabet, bitsPerChar, name) => { // Build the character lookup table: /** @type {Record<string, number>} */ const codes = {}; for (let i = 0; i < alphabet.length; ++i) { codes[alphabet[i]] = i; } // Count the padding bytes: let end = string.length; while (string[end - 1] === '=') { --end; } // Allocate the output: const out = new Uint8Array((end * bitsPerChar / 8) | 0); // Parse the data: let bits = 0; // Number of bits currently in the buffer let buffer = 0; // Bits waiting to be written out, MSB first let written = 0; // Next byte to write for (let i = 0; i < end; ++i) { // Read one character from the string: const value = codes[string[i]]; if (value === undefined) { throw new SyntaxError(`Non-${name} character`) } // Append the bits to the buffer: buffer = (buffer << bitsPerChar) | value; bits += bitsPerChar; // Write out some bits if the buffer has a byte's worth: if (bits >= 8) { bits -= 8; out[written++] = 0xff & (buffer >> bits); } } // Verify that we have received just enough bits: if (bits >= bitsPerChar || 0xff & (buffer << (8 - bits))) { throw new SyntaxError('Unexpected end of data') } return out }; /** * @param {Uint8Array} data * @param {string} alphabet * @param {number} bitsPerChar * @returns {string} */ const encode$9 = (data, alphabet, bitsPerChar) => { const pad = alphabet[alphabet.length - 1] === '='; const mask = (1 << bitsPerChar) - 1; let out = ''; let bits = 0; // Number of bits currently in the buffer let buffer = 0; // Bits waiting to be written out, MSB first for (let i = 0; i < data.length; ++i) { // Slurp data into the buffer: buffer = (buffer << 8) | data[i]; bits += 8; // Write out as much as we can: while (bits > bitsPerChar) { bits -= bitsPerChar; out += alphabet[mask & (buffer >> bits)]; } } // Partial character: if (bits) { out += alphabet[mask & (buffer << (bitsPerChar - bits))]; } // Add padding characters until we hit a byte boundary: if (pad) { while ((out.length * bitsPerChar) & 7) { out += '='; } } return out }; /** * RFC4648 Factory * * @template {string} Base * @template {string} Prefix * @param {object} options * @param {Base} options.name * @param {Prefix} options.prefix * @param {string} options.alphabet * @param {number} options.bitsPerChar */ const rfc4648$1 = ({ name, prefix, bitsPerChar, alphabet }) => { return from$4({ prefix, name, encode (input) { return encode$9(input, alphabet, bitsPerChar) }, decode (input) { return decode$b(input, alphabet, bitsPerChar, name) } }) }; const base58btc$1 = baseX$1({ name: 'base58btc', prefix: 'z', alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' }); baseX$1({ name: 'base58flickr', prefix: 'Z', alphabet: '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' }); const base32$1 = rfc4648$1({ prefix: 'b', name: 'base32', alphabet: 'abcdefghijklmnopqrstuvwxyz234567', bitsPerChar: 5 }); rfc4648$1({ prefix: 'B', name: 'base32upper', alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', bitsPerChar: 5 }); rfc4648$1({ prefix: 'c', name: 'base32pad', alphabet: 'abcdefghijklmnopqrstuvwxyz234567=', bitsPerChar: 5 }); rfc4648$1({ prefix: 'C', name: 'base32padupper', alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=', bitsPerChar: 5 }); rfc4648$1({ prefix: 'v', name: 'base32hex', alphabet: '0123456789abcdefghijklmnopqrstuv', bitsPerChar: 5 }); rfc4648$1({ prefix: 'V', name: 'base32hexupper', alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV', bitsPerChar: 5 }); rfc4648$1({ prefix: 't', name: 'base32hexpad', alphabet: '0123456789abcdefghijklmnopqrstuv=', bitsPerChar: 5 }); rfc4648$1({ prefix: 'T', name: 'base32hexpadupper', alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV=', bitsPerChar: 5 }); rfc4648$1({ prefix: 'h', name: 'base32z', alphabet: 'ybndrfg8ejkmcpqxot1uwisza345h769', bitsPerChar: 5 }); /** * @template {API.Link<unknown, number, number, API.Version>} T * @template {string} Prefix * @param {T} link * @param {API.MultibaseEncoder<Prefix>} [base] * @returns {API.ToString<T, Prefix>} */ const format$2 = (link, base) => { const { bytes, version } = link; switch (version) { case 0: return toStringV0$1( bytes, baseCache$1(link), /** @type {API.MultibaseEncoder<"z">} */ (base) || base58btc$1.encoder ) default: return toStringV1$1( bytes, baseCache$1(link), /** @type {API.MultibaseEncoder<Prefix>} */ (base || base32$1.encoder) ) } }; /** @type {WeakMap<API.UnknownLink, Map<string, string>>} */ const cache$1 = new WeakMap(); /** * @param {API.UnknownLink} cid * @returns {Map<string, string>} */ const baseCache$1 = cid => { const baseCache = cache$1.get(cid); if (baseCache == null) { const baseCache = new Map(); cache$1.set(cid, baseCache); return baseCache } return baseCache }; /** * @template {unknown} [Data=unknown] * @template {number} [Format=number] * @template {number} [Alg=number] * @template {API.Version} [Version=API.Version] * @implements {API.Link<Data, Format, Alg, Version>} */ let CID$1 = class CID { /** * @param {Version} version - Version of the CID * @param {Format} code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv * @param {API.MultihashDigest<Alg>} multihash - (Multi)hash of the of the content. * @param {Uint8Array} bytes * */ constructor (version, code, multihash, bytes) { /** @readonly */ this.code = code; /** @readonly */ this.version = version; /** @readonly */ this.multihash = multihash; /** @readonly */ this.bytes = bytes; // flag to serializers that this is a CID and // should be treated specially /** @readonly */ this['/'] = bytes; } /** * Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes` * please either use `CID.asCID(cid)` or switch to new signalling mechanism * * @deprecated */ get asCID () { return this } // ArrayBufferView get byteOffset () { return this.bytes.byteOffset } // ArrayBufferView get byteLength () { return this.bytes.byteLength } /** * @returns {CID<Data, API.DAG_PB, API.SHA_256, 0>} */ toV0 () { switch (this.version) { case 0: { return /** @type {CID<Data, API.DAG_PB, API.SHA_256, 0>} */ (this) } case 1: { const { code, multihash } = this; if (code !== DAG_PB_CODE$1) { throw new Error('Cannot convert a non dag-pb CID to CIDv0') } // sha2-256 if (multihash.code !== SHA_256_CODE$1) { throw new Error('Cannot convert non sha2-256 multihash CID to CIDv0') } return /** @type {CID<Data, API.DAG_PB, API.SHA_256, 0>} */ ( CID.createV0( /** @type {API.MultihashDigest<API.SHA_256>} */ (multihash) ) ) } default: { throw Error( `Can not convert CID version ${this.version} to version 0. This is a bug please report` ) } } } /** * @returns {CID<Data, Format, Alg, 1>} */ toV1 () { switch (this.version) { case 0: { const { code, digest } = this.multihash; const multihash = create$6(code, digest); return /** @type {CID<Data, Format, Alg, 1>} */ ( CID.createV1(this.code, multihash) ) } case 1: { return /** @type {CID<Data, Format, Alg, 1>} */ (this) } default: { throw Error( `Can not convert CID version ${this.version} to version 1. This is a bug please report` ) } } } /** * @param {unknown} other * @returns {other is CID<Data, Format, Alg, Version>} */ equals (other) { return CID.equals(this, other) } /** * @template {unknown} Data * @template {number} Format * @template {number} Alg * @template {API.Version} Version * @param {API.Link<Data, Format, Alg, Version>} self * @param {unknown} other * @returns {other is CID} */ static equals (self, other) { const unknown = /** @type {{code?:unknown, version?:unknown, multihash?:unknown}} */ ( other ); return ( unknown && self.code === unknown.code && self.version === unknown.version && equals$2(self.multihash, unknown.multihash) ) } /** * @param {API.MultibaseEncoder<string>} [base] * @returns {string} */ toString (base) { return format$2(this, base) } toJSON () { return { '/': format$2(this) } } link () { return this } get [Symbol.toStringTag] () { return 'CID' } // Legacy [Symbol.for('nodejs.util.inspect.custom')] () { return `CID(${this.toString()})` } /** * Takes any input `value` and returns a `CID` instance if it was * a `CID` otherwise returns `null`. If `value` is instanceof `CID` * it will return value back. If `value` is not instance of this CID * class, but is compatible CID it will return new instance of this * `CID` class. Otherwise returns null. * * This allows two different incompatible versions of CID library to * co-exist and interop as long as binary interface is compatible. * * @template {unknown} Data * @template {number} Format * @template {number} Alg * @template {API.Version} Version * @template {unknown} U * @param {API.Link<Data, Format, Alg, Version>|U} input * @returns {CID<Data, Format, Alg, Version>|null} */ static asCID (input) { if (input == null) { return null } const value = /** @type {any} */ (input); if (value instanceof CID) { // If value is instance of CID then we're all set. return value } else if ((value['/'] != null && value['/'] === value.bytes) || value.asCID === value) { // If value isn't instance of this CID class but `this.asCID === this` or // `value['/'] === value.bytes` is true it is CID instance coming from a // different implementation (diff version or duplicate). In that case we // rebase it to this `CID` implementation so caller is guaranteed to get // instance with expected API. const { version, code, multihash, bytes } = value; return new CID( version, code, /** @type {API.MultihashDigest<Alg>} */ (multihash), bytes || encodeCID$1(version, code, multihash.bytes) ) } else if (value[cidSymbol$1] === true) { // If value is a CID from older implementation that used to be tagged via // symbol we still rebase it to the this `CID` implementation by // delegating that to a constructor. const { version, multihash, code } = value; const digest = /** @type {API.MultihashDigest<Alg>} */ (decode$c(multihash)); return CID.create(version, code, digest) } else { // Otherwise value is not a CID (or an incompatible version of it) in // which case we return `null`. return null } } /** * * @template {unknown} Data * @template {number} Format * @template {number} Alg * @template {API.Version} Version * @param {Version} version - Version of the CID * @param {Format} code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv * @param {API.MultihashDigest<Alg>} digest - (Multi)hash of the of the content. * @returns {CID<Data, Format, Alg, Version>} */ static create (version, code, digest) { if (typeof code !== 'number') { throw new Error('String codecs are no longer supported') } if (!(digest.bytes instanceof Uint8Array)) { throw new Error('Invalid digest') } switch (version) { case 0: { if (code !== DAG_PB_CODE$1) { throw new Error( `Version 0 CID must use dag-pb (code: ${DAG_PB_CODE$1}) block encoding` ) } else { return new CID(version, code, digest, digest.bytes) } } case 1: { const bytes = encodeCID$1(version, code, digest.bytes); return new CID(version, code, digest, bytes) } default: { throw new Error('Invalid version') } } } /** * Simplified version of `create` for CIDv0. * * @template {unknown} [T=unknown] * @param {API.MultihashDigest<typeof SHA_256_CODE>} digest - Multihash. * @returns {CID<T, typeof DAG_PB_CODE, typeof SHA_256_CODE, 0>} */ static createV0 (digest) { return CID.create(0, DAG_PB_CODE$1, digest) } /** * Simplified version of `create` for CIDv1. * * @template {unknown} Data * @template {number} Code * @template {number} Alg * @param {Code} code - Content encoding format code. * @param {API.MultihashDigest<Alg>} digest - Miltihash of the content. * @returns {CID<Data, Code, Alg, 1>} */ static createV1 (code, digest) { return CID.create(1, code, digest) } /** * Decoded a CID from its binary representation. The byte array must contain * only the CID with no additional bytes. * * An error will be thrown if the bytes provided do not contain a valid * binary representation of a CID. * * @template {unknown} Data * @template {number} Code * @template {number} Alg * @template {API.Version} Ver * @param {API.ByteView<API.Link<Data, Code, Alg, Ver>>} bytes * @returns {CID<Data, Code, Alg, Ver>} */ static decode (bytes) { const [cid, remainder] = CID.decodeFirst(bytes); if (remainder.length) { throw new Error('Incorrect length') } return cid } /** * Decoded a CID from its binary representation at the beginning of a byte * array. * * Returns an array with the first element containing the CID and the second * element containing the remainder of the original byte array. The remainder * will be a zero-length byte array if the provided bytes only contained a * binary CID representation. * * @template {unknown} T * @template {number} C * @template {number} A * @template {API.Version} V * @param {API.ByteView<API.Link<T, C, A, V>>} bytes * @returns {[CID<T, C, A, V>, Uint8Array]} */ static decodeFirst (bytes) { const specs = CID.inspectBytes(bytes); const prefixSize = specs.size - specs.multihashSize; const multihashBytes = coerce$1( bytes.subarray(prefixSize, prefixSize + specs.multihashSize) ); if (multihashBytes.byteLength !== specs.multihashSize) { throw new Error('Incorrect length') } const digestBytes = multihashBytes.subarray( specs.multihashSize - specs.digestSize ); const digest = new Digest$1( specs.multihashCode, specs.digestSize, digestBytes, multihashBytes ); const cid = specs.version === 0 ? CID.createV0(/** @type {API.MultihashDigest<API.SHA_256>} */ (digest)) : CID.createV1(specs.codec, digest); return [/** @type {CID<T, C, A, V>} */(cid), bytes.subarray(specs.size)] } /** * Inspect the initial bytes of a CID to determine its properties. * * Involves decoding up to 4 varints. Typically this will require only 4 to 6 * bytes but for larger multicodec code values and larger multihash digest * lengths these varints can be quite large. It is recommended that at least * 10 bytes be made available in the `initialBytes` argument for a complete * inspection. * * @template {unknown} T * @template {number} C * @template {number} A * @template {API.Version} V * @param {API.ByteView<API.Link<T, C, A, V>>} initialBytes * @returns {{ version:V, codec:C, multihashCode:A, digestSize:number, multihashSize:number, size:number }} */ static inspectBytes (initialBytes) { let offset = 0; const next = () => { const [i, length] = decode$d(initialBytes.subarray(offset)); offset += length; return i }; let version = /** @type {V} */ (next()); let codec = /** @type {C} */ (DAG_PB_CODE$1); if (/** @type {number} */(version) === 18) { // CIDv0 version = /** @type {V} */ (0); offset = 0; } else { codec = /** @type {C} */ (next()); } if (version !== 0 && version !== 1) { throw new RangeError(`Invalid CID version ${version}`) } const prefixSize = offset; const multihashCode = /** @type {A} */ (next()); // multihash code const digestSize = next(); // multihash length const size = offset + digestSize; const multihashSize = size - prefixSize; return { version, codec, multihashCode, digestSize, multihashSize, size } } /** * Takes cid in a string representation and creates an instance. If `base` * decoder is not provided will use a default from the configuration. It will * throw an error if encoding of the CID is not compatible with supplied (or * a default decoder). * * @template {string} Prefix * @template {unknown} Data * @template {number} Code * @template {number} Alg * @template {API.Version} Ver * @param {API.ToString<API.Link<Data, Code, Alg, Ver>, Prefix>} source * @param {API.MultibaseDecoder<Prefix>} [base] * @returns {CID<Data, Code, Alg, Ver>} */ static parse (source, base) { const [prefix, bytes] = parseCIDtoBytes$1(source, base); const cid = CID.decode(bytes); if (cid.version === 0 && source[0] !== 'Q') { throw Error('Version 0 CID string must not include multibase prefix') } // Cache string representation to avoid computing it on `this.toString()` baseCache$1(cid).set(prefix, source); return cid } }; /** * @template {string} Prefix * @template {unknown} Data * @template {number} Code * @template {number} Alg * @template {API.Version} Ver * @param {API.ToString<API.Link<Data, Code, Alg, Ver>, Prefix>} source * @param {API.MultibaseDecoder<Prefix>} [base] * @returns {[Prefix, API.ByteView<API.Link<Data, Code, Alg, Ver>>]} */ const parseCIDtoBytes$1 = (source, base) => { switch (source[0]) { // CIDv0 is parsed differently case 'Q': { const decoder = base || base58btc$1; return [ /** @type {Prefix} */ (base58btc$1.prefix), decoder.decode(`${base58btc$1.prefix}${source}`) ] } case base58btc$1.prefix: { const decoder = base || base58btc$1; return [/** @type {Prefix} */(base58btc$1.prefix), decoder.decode(source)] } case base32$1.prefix: { const decoder = base || base32$1; return [/** @type {Prefix} */(base32$1.prefix), decoder.decode(source)] } default: { if (base == null) { throw Error( 'To parse non base32 or base58btc encoded CID multibase decoder must be provided' ) } return [/** @type {Prefix} */(source[0]), base.decode(source)] } } }; /** * * @param {Uint8Array} bytes * @param {Map<string, string>} cache * @param {API.MultibaseEncoder<'z'>} base */ const toStringV0$1 = (bytes, cache, base) => { const { prefix } = base; if (prefix !== base58btc$1.prefix) { throw Error(`Cannot string encode V0 in ${base.name} encoding`) } const cid = cache.get(prefix); if (cid == null) { const cid = base.encode(bytes).slice(1); cache.set(prefix, cid); return cid } else { return cid } }; /** * @template {string} Prefix * @param {Uint8Array} bytes * @param {Map<string, string>} cache * @param {API.MultibaseEncoder<Prefix>} base */ const toStringV1$1 = (bytes, cache, base) => { const { prefix } = base; const cid = cache.get(prefix); if (cid == null) { const cid = base.encode(bytes); cache.set(prefix, cid); return cid } else { return cid } }; const DAG_PB_CODE$1 = 0x70; const SHA_256_CODE$1 = 0x12; /** * @param {API.Version} version * @param {number} code * @param {Uint8Array} multihash * @returns {Uint8Array} */ const encodeCID$1 = (version, code, multihash) => { const codeOffset = encodingLength$1(version); const hashOffset = codeOffset + encodingLength$1(code); const bytes = new Uint8Array(hashOffset + multihash.byteLength); encodeTo$1(version, bytes, 0); encodeTo$1(code, bytes, codeOffset); bytes.set(multihash, hashOffset); return bytes }; const cidSymbol$1 = Symbol.for('@ipld/js-cid/CID'); // Linter can see that API is used in types. /** * Takes cid in a string representation and creates an instance. If `base` * decoder is not provided will use a default from the configuration. It will * throw an error if encoding of the CID is not compatible with supplied (or * a default decoder). * * @template {string} Prefix * @template {unknown} Data * @template {number} Code * @template {number} Alg * @template {API.Version} Ver * @param {API.ToString<API.Link<Data, Code, Alg, Ver>, Prefix>} source * @param {API.MultibaseDecoder<Prefix>} [base] * @returns {API.Link<Data, Code, Alg, Ver>} */ const parse = (source, base) => CID$1.parse(source, base); /** * @typedef {{ cid: import('./link').AnyLink, bytes: Uint8Array }} AnyBlock * @typedef {{ get: (link: import('./link').AnyLink) => Promise<AnyBlock | undefined> }} BlockFetcher */ /** @implements {BlockFetcher} */ class MemoryBlockstore { /** @type {Map<string, Uint8Array>} */ #blocks = new Map() /** * @param {Array<AnyBlock>} [blocks] */ constructor (blocks) { if (blocks) { this.#blocks = new Map(blocks.map(b => [b.cid.toString(), b.bytes])); } } /** * @param {import('./link').AnyLink} cid * @returns {Promise<AnyBlock | undefined>} */ async get (cid) { const bytes = this.#blocks.get(cid.toString()); if (!bytes) return return { cid, bytes } } /** * @param {import('./link').AnyLink} cid * @param {Uint8Array} bytes */ async put (cid, bytes) { this.#blocks.set(cid.toString(), bytes); } /** * @param {import('./link').AnyLink} cid * @param {Uint8Array} bytes */ putSync (cid, bytes) { this.#blocks.set(cid.toString(), bytes); } /** @param {import('./link').AnyLink} cid */ async delete (cid) { this.#blocks.delete(cid.toString()); } /** @param {import('./link').AnyLink} cid */ deleteSync (cid) { this.#blocks.delete(cid.toString()); } * entries () { for (const [str, bytes] of this.#blocks) { yield { cid: parse(str), bytes }; } } } class MultiBlockFetcher { /** @type {BlockFetcher[]} */ #fetchers /** @param {BlockFetcher[]} fetchers */ constructor (...fetchers) { this.#fetchers = fetchers; } /** @param {import('./link').AnyLink} link */ async get (link) { for (const f of this.#fetchers) { const v = await f.get(link); if (v) return v } } } const typeofs$1 = [ 'string', 'number', 'bigint', 'symbol' ]; const objectTypeNames$1 = [ 'Function', 'Generator', 'AsyncGenerator', 'GeneratorFunction', 'AsyncGeneratorFunction', 'AsyncFunction', 'Observable', 'Array', 'Buffer', 'Object', 'RegExp', 'Date', 'Error', 'Map', 'Set', 'WeakMap', 'WeakSet', 'ArrayBuffer', 'SharedArrayBuffer', 'DataView', 'Promise', 'URL', 'HTMLElement', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array', 'Float64Array', 'BigInt64Array', 'BigUint64Array' ]; function is$1(value) { if (value === null) { return 'null'; } if (value === undefined) { return 'undefined'; } if (value === true || value === false) { return 'boolean'; } const typeOf = typeof value; if (typeofs$1.includes(typeOf)) { return typeOf; } if (typeOf === 'function') { return 'Function'; } if (Array.isArray(value)) { return 'Array'; } if (isBuffer$5(value)) { return 'Buffer'; } const objectType = getObjectType$1(value); if (objectType) { return objectType; } return 'Object'; } function isBuffer$5(value) { return value && value.constructor && value.constructor.isBuffer && value.constructor.isBuffer.call(null, value); } function getObjectType$1(value) { const objectTypeName = Object.prototype.toString.call(value).slice(8, -1); if (objectTypeNames$1.includes(objectTypeName)) { return objectTypeName; } return undefined; } let Type$1 = class Type { constructor(major, name, terminal) { this.major = major; this.majorEncoded = major << 5; this.name = name; this.terminal = terminal; } toString() { return `Type[${ this.major }].${ this.name }`; } compare(typ) { return this.major < typ.major ? -1 : this.major > typ.major ? 1 : 0; } }; Type$1.uint = new Type$1(0, 'uint', true); Type$1.negint = new Type$1(1, 'negint', true); Type$1.bytes = new Type$1(2, 'bytes', true); Type$1.string = new Type$1(3, 'string', true); Type$1.array = new Type$1(4, 'array', false); Type$1.map = new Type$1(5, 'map', false); Type$1.tag = new Type$1(6, 'tag', false); Type$1.float = new Type$1(7, 'float', true); Type$1.false = new Type$1(7, 'false', true); Type$1.true = new Type$1(7, 'true', true); Type$1.null = new Type$1(7, 'null', true); Type$1.undefined = new Type$1(7, 'undefined', true); Type$1.break = new Type$1(7, 'break', true); let Token$1 = class Token { constructor(type, value, encodedLength) { this.type = type; this.value = value; this.encodedLength = encodedLength; this.encodedBytes = undefined; this.byteValue = undefined; } toString() { return `Token[${ this.type }].${ this.value }`; } }; const useBuffer$1 = globalThis.process && !globalThis.process.browser && globalThis.Buffer && typeof globalThis.Buffer.isBuffer === 'function'; const textDecoder = new TextDecoder(); const textEncoder$1 = new TextEncoder(); function isBuffer$4(buf) { return useBuffer$1 && globalThis.Buffer.isBuffer(buf); } function asU8A(buf) { if (!(buf instanceof Uint8Array)) { return Uint8Array.from(buf); } return isBuffer$4(buf) ? new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength) : buf; } const toString$1 = useBuffer$1 ? (bytes, start, end) => { return end - start > 64 ? globalThis.Buffer.from(bytes.subarray(start, end)).toString('utf8') : utf8Slice$1(bytes, start, end); } : (bytes, start, end) => { return end - start > 64 ? textDecoder.decode(bytes.subarray(start, end)) : utf8Slice$1(bytes, start, end); }; const fromString$2 = useBuffer$1 ? string => { return string.length > 64 ? globalThis.Buffer.from(string) : utf8ToBytes$2(string); } : string => { return string.length > 64 ? textEncoder$1.encode(string) : utf8ToBytes$2(string); }; const fromArray$2 = arr => { return Uint8Array.from(arr); }; const slice = useBuffer$1 ? (bytes, start, end) => { if (isBuffer$4(bytes)) { return new Uint8Array(bytes.subarray(start, end)); } return bytes.slice(start, end); } : (bytes, start, end) => { return bytes.slice(start, end); }; const concat$2 = useBuffer$1 ? (chunks, length) => { chunks = chunks.map(c => c instanceof Uint8Array ? c : globalThis.Buffer.from(c)); return asU8A(globalThis.Buffer.concat(chunks, length)); } : (chunks, length) => { const out = new Uint8Array(length); let off = 0; for (let b of chunks) { if (off + b.length > out.length) { b = b.subarray(0, out.length - off); } out.set(b, off); off += b.length; } return out; }; const alloc$1 = useBuffer$1 ? size => { return globalThis.Buffer.allocUnsafe(size); } : size => { return new Uint8Array(size); }; function compare$5(b1, b2) { if (isBuffer$4(b1) && isBuffer$4(b2)) { return b1.compare(b2); } for (let i = 0; i < b1.length; i++) { if (b1[i] === b2[i]) { continue; } return b1[i] < b2[i] ? -1 : 1; } return 0; } function utf8ToBytes$2(string, units = Infinity) { let codePoint; const length = string.length; let leadSurrogate = null; const bytes = []; for (let i = 0; i < length; ++i) { codePoint = string.charCodeAt(i); if (codePoint > 55295 && codePoint < 57344) { if (!leadSurrogate) { if (codePoint > 56319) { if ((units -= 3) > -1) bytes.push(239, 191, 189); continue; } else if (i + 1 === length) { if ((units -= 3) > -1) bytes.push(239, 191, 189); continue; } leadSurrogate = codePoint; continue; } if (codePoint < 56320) { if ((units -= 3) > -1) bytes.push(239, 191, 189); leadSurrogate = codePoint; continue; } codePoint = (leadSurrogate - 55296 << 10 | codePoint - 56320) + 65536; } else if (leadSurrogate) { if ((units -= 3) > -1) bytes.push(239, 191, 189); } leadSurrogate = null; if (codePoint < 128) { if ((units -= 1) < 0) break; bytes.push(codePoint); } else if (codePoint < 2048) { if ((units -= 2) < 0) break; bytes.push(codePoint >> 6 | 192, codePoint & 63 | 128); } else if (codePoint < 65536) { if ((units -= 3) < 0) break; bytes.push(codePoint >> 12 | 224, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); } else if (codePoint < 1114112) { if ((units -= 4) < 0) break; bytes.push(codePoint >> 18 | 240, codePoint >> 12 & 63 | 128, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); } else { throw new Error('Invalid code point'); } } return bytes; } function utf8Slice$1(buf, offset, end) { const res = []; while (offset < end) { const firstByte = buf[offset]; let codePoint = null; let bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1; if (offset + bytesPerSequence <= end) { let secondByte, thirdByte, fourthByte, tempCodePoint; switch (bytesPerSequence) { case 1: if (firstByte < 128) { codePoint = firstByte; } break; case 2: secondByte = buf[offset + 1]; if ((secondByte & 192) === 128) { tempCodePoint = (firstByte & 31) << 6 | secondByte & 63; if (tempCodePoint > 127) { codePoint = tempCodePoint; } } break; case 3: secondByte = buf[offset + 1]; thirdByte = buf[offset + 2]; if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) { tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63; if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) { codePoint = tempCodePoint; } } break; case 4: secondByte = buf[offset + 1]; thirdByte = buf[offset + 2]; fourthByte = buf[offset + 3]; if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) { tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63; if (tempCodePoint > 65535 && tempCodePoint < 1114112) { codePoint = tempCodePoint; } } } } if (codePoint === null) { codePoint = 65533; bytesPerSequence = 1; } else if (codePoint > 65535) { codePoint -= 65536; res.push(codePoint >>> 10 & 1023 | 55296); codePoint = 56320 | codePoint & 1023; } res.push(codePoint); offset += bytesPerSequence; } return decodeCodePointsArray$1(res); } const MAX_ARGUMENTS_LENGTH$1 = 4096; function decodeCodePointsArray$1(codePoints) { const len = codePoints.length; if (len <= MAX_ARGUMENTS_LENGTH$1) { return String.fromCharCode.apply(String, codePoints); } let res = ''; let i = 0; while (i < len) { res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH$1)); } return res; } const defaultChunkSize = 256; class Bl { constructor(chunkSize = defaultChunkSize) { this.chunkSize = chunkSize; this.cursor = 0; this.maxCursor = -1; this.chunks = []; this._initReuseChunk = null; } reset() { this.cursor = 0; this.maxCursor = -1; if (this.chunks.length) { this.chunks = []; } if (this._initReuseChunk !== null) { this.chunks.push(this._initReuseChunk); this.maxCursor = this._initReuseChunk.length - 1; } } push(bytes) { let topChunk = this.chunks[this.chunks.length - 1]; const newMax = this.cursor + bytes.length; if (newMax <= this.maxCursor + 1) { const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; topChunk.set(bytes, chunkPos); } else { if (topChunk) { const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1; if (chunkPos < topChunk.length) { this.chunks[this.chunks.length - 1] = topChunk.subarray(0, chunkPos); this.maxCursor = this.cursor - 1; } } if (bytes.length < 64 && bytes.length < this.chunkSize) { topChunk = alloc$1(this.chunkSize); this.chunks.push(topChunk); this.maxCursor += topChunk.length; if (this._initReuseChunk === null) { this._initReuseChunk = topChunk; } topChunk.set(bytes, 0); } else { this.chunks.push(bytes); this.maxCursor += bytes.length; } } this.cursor += bytes.length; } toBytes(reset = false) { let byts; if (this.chunks.length === 1) { const chunk = this.ch