this repo has no description

feat: add deterministic CBOR encoding

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+68
src
+68
src/pds.js
··· 1 export class PersonalDataServer { 2 constructor(state, env) { 3 this.state = state ··· 5 } 6 7 async fetch(request) { 8 return new Response('pds running', { status: 200 }) 9 } 10 }
··· 1 + // === CBOR ENCODING === 2 + // Minimal deterministic CBOR (RFC 8949) - sorted keys, minimal integers 3 + 4 + function cborEncode(value) { 5 + const parts = [] 6 + 7 + function encode(val) { 8 + if (val === null) { 9 + parts.push(0xf6) // null 10 + } else if (val === true) { 11 + parts.push(0xf5) // true 12 + } else if (val === false) { 13 + parts.push(0xf4) // false 14 + } else if (typeof val === 'number') { 15 + encodeInteger(val) 16 + } else if (typeof val === 'string') { 17 + const bytes = new TextEncoder().encode(val) 18 + encodeHead(3, bytes.length) // major type 3 = text string 19 + parts.push(...bytes) 20 + } else if (val instanceof Uint8Array) { 21 + encodeHead(2, val.length) // major type 2 = byte string 22 + parts.push(...val) 23 + } else if (Array.isArray(val)) { 24 + encodeHead(4, val.length) // major type 4 = array 25 + for (const item of val) encode(item) 26 + } else if (typeof val === 'object') { 27 + // Sort keys for deterministic encoding 28 + const keys = Object.keys(val).sort() 29 + encodeHead(5, keys.length) // major type 5 = map 30 + for (const key of keys) { 31 + encode(key) 32 + encode(val[key]) 33 + } 34 + } 35 + } 36 + 37 + function encodeHead(majorType, length) { 38 + const mt = majorType << 5 39 + if (length < 24) { 40 + parts.push(mt | length) 41 + } else if (length < 256) { 42 + parts.push(mt | 24, length) 43 + } else if (length < 65536) { 44 + parts.push(mt | 25, length >> 8, length & 0xff) 45 + } else if (length < 4294967296) { 46 + parts.push(mt | 26, (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff) 47 + } 48 + } 49 + 50 + function encodeInteger(n) { 51 + if (n >= 0) { 52 + encodeHead(0, n) // major type 0 = unsigned int 53 + } else { 54 + encodeHead(1, -n - 1) // major type 1 = negative int 55 + } 56 + } 57 + 58 + encode(value) 59 + return new Uint8Array(parts) 60 + } 61 + 62 export class PersonalDataServer { 63 constructor(state, env) { 64 this.state = state ··· 66 } 67 68 async fetch(request) { 69 + const url = new URL(request.url) 70 + if (url.pathname === '/test/cbor') { 71 + const encoded = cborEncode({ hello: 'world', num: 42 }) 72 + return new Response(encoded, { 73 + headers: { 'content-type': 'application/cbor' } 74 + }) 75 + } 76 return new Response('pds running', { status: 200 }) 77 } 78 }