@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/src/index.ts ADDED
@@ -0,0 +1,434 @@
1
+ /**
2
+ * NACHOS - Not Another CBOR Handling Object System
3
+ *
4
+ * RFC 8949 CBOR (Concise Binary Object Representation) encoder and decoder
5
+ * with full source map support for interactive debugging.
6
+ *
7
+ * @module @marcuspuchalla/nachos
8
+ * @see https://datatracker.ietf.org/doc/html/rfc8949
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Simple decoding
13
+ * import { decode } from '@marcuspuchalla/nachos'
14
+ * const result = decode('1864') // { value: 100, bytesRead: 2 }
15
+ *
16
+ * // Simple encoding
17
+ * import { encode } from '@marcuspuchalla/nachos'
18
+ * const { hex, bytes } = encode(100) // hex: "1864"
19
+ *
20
+ * // With source maps for debugging
21
+ * import { decodeWithSourceMap } from '@marcuspuchalla/nachos'
22
+ * const { value, sourceMap } = decodeWithSourceMap('d87980')
23
+ * // sourceMap links hex bytes to decoded values
24
+ * ```
25
+ */
26
+
27
+ // Re-export from parser (decoder)
28
+ export { useCborParser } from './parser/composables/useCborParser'
29
+ export { useCborInteger } from './parser/composables/useCborInteger'
30
+ export { useCborString } from './parser/composables/useCborString'
31
+ export { useCborCollection } from './parser/composables/useCborCollection'
32
+ export { useCborFloat } from './parser/composables/useCborFloat'
33
+ export { useCborTag } from './parser/composables/useCborTag'
34
+ export { useCborDiagnostic } from './parser/composables/useCborDiagnostic'
35
+ export type { DiagnosticOptions } from './parser/composables/useCborDiagnostic'
36
+
37
+ // Re-export utilities
38
+ export { PathBuilder } from './parser/utils/pathBuilder'
39
+
40
+ // Re-export from encoder
41
+ export { useCborEncoder } from './encoder/composables/useCborEncoder'
42
+ export { useCborIntegerEncoder } from './encoder/composables/useCborIntegerEncoder'
43
+ export { useCborStringEncoder } from './encoder/composables/useCborStringEncoder'
44
+ export { useCborCollectionEncoder } from './encoder/composables/useCborCollectionEncoder'
45
+ export { useCborSimpleEncoder } from './encoder/composables/useCborSimpleEncoder'
46
+
47
+ // Re-export types
48
+ export type {
49
+ // Parser types
50
+ ParseResult,
51
+ ParseResultWithMap,
52
+ ParseOptions,
53
+ ParseError,
54
+ ParserLimits,
55
+ CborContext,
56
+ CborValue,
57
+ CborMap,
58
+ TaggedValue,
59
+ PlutusData,
60
+ PlutusConstr,
61
+ PlutusMap,
62
+ PlutusList,
63
+ PlutusInt,
64
+ PlutusBytes,
65
+ SourceMapEntry,
66
+ Result
67
+ } from './parser/types'
68
+
69
+ export {
70
+ // Default options
71
+ DEFAULT_OPTIONS,
72
+ DEFAULT_LIMITS,
73
+ // Enums
74
+ CborMajorType,
75
+ CborAdditionalInfo,
76
+ CborSimpleValue,
77
+ CborTag
78
+ } from './parser/types'
79
+
80
+ export type {
81
+ // Encoder types
82
+ EncodeResult,
83
+ EncodeOptions,
84
+ EncodableValue,
85
+ EncodeContext
86
+ } from './encoder/types'
87
+
88
+ export {
89
+ DEFAULT_ENCODE_OPTIONS
90
+ } from './encoder/types'
91
+
92
+ // Convenience exports with cleaner names for library users
93
+ import { useCborParser } from './parser/composables/useCborParser'
94
+ import { useCborEncoder } from './encoder/composables/useCborEncoder'
95
+ import type { ParseResult, ParseResultWithMap, ParseOptions } from './parser/types'
96
+ import type { EncodeResult, EncodeOptions, EncodableValue } from './encoder/types'
97
+
98
+ /**
99
+ * Decode CBOR hex string to JavaScript value
100
+ *
101
+ * @param hexString - CBOR data as hex string (e.g., "1864" for integer 100)
102
+ * @param options - Optional parser configuration
103
+ * @returns Decoded value and number of bytes consumed
104
+ *
105
+ * @throws {Error} If input is invalid or malformed CBOR
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Decode integer
110
+ * decode('1864') // { value: 100, bytesRead: 2 }
111
+ *
112
+ * // Decode string
113
+ * decode('6449455446') // { value: "IETF", bytesRead: 5 }
114
+ *
115
+ * // Decode array
116
+ * decode('83010203') // { value: [1, 2, 3], bytesRead: 4 }
117
+ *
118
+ * // With strict validation
119
+ * decode('1864', { strict: true })
120
+ *
121
+ * // With canonical validation
122
+ * decode('a16161 01', { validateCanonical: true })
123
+ * ```
124
+ *
125
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc8949 | RFC 8949}
126
+ */
127
+ export function decode(hexString: string, options?: ParseOptions): ParseResult {
128
+ const { parse } = useCborParser()
129
+ return parse(hexString, options)
130
+ }
131
+
132
+ /**
133
+ * Decode CBOR hex string with source map generation
134
+ *
135
+ * Source maps provide bidirectional linking between hex bytes and decoded values,
136
+ * enabling interactive debugging visualizations.
137
+ *
138
+ * @param hexString - CBOR data as hex string
139
+ * @param options - Optional parser configuration
140
+ * @returns Decoded value, byte count, and source map
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const { value, sourceMap } = decodeWithSourceMap('d87980')
145
+ * // value: { tag: 121, value: [] }
146
+ * // sourceMap: [
147
+ * // { path: '', start: 0, end: 3, majorType: 6, type: 'Tag 121', children: ['.value'] },
148
+ * // { path: '.value', start: 2, end: 3, majorType: 4, type: 'Array', parent: '' }
149
+ * // ]
150
+ *
151
+ * // Use source map for hex-to-JSON linking
152
+ * const entry = sourceMap.find(e => e.path === '.value')
153
+ * console.log(`Value is at bytes ${entry.start}-${entry.end}`)
154
+ * ```
155
+ */
156
+ export function decodeWithSourceMap(hexString: string, options?: ParseOptions): ParseResultWithMap {
157
+ const { parseWithSourceMap } = useCborParser()
158
+ return parseWithSourceMap(hexString, options)
159
+ }
160
+
161
+ /**
162
+ * Encode JavaScript value to CBOR
163
+ *
164
+ * Automatically detects value type and uses appropriate CBOR encoding.
165
+ * Supports: numbers, bigints, strings, booleans, null, undefined, Uint8Arrays, arrays, objects, and tagged values.
166
+ *
167
+ * @param value - JavaScript value to encode
168
+ * @param options - Optional encoder configuration
169
+ * @returns CBOR bytes and hex string
170
+ *
171
+ * @throws {Error} If value type is unsupported or encoding fails
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Encode number
176
+ * encode(100) // { hex: "1864", bytes: Uint8Array[0x18, 0x64] }
177
+ *
178
+ * // Encode string
179
+ * encode("IETF") // { hex: "6449455446", bytes: ... }
180
+ *
181
+ * // Encode array
182
+ * encode([1, 2, 3]) // { hex: "83010203", bytes: ... }
183
+ *
184
+ * // Encode map (canonical - sorted keys)
185
+ * encode({ z: 1, a: 2 }, { canonical: true })
186
+ * // Keys will be sorted: { a: 2, z: 1 }
187
+ *
188
+ * // Encode tagged value
189
+ * encode({ tag: 121, value: [] }) // { hex: "d87980", bytes: ... }
190
+ * ```
191
+ */
192
+ export function encode(value: EncodableValue, options?: Partial<EncodeOptions>): EncodeResult {
193
+ const { encode: encodeValue } = useCborEncoder(options)
194
+ return encodeValue(value)
195
+ }
196
+
197
+ /**
198
+ * Encode JavaScript value to CBOR hex string
199
+ *
200
+ * Convenience function that returns only the hex string (not the bytes).
201
+ *
202
+ * @param value - JavaScript value to encode
203
+ * @param options - Optional encoder configuration
204
+ * @returns CBOR hex string
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * encodeToHex(100) // "1864"
209
+ * encodeToHex([1, 2, 3]) // "83010203"
210
+ * encodeToHex({ a: 1 }, { canonical: true }) // "a16161 01"
211
+ * ```
212
+ */
213
+ export function encodeToHex(value: EncodableValue, options?: Partial<EncodeOptions>): string {
214
+ const { encodeToHex: encodeValueToHex } = useCborEncoder(options)
215
+ return encodeValueToHex(value)
216
+ }
217
+
218
+ /**
219
+ * Encode JavaScript value to CBOR bytes
220
+ *
221
+ * Convenience function that returns only the bytes (not the hex string).
222
+ *
223
+ * @param value - JavaScript value to encode
224
+ * @param options - Optional encoder configuration
225
+ * @returns CBOR bytes as Uint8Array
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * const bytes = encodeToBytes(100) // Uint8Array[0x18, 0x64]
230
+ * const bytes = encodeToBytes([1, 2, 3]) // Uint8Array[0x83, 0x01, 0x02, 0x03]
231
+ * ```
232
+ */
233
+ export function encodeToBytes(value: EncodableValue, options?: Partial<EncodeOptions>): Uint8Array {
234
+ const { encodeToBytes: encodeValueToBytes } = useCborEncoder(options)
235
+ return encodeValueToBytes(value)
236
+ }
237
+
238
+ /**
239
+ * Encode multiple values as CBOR sequence
240
+ *
241
+ * Creates a CBOR sequence (RFC 8742) by concatenating multiple encoded values.
242
+ * Useful for streaming or batch encoding.
243
+ *
244
+ * @param values - Array of values to encode
245
+ * @param options - Optional encoder configuration
246
+ * @returns Concatenated CBOR bytes and hex string
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * encodeSequence([1, "hello", [2, 3]])
251
+ * // Returns concatenated encoding: 0x01 + 0x6568656c6c6f + 0x820203
252
+ * ```
253
+ *
254
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc8742 | RFC 8742 - CBOR Sequences}
255
+ */
256
+ export function encodeSequence(values: EncodableValue[], options?: Partial<EncodeOptions>): EncodeResult {
257
+ const { encodeSequence: encodeSeq } = useCborEncoder(options)
258
+ return encodeSeq(values)
259
+ }
260
+
261
+ /**
262
+ * Class-based CBOR decoder
263
+ *
264
+ * Provides an object-oriented interface for CBOR decoding.
265
+ * Useful when you need to maintain decoder state or configuration.
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * const decoder = new CborDecoder({ strict: true })
270
+ *
271
+ * const result1 = decoder.decode('1864')
272
+ * const result2 = decoder.decode('6449455446')
273
+ *
274
+ * const withMap = decoder.decodeWithSourceMap('d87980')
275
+ * ```
276
+ */
277
+ export class CborDecoder {
278
+ private options: ParseOptions
279
+
280
+ /**
281
+ * Create a new CBOR decoder
282
+ *
283
+ * @param options - Parser configuration
284
+ */
285
+ constructor(options?: ParseOptions) {
286
+ this.options = options || {}
287
+ }
288
+
289
+ /**
290
+ * Decode CBOR hex string
291
+ *
292
+ * @param hexString - CBOR data as hex string
293
+ * @returns Decoded value and byte count
294
+ */
295
+ decode(hexString: string): ParseResult {
296
+ return decode(hexString, this.options)
297
+ }
298
+
299
+ /**
300
+ * Decode CBOR hex string with source map
301
+ *
302
+ * @param hexString - CBOR data as hex string
303
+ * @returns Decoded value, byte count, and source map
304
+ */
305
+ decodeWithSourceMap(hexString: string): ParseResultWithMap {
306
+ return decodeWithSourceMap(hexString, this.options)
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Class-based CBOR encoder
312
+ *
313
+ * Provides an object-oriented interface for CBOR encoding.
314
+ * Useful when you need to maintain encoder state or configuration.
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * const encoder = new CborEncoder({ canonical: true })
319
+ *
320
+ * const result1 = encoder.encode(100)
321
+ * const result2 = encoder.encode([1, 2, 3])
322
+ *
323
+ * const hex = encoder.encodeToHex({ a: 1 }) // Keys will be sorted
324
+ * ```
325
+ */
326
+ export class CborEncoder {
327
+ private options: Partial<EncodeOptions>
328
+
329
+ /**
330
+ * Create a new CBOR encoder
331
+ *
332
+ * @param options - Encoder configuration
333
+ */
334
+ constructor(options?: Partial<EncodeOptions>) {
335
+ this.options = options || {}
336
+ }
337
+
338
+ /**
339
+ * Encode value to CBOR
340
+ *
341
+ * @param value - JavaScript value to encode
342
+ * @returns CBOR bytes and hex string
343
+ */
344
+ encode(value: EncodableValue): EncodeResult {
345
+ return encode(value, this.options)
346
+ }
347
+
348
+ /**
349
+ * Encode value to CBOR hex string
350
+ *
351
+ * @param value - JavaScript value to encode
352
+ * @returns CBOR hex string
353
+ */
354
+ encodeToHex(value: EncodableValue): string {
355
+ return encodeToHex(value, this.options)
356
+ }
357
+
358
+ /**
359
+ * Encode value to CBOR bytes
360
+ *
361
+ * @param value - JavaScript value to encode
362
+ * @returns CBOR bytes
363
+ */
364
+ encodeToBytes(value: EncodableValue): Uint8Array {
365
+ return encodeToBytes(value, this.options)
366
+ }
367
+
368
+ /**
369
+ * Encode multiple values as CBOR sequence
370
+ *
371
+ * @param values - Array of values to encode
372
+ * @returns Concatenated CBOR encoding
373
+ */
374
+ encodeSequence(values: EncodableValue[]): EncodeResult {
375
+ return encodeSequence(values, this.options)
376
+ }
377
+ }
378
+
379
+ // Import diagnostic notation utilities
380
+ import { useCborDiagnostic } from './parser/composables/useCborDiagnostic'
381
+ import type { DiagnosticOptions } from './parser/composables/useCborDiagnostic'
382
+
383
+ /**
384
+ * Convert a JavaScript value to RFC 8949 diagnostic notation
385
+ *
386
+ * Diagnostic notation is a human-readable representation of CBOR data
387
+ * as defined in RFC 8949 Appendix B.
388
+ *
389
+ * @param value - JavaScript value to convert
390
+ * @param options - Optional formatting options
391
+ * @returns Diagnostic notation string
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * toDiagnostic(100) // "100"
396
+ * toDiagnostic(new Uint8Array([1,2])) // "h'0102'"
397
+ * toDiagnostic([1, 2, 3]) // "[1, 2, 3]"
398
+ * toDiagnostic({a: 1}) // '{"a": 1}'
399
+ * toDiagnostic({tag: 1, value: 123}) // "1(123)"
400
+ *
401
+ * // Pretty print
402
+ * toDiagnostic([1, 2], { pretty: true })
403
+ * // "[\n 1,\n 2\n]"
404
+ *
405
+ * // Indefinite length
406
+ * toDiagnostic([1, 2], { indefinite: true })
407
+ * // "[_ 1, 2]"
408
+ * ```
409
+ */
410
+ export function toDiagnostic(value: unknown, options?: DiagnosticOptions): string {
411
+ const { toDiagnostic: convert } = useCborDiagnostic()
412
+ return convert(value, options)
413
+ }
414
+
415
+ /**
416
+ * Decode CBOR and return diagnostic notation
417
+ *
418
+ * Combines decoding and diagnostic conversion in one step.
419
+ *
420
+ * @param hexString - CBOR data as hex string
421
+ * @param options - Optional formatting options
422
+ * @returns Diagnostic notation string
423
+ *
424
+ * @example
425
+ * ```typescript
426
+ * decodeToDiagnostic('1864') // "100"
427
+ * decodeToDiagnostic('83010203') // "[1, 2, 3]"
428
+ * decodeToDiagnostic('d87980') // "121([])"
429
+ * ```
430
+ */
431
+ export function decodeToDiagnostic(hexString: string, options?: DiagnosticOptions): string {
432
+ const { value } = decode(hexString)
433
+ return toDiagnostic(value, options)
434
+ }