@marcuspuchalla/nachos 0.1.0

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.
Files changed (100) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +674 -0
  3. package/README.md +345 -0
  4. package/dist/chunk-2FUTHZQQ.cjs +755 -0
  5. package/dist/chunk-2FUTHZQQ.cjs.map +1 -0
  6. package/dist/chunk-2HBCILJS.cjs +2034 -0
  7. package/dist/chunk-2HBCILJS.cjs.map +1 -0
  8. package/dist/chunk-7CFYWHS6.js +742 -0
  9. package/dist/chunk-7CFYWHS6.js.map +1 -0
  10. package/dist/chunk-PD72MVTX.cjs +160 -0
  11. package/dist/chunk-PD72MVTX.cjs.map +1 -0
  12. package/dist/chunk-ZDZ2B5PE.js +149 -0
  13. package/dist/chunk-ZDZ2B5PE.js.map +1 -0
  14. package/dist/chunk-ZRPJUEIZ.js +2020 -0
  15. package/dist/chunk-ZRPJUEIZ.js.map +1 -0
  16. package/dist/encoder/index.cjs +57 -0
  17. package/dist/encoder/index.cjs.map +1 -0
  18. package/dist/encoder/index.d.cts +72 -0
  19. package/dist/encoder/index.d.ts +72 -0
  20. package/dist/encoder/index.js +4 -0
  21. package/dist/encoder/index.js.map +1 -0
  22. package/dist/index.cjs +606 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +494 -0
  25. package/dist/index.d.ts +494 -0
  26. package/dist/index.js +523 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/metafile-cjs.json +1 -0
  29. package/dist/metafile-esm.json +1 -0
  30. package/dist/parser/index.cjs +85 -0
  31. package/dist/parser/index.cjs.map +1 -0
  32. package/dist/parser/index.d.cts +72 -0
  33. package/dist/parser/index.d.ts +72 -0
  34. package/dist/parser/index.js +4 -0
  35. package/dist/parser/index.js.map +1 -0
  36. package/dist/types-DvNlfbKB.d.cts +301 -0
  37. package/dist/types-DvNlfbKB.d.ts +301 -0
  38. package/dist/useCborSimpleEncoder-ButVU988.d.cts +268 -0
  39. package/dist/useCborSimpleEncoder-TVxzNJ_9.d.ts +268 -0
  40. package/dist/useCborTag-B_iaShG6.d.ts +142 -0
  41. package/dist/useCborTag-BfTIV8HM.d.cts +142 -0
  42. package/package.json +102 -0
  43. package/src/__tests__/public-api.test.ts +326 -0
  44. package/src/encoder/__tests__/cbor-collection-encoder.test.ts +331 -0
  45. package/src/encoder/__tests__/cbor-integer-encoder.test.ts +283 -0
  46. package/src/encoder/__tests__/cbor-simple-encoder.test.ts +224 -0
  47. package/src/encoder/__tests__/cbor-string-encoder.test.ts +345 -0
  48. package/src/encoder/__tests__/cbor-tag-encoder.test.ts +565 -0
  49. package/src/encoder/composables/#useCborTagEncoder.ts# +158 -0
  50. package/src/encoder/composables/useCborCollectionEncoder.ts +424 -0
  51. package/src/encoder/composables/useCborEncoder.ts +203 -0
  52. package/src/encoder/composables/useCborIntegerEncoder.ts +188 -0
  53. package/src/encoder/composables/useCborSimpleEncoder.ts +266 -0
  54. package/src/encoder/composables/useCborStringEncoder.ts +266 -0
  55. package/src/encoder/composables/useCborTagEncoder.ts +158 -0
  56. package/src/encoder/index.ts +35 -0
  57. package/src/encoder/types.ts +88 -0
  58. package/src/encoder/utils.ts +80 -0
  59. package/src/index.ts +434 -0
  60. package/src/parser/__tests__/ast-tree-structure.test.ts +311 -0
  61. package/src/parser/__tests__/cbor-collection-errors.test.ts +296 -0
  62. package/src/parser/__tests__/cbor-collection.test.ts +369 -0
  63. package/src/parser/__tests__/cbor-deterministic-encoding.test.ts +432 -0
  64. package/src/parser/__tests__/cbor-diagnostic.test.ts +333 -0
  65. package/src/parser/__tests__/cbor-duplicate-keys.test.ts +235 -0
  66. package/src/parser/__tests__/cbor-float-errors.test.ts +222 -0
  67. package/src/parser/__tests__/cbor-float.test.ts +502 -0
  68. package/src/parser/__tests__/cbor-integer-errors.test.ts +139 -0
  69. package/src/parser/__tests__/cbor-integer.test.ts +200 -0
  70. package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +403 -0
  71. package/src/parser/__tests__/cbor-parser-errors.test.ts +126 -0
  72. package/src/parser/__tests__/cbor-security-dos-protection.test.ts +503 -0
  73. package/src/parser/__tests__/cbor-sequences.test.ts +150 -0
  74. package/src/parser/__tests__/cbor-source-map.test.ts +321 -0
  75. package/src/parser/__tests__/cbor-standard-tags.test.ts +340 -0
  76. package/src/parser/__tests__/cbor-string-errors.test.ts +227 -0
  77. package/src/parser/__tests__/cbor-string.test.ts +224 -0
  78. package/src/parser/__tests__/cbor-tag-advanced.test.ts +500 -0
  79. package/src/parser/__tests__/cbor-tag-errors.test.ts +447 -0
  80. package/src/parser/__tests__/cbor-tag-source-map.test.ts +360 -0
  81. package/src/parser/__tests__/cbor-tag.test.ts +684 -0
  82. package/src/parser/__tests__/extreme-edge-cases.test.ts +146 -0
  83. package/src/parser/__tests__/pathBuilder.test.ts +256 -0
  84. package/src/parser/__tests__/rfc-test-vectors.test.ts +607 -0
  85. package/src/parser/__tests__/security-limits.test.ts +248 -0
  86. package/src/parser/__tests__/utils-errors.test.ts +127 -0
  87. package/src/parser/composables/useCborCollection.ts +509 -0
  88. package/src/parser/composables/useCborDiagnostic.ts +381 -0
  89. package/src/parser/composables/useCborFloat.ts +256 -0
  90. package/src/parser/composables/useCborInteger.ts +114 -0
  91. package/src/parser/composables/useCborParser.ts +951 -0
  92. package/src/parser/composables/useCborString.ts +330 -0
  93. package/src/parser/composables/useCborStringTypes.ts +129 -0
  94. package/src/parser/composables/useCborTag.ts +739 -0
  95. package/src/parser/index.ts +56 -0
  96. package/src/parser/types.ts +371 -0
  97. package/src/parser/utils/pathBuilder.ts +259 -0
  98. package/src/parser/utils.ts +398 -0
  99. package/src/utils/__tests__/logger.test.ts +186 -0
  100. package/src/utils/logger.ts +96 -0
package/README.md ADDED
@@ -0,0 +1,345 @@
1
+ <p align="center">
2
+ <img src="assets/img2.jpg" alt="NACHOS Logo" height="242">
3
+ </p>
4
+
5
+ <h1 align="center">NACHOS</h1>
6
+
7
+ <p align="center"><strong>Not Another CBOR Handling Object System</strong></p>
8
+
9
+ > RFC 8949 CBOR encoder/decoder with full source map support for interactive debugging
10
+
11
+ [![npm version](https://img.shields.io/npm/v/@marcuspuchalla/nachos.svg)](https://www.npmjs.com/package/@marcuspuchalla/nachos)
12
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue.svg)](https://www.typescriptlang.org/)
13
+ [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
14
+ [![Test Coverage](https://img.shields.io/badge/coverage-99.4%25-brightgreen.svg)]()
15
+
16
+ A production-ready, zero-dependency CBOR (Concise Binary Object Representation) codec implementation in TypeScript. Works in Node.js and browsers.
17
+
18
+ ## Features
19
+
20
+ - ✅ **RFC 8949 Compliant** - Full implementation of CBOR specification
21
+ - ✅ **Zero Dependencies** - No runtime dependencies, ~25KB minified
22
+ - ✅ **TypeScript First** - Complete type definitions with strict mode
23
+ - ✅ **Source Maps** - Bidirectional linking between hex bytes and decoded values
24
+ - ✅ **Cardano Support** - Plutus constructor tags (121-127, 1280-1400, 102)
25
+ - ✅ **Canonical Encoding** - Deterministic encoding for blockchain use cases
26
+ - ✅ **Tree-Shakeable** - Import only what you need
27
+ - ✅ **Browser & Node.js** - Works everywhere with ES2020 support
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install @marcuspuchalla/nachos
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ### Decoding CBOR
38
+
39
+ ```typescript
40
+ import { decode } from '@marcuspuchalla/nachos'
41
+
42
+ // Decode integer
43
+ const result = decode('1864')
44
+ console.log(result.value) // 100
45
+
46
+ // Decode string
47
+ decode('6449455446') // { value: "IETF", bytesRead: 5 }
48
+
49
+ // Decode array
50
+ decode('83010203') // { value: [1, 2, 3], bytesRead: 4 }
51
+
52
+ // Decode map
53
+ decode('a16161 01') // { value: { a: 1 }, bytesRead: 4 }
54
+
55
+ // Decode tagged value (Cardano)
56
+ decode('d87980') // { value: { tag: 121, value: [] }, bytesRead: 3 }
57
+ ```
58
+
59
+ ### Encoding CBOR
60
+
61
+ ```typescript
62
+ import { encode } from '@marcuspuchalla/nachos'
63
+
64
+ // Encode number
65
+ encode(100) // { hex: "1864", bytes: Uint8Array[0x18, 0x64] }
66
+
67
+ // Encode string
68
+ encode("IETF") // { hex: "6449455446", bytes: ... }
69
+
70
+ // Encode array
71
+ encode([1, 2, 3]) // { hex: "83010203", bytes: ... }
72
+
73
+ // Encode map with canonical ordering (sorted keys)
74
+ encode({ z: 1, a: 2 }, { canonical: true })
75
+ // Keys are sorted alphabetically: { a: 2, z: 1 }
76
+
77
+ // Encode tagged value
78
+ encode({ tag: 121, value: [] }) // { hex: "d87980", bytes: ... }
79
+ ```
80
+
81
+ ### Source Maps (Interactive Debugging)
82
+
83
+ ```typescript
84
+ import { decodeWithSourceMap } from '@marcuspuchalla/nachos'
85
+
86
+ const { value, sourceMap } = decodeWithSourceMap('d87980')
87
+
88
+ // Source map links hex bytes to decoded values
89
+ console.log(sourceMap)
90
+ // [
91
+ // {
92
+ // path: '',
93
+ // start: 0,
94
+ // end: 3,
95
+ // majorType: 6,
96
+ // type: 'Tag 121',
97
+ // children: ['.value']
98
+ // },
99
+ // {
100
+ // path: '.value',
101
+ // start: 2,
102
+ // end: 3,
103
+ // majorType: 4,
104
+ // type: 'Array',
105
+ // parent: ''
106
+ // }
107
+ // ]
108
+
109
+ // Use for hex-to-JSON highlighting in visualizers
110
+ const entry = sourceMap.find(e => e.path === '.value')
111
+ console.log(`Array is at hex bytes ${entry.start}-${entry.end}`)
112
+ ```
113
+
114
+ ## API Reference
115
+
116
+ ### Functional API (Recommended)
117
+
118
+ ```typescript
119
+ // Decoder
120
+ import { decode, decodeWithSourceMap } from '@marcuspuchalla/nachos'
121
+
122
+ decode(hexString: string, options?: ParseOptions): ParseResult
123
+ decodeWithSourceMap(hexString: string, options?: ParseOptions): ParseResultWithMap
124
+
125
+ // Encoder
126
+ import { encode, encodeToHex, encodeToBytes, encodeSequence } from '@marcuspuchalla/nachos'
127
+
128
+ encode(value: EncodableValue, options?: EncodeOptions): EncodeResult
129
+ encodeToHex(value: EncodableValue, options?: EncodeOptions): string
130
+ encodeToBytes(value: EncodableValue, options?: EncodeOptions): Uint8Array
131
+ encodeSequence(values: EncodableValue[], options?: EncodeOptions): EncodeResult
132
+ ```
133
+
134
+ ### Class API (Alternative)
135
+
136
+ ```typescript
137
+ import { CborDecoder, CborEncoder } from '@marcuspuchalla/nachos'
138
+
139
+ // Decoder with persistent options
140
+ const decoder = new CborDecoder({ strict: true })
141
+ const result1 = decoder.decode('1864')
142
+ const result2 = decoder.decodeWithSourceMap('d87980')
143
+
144
+ // Encoder with persistent options
145
+ const encoder = new CborEncoder({ canonical: true })
146
+ const encoded1 = encoder.encode(100)
147
+ const encoded2 = encoder.encodeToHex([1, 2, 3])
148
+ ```
149
+
150
+ ## Options
151
+
152
+ ### Parser Options
153
+
154
+ ```typescript
155
+ interface ParseOptions {
156
+ strict?: boolean // Enable all validations (Cardano mode)
157
+ validateCanonical?: boolean // Validate canonical encoding
158
+ allowIndefinite?: boolean // Allow indefinite-length encoding
159
+ rejectDuplicateKeys?: boolean // Reject duplicate map keys
160
+ validateUtf8Strict?: boolean // Strict UTF-8 validation
161
+ limits?: {
162
+ maxInputSize?: number // Max input bytes (default: 10 MB)
163
+ maxOutputSize?: number // Max output bytes (default: 100 MB)
164
+ maxStringLength?: number // Max string length (default: 1 MB)
165
+ maxArrayLength?: number // Max array length (default: 10,000)
166
+ maxMapSize?: number // Max map size (default: 10,000)
167
+ maxDepth?: number // Max nesting depth (default: 64)
168
+ maxParseTime?: number // Max parse time ms (default: 1000)
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Encoder Options
174
+
175
+ ```typescript
176
+ interface EncodeOptions {
177
+ canonical?: boolean // Canonical encoding (shortest form, sorted maps)
178
+ allowIndefinite?: boolean // Allow indefinite-length encoding
179
+ rejectDuplicateKeys?: boolean // Reject duplicate map keys
180
+ maxDepth?: number // Maximum nesting depth (default: 64)
181
+ maxOutputSize?: number // Maximum output size bytes (default: 100 MB)
182
+ }
183
+ ```
184
+
185
+ ## Examples
186
+
187
+ ### Cardano Transaction Decoding
188
+
189
+ ```typescript
190
+ import { decode } from '@marcuspuchalla/nachos'
191
+
192
+ // Real Cardano UTXO collateral
193
+ const collateralHex = '8282582048bd01d51e580cde15afa6d28f63d89c9137b93a910e5941192e26b12906106700'
194
+ const result = decode(collateralHex)
195
+
196
+ console.log(result.value)
197
+ // [[<txHash>, <outputIndex>], ...]
198
+ ```
199
+
200
+ ### Canonical Encoding for Blockchain
201
+
202
+ ```typescript
203
+ import { encode } from '@marcuspuchalla/nachos'
204
+
205
+ // Canonical encoding ensures deterministic output
206
+ const tx = {
207
+ inputs: [{ txId: "abc", index: 0 }],
208
+ outputs: [{ address: "addr1...", amount: 1000000 }]
209
+ }
210
+
211
+ const { hex } = encode(tx, { canonical: true })
212
+ // Always produces the same hex string (deterministic)
213
+ ```
214
+
215
+ ### Round-Trip Encoding/Decoding
216
+
217
+ ```typescript
218
+ import { encode, decode } from '@marcuspuchalla/nachos'
219
+
220
+ const original = { a: 1, b: [2, 3], c: "hello" }
221
+
222
+ // Encode
223
+ const { hex } = encode(original)
224
+
225
+ // Decode
226
+ const { value } = decode(hex)
227
+
228
+ console.log(value) // { a: 1, b: [2, 3], c: "hello" }
229
+ ```
230
+
231
+ ### Streaming with CBOR Sequences
232
+
233
+ ```typescript
234
+ import { encodeSequence, decode } from '@marcuspuchalla/nachos'
235
+
236
+ // Encode multiple values as sequence (RFC 8742)
237
+ const { hex } = encodeSequence([1, "hello", [2, 3]])
238
+
239
+ // Decode manually (parser stops after each value)
240
+ const result1 = decode(hex) // 1
241
+ const result2 = decode(hex.slice(result1.bytesRead * 2)) // "hello"
242
+ // ... etc
243
+ ```
244
+
245
+ ## Supported CBOR Types
246
+
247
+ | CBOR Type | JavaScript Type | Example |
248
+ |-----------|-----------------|---------|
249
+ | Unsigned Integer (MT 0) | `number`, `bigint` | `42`, `18446744073709551615n` |
250
+ | Negative Integer (MT 1) | `number`, `bigint` | `-1`, `-18446744073709551616n` |
251
+ | Byte String (MT 2) | `Uint8Array` | `new Uint8Array([0xff, 0x00])` |
252
+ | Text String (MT 3) | `string` | `"hello"` |
253
+ | Array (MT 4) | `Array` | `[1, 2, 3]` |
254
+ | Map (MT 5) | `Object`, `Map` | `{ a: 1 }` |
255
+ | Tagged Value (MT 6) | `{ tag, value }` | `{ tag: 121, value: [] }` |
256
+ | Simple/Float (MT 7) | `boolean`, `null`, `undefined`, `number` | `true`, `null`, `3.14` |
257
+
258
+ ![NACHOS](assets/img1.jpg)
259
+
260
+ ## Cardano Support
261
+
262
+ Full support for Cardano Plutus Data encoding:
263
+
264
+ - **Tag 121-127**: Compact constructors (0-6 fields)
265
+ - **Tag 1280-1400**: Extended constructors (7+)
266
+ - **Tag 102**: Alternative constructor encoding
267
+
268
+ ```typescript
269
+ import { decode } from '@marcuspuchalla/nachos'
270
+
271
+ // Plutus constructor tag 121 (Constructor 0)
272
+ const plutusData = decode('d87980') // Constructor 0, []
273
+
274
+ // Tag 122 (Constructor 1, 1 field)
275
+ decode('d87a81182a') // Constructor 1, [42]
276
+
277
+ // Tag 102 (Alternative encoding)
278
+ decode('d8668218c8811863') // Constructor 200, [[99]]
279
+ ```
280
+
281
+ ## Testing
282
+
283
+ This library is validated against the [core-cbor](https://github.com/marcuspuchalla/core-cbor) correctness test suite, ensuring RFC 8949 compliance and proper handling of edge cases.
284
+
285
+ ## Browser Compatibility
286
+
287
+ Requires ES2020+ for BigInt support:
288
+
289
+ - ✅ Chrome 67+
290
+ - ✅ Firefox 68+
291
+ - ✅ Safari 14+
292
+ - ✅ Edge 79+
293
+ - ✅ Node.js 18+
294
+
295
+ ## Security
296
+
297
+ Security features:
298
+ - ✅ **Depth limits** - Prevents stack overflow (default: 64)
299
+ - ✅ **Size limits** - Prevents memory exhaustion
300
+ - ✅ **Timeout protection** - Prevents infinite loops
301
+ - ✅ **UTF-8 validation** - Rejects invalid sequences
302
+ - ✅ **Overflow detection** - Safe integer arithmetic
303
+
304
+ Report security issues via [GitHub Issues](https://github.com/marcuspuchalla/nachos/issues).
305
+
306
+ ## Development
307
+
308
+ ```bash
309
+ # Install dependencies
310
+ npm install
311
+
312
+ # Build library
313
+ npm run build
314
+
315
+ # Run tests
316
+ npm test
317
+
318
+ # Type check
319
+ npm run type-check
320
+
321
+ # Watch mode
322
+ npm run build:watch
323
+ ```
324
+
325
+ ## License
326
+
327
+ GPL-3.0 © 2025 Marcus Puchalla
328
+
329
+ ## Demo
330
+
331
+ See this library in action at [cbor.app](https://cbor.app).
332
+
333
+ ## Related
334
+
335
+ - [RFC 8949 - CBOR Specification](https://datatracker.ietf.org/doc/html/rfc8949)
336
+ - [RFC 8742 - CBOR Sequences](https://datatracker.ietf.org/doc/html/rfc8742)
337
+ - [Cardano Plutus Data Encoding](https://cips.cardano.org/)
338
+
339
+ ## Contributing
340
+
341
+ Contributions welcome! Please open an issue or PR.
342
+
343
+ ## Changelog
344
+
345
+ See [CHANGELOG.md](./CHANGELOG.md) for release history.