@bcts/envelope 1.0.0-alpha.10

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 (44) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +23 -0
  3. package/dist/index.cjs +2646 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +782 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.mts +782 -0
  8. package/dist/index.d.mts.map +1 -0
  9. package/dist/index.iife.js +2644 -0
  10. package/dist/index.iife.js.map +1 -0
  11. package/dist/index.mjs +2552 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +84 -0
  14. package/src/base/assertion.ts +179 -0
  15. package/src/base/assertions.ts +153 -0
  16. package/src/base/cbor.ts +122 -0
  17. package/src/base/digest.ts +204 -0
  18. package/src/base/elide.ts +390 -0
  19. package/src/base/envelope-decodable.ts +186 -0
  20. package/src/base/envelope-encodable.ts +71 -0
  21. package/src/base/envelope.ts +988 -0
  22. package/src/base/error.ts +421 -0
  23. package/src/base/index.ts +56 -0
  24. package/src/base/leaf.ts +147 -0
  25. package/src/base/queries.ts +244 -0
  26. package/src/base/walk.ts +215 -0
  27. package/src/base/wrap.ts +26 -0
  28. package/src/extension/attachment.ts +280 -0
  29. package/src/extension/compress.ts +176 -0
  30. package/src/extension/encrypt.ts +297 -0
  31. package/src/extension/expression.ts +404 -0
  32. package/src/extension/index.ts +72 -0
  33. package/src/extension/proof.ts +227 -0
  34. package/src/extension/recipient.ts +440 -0
  35. package/src/extension/salt.ts +114 -0
  36. package/src/extension/signature.ts +398 -0
  37. package/src/extension/types.ts +92 -0
  38. package/src/format/diagnostic.ts +116 -0
  39. package/src/format/hex.ts +25 -0
  40. package/src/format/index.ts +13 -0
  41. package/src/format/tree.ts +168 -0
  42. package/src/index.ts +32 -0
  43. package/src/utils/index.ts +8 -0
  44. package/src/utils/string.ts +48 -0
@@ -0,0 +1,186 @@
1
+ import type { Cbor } from "@bcts/dcbor";
2
+ import { tryIntoText, tryIntoBool, tryIntoByteString, isNull, decodeCbor } from "@bcts/dcbor";
3
+ import { Envelope } from "./envelope";
4
+ import { EnvelopeError } from "./error";
5
+
6
+ /// Provides functions for extracting typed values from envelopes.
7
+ ///
8
+ /// This module defines conversion functions that parallel Rust's `TryFrom<Envelope>`
9
+ /// implementations. These allow extracting specific types from envelope leaf values.
10
+ ///
11
+ /// In the Rust version, a macro (`impl_envelope_decodable!`) is used to generate
12
+ /// these implementations for many types. In TypeScript, we provide explicit
13
+ /// conversion functions instead.
14
+
15
+ /// Extracts a string value from an envelope.
16
+ ///
17
+ /// @param envelope - The envelope to extract from
18
+ /// @returns The string value
19
+ /// @throws {EnvelopeError} If the envelope is not a leaf or cannot be converted
20
+ export function extractString(envelope: Envelope): string {
21
+ const cbor = envelope.tryLeaf();
22
+ try {
23
+ return tryIntoText(cbor);
24
+ } catch (error) {
25
+ throw EnvelopeError.cbor(
26
+ "envelope does not contain a string",
27
+ error instanceof Error ? error : undefined,
28
+ );
29
+ }
30
+ }
31
+
32
+ /// Extracts a number value from an envelope.
33
+ ///
34
+ /// @param envelope - The envelope to extract from
35
+ /// @returns The number value
36
+ /// @throws {EnvelopeError} If the envelope is not a leaf or cannot be converted
37
+ export function extractNumber(envelope: Envelope): number {
38
+ const cbor = envelope.tryLeaf();
39
+
40
+ // Handle unsigned, negative, and simple (float) types
41
+ if ("type" in cbor) {
42
+ switch (cbor.type) {
43
+ case 0: // MajorType.Unsigned
44
+ return typeof cbor.value === "bigint" ? Number(cbor.value) : cbor.value;
45
+ case 1: {
46
+ // MajorType.Negative
47
+ // Negative values are stored as magnitude, convert back
48
+ const magnitude = typeof cbor.value === "bigint" ? Number(cbor.value) : cbor.value;
49
+ return -magnitude - 1;
50
+ }
51
+ case 7: // MajorType.Simple
52
+ if (
53
+ typeof cbor.value === "object" &&
54
+ cbor.value !== null &&
55
+ "type" in cbor.value &&
56
+ cbor.value.type === "Float"
57
+ ) {
58
+ return cbor.value.value;
59
+ }
60
+ break;
61
+ case 2: // MajorType.ByteString
62
+ case 3: // MajorType.TextString
63
+ case 4: // MajorType.Array
64
+ case 5: // MajorType.Map
65
+ case 6: // MajorType.Tag
66
+ // These CBOR types don't represent numbers
67
+ break;
68
+ }
69
+ }
70
+
71
+ throw EnvelopeError.cbor("envelope does not contain a number");
72
+ }
73
+
74
+ /// Extracts a boolean value from an envelope.
75
+ ///
76
+ /// @param envelope - The envelope to extract from
77
+ /// @returns The boolean value
78
+ /// @throws {EnvelopeError} If the envelope is not a leaf or cannot be converted
79
+ export function extractBoolean(envelope: Envelope): boolean {
80
+ const cbor = envelope.tryLeaf();
81
+ try {
82
+ return tryIntoBool(cbor);
83
+ } catch (error) {
84
+ throw EnvelopeError.cbor(
85
+ "envelope does not contain a boolean",
86
+ error instanceof Error ? error : undefined,
87
+ );
88
+ }
89
+ }
90
+
91
+ /// Extracts a byte array value from an envelope.
92
+ ///
93
+ /// @param envelope - The envelope to extract from
94
+ /// @returns The byte array value
95
+ /// @throws {EnvelopeError} If the envelope is not a leaf or cannot be converted
96
+ export function extractBytes(envelope: Envelope): Uint8Array {
97
+ const cbor = envelope.tryLeaf();
98
+ try {
99
+ return tryIntoByteString(cbor);
100
+ } catch (error) {
101
+ throw EnvelopeError.cbor(
102
+ "envelope does not contain bytes",
103
+ error instanceof Error ? error : undefined,
104
+ );
105
+ }
106
+ }
107
+
108
+ /// Extracts null from an envelope.
109
+ ///
110
+ /// @param envelope - The envelope to extract from
111
+ /// @throws {EnvelopeError} If the envelope is not a leaf containing null
112
+ export function extractNull(envelope: Envelope): null {
113
+ const cbor = envelope.tryLeaf();
114
+ if (isNull(cbor)) {
115
+ return null;
116
+ }
117
+ throw EnvelopeError.cbor("envelope does not contain null");
118
+ }
119
+
120
+ /// Static methods for creating envelopes from CBOR data.
121
+ ///
122
+ /// These are convenience methods that mirror the Rust implementation.
123
+ export class EnvelopeDecoder {
124
+ /// Creates an envelope from a CBOR value.
125
+ ///
126
+ /// @param cbor - The CBOR value to convert into an envelope
127
+ /// @returns A new envelope created from the CBOR data
128
+ /// @throws {EnvelopeError} If the CBOR does not represent a valid envelope
129
+ static tryFromCbor(cbor: Cbor): Envelope {
130
+ try {
131
+ return Envelope.fromTaggedCbor(cbor);
132
+ } catch (error) {
133
+ throw EnvelopeError.cbor("invalid envelope CBOR", error instanceof Error ? error : undefined);
134
+ }
135
+ }
136
+
137
+ /// Creates an envelope from raw CBOR binary data.
138
+ ///
139
+ /// @param data - The raw CBOR binary data to convert into an envelope
140
+ /// @returns A new envelope created from the CBOR data
141
+ /// @throws {EnvelopeError} If the data is not valid CBOR or does not
142
+ /// represent a valid envelope structure
143
+ static tryFromCborData(data: Uint8Array): Envelope {
144
+ try {
145
+ const cbor = decodeCbor(data);
146
+ return EnvelopeDecoder.tryFromCbor(cbor);
147
+ } catch (error) {
148
+ throw EnvelopeError.cbor(
149
+ "invalid envelope CBOR data",
150
+ error instanceof Error ? error : undefined,
151
+ );
152
+ }
153
+ }
154
+ }
155
+
156
+ /// Add the tryLeaf method to Envelope prototype.
157
+ ///
158
+ /// This extracts the leaf CBOR value from an envelope.
159
+ Envelope.prototype.tryLeaf = function (this: Envelope): Cbor {
160
+ const c = this.case();
161
+ if (c.type !== "leaf") {
162
+ throw EnvelopeError.notLeaf();
163
+ }
164
+ return c.cbor;
165
+ };
166
+
167
+ /// Add extraction convenience methods to Envelope prototype
168
+ Envelope.prototype.extractString = function (this: Envelope): string {
169
+ return extractString(this);
170
+ };
171
+
172
+ Envelope.prototype.extractNumber = function (this: Envelope): number {
173
+ return extractNumber(this);
174
+ };
175
+
176
+ Envelope.prototype.extractBoolean = function (this: Envelope): boolean {
177
+ return extractBoolean(this);
178
+ };
179
+
180
+ Envelope.prototype.extractBytes = function (this: Envelope): Uint8Array {
181
+ return extractBytes(this);
182
+ };
183
+
184
+ Envelope.prototype.extractNull = function (this: Envelope): null {
185
+ return extractNull(this);
186
+ };
@@ -0,0 +1,71 @@
1
+ import type { Envelope } from "./envelope";
2
+
3
+ /// A trait for types that can be encoded as a Gordian Envelope.
4
+ ///
5
+ /// This interface defines the contract for converting a value into an envelope.
6
+ /// Types implementing this interface can be used directly with envelope
7
+ /// construction functions without explicit conversion.
8
+ ///
9
+ /// There are numerous built-in implementations for common types including:
10
+ /// - Primitive types (numbers, strings, booleans)
11
+ /// - CBOR values
12
+ /// - Cryptographic types (digests, keys, etc.)
13
+ /// - Assertions
14
+ /// - Other envelopes
15
+ ///
16
+ /// @example
17
+ /// ```typescript
18
+ /// // String implements EnvelopeEncodable
19
+ /// const e1 = Envelope.new("Hello");
20
+ ///
21
+ /// // Numbers implement EnvelopeEncodable
22
+ /// const e2 = Envelope.new(42);
23
+ ///
24
+ /// // Using in envelope construction
25
+ /// const envelope = Envelope.new("subject")
26
+ /// .addAssertion("name", "Alice") // Uses EnvelopeEncodable for both predicate and object
27
+ /// .addAssertion("age", 30); // Uses EnvelopeEncodable for the numeric object
28
+ /// ```
29
+ export interface EnvelopeEncodable {
30
+ /// Converts this value into a Gordian Envelope.
31
+ ///
32
+ /// This is the core method of the interface, converting the implementing type
33
+ /// into an envelope representation. Most implementations will convert the
34
+ /// value to a leaf envelope containing the value.
35
+ ///
36
+ /// @returns A new envelope containing the value.
37
+ intoEnvelope(): Envelope;
38
+ }
39
+
40
+ /// Type guard to check if a value implements EnvelopeEncodable.
41
+ ///
42
+ /// @param value - The value to check
43
+ /// @returns `true` if the value implements EnvelopeEncodable, `false` otherwise
44
+ export function isEnvelopeEncodable(value: unknown): value is EnvelopeEncodable {
45
+ return (
46
+ typeof value === "object" &&
47
+ value !== null &&
48
+ "intoEnvelope" in value &&
49
+ typeof (value as EnvelopeEncodable).intoEnvelope === "function"
50
+ );
51
+ }
52
+
53
+ /// Helper type for values that can be encoded as envelopes.
54
+ ///
55
+ /// This includes:
56
+ /// - Types that directly implement EnvelopeEncodable
57
+ /// - Primitive types (string, number, boolean)
58
+ /// - Uint8Array (for binary data)
59
+ /// - null and undefined
60
+ ///
61
+ /// The Envelope class will handle conversion of these types automatically.
62
+ export type EnvelopeEncodableValue =
63
+ | EnvelopeEncodable
64
+ | string
65
+ | number
66
+ | boolean
67
+ | bigint
68
+ | Uint8Array
69
+ | null
70
+ | undefined
71
+ | Envelope;