@bcts/envelope 1.0.0-alpha.5
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 +978 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +978 -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 +85 -0
- package/src/base/assertion.ts +179 -0
- package/src/base/assertions.ts +304 -0
- package/src/base/cbor.ts +122 -0
- package/src/base/digest.ts +204 -0
- package/src/base/elide.ts +526 -0
- package/src/base/envelope-decodable.ts +229 -0
- package/src/base/envelope-encodable.ts +71 -0
- package/src/base/envelope.ts +790 -0
- package/src/base/error.ts +421 -0
- package/src/base/index.ts +56 -0
- package/src/base/leaf.ts +226 -0
- package/src/base/queries.ts +374 -0
- package/src/base/walk.ts +241 -0
- package/src/base/wrap.ts +72 -0
- package/src/extension/attachment.ts +369 -0
- package/src/extension/compress.ts +293 -0
- package/src/extension/encrypt.ts +379 -0
- package/src/extension/expression.ts +404 -0
- package/src/extension/index.ts +72 -0
- package/src/extension/proof.ts +276 -0
- package/src/extension/recipient.ts +557 -0
- package/src/extension/salt.ts +223 -0
- package/src/extension/signature.ts +463 -0
- package/src/extension/types.ts +222 -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,421 @@
|
|
|
1
|
+
/// Error types returned when operating on Gordian Envelopes.
|
|
2
|
+
///
|
|
3
|
+
/// These errors capture various conditions that can occur when working with
|
|
4
|
+
/// envelopes, including structure validation, operation constraints, and
|
|
5
|
+
/// extension-specific errors.
|
|
6
|
+
///
|
|
7
|
+
/// The errors are organized by category, reflecting the base envelope
|
|
8
|
+
/// specification and various extensions defined in the Gordian Envelope
|
|
9
|
+
/// Internet Draft and Blockchain Commons Research (BCR) documents.
|
|
10
|
+
|
|
11
|
+
export enum ErrorCode {
|
|
12
|
+
// Base Specification
|
|
13
|
+
ALREADY_ELIDED = "ALREADY_ELIDED",
|
|
14
|
+
AMBIGUOUS_PREDICATE = "AMBIGUOUS_PREDICATE",
|
|
15
|
+
INVALID_DIGEST = "INVALID_DIGEST",
|
|
16
|
+
INVALID_FORMAT = "INVALID_FORMAT",
|
|
17
|
+
MISSING_DIGEST = "MISSING_DIGEST",
|
|
18
|
+
NONEXISTENT_PREDICATE = "NONEXISTENT_PREDICATE",
|
|
19
|
+
NOT_WRAPPED = "NOT_WRAPPED",
|
|
20
|
+
NOT_LEAF = "NOT_LEAF",
|
|
21
|
+
NOT_ASSERTION = "NOT_ASSERTION",
|
|
22
|
+
INVALID_ASSERTION = "INVALID_ASSERTION",
|
|
23
|
+
|
|
24
|
+
// Attachments Extension
|
|
25
|
+
INVALID_ATTACHMENT = "INVALID_ATTACHMENT",
|
|
26
|
+
NONEXISTENT_ATTACHMENT = "NONEXISTENT_ATTACHMENT",
|
|
27
|
+
AMBIGUOUS_ATTACHMENT = "AMBIGUOUS_ATTACHMENT",
|
|
28
|
+
|
|
29
|
+
// Compression Extension
|
|
30
|
+
ALREADY_COMPRESSED = "ALREADY_COMPRESSED",
|
|
31
|
+
NOT_COMPRESSED = "NOT_COMPRESSED",
|
|
32
|
+
|
|
33
|
+
// Symmetric Encryption Extension
|
|
34
|
+
ALREADY_ENCRYPTED = "ALREADY_ENCRYPTED",
|
|
35
|
+
NOT_ENCRYPTED = "NOT_ENCRYPTED",
|
|
36
|
+
|
|
37
|
+
// Known Values Extension
|
|
38
|
+
NOT_KNOWN_VALUE = "NOT_KNOWN_VALUE",
|
|
39
|
+
|
|
40
|
+
// Public Key Encryption Extension
|
|
41
|
+
UNKNOWN_RECIPIENT = "UNKNOWN_RECIPIENT",
|
|
42
|
+
|
|
43
|
+
// Encrypted Key Extension
|
|
44
|
+
UNKNOWN_SECRET = "UNKNOWN_SECRET",
|
|
45
|
+
|
|
46
|
+
// Public Key Signing Extension
|
|
47
|
+
UNVERIFIED_SIGNATURE = "UNVERIFIED_SIGNATURE",
|
|
48
|
+
INVALID_OUTER_SIGNATURE_TYPE = "INVALID_OUTER_SIGNATURE_TYPE",
|
|
49
|
+
INVALID_INNER_SIGNATURE_TYPE = "INVALID_INNER_SIGNATURE_TYPE",
|
|
50
|
+
UNVERIFIED_INNER_SIGNATURE = "UNVERIFIED_INNER_SIGNATURE",
|
|
51
|
+
INVALID_SIGNATURE_TYPE = "INVALID_SIGNATURE_TYPE",
|
|
52
|
+
|
|
53
|
+
// SSKR Extension
|
|
54
|
+
INVALID_SHARES = "INVALID_SHARES",
|
|
55
|
+
SSKR = "SSKR",
|
|
56
|
+
|
|
57
|
+
// Types Extension
|
|
58
|
+
INVALID_TYPE = "INVALID_TYPE",
|
|
59
|
+
AMBIGUOUS_TYPE = "AMBIGUOUS_TYPE",
|
|
60
|
+
|
|
61
|
+
// Expressions Extension
|
|
62
|
+
UNEXPECTED_RESPONSE_ID = "UNEXPECTED_RESPONSE_ID",
|
|
63
|
+
INVALID_RESPONSE = "INVALID_RESPONSE",
|
|
64
|
+
|
|
65
|
+
// External errors
|
|
66
|
+
CBOR = "CBOR",
|
|
67
|
+
COMPONENTS = "COMPONENTS",
|
|
68
|
+
GENERAL = "GENERAL",
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class EnvelopeError extends Error {
|
|
72
|
+
readonly code: ErrorCode;
|
|
73
|
+
declare readonly cause?: Error;
|
|
74
|
+
|
|
75
|
+
constructor(code: ErrorCode, message: string, cause?: Error) {
|
|
76
|
+
super(message);
|
|
77
|
+
this.name = "EnvelopeError";
|
|
78
|
+
this.code = code;
|
|
79
|
+
if (cause !== undefined) {
|
|
80
|
+
this.cause = cause;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
84
|
+
if ("captureStackTrace" in Error) {
|
|
85
|
+
(
|
|
86
|
+
Error as {
|
|
87
|
+
captureStackTrace(target: object, constructor: typeof EnvelopeError): void;
|
|
88
|
+
}
|
|
89
|
+
).captureStackTrace(this, EnvelopeError);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//
|
|
94
|
+
// Base Specification
|
|
95
|
+
/// Returned when attempting to compress or encrypt an envelope that has
|
|
96
|
+
/// already been elided.
|
|
97
|
+
///
|
|
98
|
+
/// This error occurs because an elided envelope only contains a digest
|
|
99
|
+
/// reference and no longer has a subject that can be compressed or
|
|
100
|
+
/// encrypted.
|
|
101
|
+
static alreadyElided(): EnvelopeError {
|
|
102
|
+
return new EnvelopeError(
|
|
103
|
+
ErrorCode.ALREADY_ELIDED,
|
|
104
|
+
"envelope was elided, so it cannot be compressed or encrypted",
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Returned when attempting to retrieve an assertion by predicate, but
|
|
109
|
+
/// multiple matching assertions exist.
|
|
110
|
+
///
|
|
111
|
+
/// For queries that expect a single result (like `objectForPredicate`),
|
|
112
|
+
/// having multiple matching assertions is ambiguous and requires more
|
|
113
|
+
/// specific targeting.
|
|
114
|
+
static ambiguousPredicate(): EnvelopeError {
|
|
115
|
+
return new EnvelopeError(
|
|
116
|
+
ErrorCode.AMBIGUOUS_PREDICATE,
|
|
117
|
+
"more than one assertion matches the predicate",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Returned when a digest validation fails.
|
|
122
|
+
///
|
|
123
|
+
/// This can occur when unwrapping an envelope, verifying signatures, or
|
|
124
|
+
/// other operations that rely on the integrity of envelope digests.
|
|
125
|
+
static invalidDigest(): EnvelopeError {
|
|
126
|
+
return new EnvelopeError(ErrorCode.INVALID_DIGEST, "digest did not match");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Returned when an envelope's format is invalid.
|
|
130
|
+
///
|
|
131
|
+
/// This typically occurs during parsing or decoding of an envelope from
|
|
132
|
+
/// CBOR.
|
|
133
|
+
static invalidFormat(): EnvelopeError {
|
|
134
|
+
return new EnvelopeError(ErrorCode.INVALID_FORMAT, "invalid format");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/// Returned when a digest is expected but not found.
|
|
138
|
+
///
|
|
139
|
+
/// This can occur when working with envelope structures that require digest
|
|
140
|
+
/// information, such as when working with elided envelopes.
|
|
141
|
+
static missingDigest(): EnvelopeError {
|
|
142
|
+
return new EnvelopeError(ErrorCode.MISSING_DIGEST, "a digest was expected but not found");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Returned when attempting to retrieve an assertion by predicate, but no
|
|
146
|
+
/// matching assertion exists.
|
|
147
|
+
///
|
|
148
|
+
/// This error occurs with functions like `objectForPredicate` when the
|
|
149
|
+
/// specified predicate doesn't match any assertion in the envelope.
|
|
150
|
+
static nonexistentPredicate(): EnvelopeError {
|
|
151
|
+
return new EnvelopeError(ErrorCode.NONEXISTENT_PREDICATE, "no assertion matches the predicate");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// Returned when attempting to unwrap an envelope that wasn't wrapped.
|
|
155
|
+
///
|
|
156
|
+
/// This error occurs when calling `Envelope.tryUnwrap` on an
|
|
157
|
+
/// envelope that doesn't have the wrapped format.
|
|
158
|
+
static notWrapped(): EnvelopeError {
|
|
159
|
+
return new EnvelopeError(
|
|
160
|
+
ErrorCode.NOT_WRAPPED,
|
|
161
|
+
"cannot unwrap an envelope that was not wrapped",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// Returned when expecting an envelope's subject to be a leaf, but it
|
|
166
|
+
/// isn't.
|
|
167
|
+
///
|
|
168
|
+
/// This error occurs when calling methods that require access to a leaf
|
|
169
|
+
/// value but the envelope's subject is an assertion, node, or elided.
|
|
170
|
+
static notLeaf(): EnvelopeError {
|
|
171
|
+
return new EnvelopeError(ErrorCode.NOT_LEAF, "the envelope's subject is not a leaf");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/// Returned when expecting an envelope's subject to be an assertion, but it
|
|
175
|
+
/// isn't.
|
|
176
|
+
///
|
|
177
|
+
/// This error occurs when calling methods that require an assertion
|
|
178
|
+
/// structure but the envelope's subject has a different format.
|
|
179
|
+
static notAssertion(): EnvelopeError {
|
|
180
|
+
return new EnvelopeError(ErrorCode.NOT_ASSERTION, "the envelope's subject is not an assertion");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// Returned when assertion is invalid
|
|
184
|
+
static invalidAssertion(): EnvelopeError {
|
|
185
|
+
return new EnvelopeError(
|
|
186
|
+
ErrorCode.INVALID_ASSERTION,
|
|
187
|
+
"assertion must be a map with exactly one element",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//
|
|
192
|
+
// Attachments Extension
|
|
193
|
+
/// Returned when an attachment's format is invalid.
|
|
194
|
+
///
|
|
195
|
+
/// This error occurs when an envelope contains an attachment with an
|
|
196
|
+
/// invalid structure according to the Envelope Attachment specification
|
|
197
|
+
/// (BCR-2023-006).
|
|
198
|
+
static invalidAttachment(): EnvelopeError {
|
|
199
|
+
return new EnvelopeError(ErrorCode.INVALID_ATTACHMENT, "invalid attachment");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// Returned when an attachment is requested but does not exist.
|
|
203
|
+
///
|
|
204
|
+
/// This error occurs when attempting to retrieve an attachment by ID that
|
|
205
|
+
/// doesn't exist in the envelope.
|
|
206
|
+
static nonexistentAttachment(): EnvelopeError {
|
|
207
|
+
return new EnvelopeError(ErrorCode.NONEXISTENT_ATTACHMENT, "nonexistent attachment");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// Returned when multiple attachments match a single query.
|
|
211
|
+
///
|
|
212
|
+
/// This error occurs when multiple attachments have the same ID, making
|
|
213
|
+
/// it ambiguous which attachment should be returned.
|
|
214
|
+
static ambiguousAttachment(): EnvelopeError {
|
|
215
|
+
return new EnvelopeError(ErrorCode.AMBIGUOUS_ATTACHMENT, "ambiguous attachment");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
//
|
|
219
|
+
// Compression Extension
|
|
220
|
+
/// Returned when attempting to compress an envelope that is already
|
|
221
|
+
/// compressed.
|
|
222
|
+
///
|
|
223
|
+
/// This error occurs when calling compression functions on an envelope that
|
|
224
|
+
/// already has compressed content, as defined in BCR-2023-005.
|
|
225
|
+
static alreadyCompressed(): EnvelopeError {
|
|
226
|
+
return new EnvelopeError(ErrorCode.ALREADY_COMPRESSED, "envelope was already compressed");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/// Returned when attempting to decompress an envelope that is not
|
|
230
|
+
/// compressed.
|
|
231
|
+
///
|
|
232
|
+
/// This error occurs when calling decompression functions on an envelope
|
|
233
|
+
/// that doesn't contain compressed content.
|
|
234
|
+
static notCompressed(): EnvelopeError {
|
|
235
|
+
return new EnvelopeError(
|
|
236
|
+
ErrorCode.NOT_COMPRESSED,
|
|
237
|
+
"cannot decompress an envelope that was not compressed",
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
//
|
|
242
|
+
// Symmetric Encryption Extension
|
|
243
|
+
/// Returned when attempting to encrypt an envelope that is already
|
|
244
|
+
/// encrypted or compressed.
|
|
245
|
+
///
|
|
246
|
+
/// This error occurs to prevent multiple layers of encryption or encryption
|
|
247
|
+
/// of compressed data, which could reduce security, as defined in
|
|
248
|
+
/// BCR-2023-004.
|
|
249
|
+
static alreadyEncrypted(): EnvelopeError {
|
|
250
|
+
return new EnvelopeError(
|
|
251
|
+
ErrorCode.ALREADY_ENCRYPTED,
|
|
252
|
+
"envelope was already encrypted or compressed, so it cannot be encrypted",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/// Returned when attempting to decrypt an envelope that is not encrypted.
|
|
257
|
+
///
|
|
258
|
+
/// This error occurs when calling decryption functions on an envelope that
|
|
259
|
+
/// doesn't contain encrypted content.
|
|
260
|
+
static notEncrypted(): EnvelopeError {
|
|
261
|
+
return new EnvelopeError(
|
|
262
|
+
ErrorCode.NOT_ENCRYPTED,
|
|
263
|
+
"cannot decrypt an envelope that was not encrypted",
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
//
|
|
268
|
+
// Known Values Extension
|
|
269
|
+
/// Returned when expecting an envelope's subject to be a known value, but
|
|
270
|
+
/// it isn't.
|
|
271
|
+
///
|
|
272
|
+
/// This error occurs when calling methods that require a known value (as
|
|
273
|
+
/// defined in BCR-2023-003) but the envelope's subject is a different
|
|
274
|
+
/// type.
|
|
275
|
+
static notKnownValue(): EnvelopeError {
|
|
276
|
+
return new EnvelopeError(
|
|
277
|
+
ErrorCode.NOT_KNOWN_VALUE,
|
|
278
|
+
"the envelope's subject is not a known value",
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
//
|
|
283
|
+
// Public Key Encryption Extension
|
|
284
|
+
/// Returned when attempting to decrypt an envelope with a recipient that
|
|
285
|
+
/// doesn't match.
|
|
286
|
+
///
|
|
287
|
+
/// This error occurs when trying to use a private key to decrypt an
|
|
288
|
+
/// envelope that wasn't encrypted for the corresponding public key.
|
|
289
|
+
static unknownRecipient(): EnvelopeError {
|
|
290
|
+
return new EnvelopeError(ErrorCode.UNKNOWN_RECIPIENT, "unknown recipient");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
//
|
|
294
|
+
// Encrypted Key Extension
|
|
295
|
+
/// Returned when attempting to decrypt an envelope with a secret that
|
|
296
|
+
/// doesn't match.
|
|
297
|
+
///
|
|
298
|
+
/// This error occurs when trying to use a secret that does not correspond
|
|
299
|
+
/// to the expected recipient, preventing successful decryption.
|
|
300
|
+
static unknownSecret(): EnvelopeError {
|
|
301
|
+
return new EnvelopeError(ErrorCode.UNKNOWN_SECRET, "secret not found");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
//
|
|
305
|
+
// Public Key Signing Extension
|
|
306
|
+
/// Returned when a signature verification fails.
|
|
307
|
+
///
|
|
308
|
+
/// This error occurs when a signature does not validate against its
|
|
309
|
+
/// purported public key.
|
|
310
|
+
static unverifiedSignature(): EnvelopeError {
|
|
311
|
+
return new EnvelopeError(ErrorCode.UNVERIFIED_SIGNATURE, "could not verify a signature");
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/// Returned when the outer signature object type is not `Signature`.
|
|
315
|
+
static invalidOuterSignatureType(): EnvelopeError {
|
|
316
|
+
return new EnvelopeError(
|
|
317
|
+
ErrorCode.INVALID_OUTER_SIGNATURE_TYPE,
|
|
318
|
+
"unexpected outer signature object type",
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/// Returned when the inner signature object type is not `Signature`.
|
|
323
|
+
static invalidInnerSignatureType(): EnvelopeError {
|
|
324
|
+
return new EnvelopeError(
|
|
325
|
+
ErrorCode.INVALID_INNER_SIGNATURE_TYPE,
|
|
326
|
+
"unexpected inner signature object type",
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/// Returned when the inner signature is not made with the same key as the
|
|
331
|
+
/// outer signature.
|
|
332
|
+
static unverifiedInnerSignature(): EnvelopeError {
|
|
333
|
+
return new EnvelopeError(
|
|
334
|
+
ErrorCode.UNVERIFIED_INNER_SIGNATURE,
|
|
335
|
+
"inner signature not made with same key as outer signature",
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/// Returned when the signature object is not a `Signature`.
|
|
340
|
+
static invalidSignatureType(): EnvelopeError {
|
|
341
|
+
return new EnvelopeError(ErrorCode.INVALID_SIGNATURE_TYPE, "unexpected signature object type");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//
|
|
345
|
+
// SSKR Extension
|
|
346
|
+
/// Returned when SSKR shares are invalid or insufficient for
|
|
347
|
+
/// reconstruction.
|
|
348
|
+
///
|
|
349
|
+
/// This error occurs when attempting to join SSKR shares that are
|
|
350
|
+
/// malformed, from different splits, or insufficient to meet the
|
|
351
|
+
/// recovery threshold.
|
|
352
|
+
static invalidShares(): EnvelopeError {
|
|
353
|
+
return new EnvelopeError(ErrorCode.INVALID_SHARES, "invalid SSKR shares");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/// SSKR error wrapper
|
|
357
|
+
static sskr(message: string, cause?: Error): EnvelopeError {
|
|
358
|
+
return new EnvelopeError(ErrorCode.SSKR, `sskr error: ${message}`, cause);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
//
|
|
362
|
+
// Types Extension
|
|
363
|
+
/// Returned when an envelope contains an invalid type.
|
|
364
|
+
///
|
|
365
|
+
/// This error occurs when an envelope's type information doesn't match
|
|
366
|
+
/// the expected format or value.
|
|
367
|
+
static invalidType(): EnvelopeError {
|
|
368
|
+
return new EnvelopeError(ErrorCode.INVALID_TYPE, "invalid type");
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/// Returned when an envelope contains ambiguous type information.
|
|
372
|
+
///
|
|
373
|
+
/// This error occurs when multiple type assertions exist that conflict
|
|
374
|
+
/// with each other or create ambiguity about the envelope's type.
|
|
375
|
+
static ambiguousType(): EnvelopeError {
|
|
376
|
+
return new EnvelopeError(ErrorCode.AMBIGUOUS_TYPE, "ambiguous type");
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
//
|
|
380
|
+
// Expressions Extension
|
|
381
|
+
/// Returned when a response envelope has an unexpected ID.
|
|
382
|
+
///
|
|
383
|
+
/// This error occurs when processing a response envelope and the ID doesn't
|
|
384
|
+
/// match the expected request ID, as defined in BCR-2023-012.
|
|
385
|
+
static unexpectedResponseId(): EnvelopeError {
|
|
386
|
+
return new EnvelopeError(ErrorCode.UNEXPECTED_RESPONSE_ID, "unexpected response ID");
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/// Returned when a response envelope is invalid.
|
|
390
|
+
static invalidResponse(): EnvelopeError {
|
|
391
|
+
return new EnvelopeError(ErrorCode.INVALID_RESPONSE, "invalid response");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
//
|
|
395
|
+
// External errors
|
|
396
|
+
/// dcbor error wrapper
|
|
397
|
+
static cbor(message: string, cause?: Error): EnvelopeError {
|
|
398
|
+
return new EnvelopeError(ErrorCode.CBOR, `dcbor error: ${message}`, cause);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/// Components error wrapper
|
|
402
|
+
static components(message: string, cause?: Error): EnvelopeError {
|
|
403
|
+
return new EnvelopeError(ErrorCode.COMPONENTS, `components error: ${message}`, cause);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/// General error wrapper
|
|
407
|
+
static general(message: string, cause?: Error): EnvelopeError {
|
|
408
|
+
return new EnvelopeError(ErrorCode.GENERAL, `general error: ${message}`, cause);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/// Create error with custom message (equivalent to Rust's Error::msg)
|
|
412
|
+
static msg(message: string): EnvelopeError {
|
|
413
|
+
return EnvelopeError.general(message);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/// Type alias for Result type (for Rust compatibility)
|
|
418
|
+
export type Result<T> = T;
|
|
419
|
+
|
|
420
|
+
/// Export for backward compatibility
|
|
421
|
+
export type { EnvelopeError as Error };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/// Base module exports for Gordian Envelope.
|
|
2
|
+
///
|
|
3
|
+
/// This module provides the core functionality for working with Gordian
|
|
4
|
+
/// Envelopes, including the main Envelope class, assertions, digests,
|
|
5
|
+
/// error handling, and various utility functions.
|
|
6
|
+
|
|
7
|
+
// Core types
|
|
8
|
+
export { Envelope, type EnvelopeCase } from "./envelope";
|
|
9
|
+
export { Assertion } from "./assertion";
|
|
10
|
+
export { Digest, type DigestProvider } from "./digest";
|
|
11
|
+
|
|
12
|
+
// Error handling
|
|
13
|
+
export { EnvelopeError, ErrorCode } from "./error";
|
|
14
|
+
|
|
15
|
+
// Encodable/Decodable traits
|
|
16
|
+
export {
|
|
17
|
+
type EnvelopeEncodable,
|
|
18
|
+
type EnvelopeEncodableValue,
|
|
19
|
+
isEnvelopeEncodable,
|
|
20
|
+
} from "./envelope-encodable";
|
|
21
|
+
|
|
22
|
+
// CBOR encoding/decoding
|
|
23
|
+
export {
|
|
24
|
+
EnvelopeCBORTagged,
|
|
25
|
+
EnvelopeCBORTaggedEncodable,
|
|
26
|
+
EnvelopeCBORTaggedDecodable,
|
|
27
|
+
envelopeToCbor,
|
|
28
|
+
envelopeFromCbor,
|
|
29
|
+
envelopeToBytes,
|
|
30
|
+
envelopeFromBytes,
|
|
31
|
+
} from "./cbor";
|
|
32
|
+
|
|
33
|
+
// Envelope decoding utilities
|
|
34
|
+
export {
|
|
35
|
+
extractString,
|
|
36
|
+
extractNumber,
|
|
37
|
+
extractBoolean,
|
|
38
|
+
extractBytes,
|
|
39
|
+
extractNull,
|
|
40
|
+
EnvelopeDecoder,
|
|
41
|
+
} from "./envelope-decodable";
|
|
42
|
+
|
|
43
|
+
// Elision and selective disclosure
|
|
44
|
+
export { ObscureType, type ObscureAction, elideAction } from "./elide";
|
|
45
|
+
|
|
46
|
+
// Walking/traversal
|
|
47
|
+
export { EdgeType, edgeLabel, type Visitor } from "./walk";
|
|
48
|
+
|
|
49
|
+
// Import side-effect modules to register prototype extensions
|
|
50
|
+
import "./assertions";
|
|
51
|
+
import "./leaf";
|
|
52
|
+
import "./queries";
|
|
53
|
+
import "./elide";
|
|
54
|
+
import "./wrap";
|
|
55
|
+
import "./walk";
|
|
56
|
+
import "./envelope-decodable";
|
package/src/base/leaf.ts
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import type { Cbor, CborMap } from "@bcts/dcbor";
|
|
2
|
+
import { isNumber, isNaN, asArray, asMap, asText } from "@bcts/dcbor";
|
|
3
|
+
import { Envelope } from "./envelope";
|
|
4
|
+
|
|
5
|
+
/// Provides methods for working with envelope leaf nodes,
|
|
6
|
+
/// which are dCBOR values of any kind.
|
|
7
|
+
///
|
|
8
|
+
/// This module extends the Envelope class with convenience methods for
|
|
9
|
+
/// working with leaf values, including type checking and extraction.
|
|
10
|
+
|
|
11
|
+
declare module "./envelope" {
|
|
12
|
+
interface Envelope {
|
|
13
|
+
/// Checks if this envelope contains false.
|
|
14
|
+
///
|
|
15
|
+
/// @returns `true` if the envelope's subject is false, `false` otherwise
|
|
16
|
+
isFalse(): boolean;
|
|
17
|
+
|
|
18
|
+
/// Checks if this envelope contains true.
|
|
19
|
+
///
|
|
20
|
+
/// @returns `true` if the envelope's subject is true, `false` otherwise
|
|
21
|
+
isTrue(): boolean;
|
|
22
|
+
|
|
23
|
+
/// Checks if this envelope contains a boolean value.
|
|
24
|
+
///
|
|
25
|
+
/// @returns `true` if the envelope's subject is a boolean, `false`
|
|
26
|
+
/// otherwise
|
|
27
|
+
isBool(): boolean;
|
|
28
|
+
|
|
29
|
+
/// Checks if this envelope is a leaf node that contains a number.
|
|
30
|
+
///
|
|
31
|
+
/// @returns `true` if the envelope is a leaf containing a number, `false`
|
|
32
|
+
/// otherwise
|
|
33
|
+
isNumber(): boolean;
|
|
34
|
+
|
|
35
|
+
/// Checks if the subject of this envelope is a number.
|
|
36
|
+
///
|
|
37
|
+
/// @returns `true` if the subject is a number, `false` otherwise
|
|
38
|
+
isSubjectNumber(): boolean;
|
|
39
|
+
|
|
40
|
+
/// Checks if this envelope is a leaf node that contains NaN.
|
|
41
|
+
///
|
|
42
|
+
/// @returns `true` if the envelope is a leaf containing NaN, `false`
|
|
43
|
+
/// otherwise
|
|
44
|
+
isNaN(): boolean;
|
|
45
|
+
|
|
46
|
+
/// Checks if the subject of this envelope is NaN.
|
|
47
|
+
///
|
|
48
|
+
/// @returns `true` if the subject is NaN, `false` otherwise
|
|
49
|
+
isSubjectNaN(): boolean;
|
|
50
|
+
|
|
51
|
+
/// Checks if this envelope contains null.
|
|
52
|
+
///
|
|
53
|
+
/// @returns `true` if the envelope's subject is null, `false` otherwise
|
|
54
|
+
isNull(): boolean;
|
|
55
|
+
|
|
56
|
+
/// Attempts to extract the leaf CBOR as a byte string.
|
|
57
|
+
///
|
|
58
|
+
/// @returns The byte string value
|
|
59
|
+
/// @throws {EnvelopeError} If the envelope is not a leaf or not a byte
|
|
60
|
+
/// string
|
|
61
|
+
tryByteString(): Uint8Array;
|
|
62
|
+
|
|
63
|
+
/// Returns the leaf CBOR as a byte string if possible.
|
|
64
|
+
///
|
|
65
|
+
/// @returns The byte string value or undefined
|
|
66
|
+
asByteString(): Uint8Array | undefined;
|
|
67
|
+
|
|
68
|
+
/// Returns the leaf CBOR as an array if possible.
|
|
69
|
+
///
|
|
70
|
+
/// @returns The array value or undefined
|
|
71
|
+
asArray(): readonly Cbor[] | undefined;
|
|
72
|
+
|
|
73
|
+
/// Returns the leaf CBOR as a map if possible.
|
|
74
|
+
///
|
|
75
|
+
/// @returns The map value or undefined
|
|
76
|
+
asMap(): CborMap | undefined;
|
|
77
|
+
|
|
78
|
+
/// Returns the leaf CBOR as text if possible.
|
|
79
|
+
///
|
|
80
|
+
/// @returns The text value or undefined
|
|
81
|
+
asText(): string | undefined;
|
|
82
|
+
|
|
83
|
+
/// Returns the leaf CBOR value if this envelope is a leaf.
|
|
84
|
+
///
|
|
85
|
+
/// @returns The CBOR value or undefined
|
|
86
|
+
asLeaf(): Cbor | undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Note: Static methods Envelope.false() and Envelope.true() are implemented below
|
|
91
|
+
// but cannot be declared in TypeScript module augmentation due to reserved keywords.
|
|
92
|
+
|
|
93
|
+
/// Implementation of static false()
|
|
94
|
+
(Envelope as unknown as { false: () => Envelope }).false = function (): Envelope {
|
|
95
|
+
return Envelope.newLeaf(false);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/// Implementation of static true()
|
|
99
|
+
(Envelope as unknown as { true: () => Envelope }).true = function (): Envelope {
|
|
100
|
+
return Envelope.newLeaf(true);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/// Implementation of isFalse()
|
|
104
|
+
Envelope.prototype.isFalse = function (this: Envelope): boolean {
|
|
105
|
+
try {
|
|
106
|
+
return this.extractBoolean() === false;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/// Implementation of isTrue()
|
|
113
|
+
Envelope.prototype.isTrue = function (this: Envelope): boolean {
|
|
114
|
+
try {
|
|
115
|
+
return this.extractBoolean() === true;
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/// Implementation of isBool()
|
|
122
|
+
Envelope.prototype.isBool = function (this: Envelope): boolean {
|
|
123
|
+
try {
|
|
124
|
+
const value = this.extractBoolean();
|
|
125
|
+
return typeof value === "boolean";
|
|
126
|
+
} catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/// Implementation of isNumber()
|
|
132
|
+
Envelope.prototype.isNumber = function (this: Envelope): boolean {
|
|
133
|
+
const leaf = this.asLeaf();
|
|
134
|
+
if (leaf === undefined) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return isNumber(leaf);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/// Implementation of isSubjectNumber()
|
|
142
|
+
Envelope.prototype.isSubjectNumber = function (this: Envelope): boolean {
|
|
143
|
+
return this.subject().isNumber();
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/// Implementation of isNaN()
|
|
147
|
+
Envelope.prototype.isNaN = function (this: Envelope): boolean {
|
|
148
|
+
const leaf = this.asLeaf();
|
|
149
|
+
if (leaf === undefined) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check for NaN in CBOR simple types
|
|
154
|
+
if ("type" in leaf && leaf.type === 7) {
|
|
155
|
+
return isNaN(leaf as unknown as Parameters<typeof isNaN>[0]);
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/// Implementation of isSubjectNaN()
|
|
161
|
+
Envelope.prototype.isSubjectNaN = function (this: Envelope): boolean {
|
|
162
|
+
return this.subject().isNaN();
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/// Implementation of isNull()
|
|
166
|
+
Envelope.prototype.isNull = function (this: Envelope): boolean {
|
|
167
|
+
try {
|
|
168
|
+
this.extractNull();
|
|
169
|
+
return true;
|
|
170
|
+
} catch (_error) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/// Implementation of tryByteString()
|
|
176
|
+
Envelope.prototype.tryByteString = function (this: Envelope): Uint8Array {
|
|
177
|
+
return this.extractBytes();
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/// Implementation of asByteString()
|
|
181
|
+
Envelope.prototype.asByteString = function (this: Envelope): Uint8Array | undefined {
|
|
182
|
+
try {
|
|
183
|
+
return this.extractBytes();
|
|
184
|
+
} catch {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/// Implementation of asArray()
|
|
190
|
+
Envelope.prototype.asArray = function (this: Envelope): readonly Cbor[] | undefined {
|
|
191
|
+
const leaf = this.asLeaf();
|
|
192
|
+
if (leaf === undefined) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return asArray(leaf);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/// Implementation of asMap()
|
|
200
|
+
Envelope.prototype.asMap = function (this: Envelope) {
|
|
201
|
+
const leaf = this.asLeaf();
|
|
202
|
+
if (leaf === undefined) {
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return asMap(leaf);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/// Implementation of asText()
|
|
210
|
+
Envelope.prototype.asText = function (this: Envelope): string | undefined {
|
|
211
|
+
const leaf = this.asLeaf();
|
|
212
|
+
if (leaf === undefined) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return asText(leaf);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/// Implementation of asLeaf()
|
|
220
|
+
Envelope.prototype.asLeaf = function (this: Envelope): Cbor | undefined {
|
|
221
|
+
const c = this.case();
|
|
222
|
+
if (c.type === "leaf") {
|
|
223
|
+
return c.cbor;
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
};
|