@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.
- package/LICENSE +48 -0
- package/README.md +23 -0
- package/dist/index.cjs +2646 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +782 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +782 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.iife.js +2644 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.mjs +2552 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +84 -0
- package/src/base/assertion.ts +179 -0
- package/src/base/assertions.ts +153 -0
- package/src/base/cbor.ts +122 -0
- package/src/base/digest.ts +204 -0
- package/src/base/elide.ts +390 -0
- package/src/base/envelope-decodable.ts +186 -0
- package/src/base/envelope-encodable.ts +71 -0
- package/src/base/envelope.ts +988 -0
- package/src/base/error.ts +421 -0
- package/src/base/index.ts +56 -0
- package/src/base/leaf.ts +147 -0
- package/src/base/queries.ts +244 -0
- package/src/base/walk.ts +215 -0
- package/src/base/wrap.ts +26 -0
- package/src/extension/attachment.ts +280 -0
- package/src/extension/compress.ts +176 -0
- package/src/extension/encrypt.ts +297 -0
- package/src/extension/expression.ts +404 -0
- package/src/extension/index.ts +72 -0
- package/src/extension/proof.ts +227 -0
- package/src/extension/recipient.ts +440 -0
- package/src/extension/salt.ts +114 -0
- package/src/extension/signature.ts +398 -0
- package/src/extension/types.ts +92 -0
- package/src/format/diagnostic.ts +116 -0
- package/src/format/hex.ts +25 -0
- package/src/format/index.ts +13 -0
- package/src/format/tree.ts +168 -0
- package/src/index.ts +32 -0
- package/src/utils/index.ts +8 -0
- 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;
|