diff --git a/.gitignore b/.gitignore index 7ad9e674..f115d26b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ node_modules package-lock.json yarn.lock .vscode +.tmp-compiled-docs +tsconfig-doc-check.aegir.json diff --git a/package.json b/package.json index 4ffb609f..732bf850 100644 --- a/package.json +++ b/package.json @@ -48,132 +48,155 @@ "exports": { ".": { "types": "./dist/src/index.d.ts", - "import": "./dist/src/index.js" + "import": "./dist/src/index.js", + "module-sync": "./dist/src/index.js" }, "./bases/base10": { "types": "./dist/src/bases/base10.d.ts", - "import": "./dist/src/bases/base10.js" + "import": "./dist/src/bases/base10.js", + "module-sync": "./dist/src/bases/base10.js" }, "./bases/base16": { "types": "./dist/src/bases/base16.d.ts", - "import": "./dist/src/bases/base16.js" + "import": "./dist/src/bases/base16.js", + "module-sync": "./dist/src/bases/base16.js" }, "./bases/base2": { "types": "./dist/src/bases/base2.d.ts", - "import": "./dist/src/bases/base2.js" + "import": "./dist/src/bases/base2.js", + "module-sync": "./dist/src/bases/base2.js" }, "./bases/base256emoji": { "types": "./dist/src/bases/base256emoji.d.ts", - "import": "./dist/src/bases/base256emoji.js" + "import": "./dist/src/bases/base256emoji.js", + "module-sync": "./dist/src/bases/base256emoji.js" }, "./bases/base32": { "types": "./dist/src/bases/base32.d.ts", - "import": "./dist/src/bases/base32.js" + "import": "./dist/src/bases/base32.js", + "module-sync": "./dist/src/bases/base32.js" }, "./bases/base36": { "types": "./dist/src/bases/base36.d.ts", - "import": "./dist/src/bases/base36.js" + "import": "./dist/src/bases/base36.js", + "module-sync": "./dist/src/bases/base36.js" }, "./bases/base58": { "types": "./dist/src/bases/base58.d.ts", - "import": "./dist/src/bases/base58.js" + "import": "./dist/src/bases/base58.js", + "module-sync": "./dist/src/bases/base58.js" }, "./bases/base64": { "types": "./dist/src/bases/base64.d.ts", - "import": "./dist/src/bases/base64.js" + "import": "./dist/src/bases/base64.js", + "module-sync": "./dist/src/bases/base64.js" }, "./bases/base8": { "types": "./dist/src/bases/base8.d.ts", - "import": "./dist/src/bases/base8.js" + "import": "./dist/src/bases/base8.js", + "module-sync": "./dist/src/bases/base8.js" }, "./bases/identity": { "types": "./dist/src/bases/identity.d.ts", - "import": "./dist/src/bases/identity.js" + "import": "./dist/src/bases/identity.js", + "module-sync": "./dist/src/bases/identity.js" }, "./bases/interface": { "types": "./dist/src/bases/interface.d.ts", - "import": "./dist/src/bases/interface.js" + "import": "./dist/src/bases/interface.js", + "module-sync": "./dist/src/bases/interface.js" }, "./basics": { "types": "./dist/src/basics.d.ts", - "import": "./dist/src/basics.js" + "import": "./dist/src/basics.js", + "module-sync": "./dist/src/basics.js" }, "./block": { "types": "./dist/src/block.d.ts", - "import": "./dist/src/block.js" + "import": "./dist/src/block.js", + "module-sync": "./dist/src/block.js" }, "./block/interface": { "types": "./dist/src/block/interface.d.ts", - "import": "./dist/src/block/interface.js" + "import": "./dist/src/block/interface.js", + "module-sync": "./dist/src/block/interface.js" }, "./bytes": { "types": "./dist/src/bytes.d.ts", - "import": "./dist/src/bytes.js" + "import": "./dist/src/bytes.js", + "module-sync": "./dist/src/bytes.js" }, "./cid": { "types": "./dist/src/cid.d.ts", - "import": "./dist/src/cid.js" + "import": "./dist/src/cid.js", + "module-sync": "./dist/src/cid.js" }, "./codecs/interface": { "types": "./dist/src/codecs/interface.d.ts", - "import": "./dist/src/codecs/interface.js" + "import": "./dist/src/codecs/interface.js", + "module-sync": "./dist/src/codecs/interface.js" }, "./codecs/json": { "types": "./dist/src/codecs/json.d.ts", - "import": "./dist/src/codecs/json.js" + "import": "./dist/src/codecs/json.js", + "module-sync": "./dist/src/codecs/json.js" }, "./codecs/raw": { "types": "./dist/src/codecs/raw.d.ts", - "import": "./dist/src/codecs/raw.js" + "import": "./dist/src/codecs/raw.js", + "module-sync": "./dist/src/codecs/raw.js" }, "./hashes/digest": { "types": "./dist/src/hashes/digest.d.ts", - "import": "./dist/src/hashes/digest.js" + "import": "./dist/src/hashes/digest.js", + "module-sync": "./dist/src/hashes/digest.js" }, "./hashes/hasher": { "types": "./dist/src/hashes/hasher.d.ts", - "import": "./dist/src/hashes/hasher.js" + "import": "./dist/src/hashes/hasher.js", + "module-sync": "./dist/src/hashes/hasher.js" }, "./hashes/identity": { "types": "./dist/src/hashes/identity.d.ts", - "import": "./dist/src/hashes/identity.js" + "import": "./dist/src/hashes/identity.js", + "module-sync": "./dist/src/hashes/identity.js" }, "./hashes/interface": { "types": "./dist/src/hashes/interface.d.ts", - "import": "./dist/src/hashes/interface.js" + "import": "./dist/src/hashes/interface.js", + "module-sync": "./dist/src/hashes/interface.js" }, "./hashes/sha1": { "types": "./dist/types/src/hashes/sha1.d.ts", "browser": "./dist/src/hashes/sha1-browser.js", - "import": "./dist/src/hashes/sha1.js" + "import": "./dist/src/hashes/sha1.js", + "module-sync": "./dist/src/hashes/sha1.js" }, "./hashes/sha2": { "types": "./dist/src/hashes/sha2.d.ts", "browser": "./dist/src/hashes/sha2-browser.js", - "import": "./dist/src/hashes/sha2.js" + "import": "./dist/src/hashes/sha2.js", + "module-sync": "./dist/src/hashes/sha2.js" }, "./interface": { "types": "./dist/src/interface.d.ts", - "import": "./dist/src/interface.js" + "import": "./dist/src/interface.js", + "module-sync": "./dist/src/interface.js" }, "./link": { "types": "./dist/src/link.d.ts", - "import": "./dist/src/link.js" + "import": "./dist/src/link.js", + "module-sync": "./dist/src/link.js" }, "./link/interface": { "types": "./dist/src/link/interface.d.ts", - "import": "./dist/src/link/interface.js" + "import": "./dist/src/link/interface.js", + "module-sync": "./dist/src/link/interface.js" }, "./traversal": { "types": "./dist/src/traversal.d.ts", - "import": "./dist/src/traversal.js" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" + "import": "./dist/src/traversal.js", + "module-sync": "./dist/src/traversal.js" } }, "release": { @@ -286,20 +309,11 @@ "devDependencies": { "@stablelib/sha256": "^2.0.0", "@stablelib/sha512": "^2.0.0", - "@types/node": "^25.0.0", - "aegir": "^47.0.7", + "aegir": "^48.0.1", "buffer": "^6.0.3", "cids": "^1.1.9", "crypto-hash": "^4.0.0" }, - "aegir": { - "test": { - "target": [ - "node", - "browser" - ] - } - }, "browser": { "./hashes/sha1": "./dist/src/hashes/sha1-browser.js", "./dist/src/hashes/sha1.js": "./dist/src/hashes/sha1-browser.js", diff --git a/src/bases/base.ts b/src/bases/base.ts index 12bea63b..afe6425c 100644 --- a/src/bases/base.ts +++ b/src/bases/base.ts @@ -1,9 +1,9 @@ -import { coerce } from '../bytes.js' +import { coerce } from '../bytes.ts' import basex from '../vendor/base-x.js' -import type { BaseCodec, BaseDecoder, BaseEncoder, CombobaseDecoder, Multibase, MultibaseCodec, MultibaseDecoder, MultibaseEncoder, UnibaseDecoder } from './interface.js' +import type { BaseCodec, BaseDecoder, BaseEncoder, CombobaseDecoder, Multibase, MultibaseCodec, MultibaseDecoder, MultibaseEncoder, UnibaseDecoder } from './interface.ts' interface EncodeFn { (bytes: Uint8Array): string } -interface DecodeFn { (text: string): Uint8Array } +interface DecodeFn { (text: string): Uint8Array } /** * Class represents both BaseEncoder and MultibaseEncoder meaning it @@ -53,7 +53,7 @@ class Decoder implements MultibaseDe this.baseDecode = baseDecode } - decode (text: string): Uint8Array { + decode (text: string): Uint8Array { 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}`) @@ -82,7 +82,7 @@ class ComposedDecoder implements MultibaseDecoder return or(this, decoder) } - decode (input: string): Uint8Array { + decode (input: string): Uint8Array { const prefix = input[0] as Prefix const decoder = this.decoders[prefix] if (decoder != null) { @@ -121,7 +121,7 @@ export class Codec implements Multib return this.encoder.encode(input) } - decode (input: string): Uint8Array { + decode (input: string): Uint8Array { return this.decoder.decode(input) } } @@ -136,11 +136,11 @@ export function baseX ({ name, pref prefix, name, encode, - decode: (text: string): Uint8Array => coerce(decode(text)) + decode: (text: string): Uint8Array => coerce(decode(text)) }) } -function decode (string: string, alphabetIdx: Record, bitsPerChar: number, name: string): Uint8Array { +function decode (string: string, alphabetIdx: Record, bitsPerChar: number, name: string): Uint8Array { // Count the padding bytes: let end = string.length while (string[end - 1] === '=') { @@ -234,7 +234,7 @@ export function rfc4648 ({ name, pr encode (input: Uint8Array): string { return encode(input, alphabet, bitsPerChar) }, - decode (input: string): Uint8Array { + decode (input: string): Uint8Array { return decode(input, alphabetIdx, bitsPerChar, name) } }) diff --git a/src/bases/base10.ts b/src/bases/base10.ts index fca32758..7b2941d1 100644 --- a/src/bases/base10.ts +++ b/src/bases/base10.ts @@ -1,4 +1,4 @@ -import { baseX } from './base.js' +import { baseX } from './base.ts' export const base10 = baseX({ prefix: '9', diff --git a/src/bases/base16.ts b/src/bases/base16.ts index 8e7b2380..4797518f 100644 --- a/src/bases/base16.ts +++ b/src/bases/base16.ts @@ -1,4 +1,4 @@ -import { rfc4648 } from './base.js' +import { rfc4648 } from './base.ts' export const base16 = rfc4648({ prefix: 'f', diff --git a/src/bases/base2.ts b/src/bases/base2.ts index 2ff4977d..427b2db2 100644 --- a/src/bases/base2.ts +++ b/src/bases/base2.ts @@ -1,4 +1,4 @@ -import { rfc4648 } from './base.js' +import { rfc4648 } from './base.ts' export const base2 = rfc4648({ prefix: '0', diff --git a/src/bases/base256emoji.ts b/src/bases/base256emoji.ts index 9950cb9d..962e3b64 100644 --- a/src/bases/base256emoji.ts +++ b/src/bases/base256emoji.ts @@ -1,4 +1,4 @@ -import { from } from './base.js' +import { from } from './base.ts' const alphabet = Array.from('๐Ÿš€๐Ÿชโ˜„๐Ÿ›ฐ๐ŸŒŒ๐ŸŒ‘๐ŸŒ’๐ŸŒ“๐ŸŒ”๐ŸŒ•๐ŸŒ–๐ŸŒ—๐ŸŒ˜๐ŸŒ๐ŸŒ๐ŸŒŽ๐Ÿ‰โ˜€๐Ÿ’ป๐Ÿ–ฅ๐Ÿ’พ๐Ÿ’ฟ๐Ÿ˜‚โค๐Ÿ˜๐Ÿคฃ๐Ÿ˜Š๐Ÿ™๐Ÿ’•๐Ÿ˜ญ๐Ÿ˜˜๐Ÿ‘๐Ÿ˜…๐Ÿ‘๐Ÿ˜๐Ÿ”ฅ๐Ÿฅฐ๐Ÿ’”๐Ÿ’–๐Ÿ’™๐Ÿ˜ข๐Ÿค”๐Ÿ˜†๐Ÿ™„๐Ÿ’ช๐Ÿ˜‰โ˜บ๐Ÿ‘Œ๐Ÿค—๐Ÿ’œ๐Ÿ˜”๐Ÿ˜Ž๐Ÿ˜‡๐ŸŒน๐Ÿคฆ๐ŸŽ‰๐Ÿ’žโœŒโœจ๐Ÿคท๐Ÿ˜ฑ๐Ÿ˜Œ๐ŸŒธ๐Ÿ™Œ๐Ÿ˜‹๐Ÿ’—๐Ÿ’š๐Ÿ˜๐Ÿ’›๐Ÿ™‚๐Ÿ’“๐Ÿคฉ๐Ÿ˜„๐Ÿ˜€๐Ÿ–ค๐Ÿ˜ƒ๐Ÿ’ฏ๐Ÿ™ˆ๐Ÿ‘‡๐ŸŽถ๐Ÿ˜’๐Ÿคญโฃ๐Ÿ˜œ๐Ÿ’‹๐Ÿ‘€๐Ÿ˜ช๐Ÿ˜‘๐Ÿ’ฅ๐Ÿ™‹๐Ÿ˜ž๐Ÿ˜ฉ๐Ÿ˜ก๐Ÿคช๐Ÿ‘Š๐Ÿฅณ๐Ÿ˜ฅ๐Ÿคค๐Ÿ‘‰๐Ÿ’ƒ๐Ÿ˜ณโœ‹๐Ÿ˜š๐Ÿ˜๐Ÿ˜ด๐ŸŒŸ๐Ÿ˜ฌ๐Ÿ™ƒ๐Ÿ€๐ŸŒท๐Ÿ˜ป๐Ÿ˜“โญโœ…๐Ÿฅบ๐ŸŒˆ๐Ÿ˜ˆ๐Ÿค˜๐Ÿ’ฆโœ”๐Ÿ˜ฃ๐Ÿƒ๐Ÿ’โ˜น๐ŸŽŠ๐Ÿ’˜๐Ÿ˜ โ˜๐Ÿ˜•๐ŸŒบ๐ŸŽ‚๐ŸŒป๐Ÿ˜๐Ÿ–•๐Ÿ’๐Ÿ™Š๐Ÿ˜น๐Ÿ—ฃ๐Ÿ’ซ๐Ÿ’€๐Ÿ‘‘๐ŸŽต๐Ÿคž๐Ÿ˜›๐Ÿ”ด๐Ÿ˜ค๐ŸŒผ๐Ÿ˜ซโšฝ๐Ÿค™โ˜•๐Ÿ†๐Ÿคซ๐Ÿ‘ˆ๐Ÿ˜ฎ๐Ÿ™†๐Ÿป๐Ÿƒ๐Ÿถ๐Ÿ’๐Ÿ˜ฒ๐ŸŒฟ๐Ÿงก๐ŸŽโšก๐ŸŒž๐ŸŽˆโŒโœŠ๐Ÿ‘‹๐Ÿ˜ฐ๐Ÿคจ๐Ÿ˜ถ๐Ÿค๐Ÿšถ๐Ÿ’ฐ๐Ÿ“๐Ÿ’ข๐ŸคŸ๐Ÿ™๐Ÿšจ๐Ÿ’จ๐Ÿคฌโœˆ๐ŸŽ€๐Ÿบ๐Ÿค“๐Ÿ˜™๐Ÿ’Ÿ๐ŸŒฑ๐Ÿ˜–๐Ÿ‘ถ๐Ÿฅดโ–ถโžกโ“๐Ÿ’Ž๐Ÿ’ธโฌ‡๐Ÿ˜จ๐ŸŒš๐Ÿฆ‹๐Ÿ˜ท๐Ÿ•บโš ๐Ÿ™…๐Ÿ˜Ÿ๐Ÿ˜ต๐Ÿ‘Ž๐Ÿคฒ๐Ÿค ๐Ÿคง๐Ÿ“Œ๐Ÿ”ต๐Ÿ’…๐Ÿง๐Ÿพ๐Ÿ’๐Ÿ˜—๐Ÿค‘๐ŸŒŠ๐Ÿคฏ๐Ÿทโ˜Ž๐Ÿ’ง๐Ÿ˜ฏ๐Ÿ’†๐Ÿ‘†๐ŸŽค๐Ÿ™‡๐Ÿ‘โ„๐ŸŒด๐Ÿ’ฃ๐Ÿธ๐Ÿ’Œ๐Ÿ“๐Ÿฅ€๐Ÿคข๐Ÿ‘…๐Ÿ’ก๐Ÿ’ฉ๐Ÿ‘๐Ÿ“ธ๐Ÿ‘ป๐Ÿค๐Ÿคฎ๐ŸŽผ๐Ÿฅต๐Ÿšฉ๐ŸŽ๐ŸŠ๐Ÿ‘ผ๐Ÿ’๐Ÿ“ฃ๐Ÿฅ‚') const alphabetBytesToChars: string[] = (alphabet.reduce((p, c, i) => { p[i] = c; return p }, ([]))) @@ -18,7 +18,7 @@ function encode (data: Uint8Array): string { }, '') } -function decode (str: string): Uint8Array { +function decode (str: string): Uint8Array { const byts = [] for (const char of str) { const codePoint = char.codePointAt(0) diff --git a/src/bases/base32.ts b/src/bases/base32.ts index c28f4f57..f3717d9b 100644 --- a/src/bases/base32.ts +++ b/src/bases/base32.ts @@ -1,4 +1,4 @@ -import { rfc4648 } from './base.js' +import { rfc4648 } from './base.ts' export const base32 = rfc4648({ prefix: 'b', diff --git a/src/bases/base36.ts b/src/bases/base36.ts index 12990af5..bb087871 100644 --- a/src/bases/base36.ts +++ b/src/bases/base36.ts @@ -1,4 +1,4 @@ -import { baseX } from './base.js' +import { baseX } from './base.ts' export const base36 = baseX({ prefix: 'k', diff --git a/src/bases/base58.ts b/src/bases/base58.ts index 15432731..3ea300d4 100644 --- a/src/bases/base58.ts +++ b/src/bases/base58.ts @@ -1,4 +1,4 @@ -import { baseX } from './base.js' +import { baseX } from './base.ts' export const base58btc = baseX({ name: 'base58btc', diff --git a/src/bases/base64.ts b/src/bases/base64.ts index 6e66d933..abd2f173 100644 --- a/src/bases/base64.ts +++ b/src/bases/base64.ts @@ -1,4 +1,4 @@ -import { rfc4648 } from './base.js' +import { rfc4648 } from './base.ts' export const base64 = rfc4648({ prefix: 'm', diff --git a/src/bases/base8.ts b/src/bases/base8.ts index 7c584a57..8e824b14 100644 --- a/src/bases/base8.ts +++ b/src/bases/base8.ts @@ -1,4 +1,4 @@ -import { rfc4648 } from './base.js' +import { rfc4648 } from './base.ts' export const base8 = rfc4648({ prefix: '7', diff --git a/src/bases/identity.ts b/src/bases/identity.ts index 301ac7a8..fd59db48 100644 --- a/src/bases/identity.ts +++ b/src/bases/identity.ts @@ -1,5 +1,5 @@ -import { fromString, toString } from '../bytes.js' -import { from } from './base.js' +import { fromString, toString } from '../bytes.ts' +import { from } from './base.ts' export const identity = from({ prefix: '\x00', diff --git a/src/bases/interface.ts b/src/bases/interface.ts index f0b63abe..315efedb 100644 --- a/src/bases/interface.ts +++ b/src/bases/interface.ts @@ -20,7 +20,7 @@ export interface BaseDecoder { * Decodes **plain** (and not a multibase) string. Unlike * decode */ - baseDecode(text: string): Uint8Array + baseDecode(text: string): Uint8Array } /** @@ -70,7 +70,7 @@ export interface MultibaseDecoder { * Decodes **multibase** string (which must have a multibase prefix added). * If prefix does not match */ - decode(multibase: Multibase): Uint8Array + decode(multibase: Multibase): Uint8Array } /** diff --git a/src/basics.ts b/src/basics.ts index 11b45ed1..d4c2a556 100644 --- a/src/basics.ts +++ b/src/basics.ts @@ -1,18 +1,18 @@ -import * as base10 from './bases/base10.js' -import * as base16 from './bases/base16.js' -import * as base2 from './bases/base2.js' -import * as base256emoji from './bases/base256emoji.js' -import * as base32 from './bases/base32.js' -import * as base36 from './bases/base36.js' -import * as base58 from './bases/base58.js' -import * as base64 from './bases/base64.js' -import * as base8 from './bases/base8.js' -import * as identityBase from './bases/identity.js' -import * as json from './codecs/json.js' -import * as raw from './codecs/raw.js' -import * as identity from './hashes/identity.js' -import * as sha2 from './hashes/sha2.js' -import { CID, hasher, digest, varint, bytes } from './index.js' +import * as base10 from './bases/base10.ts' +import * as base16 from './bases/base16.ts' +import * as base2 from './bases/base2.ts' +import * as base256emoji from './bases/base256emoji.ts' +import * as base32 from './bases/base32.ts' +import * as base36 from './bases/base36.ts' +import * as base58 from './bases/base58.ts' +import * as base64 from './bases/base64.ts' +import * as base8 from './bases/base8.ts' +import * as identityBase from './bases/identity.ts' +import * as json from './codecs/json.ts' +import * as raw from './codecs/raw.ts' +import * as identity from './hashes/identity.ts' +import * as sha2 from './hashes/sha2.ts' +import { CID, hasher, digest, varint, bytes } from './index.ts' export const bases = { ...identityBase, ...base2, ...base8, ...base10, ...base16, ...base32, ...base36, ...base58, ...base64, ...base256emoji } export const hashes = { ...sha2, ...identity } diff --git a/src/block.ts b/src/block.ts index 55f625c2..0383f99f 100644 --- a/src/block.ts +++ b/src/block.ts @@ -1,5 +1,5 @@ -import { bytes as binary, CID } from './index.js' -import type * as API from './interface.js' +import { bytes as binary, CID } from './index.ts' +import type * as API from './interface.ts' function readonly ({ enumerable = true, configurable = false } = {}): { enumerable: boolean, configurable: boolean, writable: false } { return { enumerable, configurable, writable: false } diff --git a/src/block/interface.ts b/src/block/interface.ts index d09c73c5..8c2c0823 100644 --- a/src/block/interface.ts +++ b/src/block/interface.ts @@ -1,5 +1,5 @@ -import type { CID } from '../cid.js' -import type { Link, Version } from '../link/interface.js' +import type { CID } from '../cid.ts' +import type { Link, Version } from '../link/interface.ts' /** * A byte-encoded representation of some type of `Data`. diff --git a/src/bytes.ts b/src/bytes.ts index 72c5899f..8a6f9319 100644 --- a/src/bytes.ts +++ b/src/bytes.ts @@ -4,7 +4,7 @@ export function toHex (d: Uint8Array): string { return d.reduce((hex, byte) => hex + byte.toString(16).padStart(2, '0'), '') } -export function fromHex (hex: string): Uint8Array { +export function fromHex (hex: string): Uint8Array { const hexes = hex.match(/../g) return hexes != null ? new Uint8Array(hexes.map(b => parseInt(b, 16))) : empty } @@ -24,11 +24,24 @@ export function equals (aa: Uint8Array, bb: Uint8Array): boolean { return true } -export function coerce (o: ArrayBufferView | ArrayBuffer | Uint8Array): Uint8Array { - if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') { return o } - if (o instanceof ArrayBuffer) { return new Uint8Array(o) } +/** + * Normalize binary input to a plain `Uint8Array` backed by an `ArrayBuffer`. + * + * Returns the input itself when it is already a plain `Uint8Array` over an + * `ArrayBuffer`, otherwise a fresh view (or, for `SharedArrayBuffer`-backed + * input, a copy) over the same bytes. + * + * Throws if input is not a recognised binary type. + */ +export function coerce (o: ArrayBufferView | ArrayBuffer | Uint8Array): Uint8Array { + if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') { + return toArrayBufferBackedArray(o) + } + if (o instanceof ArrayBuffer) { + return new Uint8Array(o) + } if (ArrayBuffer.isView(o)) { - return new Uint8Array(o.buffer, o.byteOffset, o.byteLength) + return toArrayBufferBackedArray(new Uint8Array(o.buffer, o.byteOffset, o.byteLength)) } throw new Error('Unknown type, must be binary type') } @@ -37,10 +50,26 @@ export function isBinary (o: unknown): o is ArrayBuffer | ArrayBufferView { return o instanceof ArrayBuffer || ArrayBuffer.isView(o) } -export function fromString (str: string): Uint8Array { +export function fromString (str: string): Uint8Array { return new TextEncoder().encode(str) } export function toString (b: Uint8Array): string { return new TextDecoder().decode(b) } + +function isByteArrayWithArrayBuffer (b?: Uint8Array): b is Uint8Array { + return b?.buffer instanceof ArrayBuffer +} + +/** + * Ensures `b` is backed by an ArrayBuffer - if not a new Uint8Array will be + * created and the contents of `b` copied into it. + */ +export function toArrayBufferBackedArray (b: Uint8Array): Uint8Array { + if (isByteArrayWithArrayBuffer(b)) { + return b + } + + return b.slice() +} diff --git a/src/cid.ts b/src/cid.ts index d8b626b6..594162c2 100644 --- a/src/cid.ts +++ b/src/cid.ts @@ -1,13 +1,13 @@ -import { base32 } from './bases/base32.js' -import { base36 } from './bases/base36.js' -import { base58btc } from './bases/base58.js' -import { coerce } from './bytes.js' -import * as Digest from './hashes/digest.js' -import * as varint from './varint.js' -import type * as API from './link/interface.js' +import { base32 } from './bases/base32.ts' +import { base36 } from './bases/base36.ts' +import { base58btc } from './bases/base58.ts' +import { coerce, toArrayBufferBackedArray } from './bytes.ts' +import * as Digest from './hashes/digest.ts' +import * as varint from './varint.ts' +import type * as API from './link/interface.ts' // This way TS will also expose all the types from module -export * from './link/interface.js' +export * from './link/interface.ts' export function format , Prefix extends string> (link: T, base?: API.MultibaseEncoder): API.ToString { const { bytes, version } = link @@ -53,8 +53,8 @@ export class CID - readonly bytes: Uint8Array - readonly '/': Uint8Array + readonly bytes: Uint8Array + readonly '/': Uint8Array /** * @param version - Version of the CID @@ -65,11 +65,11 @@ export class CID implements MultihashDigest { readonly code: Code readonly size: Size - readonly digest: Uint8Array - readonly bytes: Uint8Array + readonly digest: Uint8Array + readonly bytes: Uint8Array /** * Creates a multihash digest. @@ -65,8 +65,8 @@ export class Digest implements Multiha constructor (code: Code, size: Size, digest: Uint8Array, bytes: Uint8Array) { this.code = code this.size = size - this.digest = digest - this.bytes = bytes + this.digest = toArrayBufferBackedArray(digest) + this.bytes = toArrayBufferBackedArray(bytes) } } diff --git a/src/hashes/hasher.ts b/src/hashes/hasher.ts index b711da2b..b4715f01 100644 --- a/src/hashes/hasher.ts +++ b/src/hashes/hasher.ts @@ -1,5 +1,5 @@ -import * as Digest from './digest.js' -import type { MultihashHasher } from './interface.js' +import * as Digest from './digest.ts' +import type { MultihashHasher } from './interface.ts' type Await = Promise | T diff --git a/src/hashes/identity.ts b/src/hashes/identity.ts index d13d575b..4657707b 100644 --- a/src/hashes/identity.ts +++ b/src/hashes/identity.ts @@ -1,6 +1,6 @@ -import { coerce } from '../bytes.js' -import * as Digest from './digest.js' -import type { DigestOptions } from './hasher.js' +import { coerce } from '../bytes.ts' +import * as Digest from './digest.ts' +import type { DigestOptions } from './hasher.ts' const code: 0x0 = 0x0 const name = 'identity' diff --git a/src/hashes/interface.ts b/src/hashes/interface.ts index 92c4be09..5a6c944e 100644 --- a/src/hashes/interface.ts +++ b/src/hashes/interface.ts @@ -1,6 +1,6 @@ // # Multihash -import type { DigestOptions } from './hasher.js' +import type { DigestOptions } from './hasher.ts' /** * Represents a multihash digest which carries information about the @@ -20,7 +20,7 @@ export interface MultihashDigest { /** * Raw digest (without a hashing algorithm info) */ - digest: Uint8Array + digest: Uint8Array /** * byte length of the `this.digest` @@ -30,7 +30,7 @@ export interface MultihashDigest { /** * Binary representation of this multihash digest. */ - bytes: Uint8Array + bytes: Uint8Array } /** diff --git a/src/hashes/sha1-browser.ts b/src/hashes/sha1-browser.ts index 6764ba8e..a4c81ffe 100644 --- a/src/hashes/sha1-browser.ts +++ b/src/hashes/sha1-browser.ts @@ -1,9 +1,9 @@ /* global crypto */ -import { from } from './hasher.js' +import { from } from './hasher.ts' const sha = (name: AlgorithmIdentifier) => - async (data: Uint8Array) => new Uint8Array(await crypto.subtle.digest(name, data)) + async (data: Uint8Array) => new Uint8Array(await crypto.subtle.digest(name, data)) export const sha1 = from({ name: 'sha-1', diff --git a/src/hashes/sha1.ts b/src/hashes/sha1.ts index f8480519..fbd9dd5f 100644 --- a/src/hashes/sha1.ts +++ b/src/hashes/sha1.ts @@ -1,6 +1,6 @@ -import crypto from 'crypto' -import { coerce } from '../bytes.js' -import { from } from './hasher.js' +import crypto from 'node:crypto' +import { coerce } from '../bytes.ts' +import { from } from './hasher.ts' export const sha1 = from({ name: 'sha-1', diff --git a/src/hashes/sha2-browser.ts b/src/hashes/sha2-browser.ts index cbf0b7b8..b8c424c8 100644 --- a/src/hashes/sha2-browser.ts +++ b/src/hashes/sha2-browser.ts @@ -1,8 +1,8 @@ /* global crypto */ -import { from } from './hasher.js' +import { from } from './hasher.ts' -function sha (name: AlgorithmIdentifier): (data: Uint8Array) => Promise { +function sha (name: AlgorithmIdentifier): (data: Uint8Array) => Promise { return async data => new Uint8Array(await crypto.subtle.digest(name, data)) } diff --git a/src/hashes/sha2.ts b/src/hashes/sha2.ts index 37d6f2bd..c2a5ade3 100644 --- a/src/hashes/sha2.ts +++ b/src/hashes/sha2.ts @@ -1,6 +1,6 @@ -import crypto from 'crypto' -import { coerce } from '../bytes.js' -import { from } from './hasher.js' +import crypto from 'node:crypto' +import { coerce } from '../bytes.ts' +import { from } from './hasher.ts' export const sha256 = from({ name: 'sha2-256', diff --git a/src/index.ts b/src/index.ts index 677ef877..494f6a12 100644 --- a/src/index.ts +++ b/src/index.ts @@ -200,13 +200,13 @@ * | `dag-jose` | `dag-jose` | [ceramicnetwork/js-dag-jose](https://github.com/ceramicnetwork/js-dag-jose) | */ -import * as bytes from './bytes.js' -import { CID } from './cid.js' -import * as digest from './hashes/digest.js' -import * as hasher from './hashes/hasher.js' -import * as varint from './varint.js' +import * as bytes from './bytes.ts' +import { CID } from './cid.ts' +import * as digest from './hashes/digest.ts' +import * as hasher from './hashes/hasher.ts' +import * as varint from './varint.ts' // This way TS will also expose all the types from module -export * from './interface.js' +export * from './interface.ts' export { CID, hasher, digest, varint, bytes } diff --git a/src/interface.ts b/src/interface.ts index e2a56c67..e6632051 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -1,5 +1,5 @@ -export * from './bases/interface.js' -export * from './hashes/interface.js' -export * from './codecs/interface.js' -export * from './link/interface.js' -export * from './block/interface.js' +export * from './bases/interface.ts' +export * from './hashes/interface.ts' +export * from './codecs/interface.ts' +export * from './link/interface.ts' +export * from './block/interface.ts' diff --git a/src/link.ts b/src/link.ts index c39052bd..2b09fa48 100644 --- a/src/link.ts +++ b/src/link.ts @@ -1,7 +1,7 @@ -import { CID, format, toJSON, fromJSON } from './cid.js' -import type * as API from './link/interface.js' +import { CID, format, toJSON, fromJSON } from './cid.ts' +import type * as API from './link/interface.ts' // This way TS will also expose all the types from module -export * from './link/interface.js' +export * from './link/interface.ts' const DAG_PB_CODE = 0x70 // eslint-disable-next-line diff --git a/src/link/interface.ts b/src/link/interface.ts index 31a8c366..0fd3fcd7 100644 --- a/src/link/interface.ts +++ b/src/link/interface.ts @@ -1,6 +1,6 @@ -import type { MultibaseEncoder, MultibaseDecoder, Multibase } from '../bases/interface.js' -import type { Phantom, ByteView } from '../block/interface.js' -import type { MultihashDigest } from '../hashes/interface.js' +import type { MultibaseEncoder, MultibaseDecoder, Multibase } from '../bases/interface.ts' +import type { Phantom, ByteView } from '../block/interface.ts' +import type { MultihashDigest } from '../hashes/interface.ts' export type { MultihashDigest, MultibaseEncoder, MultibaseDecoder } export type Version = 0 | 1 diff --git a/src/traversal.ts b/src/traversal.ts index abb07663..ef7d834c 100644 --- a/src/traversal.ts +++ b/src/traversal.ts @@ -1,6 +1,6 @@ -import { base58btc } from './bases/base58.js' -import type { BlockView as _BlockView } from './block/interface.js' -import type { CID, Version } from './cid.js' +import { base58btc } from './bases/base58.ts' +import type { BlockView as _BlockView } from './block/interface.ts' +import type { CID, Version } from './cid.ts' type BlockView = _BlockView diff --git a/test/test-block.spec.ts b/test/test-block.spec.ts index 2d131cd8..c2cac932 100644 --- a/test/test-block.spec.ts +++ b/test/test-block.spec.ts @@ -1,10 +1,10 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import * as main from '../src/block.js' -import * as codec from '../src/codecs/json.js' -import { sha256 as hasher } from '../src/hashes/sha2.js' -import { CID, bytes } from '../src/index.js' +import * as main from '../src/block.ts' +import * as codec from '../src/codecs/json.ts' +import { sha256 as hasher } from '../src/hashes/sha2.ts' +import { CID, bytes } from '../src/index.ts' const fixture = { hello: 'world' } const link = CID.parse('bafyreidykglsfhoixmivffc5uwhcgshx4j465xwqntbmu43nb2dzqwfvae') diff --git a/test/test-bytes.spec.ts b/test/test-bytes.spec.ts index aac7f531..205f8780 100644 --- a/test/test-bytes.spec.ts +++ b/test/test-bytes.spec.ts @@ -1,7 +1,7 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import * as bytes from '../src/bytes.js' +import * as bytes from '../src/bytes.ts' describe('bytes', () => { it('isBinary', () => { @@ -11,7 +11,6 @@ describe('bytes', () => { it('coerce', () => { const fixture = bytes.fromString('test') - // @ts-expect-error assert.deepStrictEqual(bytes.coerce(fixture.buffer), fixture) assert.deepStrictEqual(bytes.coerce(new DataView(fixture.buffer)), fixture) }) @@ -25,4 +24,18 @@ describe('bytes', () => { const fixture = 'hello world' assert.deepStrictEqual(bytes.toString(bytes.fromString(fixture)), fixture) }) + + it('toArrayBufferBackedArray()', function () { + if (globalThis.SharedArrayBuffer == null) { + return this.skip() + } + + const b = new Uint8Array(10) + assert.equal(b, bytes.toArrayBufferBackedArray(b)) + + const s = new SharedArrayBuffer(10) + const b2 = new Uint8Array(s, 0, s.byteLength) + assert.notEqual(b2, bytes.toArrayBufferBackedArray(b2) as any) + assert.deepEqual(b, bytes.toArrayBufferBackedArray(b2)) + }) }) diff --git a/test/test-cid.spec.ts b/test/test-cid.spec.ts index 7b84183a..4d34b3d6 100644 --- a/test/test-cid.spec.ts +++ b/test/test-cid.spec.ts @@ -2,15 +2,15 @@ import { assert } from 'aegir/chai' import OLDCID from 'cids' -import { base32 } from '../src/bases/base32.js' -import { base36 } from '../src/bases/base36.js' -import { base58btc } from '../src/bases/base58.js' -import { base64 } from '../src/bases/base64.js' -import { fromHex, toHex, equals } from '../src/bytes.js' -import { sha256, sha512 } from '../src/hashes/sha2.js' -import { varint, CID } from '../src/index.js' -import invalidMultihash from './fixtures/invalid-multihash.js' -import type { MultihashDigest } from '../src/index.js' +import { base32 } from '../src/bases/base32.ts' +import { base36 } from '../src/bases/base36.ts' +import { base58btc } from '../src/bases/base58.ts' +import { base64 } from '../src/bases/base64.ts' +import { fromHex, toHex, equals } from '../src/bytes.ts' +import { sha256, sha512 } from '../src/hashes/sha2.ts' +import { varint, CID } from '../src/index.ts' +import invalidMultihash from './fixtures/invalid-multihash.ts' +import type { MultihashDigest } from '../src/index.ts' const textEncoder = new TextEncoder() diff --git a/test/test-link.spec.ts b/test/test-link.spec.ts index 1165e8a4..27bb4a77 100644 --- a/test/test-link.spec.ts +++ b/test/test-link.spec.ts @@ -1,8 +1,8 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import { sha256 } from '../src/hashes/sha2.js' -import * as Link from '../src/link.js' +import { sha256 } from '../src/hashes/sha2.ts' +import * as Link from '../src/link.ts' const utf8 = new TextEncoder() diff --git a/test/test-multibase-spec.spec.ts b/test/test-multibase-spec.spec.ts index 1f7f2523..63d5acf5 100644 --- a/test/test-multibase-spec.spec.ts +++ b/test/test-multibase-spec.spec.ts @@ -1,8 +1,6 @@ -/* eslint-env mocha */ - import { assert } from 'aegir/chai' -import { bases } from '../src/basics.js' -import { fromString } from '../src/bytes.js' +import { bases } from '../src/basics.ts' +import { fromString } from '../src/bytes.ts' const encoded = [ { diff --git a/test/test-multibase.spec.ts b/test/test-multibase.spec.ts index 93b446b5..0e000595 100644 --- a/test/test-multibase.spec.ts +++ b/test/test-multibase.spec.ts @@ -1,15 +1,15 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import * as b10 from '../src/bases/base10.js' -import * as b16 from '../src/bases/base16.js' -import * as b2 from '../src/bases/base2.js' -import * as b32 from '../src/bases/base32.js' -import * as b36 from '../src/bases/base36.js' -import * as b58 from '../src/bases/base58.js' -import * as b64 from '../src/bases/base64.js' -import * as b8 from '../src/bases/base8.js' -import * as bytes from '../src/bytes.js' +import * as b10 from '../src/bases/base10.ts' +import * as b16 from '../src/bases/base16.ts' +import * as b2 from '../src/bases/base2.ts' +import * as b32 from '../src/bases/base32.ts' +import * as b36 from '../src/bases/base36.ts' +import * as b58 from '../src/bases/base58.ts' +import * as b64 from '../src/bases/base64.ts' +import * as b8 from '../src/bases/base8.ts' +import * as bytes from '../src/bytes.ts' const { base16, base32, base58btc, base64 } = { ...b16, ...b32, ...b58, ...b64 } diff --git a/test/test-multicodec.spec.ts b/test/test-multicodec.spec.ts index f2493bae..4de8148c 100644 --- a/test/test-multicodec.spec.ts +++ b/test/test-multicodec.spec.ts @@ -1,9 +1,9 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import * as bytes from '../src/bytes.js' -import * as json from '../src/codecs/json.js' -import * as raw from '../src/codecs/raw.js' +import * as bytes from '../src/bytes.ts' +import * as json from '../src/codecs/json.ts' +import * as raw from '../src/codecs/raw.ts' describe('multicodec', () => { it('encode/decode raw', () => { diff --git a/test/test-multihash.spec.ts b/test/test-multihash.spec.ts index 31a57bcd..5d7e229c 100644 --- a/test/test-multihash.spec.ts +++ b/test/test-multihash.spec.ts @@ -4,14 +4,14 @@ import { hash as slSha256 } from '@stablelib/sha256' import { hash as slSha512 } from '@stablelib/sha512' import { assert } from 'aegir/chai' import { sha1 as chSha1 } from 'crypto-hash' -import { fromHex, fromString } from '../src/bytes.js' -import { decode as decodeDigest, create as createDigest, hasCode as digestHasCode } from '../src/hashes/digest.js' -import { identity } from '../src/hashes/identity.js' -import { sha1 } from '../src/hashes/sha1.js' -import { sha256, sha512 } from '../src/hashes/sha2.js' -import invalid from './fixtures/invalid-multihash.js' -import valid from './fixtures/valid-multihash.js' -import type { MultihashDigest } from '../src/cid.js' +import { fromHex, fromString } from '../src/bytes.ts' +import { decode as decodeDigest, create as createDigest, hasCode as digestHasCode } from '../src/hashes/digest.ts' +import { identity } from '../src/hashes/identity.ts' +import { sha1 } from '../src/hashes/sha1.ts' +import { sha256, sha512 } from '../src/hashes/sha2.ts' +import invalid from './fixtures/invalid-multihash.ts' +import valid from './fixtures/valid-multihash.ts' +import type { MultihashDigest } from '../src/cid.ts' const sample = (code: number | string, size: number, hex: string): Uint8Array => { const toHex = (i: number | string): string => { @@ -197,6 +197,19 @@ describe('multihash', () => { }) }, /Invalid truncate option/) }) + + it('hash identity with non-ArrayBuffer backing buffer', function () { + if (globalThis.SharedArrayBuffer == null) { + return this.skip() + } + + const s = new SharedArrayBuffer(10) + const b = new Uint8Array(s, 0, s.byteLength) + const hash = identity.digest(b) + + assert.notEqual(b.buffer.constructor.name, hash.digest.buffer.constructor.name) + assert.deepStrictEqual(b.slice(), hash.digest) + }) }) describe('decode', () => { for (const { encoding, hex, size } of valid) { diff --git a/test/test-traversal.spec.ts b/test/test-traversal.spec.ts index 57c59cd4..87b922a3 100644 --- a/test/test-traversal.spec.ts +++ b/test/test-traversal.spec.ts @@ -1,13 +1,13 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import * as main from '../src/block.js' -import { fromString } from '../src/bytes.js' -import * as codec from '../src/codecs/json.js' -import { sha256 as hasher } from '../src/hashes/sha2.js' -import { walk } from '../src/traversal.js' -import type { BlockView } from '../src/block/interface.js' -import type { CID } from '../src/cid.js' +import * as main from '../src/block.ts' +import { fromString } from '../src/bytes.ts' +import * as codec from '../src/codecs/json.ts' +import { sha256 as hasher } from '../src/hashes/sha2.ts' +import { walk } from '../src/traversal.ts' +import type { BlockView } from '../src/block/interface.ts' +import type { CID } from '../src/cid.ts' // from dag-pb, simplified function createNode (data: Uint8Array, links: Array<{ Hash: CID, Name: string, Tsize: number }>): { Data: Uint8Array, Links: Array<{ Hash: CID, Name: string, Tsize: number }> } { diff --git a/test/test-varint.spec.ts b/test/test-varint.spec.ts index 137c9fbb..1177219a 100644 --- a/test/test-varint.spec.ts +++ b/test/test-varint.spec.ts @@ -1,7 +1,7 @@ /* globals describe, it */ import { assert } from 'aegir/chai' -import { varint } from '../src/index.js' +import { varint } from '../src/index.ts' const UTF8 = new TextEncoder()