@cbortech/hash-extension 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  Cryptographic hash application-string extension for [`@cbortech/cbor`](https://www.npmjs.com/package/@cbortech/cbor).
4
4
 
5
- This extension implements the `hash` application-extension identifier from CBOR Extended Diagnostic Notation (EDN). It computes a cryptographic hash and returns the output as a CBOR byte string.
5
+ [`@cbortech/cbor`](https://www.npmjs.com/package/@cbortech/cbor) is a TypeScript library for converting between [CBOR](https://www.rfc-editor.org/rfc/rfc8949.html), [CDN](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/), and JavaScript values.
6
+
7
+ This extension implements the `hash` application-extension identifier from [CDN](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/). It computes a cryptographic hash and returns the output as a CBOR byte string.
6
8
 
7
9
  ## Installation
8
10
 
@@ -18,25 +20,25 @@ import { hash } from '@cbortech/hash-extension';
18
20
 
19
21
  const cbor = new CBOR({ extensions: [hash] });
20
22
 
21
- // Parse CBOR-EDN containing hash values.
23
+ // Parse CDN containing hash values.
22
24
  const document = cbor.parse(`{
23
25
  "hash": hash'foo'
24
26
  }`);
25
27
  // document.hash is a bare Uint8Array.
26
28
 
27
- // Convert CBOR-EDN containing a hash value into CBOR.
28
- const encoded = cbor.fromEDN("hash'foo'").toCBOR();
29
+ // Convert CDN containing a hash value into CBOR.
30
+ const encoded = cbor.fromCDN("hash'foo'").toCBOR();
29
31
  // encoded is CBOR binary data stored as a Uint8Array.
30
32
  // Inspect the encoded CBOR value with toHexDump():
31
33
  console.log(CBOR.fromCBOR(encoded).toHexDump());
32
34
  // 58 20 2C 26 B4 6B 68 FF C6 8F F9 9B 45 3C 1D 30 41 34 13 42 2D 70 64 83 BF A0 F9 8A 5E 88 62 66 E7 AE -- h'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
33
35
 
34
- // Format CBOR-EDN with hash values as h'...'.
36
+ // Format CDN with hash values as h'...'.
35
37
  console.log(cbor.format(`{ "hash" : hash'foo' }`, { appStrings: false }));
36
38
  // {"hash":h'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'}
37
39
  ```
38
40
 
39
- ## EDN Forms
41
+ ## CDN Forms
40
42
 
41
43
  - `hash'foo'` computes SHA-256 over the UTF-8 text `foo`.
42
44
  - `hash<<'foo'>>` computes SHA-256 over the byte string `foo`.
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require(`@cbortech/cbor/ast`),t=require(`@noble/hashes/legacy.js`),n=require(`@noble/hashes/sha2.js`),r=require(`@noble/hashes/sha3.js`);var i=`hash`,a=-16,o=new Map([[-14,t.sha1],[-15,e=>(0,n.sha256)(e).slice(0,8)],[-16,n.sha256],[-17,n.sha512_256],[-18,r.shake128_32],[-43,n.sha384],[-44,n.sha512],[-45,r.shake256_64]]),s=new Map([[`SHA-1`,-14],[`SHA-256/64`,-15],[`SHA-256`,-16],[`SHA-512/256`,-17],[`SHAKE128`,-18],[`SHA-384`,-43],[`SHA-512`,-44],[`SHAKE256`,-45]]),c=new Map([...s.entries()].map(([e,t])=>[t,e])),l=class extends e.CborByteString{input;algorithmId;constructor(e,t,n){super(e),this.input=t,this.algorithmId=n}_toEDN(t,n){if(t?.appStrings===!1)return super._toEDN(t,n);let r=this.algorithmId===a;if(this.input instanceof e.CborTextString&&r)return`${i}${S(this.input.value)}`;let o=this.input instanceof e.CborTextString?S(this.input.value):y(this.input.value,t?.bstrEncoding??`hex`,t?.sqstr);if(r)return`${i}<<${o}>>`;let s=c.get(this.algorithmId);return`${i}<<${o}, ${s===void 0?String(this.algorithmId):`"${s}"`}>>`}};function u(t){if(t instanceof e.CborUint||t instanceof e.CborNint)return Number(t.value);if(t instanceof e.CborTextString){let e=s.get(t.value);if(e===void 0)throw SyntaxError(`hash: unknown algorithm name: ${JSON.stringify(t.value)}`);return e}throw SyntaxError(`hash: algorithm must be an integer or text string`)}function d(t,n){let r=t instanceof e.CborTextString?new TextEncoder().encode(t.value):t.value,i=o.get(n);if(i===void 0)throw SyntaxError(`hash: unsupported COSE algorithm ID ${n}`);return new l(i(r),t,n)}var f={appStringPrefixes:[i],parseAppString(t,n){return d(new e.CborTextString(n),a)},parseAppSequence(t,n){if(n.length===0||n.length>2)throw SyntaxError(`hash<<...>>: expected 1 or 2 items, got ${n.length}`);let r=n[0];if(!(r instanceof e.CborTextString)&&!(r instanceof e.CborByteString))throw SyntaxError(`hash: first argument must be a text or byte string`);return d(r,n.length===2?u(n[1]):a)}};function p(e){return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function m(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/=/g,``)}function h(e){return m(e).replace(/\+/g,`-`).replace(/\//g,`_`)}var g=`ABCDEFGHIJKLMNOPQRSTUVWXYZ234567`,_=`0123456789ABCDEFGHIJKLMNOPQRSTUV`;function v(e,t){let n=``,r=0,i=0;for(let a of e)for(r=r<<8|a,i+=8;i>=5;)i-=5,n+=t[r>>i&31];return i>0&&(n+=t[r<<5-i&31]),n}function y(e,t,n){if(n===`string`){let t=b(e);if(t!==null)return C(t)}if(n===`printable-string`||n===void 0){let t=b(e);if(t!==null&&!x(t))return C(t)}switch(t){case`base64`:return`b64'${m(e)}'`;case`base64url`:return`b64'${h(e)}'`;case`base32`:return`b32'${v(e,g)}'`;case`base32hex`:return`h32'${v(e,_)}'`;default:return`h'${p(e)}'`}}function b(e){try{return new TextDecoder(`utf-8`,{fatal:!0}).decode(e)}catch{return null}}function x(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<32||e===127))return!0}return!1}function S(e){return w(e,`'`)}function C(e){return w(e,`'`)}function w(e,t){let n=t,r=t.codePointAt(0);for(let i of e){let e=i.codePointAt(0);if(e!==void 0)switch(i){case`\\`:n+=`\\\\`;break;case`
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("@cbortech/cbor/ast"),t=require("@noble/hashes/legacy.js"),n=require("@noble/hashes/sha2.js"),r=require("@noble/hashes/sha3.js");var i=`hash`,a=-16,o=new Map([[-14,t.sha1],[-15,e=>(0,n.sha256)(e).slice(0,8)],[-16,n.sha256],[-17,n.sha512_256],[-18,r.shake128_32],[-43,n.sha384],[-44,n.sha512],[-45,r.shake256_64]]),s=new Map([[`SHA-1`,-14],[`SHA-256/64`,-15],[`SHA-256`,-16],[`SHA-512/256`,-17],[`SHAKE128`,-18],[`SHA-384`,-43],[`SHA-512`,-44],[`SHAKE256`,-45]]),c=new Map([...s.entries()].map(([e,t])=>[t,e])),l=class extends e.CborByteString{input;algorithmId;constructor(e,t,n){super(e),this.input=t,this.algorithmId=n}_toCDN(t,n){if(t?.appStrings===!1)return super._toCDN(t,n);let r=this.algorithmId===a;if(this.input instanceof e.CborTextString&&r)return`${i}${S(this.input.value)}`;let o=this.input instanceof e.CborTextString?S(this.input.value):y(this.input.value,t?.bstrEncoding??`hex`,t?.sqstr);if(r)return`${i}<<${o}>>`;let s=c.get(this.algorithmId);return`${i}<<${o}, ${s===void 0?String(this.algorithmId):`"${s}"`}>>`}};function u(t){if(t instanceof e.CborUint||t instanceof e.CborNint)return Number(t.value);if(t instanceof e.CborTextString){let e=s.get(t.value);if(e===void 0)throw SyntaxError(`hash: unknown algorithm name: ${JSON.stringify(t.value)}`);return e}throw SyntaxError(`hash: algorithm must be an integer or text string`)}function d(t,n){let r=t instanceof e.CborTextString?new TextEncoder().encode(t.value):t.value,i=o.get(n);if(i===void 0)throw SyntaxError(`hash: unsupported COSE algorithm ID ${n}`);return new l(i(r),t,n)}var f={appStringPrefixes:[i],parseAppString(t,n){return d(new e.CborTextString(n),a)},parseAppSequence(t,n){if(n.length===0||n.length>2)throw SyntaxError(`hash<<...>>: expected 1 or 2 items, got ${n.length}`);let r=n[0];if(!(r instanceof e.CborTextString)&&!(r instanceof e.CborByteString))throw SyntaxError(`hash: first argument must be a text or byte string`);return d(r,n.length===2?u(n[1]):a)}};function p(e){return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function m(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/=/g,``)}function h(e){return m(e).replace(/\+/g,`-`).replace(/\//g,`_`)}var g=`ABCDEFGHIJKLMNOPQRSTUVWXYZ234567`,_=`0123456789ABCDEFGHIJKLMNOPQRSTUV`;function v(e,t){let n=``,r=0,i=0;for(let a of e)for(r=r<<8|a,i+=8;i>=5;)i-=5,n+=t[r>>i&31];return i>0&&(n+=t[r<<5-i&31]),n}function y(e,t,n){if(n===`string`){let t=b(e);if(t!==null)return C(t)}if(n===`printable-string`||n===void 0){let t=b(e);if(t!==null&&!x(t))return C(t)}switch(t){case`base64`:return`b64'${m(e)}'`;case`base64url`:return`b64'${h(e)}'`;case`base32`:return`b32'${v(e,g)}'`;case`base32hex`:return`h32'${v(e,_)}'`;default:return`h'${p(e)}'`}}function b(e){try{return new TextDecoder(`utf-8`,{fatal:!0}).decode(e)}catch{return null}}function x(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<32||e===127))return!0}return!1}function S(e){return w(e,`'`)}function C(e){return w(e,`'`)}function w(e,t){let n=t,r=t.codePointAt(0);for(let i of e){let e=i.codePointAt(0);if(e!==void 0)switch(i){case`\\`:n+=`\\\\`;break;case`
2
2
  `:n+=`\\n`;break;case`\r`:n+=`\\r`;break;case` `:n+=`\\t`;break;default:e===r?n+=`\\${t}`:e<32||e===127||e===8232||e===8233||e===8203||e===8204||e===8205||e===65279?n+=`\\u${e.toString(16).padStart(4,`0`)}`:n+=i}}return n+t}exports.CborHashExt=l,exports.default=f,exports.hash=f;
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type CborExtension, type ToEDNOptions } from '@cbortech/cbor';\nimport {\n CborByteString,\n CborNint,\n CborTextString,\n CborUint,\n type CborItem,\n} from '@cbortech/cbor/ast';\nimport { sha1 } from '@noble/hashes/legacy.js';\nimport { sha256, sha384, sha512, sha512_256 } from '@noble/hashes/sha2.js';\nimport { shake128_32, shake256_64 } from '@noble/hashes/sha3.js';\n\ntype HashFn = (data: Uint8Array) => Uint8Array;\n\nconst PREFIX_HASH = 'hash';\nconst DEFAULT_ALGORITHM_ID = -16;\n\nconst COSE_HASH_FN = new Map<number, HashFn>([\n [-14, sha1],\n [-15, (data) => sha256(data).slice(0, 8)],\n [-16, sha256],\n [-17, sha512_256],\n [-18, shake128_32],\n [-43, sha384],\n [-44, sha512],\n [-45, shake256_64],\n]);\n\nconst COSE_NAME_TO_ID = new Map<string, number>([\n ['SHA-1', -14],\n ['SHA-256/64', -15],\n ['SHA-256', -16],\n ['SHA-512/256', -17],\n ['SHAKE128', -18],\n ['SHA-384', -43],\n ['SHA-512', -44],\n ['SHAKE256', -45],\n]);\n\nconst COSE_ID_TO_NAME = new Map<number, string>(\n [...COSE_NAME_TO_ID.entries()].map(([name, id]) => [id, name])\n);\n\nexport class CborHashExt extends CborByteString {\n private readonly input: CborTextString | CborByteString;\n private readonly algorithmId: number;\n\n constructor(\n output: Uint8Array,\n input: CborTextString | CborByteString,\n algorithmId: number\n ) {\n super(output);\n this.input = input;\n this.algorithmId = algorithmId;\n }\n\n override _toEDN(options: ToEDNOptions | undefined, depth: number): string {\n if (options?.appStrings === false) return super._toEDN(options, depth);\n\n const isDefault = this.algorithmId === DEFAULT_ALGORITHM_ID;\n\n if (this.input instanceof CborTextString && isDefault) {\n return `${PREFIX_HASH}${escapeAppString(this.input.value)}`;\n }\n\n const dataEdn =\n this.input instanceof CborTextString\n ? escapeAppString(this.input.value)\n : serializeBytes(\n this.input.value,\n options?.bstrEncoding ?? 'hex',\n options?.sqstr\n );\n\n if (isDefault) return `${PREFIX_HASH}<<${dataEdn}>>`;\n\n const algorithmName = COSE_ID_TO_NAME.get(this.algorithmId);\n const algorithmEdn =\n algorithmName === undefined\n ? String(this.algorithmId)\n : `\"${algorithmName}\"`;\n return `${PREFIX_HASH}<<${dataEdn}, ${algorithmEdn}>>`;\n }\n}\n\nfunction resolveAlgorithmId(item: CborItem): number {\n if (item instanceof CborUint) return Number(item.value);\n if (item instanceof CborNint) return Number(item.value);\n if (item instanceof CborTextString) {\n const id = COSE_NAME_TO_ID.get(item.value);\n if (id === undefined) {\n throw new SyntaxError(\n `hash: unknown algorithm name: ${JSON.stringify(item.value)}`\n );\n }\n return id;\n }\n throw new SyntaxError('hash: algorithm must be an integer or text string');\n}\n\nfunction computeHash(\n input: CborTextString | CborByteString,\n algorithmId: number\n): CborHashExt {\n const data =\n input instanceof CborTextString\n ? new TextEncoder().encode(input.value)\n : input.value;\n const fn = COSE_HASH_FN.get(algorithmId);\n if (fn === undefined) {\n throw new SyntaxError(`hash: unsupported COSE algorithm ID ${algorithmId}`);\n }\n return new CborHashExt(fn(data), input, algorithmId);\n}\n\nexport const hash: CborExtension = {\n appStringPrefixes: [PREFIX_HASH],\n\n parseAppString(_prefix: string, content: string): CborItem {\n return computeHash(new CborTextString(content), DEFAULT_ALGORITHM_ID);\n },\n\n parseAppSequence(_prefix: string, items: CborItem[]): CborItem {\n if (items.length === 0 || items.length > 2) {\n throw new SyntaxError(\n `hash<<...>>: expected 1 or 2 items, got ${items.length}`\n );\n }\n\n const input = items[0];\n if (\n !(input instanceof CborTextString) &&\n !(input instanceof CborByteString)\n ) {\n throw new SyntaxError(\n 'hash: first argument must be a text or byte string'\n );\n }\n\n const algorithmId =\n items.length === 2 ? resolveAlgorithmId(items[1]) : DEFAULT_ALGORITHM_ID;\n return computeHash(input, algorithmId);\n },\n};\n\nexport default hash;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/=/g, '');\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nconst B32_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\nconst H32_ALPHA = '0123456789ABCDEFGHIJKLMNOPQRSTUV';\n\nfunction base32Encode(bytes: Uint8Array, alphabet: string): string {\n let result = '';\n let buffer = 0;\n let bufferBits = 0;\n\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bufferBits += 8;\n while (bufferBits >= 5) {\n bufferBits -= 5;\n result += alphabet[(buffer >> bufferBits) & 0x1f];\n }\n }\n\n if (bufferBits > 0) result += alphabet[(buffer << (5 - bufferBits)) & 0x1f];\n return result;\n}\n\nfunction serializeBytes(\n bytes: Uint8Array,\n encoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex',\n sqstr?: 'printable-string' | 'string' | 'none'\n): string {\n if (sqstr === 'string') {\n const text = tryDecodeUtf8(bytes);\n if (text !== null) return escapeSingleQuoted(text);\n }\n\n if (sqstr === 'printable-string' || sqstr === undefined) {\n const text = tryDecodeUtf8(bytes);\n if (text !== null && !hasNonPrintable(text)) {\n return escapeSingleQuoted(text);\n }\n }\n\n switch (encoding) {\n case 'base64':\n return `b64'${toBase64(bytes)}'`;\n case 'base64url':\n return `b64'${toBase64Url(bytes)}'`;\n case 'base32':\n return `b32'${base32Encode(bytes, B32_ALPHA)}'`;\n case 'base32hex':\n return `h32'${base32Encode(bytes, H32_ALPHA)}'`;\n case 'hex':\n default:\n return `h'${toHex(bytes)}'`;\n }\n}\n\nfunction tryDecodeUtf8(bytes: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n return null;\n }\n}\n\nfunction hasNonPrintable(value: string): boolean {\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 0x20 || codePoint === 0x7f)) {\n return true;\n }\n }\n return false;\n}\n\nfunction escapeAppString(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeSingleQuoted(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeQuoted(value: string, quote: string): string {\n let result = quote;\n const quoteCodePoint = quote.codePointAt(0);\n\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint === undefined) continue;\n\n switch (char) {\n case '\\\\':\n result += '\\\\\\\\';\n break;\n case '\\n':\n result += '\\\\n';\n break;\n case '\\r':\n result += '\\\\r';\n break;\n case '\\t':\n result += '\\\\t';\n break;\n default:\n if (codePoint === quoteCodePoint) {\n result += `\\\\${quote}`;\n } else if (\n codePoint < 0x20 ||\n codePoint === 0x7f ||\n codePoint === 0x2028 ||\n codePoint === 0x2029 ||\n codePoint === 0x200b ||\n codePoint === 0x200c ||\n codePoint === 0x200d ||\n codePoint === 0xfeff\n ) {\n result += `\\\\u${codePoint.toString(16).padStart(4, '0')}`;\n } else {\n result += char;\n }\n }\n }\n\n return result + quote;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type CborExtension, type ToCDNOptions } from '@cbortech/cbor';\nimport {\n CborByteString,\n CborNint,\n CborTextString,\n CborUint,\n type CborItem,\n} from '@cbortech/cbor/ast';\nimport { sha1 } from '@noble/hashes/legacy.js';\nimport { sha256, sha384, sha512, sha512_256 } from '@noble/hashes/sha2.js';\nimport { shake128_32, shake256_64 } from '@noble/hashes/sha3.js';\n\ntype HashFn = (data: Uint8Array) => Uint8Array;\n\nconst PREFIX_HASH = 'hash';\nconst DEFAULT_ALGORITHM_ID = -16;\n\nconst COSE_HASH_FN = new Map<number, HashFn>([\n [-14, sha1],\n [-15, (data) => sha256(data).slice(0, 8)],\n [-16, sha256],\n [-17, sha512_256],\n [-18, shake128_32],\n [-43, sha384],\n [-44, sha512],\n [-45, shake256_64],\n]);\n\nconst COSE_NAME_TO_ID = new Map<string, number>([\n ['SHA-1', -14],\n ['SHA-256/64', -15],\n ['SHA-256', -16],\n ['SHA-512/256', -17],\n ['SHAKE128', -18],\n ['SHA-384', -43],\n ['SHA-512', -44],\n ['SHAKE256', -45],\n]);\n\nconst COSE_ID_TO_NAME = new Map<number, string>(\n [...COSE_NAME_TO_ID.entries()].map(([name, id]) => [id, name])\n);\n\nexport class CborHashExt extends CborByteString {\n private readonly input: CborTextString | CborByteString;\n private readonly algorithmId: number;\n\n constructor(\n output: Uint8Array,\n input: CborTextString | CborByteString,\n algorithmId: number\n ) {\n super(output);\n this.input = input;\n this.algorithmId = algorithmId;\n }\n\n override _toCDN(options: ToCDNOptions | undefined, depth: number): string {\n if (options?.appStrings === false) return super._toCDN(options, depth);\n\n const isDefault = this.algorithmId === DEFAULT_ALGORITHM_ID;\n\n if (this.input instanceof CborTextString && isDefault) {\n return `${PREFIX_HASH}${escapeAppString(this.input.value)}`;\n }\n\n const dataCdn =\n this.input instanceof CborTextString\n ? escapeAppString(this.input.value)\n : serializeBytes(\n this.input.value,\n options?.bstrEncoding ?? 'hex',\n options?.sqstr\n );\n\n if (isDefault) return `${PREFIX_HASH}<<${dataCdn}>>`;\n\n const algorithmName = COSE_ID_TO_NAME.get(this.algorithmId);\n const algorithmCdn =\n algorithmName === undefined\n ? String(this.algorithmId)\n : `\"${algorithmName}\"`;\n return `${PREFIX_HASH}<<${dataCdn}, ${algorithmCdn}>>`;\n }\n}\n\nfunction resolveAlgorithmId(item: CborItem): number {\n if (item instanceof CborUint) return Number(item.value);\n if (item instanceof CborNint) return Number(item.value);\n if (item instanceof CborTextString) {\n const id = COSE_NAME_TO_ID.get(item.value);\n if (id === undefined) {\n throw new SyntaxError(\n `hash: unknown algorithm name: ${JSON.stringify(item.value)}`\n );\n }\n return id;\n }\n throw new SyntaxError('hash: algorithm must be an integer or text string');\n}\n\nfunction computeHash(\n input: CborTextString | CborByteString,\n algorithmId: number\n): CborHashExt {\n const data =\n input instanceof CborTextString\n ? new TextEncoder().encode(input.value)\n : input.value;\n const fn = COSE_HASH_FN.get(algorithmId);\n if (fn === undefined) {\n throw new SyntaxError(`hash: unsupported COSE algorithm ID ${algorithmId}`);\n }\n return new CborHashExt(fn(data), input, algorithmId);\n}\n\nexport const hash: CborExtension = {\n appStringPrefixes: [PREFIX_HASH],\n\n parseAppString(_prefix: string, content: string): CborItem {\n return computeHash(new CborTextString(content), DEFAULT_ALGORITHM_ID);\n },\n\n parseAppSequence(_prefix: string, items: CborItem[]): CborItem {\n if (items.length === 0 || items.length > 2) {\n throw new SyntaxError(\n `hash<<...>>: expected 1 or 2 items, got ${items.length}`\n );\n }\n\n const input = items[0];\n if (\n !(input instanceof CborTextString) &&\n !(input instanceof CborByteString)\n ) {\n throw new SyntaxError(\n 'hash: first argument must be a text or byte string'\n );\n }\n\n const algorithmId =\n items.length === 2 ? resolveAlgorithmId(items[1]) : DEFAULT_ALGORITHM_ID;\n return computeHash(input, algorithmId);\n },\n};\n\nexport default hash;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/=/g, '');\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nconst B32_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\nconst H32_ALPHA = '0123456789ABCDEFGHIJKLMNOPQRSTUV';\n\nfunction base32Encode(bytes: Uint8Array, alphabet: string): string {\n let result = '';\n let buffer = 0;\n let bufferBits = 0;\n\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bufferBits += 8;\n while (bufferBits >= 5) {\n bufferBits -= 5;\n result += alphabet[(buffer >> bufferBits) & 0x1f];\n }\n }\n\n if (bufferBits > 0) result += alphabet[(buffer << (5 - bufferBits)) & 0x1f];\n return result;\n}\n\nfunction serializeBytes(\n bytes: Uint8Array,\n encoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex',\n sqstr?: 'printable-string' | 'string' | 'none'\n): string {\n if (sqstr === 'string') {\n const text = tryDecodeUtf8(bytes);\n if (text !== null) return escapeSingleQuoted(text);\n }\n\n if (sqstr === 'printable-string' || sqstr === undefined) {\n const text = tryDecodeUtf8(bytes);\n if (text !== null && !hasNonPrintable(text)) {\n return escapeSingleQuoted(text);\n }\n }\n\n switch (encoding) {\n case 'base64':\n return `b64'${toBase64(bytes)}'`;\n case 'base64url':\n return `b64'${toBase64Url(bytes)}'`;\n case 'base32':\n return `b32'${base32Encode(bytes, B32_ALPHA)}'`;\n case 'base32hex':\n return `h32'${base32Encode(bytes, H32_ALPHA)}'`;\n case 'hex':\n default:\n return `h'${toHex(bytes)}'`;\n }\n}\n\nfunction tryDecodeUtf8(bytes: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n return null;\n }\n}\n\nfunction hasNonPrintable(value: string): boolean {\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 0x20 || codePoint === 0x7f)) {\n return true;\n }\n }\n return false;\n}\n\nfunction escapeAppString(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeSingleQuoted(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeQuoted(value: string, quote: string): string {\n let result = quote;\n const quoteCodePoint = quote.codePointAt(0);\n\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint === undefined) continue;\n\n switch (char) {\n case '\\\\':\n result += '\\\\\\\\';\n break;\n case '\\n':\n result += '\\\\n';\n break;\n case '\\r':\n result += '\\\\r';\n break;\n case '\\t':\n result += '\\\\t';\n break;\n default:\n if (codePoint === quoteCodePoint) {\n result += `\\\\${quote}`;\n } else if (\n codePoint < 0x20 ||\n codePoint === 0x7f ||\n codePoint === 0x2028 ||\n codePoint === 0x2029 ||\n codePoint === 0x200b ||\n codePoint === 0x200c ||\n codePoint === 0x200d ||\n codePoint === 0xfeff\n ) {\n result += `\\\\u${codePoint.toString(16).padStart(4, '0')}`;\n } else {\n result += char;\n }\n }\n }\n\n return result + quote;\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { CborByteString } from '@cbortech/cbor/ast';
2
2
  import { CborExtension } from '@cbortech/cbor';
3
3
  import { CborTextString } from '@cbortech/cbor/ast';
4
- import { ToEDNOptions } from '@cbortech/cbor';
4
+ import { ToCDNOptions } from '@cbortech/cbor';
5
5
 
6
6
  export declare class CborHashExt extends CborByteString {
7
7
  private readonly input;
8
8
  private readonly algorithmId;
9
9
  constructor(output: Uint8Array, input: CborTextString | CborByteString, algorithmId: number);
10
- _toEDN(options: ToEDNOptions | undefined, depth: number): string;
10
+ _toCDN(options: ToCDNOptions | undefined, depth: number): string;
11
11
  }
12
12
 
13
13
  declare const hash: CborExtension;
package/dist/index.js CHANGED
@@ -27,8 +27,8 @@ var d = "hash", f = -16, p = new Map([
27
27
  constructor(e, t, n) {
28
28
  super(e), this.input = t, this.algorithmId = n;
29
29
  }
30
- _toEDN(e, t) {
31
- if (e?.appStrings === !1) return super._toEDN(e, t);
30
+ _toCDN(e, t) {
31
+ if (e?.appStrings === !1) return super._toCDN(e, t);
32
32
  let r = this.algorithmId === f;
33
33
  if (this.input instanceof n && r) return `${d}${k(this.input.value)}`;
34
34
  let i = this.input instanceof n ? k(this.input.value) : E(this.input.value, e?.bstrEncoding ?? "hex", e?.sqstr);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type CborExtension, type ToEDNOptions } from '@cbortech/cbor';\nimport {\n CborByteString,\n CborNint,\n CborTextString,\n CborUint,\n type CborItem,\n} from '@cbortech/cbor/ast';\nimport { sha1 } from '@noble/hashes/legacy.js';\nimport { sha256, sha384, sha512, sha512_256 } from '@noble/hashes/sha2.js';\nimport { shake128_32, shake256_64 } from '@noble/hashes/sha3.js';\n\ntype HashFn = (data: Uint8Array) => Uint8Array;\n\nconst PREFIX_HASH = 'hash';\nconst DEFAULT_ALGORITHM_ID = -16;\n\nconst COSE_HASH_FN = new Map<number, HashFn>([\n [-14, sha1],\n [-15, (data) => sha256(data).slice(0, 8)],\n [-16, sha256],\n [-17, sha512_256],\n [-18, shake128_32],\n [-43, sha384],\n [-44, sha512],\n [-45, shake256_64],\n]);\n\nconst COSE_NAME_TO_ID = new Map<string, number>([\n ['SHA-1', -14],\n ['SHA-256/64', -15],\n ['SHA-256', -16],\n ['SHA-512/256', -17],\n ['SHAKE128', -18],\n ['SHA-384', -43],\n ['SHA-512', -44],\n ['SHAKE256', -45],\n]);\n\nconst COSE_ID_TO_NAME = new Map<number, string>(\n [...COSE_NAME_TO_ID.entries()].map(([name, id]) => [id, name])\n);\n\nexport class CborHashExt extends CborByteString {\n private readonly input: CborTextString | CborByteString;\n private readonly algorithmId: number;\n\n constructor(\n output: Uint8Array,\n input: CborTextString | CborByteString,\n algorithmId: number\n ) {\n super(output);\n this.input = input;\n this.algorithmId = algorithmId;\n }\n\n override _toEDN(options: ToEDNOptions | undefined, depth: number): string {\n if (options?.appStrings === false) return super._toEDN(options, depth);\n\n const isDefault = this.algorithmId === DEFAULT_ALGORITHM_ID;\n\n if (this.input instanceof CborTextString && isDefault) {\n return `${PREFIX_HASH}${escapeAppString(this.input.value)}`;\n }\n\n const dataEdn =\n this.input instanceof CborTextString\n ? escapeAppString(this.input.value)\n : serializeBytes(\n this.input.value,\n options?.bstrEncoding ?? 'hex',\n options?.sqstr\n );\n\n if (isDefault) return `${PREFIX_HASH}<<${dataEdn}>>`;\n\n const algorithmName = COSE_ID_TO_NAME.get(this.algorithmId);\n const algorithmEdn =\n algorithmName === undefined\n ? String(this.algorithmId)\n : `\"${algorithmName}\"`;\n return `${PREFIX_HASH}<<${dataEdn}, ${algorithmEdn}>>`;\n }\n}\n\nfunction resolveAlgorithmId(item: CborItem): number {\n if (item instanceof CborUint) return Number(item.value);\n if (item instanceof CborNint) return Number(item.value);\n if (item instanceof CborTextString) {\n const id = COSE_NAME_TO_ID.get(item.value);\n if (id === undefined) {\n throw new SyntaxError(\n `hash: unknown algorithm name: ${JSON.stringify(item.value)}`\n );\n }\n return id;\n }\n throw new SyntaxError('hash: algorithm must be an integer or text string');\n}\n\nfunction computeHash(\n input: CborTextString | CborByteString,\n algorithmId: number\n): CborHashExt {\n const data =\n input instanceof CborTextString\n ? new TextEncoder().encode(input.value)\n : input.value;\n const fn = COSE_HASH_FN.get(algorithmId);\n if (fn === undefined) {\n throw new SyntaxError(`hash: unsupported COSE algorithm ID ${algorithmId}`);\n }\n return new CborHashExt(fn(data), input, algorithmId);\n}\n\nexport const hash: CborExtension = {\n appStringPrefixes: [PREFIX_HASH],\n\n parseAppString(_prefix: string, content: string): CborItem {\n return computeHash(new CborTextString(content), DEFAULT_ALGORITHM_ID);\n },\n\n parseAppSequence(_prefix: string, items: CborItem[]): CborItem {\n if (items.length === 0 || items.length > 2) {\n throw new SyntaxError(\n `hash<<...>>: expected 1 or 2 items, got ${items.length}`\n );\n }\n\n const input = items[0];\n if (\n !(input instanceof CborTextString) &&\n !(input instanceof CborByteString)\n ) {\n throw new SyntaxError(\n 'hash: first argument must be a text or byte string'\n );\n }\n\n const algorithmId =\n items.length === 2 ? resolveAlgorithmId(items[1]) : DEFAULT_ALGORITHM_ID;\n return computeHash(input, algorithmId);\n },\n};\n\nexport default hash;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/=/g, '');\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nconst B32_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\nconst H32_ALPHA = '0123456789ABCDEFGHIJKLMNOPQRSTUV';\n\nfunction base32Encode(bytes: Uint8Array, alphabet: string): string {\n let result = '';\n let buffer = 0;\n let bufferBits = 0;\n\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bufferBits += 8;\n while (bufferBits >= 5) {\n bufferBits -= 5;\n result += alphabet[(buffer >> bufferBits) & 0x1f];\n }\n }\n\n if (bufferBits > 0) result += alphabet[(buffer << (5 - bufferBits)) & 0x1f];\n return result;\n}\n\nfunction serializeBytes(\n bytes: Uint8Array,\n encoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex',\n sqstr?: 'printable-string' | 'string' | 'none'\n): string {\n if (sqstr === 'string') {\n const text = tryDecodeUtf8(bytes);\n if (text !== null) return escapeSingleQuoted(text);\n }\n\n if (sqstr === 'printable-string' || sqstr === undefined) {\n const text = tryDecodeUtf8(bytes);\n if (text !== null && !hasNonPrintable(text)) {\n return escapeSingleQuoted(text);\n }\n }\n\n switch (encoding) {\n case 'base64':\n return `b64'${toBase64(bytes)}'`;\n case 'base64url':\n return `b64'${toBase64Url(bytes)}'`;\n case 'base32':\n return `b32'${base32Encode(bytes, B32_ALPHA)}'`;\n case 'base32hex':\n return `h32'${base32Encode(bytes, H32_ALPHA)}'`;\n case 'hex':\n default:\n return `h'${toHex(bytes)}'`;\n }\n}\n\nfunction tryDecodeUtf8(bytes: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n return null;\n }\n}\n\nfunction hasNonPrintable(value: string): boolean {\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 0x20 || codePoint === 0x7f)) {\n return true;\n }\n }\n return false;\n}\n\nfunction escapeAppString(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeSingleQuoted(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeQuoted(value: string, quote: string): string {\n let result = quote;\n const quoteCodePoint = quote.codePointAt(0);\n\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint === undefined) continue;\n\n switch (char) {\n case '\\\\':\n result += '\\\\\\\\';\n break;\n case '\\n':\n result += '\\\\n';\n break;\n case '\\r':\n result += '\\\\r';\n break;\n case '\\t':\n result += '\\\\t';\n break;\n default:\n if (codePoint === quoteCodePoint) {\n result += `\\\\${quote}`;\n } else if (\n codePoint < 0x20 ||\n codePoint === 0x7f ||\n codePoint === 0x2028 ||\n codePoint === 0x2029 ||\n codePoint === 0x200b ||\n codePoint === 0x200c ||\n codePoint === 0x200d ||\n codePoint === 0xfeff\n ) {\n result += `\\\\u${codePoint.toString(16).padStart(4, '0')}`;\n } else {\n result += char;\n }\n }\n }\n\n return result + quote;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { type CborExtension, type ToCDNOptions } from '@cbortech/cbor';\nimport {\n CborByteString,\n CborNint,\n CborTextString,\n CborUint,\n type CborItem,\n} from '@cbortech/cbor/ast';\nimport { sha1 } from '@noble/hashes/legacy.js';\nimport { sha256, sha384, sha512, sha512_256 } from '@noble/hashes/sha2.js';\nimport { shake128_32, shake256_64 } from '@noble/hashes/sha3.js';\n\ntype HashFn = (data: Uint8Array) => Uint8Array;\n\nconst PREFIX_HASH = 'hash';\nconst DEFAULT_ALGORITHM_ID = -16;\n\nconst COSE_HASH_FN = new Map<number, HashFn>([\n [-14, sha1],\n [-15, (data) => sha256(data).slice(0, 8)],\n [-16, sha256],\n [-17, sha512_256],\n [-18, shake128_32],\n [-43, sha384],\n [-44, sha512],\n [-45, shake256_64],\n]);\n\nconst COSE_NAME_TO_ID = new Map<string, number>([\n ['SHA-1', -14],\n ['SHA-256/64', -15],\n ['SHA-256', -16],\n ['SHA-512/256', -17],\n ['SHAKE128', -18],\n ['SHA-384', -43],\n ['SHA-512', -44],\n ['SHAKE256', -45],\n]);\n\nconst COSE_ID_TO_NAME = new Map<number, string>(\n [...COSE_NAME_TO_ID.entries()].map(([name, id]) => [id, name])\n);\n\nexport class CborHashExt extends CborByteString {\n private readonly input: CborTextString | CborByteString;\n private readonly algorithmId: number;\n\n constructor(\n output: Uint8Array,\n input: CborTextString | CborByteString,\n algorithmId: number\n ) {\n super(output);\n this.input = input;\n this.algorithmId = algorithmId;\n }\n\n override _toCDN(options: ToCDNOptions | undefined, depth: number): string {\n if (options?.appStrings === false) return super._toCDN(options, depth);\n\n const isDefault = this.algorithmId === DEFAULT_ALGORITHM_ID;\n\n if (this.input instanceof CborTextString && isDefault) {\n return `${PREFIX_HASH}${escapeAppString(this.input.value)}`;\n }\n\n const dataCdn =\n this.input instanceof CborTextString\n ? escapeAppString(this.input.value)\n : serializeBytes(\n this.input.value,\n options?.bstrEncoding ?? 'hex',\n options?.sqstr\n );\n\n if (isDefault) return `${PREFIX_HASH}<<${dataCdn}>>`;\n\n const algorithmName = COSE_ID_TO_NAME.get(this.algorithmId);\n const algorithmCdn =\n algorithmName === undefined\n ? String(this.algorithmId)\n : `\"${algorithmName}\"`;\n return `${PREFIX_HASH}<<${dataCdn}, ${algorithmCdn}>>`;\n }\n}\n\nfunction resolveAlgorithmId(item: CborItem): number {\n if (item instanceof CborUint) return Number(item.value);\n if (item instanceof CborNint) return Number(item.value);\n if (item instanceof CborTextString) {\n const id = COSE_NAME_TO_ID.get(item.value);\n if (id === undefined) {\n throw new SyntaxError(\n `hash: unknown algorithm name: ${JSON.stringify(item.value)}`\n );\n }\n return id;\n }\n throw new SyntaxError('hash: algorithm must be an integer or text string');\n}\n\nfunction computeHash(\n input: CborTextString | CborByteString,\n algorithmId: number\n): CborHashExt {\n const data =\n input instanceof CborTextString\n ? new TextEncoder().encode(input.value)\n : input.value;\n const fn = COSE_HASH_FN.get(algorithmId);\n if (fn === undefined) {\n throw new SyntaxError(`hash: unsupported COSE algorithm ID ${algorithmId}`);\n }\n return new CborHashExt(fn(data), input, algorithmId);\n}\n\nexport const hash: CborExtension = {\n appStringPrefixes: [PREFIX_HASH],\n\n parseAppString(_prefix: string, content: string): CborItem {\n return computeHash(new CborTextString(content), DEFAULT_ALGORITHM_ID);\n },\n\n parseAppSequence(_prefix: string, items: CborItem[]): CborItem {\n if (items.length === 0 || items.length > 2) {\n throw new SyntaxError(\n `hash<<...>>: expected 1 or 2 items, got ${items.length}`\n );\n }\n\n const input = items[0];\n if (\n !(input instanceof CborTextString) &&\n !(input instanceof CborByteString)\n ) {\n throw new SyntaxError(\n 'hash: first argument must be a text or byte string'\n );\n }\n\n const algorithmId =\n items.length === 2 ? resolveAlgorithmId(items[1]) : DEFAULT_ALGORITHM_ID;\n return computeHash(input, algorithmId);\n },\n};\n\nexport default hash;\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/=/g, '');\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nconst B32_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\nconst H32_ALPHA = '0123456789ABCDEFGHIJKLMNOPQRSTUV';\n\nfunction base32Encode(bytes: Uint8Array, alphabet: string): string {\n let result = '';\n let buffer = 0;\n let bufferBits = 0;\n\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bufferBits += 8;\n while (bufferBits >= 5) {\n bufferBits -= 5;\n result += alphabet[(buffer >> bufferBits) & 0x1f];\n }\n }\n\n if (bufferBits > 0) result += alphabet[(buffer << (5 - bufferBits)) & 0x1f];\n return result;\n}\n\nfunction serializeBytes(\n bytes: Uint8Array,\n encoding?: 'hex' | 'base64' | 'base64url' | 'base32' | 'base32hex',\n sqstr?: 'printable-string' | 'string' | 'none'\n): string {\n if (sqstr === 'string') {\n const text = tryDecodeUtf8(bytes);\n if (text !== null) return escapeSingleQuoted(text);\n }\n\n if (sqstr === 'printable-string' || sqstr === undefined) {\n const text = tryDecodeUtf8(bytes);\n if (text !== null && !hasNonPrintable(text)) {\n return escapeSingleQuoted(text);\n }\n }\n\n switch (encoding) {\n case 'base64':\n return `b64'${toBase64(bytes)}'`;\n case 'base64url':\n return `b64'${toBase64Url(bytes)}'`;\n case 'base32':\n return `b32'${base32Encode(bytes, B32_ALPHA)}'`;\n case 'base32hex':\n return `h32'${base32Encode(bytes, H32_ALPHA)}'`;\n case 'hex':\n default:\n return `h'${toHex(bytes)}'`;\n }\n}\n\nfunction tryDecodeUtf8(bytes: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n return null;\n }\n}\n\nfunction hasNonPrintable(value: string): boolean {\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint !== undefined && (codePoint < 0x20 || codePoint === 0x7f)) {\n return true;\n }\n }\n return false;\n}\n\nfunction escapeAppString(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeSingleQuoted(value: string): string {\n return escapeQuoted(value, \"'\");\n}\n\nfunction escapeQuoted(value: string, quote: string): string {\n let result = quote;\n const quoteCodePoint = quote.codePointAt(0);\n\n for (const char of value) {\n const codePoint = char.codePointAt(0);\n if (codePoint === undefined) continue;\n\n switch (char) {\n case '\\\\':\n result += '\\\\\\\\';\n break;\n case '\\n':\n result += '\\\\n';\n break;\n case '\\r':\n result += '\\\\r';\n break;\n case '\\t':\n result += '\\\\t';\n break;\n default:\n if (codePoint === quoteCodePoint) {\n result += `\\\\${quote}`;\n } else if (\n codePoint < 0x20 ||\n codePoint === 0x7f ||\n codePoint === 0x2028 ||\n codePoint === 0x2029 ||\n codePoint === 0x200b ||\n codePoint === 0x200c ||\n codePoint === 0x200d ||\n codePoint === 0xfeff\n ) {\n result += `\\\\u${codePoint.toString(16).padStart(4, '0')}`;\n } else {\n result += char;\n }\n }\n }\n\n return result + quote;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@cbortech/hash-extension",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Cryptographic hash application-string extension for @cbortech/cbor",
5
5
  "keywords": [
6
6
  "cbor",
7
+ "cdn",
7
8
  "cbor-edn",
8
9
  "hash"
9
10
  ],
@@ -64,24 +65,24 @@
64
65
  "format:check": "prettier --check ."
65
66
  },
66
67
  "peerDependencies": {
67
- "@cbortech/cbor": "^0.24.0"
68
+ "@cbortech/cbor": "^0.25.1"
68
69
  },
69
70
  "dependencies": {
70
71
  "@noble/hashes": "^2.2.0"
71
72
  },
72
73
  "devDependencies": {
73
- "@cbortech/cbor": "^0.24.0",
74
- "@types/node": "^24.12.4",
75
- "@vitest/browser": "^4.1.6",
76
- "@vitest/browser-playwright": "^4.1.6",
77
- "@vitest/coverage-v8": "^4.1.6",
78
- "@vitest/ui": "^4.1.6",
74
+ "@cbortech/cbor": "^0.25.1",
75
+ "@types/node": "^24.13.0",
76
+ "@vitest/browser": "^4.1.8",
77
+ "@vitest/browser-playwright": "^4.1.8",
78
+ "@vitest/coverage-v8": "^4.1.8",
79
+ "@vitest/ui": "^4.1.8",
79
80
  "cross-env": "^10.1.0",
80
81
  "playwright": "^1.60.0",
81
82
  "prettier": "^3.8.3",
82
83
  "typescript": "^5.9.3",
83
- "vite": "^8.0.12",
84
+ "vite": "^8.0.16",
84
85
  "vite-plugin-dts": "^4.5.4",
85
- "vitest": "^4.1.6"
86
+ "vitest": "^4.1.8"
86
87
  }
87
88
  }