claim169 0.2.0-alpha → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -83,9 +83,9 @@
83
83
  *
84
84
  * @module claim169
85
85
  */
86
- export type { Algorithm, AlgorithmName, Biometric, CertificateHash, Claim169, Claim169Input, CwtMeta, CwtMetaInput, DecodeResult, DecryptorCallback, EncryptorCallback, IDecoder, IEncoder, SignerCallback, VerificationStatus, VerifierCallback, X509Headers, } from "./types.js";
87
- export { Claim169Error } from "./types.js";
88
- import type { Claim169Input, CwtMetaInput, DecodeResult, DecryptorCallback, EncryptorCallback, IDecoder, IEncoder, SignerCallback, VerifierCallback } from "./types.js";
86
+ export type { Algorithm, AlgorithmName, Biometric, CertificateHash, Claim169, Claim169ErrorCode, Claim169Input, CompressionMode, CoseType, CwtMeta, CwtMetaInput, DecodeResult, DetectedCompression, DecryptorCallback, EncodeResult, EncodeWarning, EncryptorCallback, IDecoder, IEncoder, InspectResult, SignerCallback, VerificationStatus, VerifierCallback, X509Headers, } from "./types.js";
87
+ export { BiometricFormat, Claim169Error, Gender, MaritalStatus, PhotoFormat, } from "./types.js";
88
+ import type { Claim169Input, CompressionMode, CwtMetaInput, DecodeResult, DecryptorCallback, EncodeResult, EncryptorCallback, IDecoder, IEncoder, InspectResult, SignerCallback, VerifierCallback } from "./types.js";
89
89
  /**
90
90
  * Get the library version
91
91
  */
@@ -200,7 +200,7 @@ export declare class Decoder implements IDecoder {
200
200
  */
201
201
  skipBiometrics(): Decoder;
202
202
  /**
203
- * Enable timestamp validation.
203
+ * Re-enable timestamp validation (enabled by default).
204
204
  * When enabled, expired or not-yet-valid credentials will throw an error.
205
205
  * Implemented in the host (JavaScript) to avoid WASM runtime time limitations.
206
206
  * @returns The decoder instance for chaining
@@ -277,6 +277,8 @@ export declare class Decoder implements IDecoder {
277
277
  * Notes:
278
278
  * - If you don't provide a verification key, you must explicitly set `allowUnverified: true` (testing only).
279
279
  * - Timestamp validation is enabled by default in JS (host-side). Set `validateTimestamps: false` to disable.
280
+ * - PEM keys and custom verifier/decryptor callbacks are not supported here.
281
+ * Use the `Decoder` builder class directly for those features.
280
282
  */
281
283
  export interface DecodeOptions {
282
284
  verifyWithEd25519?: Uint8Array;
@@ -403,15 +405,46 @@ export declare class Encoder implements IEncoder {
403
405
  */
404
406
  encryptWith(encryptor: EncryptorCallback, algorithm: "A256GCM" | "A128GCM"): Encoder;
405
407
  /**
406
- * Encode the credential to a Base45 QR string.
407
- * @returns Base45-encoded string suitable for QR code generation
408
+ * Set compression mode for encoding.
409
+ * @param mode - Compression mode: "zlib", "none", "adaptive", "brotli:N" (0-11), or "adaptive-brotli:N"
410
+ * @returns The encoder instance for chaining
411
+ * @throws {Claim169Error} If the mode is invalid or unsupported by the WASM build
412
+ */
413
+ compression(mode: CompressionMode): Encoder;
414
+ /**
415
+ * Encode the credential to a QR-ready result object.
416
+ * @returns Encode result with QR data, compression info, and warnings
408
417
  * @throws {Claim169Error} If encoding fails
409
418
  */
410
- encode(): string;
419
+ encode(): EncodeResult;
411
420
  }
412
421
  /**
413
422
  * Generate a random 12-byte nonce for AES-GCM encryption.
414
423
  * @returns A 12-byte Uint8Array suitable for use as a nonce
415
424
  */
416
425
  export declare function generateNonce(): Uint8Array;
426
+ /**
427
+ * Inspect credential metadata without full decoding or verification.
428
+ *
429
+ * Extracts metadata (issuer, key ID, algorithm, expiration) from a QR code
430
+ * without verifying the signature. Useful for multi-issuer key lookup.
431
+ *
432
+ * For encrypted credentials (COSE_Encrypt0), only COSE-level headers are
433
+ * available; CWT-level fields (issuer, subject, expiresAt) will be `undefined`.
434
+ *
435
+ * @param qrText - The Base45-encoded QR code content
436
+ * @returns Metadata extracted from the credential
437
+ * @throws {Claim169Error} On parse errors
438
+ *
439
+ * @example
440
+ * ```typescript
441
+ * import { inspect } from 'claim169';
442
+ *
443
+ * const meta = inspect(qrText);
444
+ * console.log(meta.issuer); // "https://issuer.example.com"
445
+ * console.log(meta.algorithm); // "EdDSA"
446
+ * console.log(meta.coseType); // "Sign1"
447
+ * ```
448
+ */
449
+ export declare function inspect(qrText: string): InspectResult;
417
450
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AAEH,YAAY,EACV,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,aAAa,EACb,MAAM,EACN,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAGV,aAAa,EACb,eAAe,EAEf,YAAY,EACZ,YAAY,EAEZ,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,cAAc,EACd,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAqBpB;;GAEG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqBlD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMpD;AA0RD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,YAAW,QAAQ;IACtC,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,yBAAyB,CAAK;IAEtC;;;OAGG;gBACS,MAAM,EAAE,MAAM;IAI1B;;;;;OAKG;IACH,iBAAiB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO;IAOjD;;;;;OAKG;IACH,mBAAmB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO;IAOnD;;;;;;OAMG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAO1C;;;;;;OAMG;IACH,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAO5C;;;;;OAKG;IACH,eAAe,IAAI,OAAO;IAK1B;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAO3C;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAO3C;;;;OAIG;IACH,cAAc,IAAI,OAAO;IAKzB;;;;;OAKG;IACH,uBAAuB,IAAI,OAAO;IAKlC;;;OAGG;IACH,0BAA0B,IAAI,OAAO;IAKrC;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;OAKG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO;IAO/C;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO;IAOlD;;;;;;OAMG;IACH,MAAM,IAAI,YAAY;CAiBvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,mBAAmB,CAAC,EAAE,UAAU,CAAC;IACjC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,YAAY,CAuCd;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,OAAQ,YAAW,QAAQ;IACtC,OAAO,CAAC,WAAW,CAAmB;IAEtC;;;;OAIG;gBACS,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY;IAM1D;;;;OAIG;IACH,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO;IAOhD;;;;OAIG;IACH,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO;IAOlD;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAO3C;;;;OAIG;IACH,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAO3C;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAKxB;;;OAGG;IACH,cAAc,IAAI,OAAO;IAKzB;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,OAAO,GAAG,OAAO,EAC5B,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,GACxB,OAAO;IAYV;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CACT,SAAS,EAAE,iBAAiB,EAC5B,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,OAAO;IAOV;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO;IAO3C;;;;OAIG;IACH,MAAM,IAAI,YAAY;CAcvB;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AA6BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAKrD"}
package/dist/index.js CHANGED
@@ -83,10 +83,25 @@
83
83
  *
84
84
  * @module claim169
85
85
  */
86
- export { Claim169Error } from "./types.js";
86
+ export { BiometricFormat, Claim169Error, Gender, MaritalStatus, PhotoFormat, } from "./types.js";
87
87
  import { Claim169Error } from "./types.js";
88
88
  // Import WASM module (auto-initialized with bundler target)
89
89
  import * as wasm from "../wasm/claim169_wasm.js";
90
+ /**
91
+ * Wrap a WASM call so that any thrown error becomes a Claim169Error.
92
+ */
93
+ function wrapWasmCall(fn) {
94
+ try {
95
+ return fn();
96
+ }
97
+ catch (error) {
98
+ throw error instanceof Claim169Error
99
+ ? error
100
+ : error instanceof Error
101
+ ? new Claim169Error(error.message)
102
+ : new Claim169Error(String(error));
103
+ }
104
+ }
90
105
  /**
91
106
  * Get the library version
92
107
  */
@@ -198,21 +213,39 @@ function transformX509Headers(raw) {
198
213
  return headers;
199
214
  }
200
215
  /**
201
- * Transform raw WASM result to typed DecodeResult
216
+ * Transform raw WASM result to typed DecodeResult.
217
+ * Performs runtime validation to catch malformed WASM output.
202
218
  */
203
219
  function transformResult(raw) {
220
+ if (typeof raw !== "object" || raw === null) {
221
+ throw new Claim169Error("Malformed WASM output: expected object");
222
+ }
204
223
  const result = raw;
224
+ if (typeof result.claim169 !== "object" || result.claim169 === null) {
225
+ throw new Claim169Error("Malformed WASM output: missing claim169");
226
+ }
227
+ if (typeof result.cwtMeta !== "object" || result.cwtMeta === null) {
228
+ throw new Claim169Error("Malformed WASM output: missing cwtMeta");
229
+ }
230
+ if (typeof result.verificationStatus !== "string") {
231
+ throw new Claim169Error("Malformed WASM output: missing verificationStatus");
232
+ }
233
+ const cwtMeta = result.cwtMeta;
205
234
  return {
206
235
  claim169: transformClaim169(result.claim169),
207
236
  cwtMeta: {
208
- issuer: result.cwtMeta.issuer,
209
- subject: result.cwtMeta.subject,
210
- expiresAt: result.cwtMeta.expiresAt,
211
- notBefore: result.cwtMeta.notBefore,
212
- issuedAt: result.cwtMeta.issuedAt,
237
+ issuer: cwtMeta.issuer,
238
+ subject: cwtMeta.subject,
239
+ expiresAt: cwtMeta.expiresAt,
240
+ notBefore: cwtMeta.notBefore,
241
+ issuedAt: cwtMeta.issuedAt,
213
242
  },
214
243
  verificationStatus: result.verificationStatus,
215
244
  x509Headers: transformX509Headers(result.x509Headers),
245
+ detectedCompression: (result.detectedCompression ?? "zlib"),
246
+ warnings: result.warnings ?? [],
247
+ keyId: safeUint8Array(result.keyId),
248
+ algorithm: result.algorithm,
216
249
  };
217
250
  }
218
251
  /**
@@ -281,12 +314,18 @@ function transformBiometrics(raw) {
281
314
  if (!raw || !Array.isArray(raw)) {
282
315
  return undefined;
283
316
  }
284
- return raw.map((b) => ({
285
- data: safeUint8Array(b.data),
286
- format: b.format,
287
- subFormat: b.subFormat,
288
- issuer: b.issuer,
289
- }));
317
+ return raw.map((b) => {
318
+ const data = safeUint8Array(b.data);
319
+ if (!data) {
320
+ throw new Claim169Error("Biometric entry missing data field");
321
+ }
322
+ return {
323
+ data,
324
+ format: b.format,
325
+ subFormat: b.subFormat,
326
+ issuer: b.issuer,
327
+ };
328
+ });
290
329
  }
291
330
  function validateTimestampsHost(cwtMeta, clockSkewToleranceSeconds) {
292
331
  const skew = Math.max(0, Math.floor(clockSkewToleranceSeconds));
@@ -378,16 +417,8 @@ export class Decoder {
378
417
  * @throws {Claim169Error} If the public key is invalid
379
418
  */
380
419
  verifyWithEd25519(publicKey) {
381
- try {
382
- this.wasmDecoder = this.wasmDecoder.verifyWithEd25519(publicKey);
383
- return this;
384
- }
385
- catch (error) {
386
- if (error instanceof Error) {
387
- throw new Claim169Error(error.message);
388
- }
389
- throw new Claim169Error(String(error));
390
- }
420
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEd25519(publicKey));
421
+ return this;
391
422
  }
392
423
  /**
393
424
  * Verify signature with ECDSA P-256 public key.
@@ -396,16 +427,8 @@ export class Decoder {
396
427
  * @throws {Claim169Error} If the public key is invalid
397
428
  */
398
429
  verifyWithEcdsaP256(publicKey) {
399
- try {
400
- this.wasmDecoder = this.wasmDecoder.verifyWithEcdsaP256(publicKey);
401
- return this;
402
- }
403
- catch (error) {
404
- if (error instanceof Error) {
405
- throw new Claim169Error(error.message);
406
- }
407
- throw new Claim169Error(String(error));
408
- }
430
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEcdsaP256(publicKey));
431
+ return this;
409
432
  }
410
433
  /**
411
434
  * Verify signature with Ed25519 public key in PEM format.
@@ -415,16 +438,8 @@ export class Decoder {
415
438
  * @throws {Claim169Error} If the PEM is invalid
416
439
  */
417
440
  verifyWithEd25519Pem(pem) {
418
- try {
419
- this.wasmDecoder = this.wasmDecoder.verifyWithEd25519Pem(pem);
420
- return this;
421
- }
422
- catch (error) {
423
- if (error instanceof Error) {
424
- throw new Claim169Error(error.message);
425
- }
426
- throw new Claim169Error(String(error));
427
- }
441
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEd25519Pem(pem));
442
+ return this;
428
443
  }
429
444
  /**
430
445
  * Verify signature with ECDSA P-256 public key in PEM format.
@@ -434,16 +449,8 @@ export class Decoder {
434
449
  * @throws {Claim169Error} If the PEM is invalid
435
450
  */
436
451
  verifyWithEcdsaP256Pem(pem) {
437
- try {
438
- this.wasmDecoder = this.wasmDecoder.verifyWithEcdsaP256Pem(pem);
439
- return this;
440
- }
441
- catch (error) {
442
- if (error instanceof Error) {
443
- throw new Claim169Error(error.message);
444
- }
445
- throw new Claim169Error(String(error));
446
- }
452
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWithEcdsaP256Pem(pem));
453
+ return this;
447
454
  }
448
455
  /**
449
456
  * Allow decoding without signature verification.
@@ -462,16 +469,8 @@ export class Decoder {
462
469
  * @throws {Claim169Error} If the key is invalid
463
470
  */
464
471
  decryptWithAes256(key) {
465
- try {
466
- this.wasmDecoder = this.wasmDecoder.decryptWithAes256(key);
467
- return this;
468
- }
469
- catch (error) {
470
- if (error instanceof Error) {
471
- throw new Claim169Error(error.message);
472
- }
473
- throw new Claim169Error(String(error));
474
- }
472
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWithAes256(key));
473
+ return this;
475
474
  }
476
475
  /**
477
476
  * Decrypt with AES-128-GCM.
@@ -480,16 +479,8 @@ export class Decoder {
480
479
  * @throws {Claim169Error} If the key is invalid
481
480
  */
482
481
  decryptWithAes128(key) {
483
- try {
484
- this.wasmDecoder = this.wasmDecoder.decryptWithAes128(key);
485
- return this;
486
- }
487
- catch (error) {
488
- if (error instanceof Error) {
489
- throw new Claim169Error(error.message);
490
- }
491
- throw new Claim169Error(String(error));
492
- }
482
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWithAes128(key));
483
+ return this;
493
484
  }
494
485
  /**
495
486
  * Skip biometric data during decoding.
@@ -501,7 +492,7 @@ export class Decoder {
501
492
  return this;
502
493
  }
503
494
  /**
504
- * Enable timestamp validation.
495
+ * Re-enable timestamp validation (enabled by default).
505
496
  * When enabled, expired or not-yet-valid credentials will throw an error.
506
497
  * Implemented in the host (JavaScript) to avoid WASM runtime time limitations.
507
498
  * @returns The decoder instance for chaining
@@ -557,16 +548,8 @@ export class Decoder {
557
548
  * ```
558
549
  */
559
550
  verifyWith(verifier) {
560
- try {
561
- this.wasmDecoder = this.wasmDecoder.verifyWith(verifier);
562
- return this;
563
- }
564
- catch (error) {
565
- if (error instanceof Error) {
566
- throw new Claim169Error(error.message);
567
- }
568
- throw new Claim169Error(String(error));
569
- }
551
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.verifyWith(verifier));
552
+ return this;
570
553
  }
571
554
  /**
572
555
  * Decrypt with a custom decryptor callback.
@@ -586,16 +569,8 @@ export class Decoder {
586
569
  * ```
587
570
  */
588
571
  decryptWith(decryptor) {
589
- try {
590
- this.wasmDecoder = this.wasmDecoder.decryptWith(decryptor);
591
- return this;
592
- }
593
- catch (error) {
594
- if (error instanceof Error) {
595
- throw new Claim169Error(error.message);
596
- }
597
- throw new Claim169Error(String(error));
598
- }
572
+ this.wasmDecoder = wrapWasmCall(() => this.wasmDecoder.decryptWith(decryptor));
573
+ return this;
599
574
  }
600
575
  /**
601
576
  * Decode the QR code with the configured options.
@@ -605,7 +580,7 @@ export class Decoder {
605
580
  * @throws {Claim169Error} If decoding fails or no verification method specified
606
581
  */
607
582
  decode() {
608
- try {
583
+ return wrapWasmCall(() => {
609
584
  const result = this.wasmDecoder.decode();
610
585
  const transformed = transformResult(result);
611
586
  // Validate date format (YYYY-MM-DD)
@@ -614,13 +589,7 @@ export class Decoder {
614
589
  validateTimestampsHost(transformed.cwtMeta, this.clockSkewToleranceSeconds);
615
590
  }
616
591
  return transformed;
617
- }
618
- catch (error) {
619
- if (error instanceof Error) {
620
- throw new Claim169Error(error.message);
621
- }
622
- throw new Claim169Error(String(error));
623
- }
592
+ });
624
593
  }
625
594
  }
626
595
  /**
@@ -695,15 +664,7 @@ export class Encoder {
695
664
  * @param cwtMeta - CWT metadata including issuer, expiration, etc.
696
665
  */
697
666
  constructor(claim169, cwtMeta) {
698
- try {
699
- this.wasmEncoder = new wasm.WasmEncoder(claim169, cwtMeta);
700
- }
701
- catch (error) {
702
- if (error instanceof Error) {
703
- throw new Claim169Error(error.message);
704
- }
705
- throw new Claim169Error(String(error));
706
- }
667
+ this.wasmEncoder = wrapWasmCall(() => new wasm.WasmEncoder(claim169, cwtMeta));
707
668
  }
708
669
  /**
709
670
  * Sign with Ed25519 private key.
@@ -711,16 +672,8 @@ export class Encoder {
711
672
  * @returns The encoder instance for chaining
712
673
  */
713
674
  signWithEd25519(privateKey) {
714
- try {
715
- this.wasmEncoder = this.wasmEncoder.signWithEd25519(privateKey);
716
- return this;
717
- }
718
- catch (error) {
719
- if (error instanceof Error) {
720
- throw new Claim169Error(error.message);
721
- }
722
- throw new Claim169Error(String(error));
723
- }
675
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWithEd25519(privateKey));
676
+ return this;
724
677
  }
725
678
  /**
726
679
  * Sign with ECDSA P-256 private key.
@@ -728,16 +681,8 @@ export class Encoder {
728
681
  * @returns The encoder instance for chaining
729
682
  */
730
683
  signWithEcdsaP256(privateKey) {
731
- try {
732
- this.wasmEncoder = this.wasmEncoder.signWithEcdsaP256(privateKey);
733
- return this;
734
- }
735
- catch (error) {
736
- if (error instanceof Error) {
737
- throw new Claim169Error(error.message);
738
- }
739
- throw new Claim169Error(String(error));
740
- }
684
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWithEcdsaP256(privateKey));
685
+ return this;
741
686
  }
742
687
  /**
743
688
  * Encrypt with AES-256-GCM.
@@ -745,16 +690,8 @@ export class Encoder {
745
690
  * @returns The encoder instance for chaining
746
691
  */
747
692
  encryptWithAes256(key) {
748
- try {
749
- this.wasmEncoder = this.wasmEncoder.encryptWithAes256(key);
750
- return this;
751
- }
752
- catch (error) {
753
- if (error instanceof Error) {
754
- throw new Claim169Error(error.message);
755
- }
756
- throw new Claim169Error(String(error));
757
- }
693
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWithAes256(key));
694
+ return this;
758
695
  }
759
696
  /**
760
697
  * Encrypt with AES-128-GCM.
@@ -762,16 +699,8 @@ export class Encoder {
762
699
  * @returns The encoder instance for chaining
763
700
  */
764
701
  encryptWithAes128(key) {
765
- try {
766
- this.wasmEncoder = this.wasmEncoder.encryptWithAes128(key);
767
- return this;
768
- }
769
- catch (error) {
770
- if (error instanceof Error) {
771
- throw new Claim169Error(error.message);
772
- }
773
- throw new Claim169Error(String(error));
774
- }
702
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWithAes128(key));
703
+ return this;
775
704
  }
776
705
  /**
777
706
  * Allow encoding without a signature.
@@ -809,19 +738,11 @@ export class Encoder {
809
738
  * ```
810
739
  */
811
740
  signWith(signer, algorithm, keyId) {
812
- try {
813
- // Wrap the callback so callers can optionally provide a keyId even if the
814
- // underlying WASM bindings don't expose key-id configuration yet.
815
- const signerWithKeyId = (alg, wasmKeyId, data) => signer(alg, keyId ?? wasmKeyId, data);
816
- this.wasmEncoder = this.wasmEncoder.signWith(signerWithKeyId, algorithm);
817
- return this;
818
- }
819
- catch (error) {
820
- if (error instanceof Error) {
821
- throw new Claim169Error(error.message);
822
- }
823
- throw new Claim169Error(String(error));
824
- }
741
+ // Wrap the callback so callers can optionally provide a keyId even if the
742
+ // underlying WASM bindings don't expose key-id configuration yet.
743
+ const signerWithKeyId = (alg, wasmKeyId, data) => signer(alg, keyId ?? wasmKeyId, data);
744
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.signWith(signerWithKeyId, algorithm));
745
+ return this;
825
746
  }
826
747
  /**
827
748
  * Encrypt with a custom encryptor callback.
@@ -842,32 +763,33 @@ export class Encoder {
842
763
  * ```
843
764
  */
844
765
  encryptWith(encryptor, algorithm) {
845
- try {
846
- this.wasmEncoder = this.wasmEncoder.encryptWith(encryptor, algorithm);
847
- return this;
848
- }
849
- catch (error) {
850
- if (error instanceof Error) {
851
- throw new Claim169Error(error.message);
852
- }
853
- throw new Claim169Error(String(error));
854
- }
766
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.encryptWith(encryptor, algorithm));
767
+ return this;
768
+ }
769
+ /**
770
+ * Set compression mode for encoding.
771
+ * @param mode - Compression mode: "zlib", "none", "adaptive", "brotli:N" (0-11), or "adaptive-brotli:N"
772
+ * @returns The encoder instance for chaining
773
+ * @throws {Claim169Error} If the mode is invalid or unsupported by the WASM build
774
+ */
775
+ compression(mode) {
776
+ this.wasmEncoder = wrapWasmCall(() => this.wasmEncoder.compression(mode));
777
+ return this;
855
778
  }
856
779
  /**
857
- * Encode the credential to a Base45 QR string.
858
- * @returns Base45-encoded string suitable for QR code generation
780
+ * Encode the credential to a QR-ready result object.
781
+ * @returns Encode result with QR data, compression info, and warnings
859
782
  * @throws {Claim169Error} If encoding fails
860
783
  */
861
784
  encode() {
862
- try {
863
- return this.wasmEncoder.encode();
864
- }
865
- catch (error) {
866
- if (error instanceof Error) {
867
- throw new Claim169Error(error.message);
868
- }
869
- throw new Claim169Error(String(error));
870
- }
785
+ return wrapWasmCall(() => {
786
+ const raw = this.wasmEncoder.encode();
787
+ return {
788
+ qrData: raw.qrData,
789
+ compressionUsed: raw.compressionUsed,
790
+ warnings: raw.warnings ?? [],
791
+ };
792
+ });
871
793
  }
872
794
  }
873
795
  /**
@@ -877,4 +799,54 @@ export class Encoder {
877
799
  export function generateNonce() {
878
800
  return new Uint8Array(wasm.generateNonce());
879
801
  }
802
+ /**
803
+ * Transform raw WASM inspect result to typed InspectResult.
804
+ */
805
+ function transformInspectResult(raw) {
806
+ if (typeof raw !== "object" || raw === null) {
807
+ throw new Claim169Error("Malformed WASM output: expected object");
808
+ }
809
+ const result = raw;
810
+ if (typeof result.coseType !== "string") {
811
+ throw new Claim169Error("Malformed WASM output: missing coseType");
812
+ }
813
+ return {
814
+ issuer: result.issuer,
815
+ subject: result.subject,
816
+ keyId: safeUint8Array(result.keyId),
817
+ algorithm: result.algorithm,
818
+ x509Headers: transformX509Headers(result.x509Headers),
819
+ expiresAt: result.expiresAt,
820
+ coseType: result.coseType,
821
+ };
822
+ }
823
+ /**
824
+ * Inspect credential metadata without full decoding or verification.
825
+ *
826
+ * Extracts metadata (issuer, key ID, algorithm, expiration) from a QR code
827
+ * without verifying the signature. Useful for multi-issuer key lookup.
828
+ *
829
+ * For encrypted credentials (COSE_Encrypt0), only COSE-level headers are
830
+ * available; CWT-level fields (issuer, subject, expiresAt) will be `undefined`.
831
+ *
832
+ * @param qrText - The Base45-encoded QR code content
833
+ * @returns Metadata extracted from the credential
834
+ * @throws {Claim169Error} On parse errors
835
+ *
836
+ * @example
837
+ * ```typescript
838
+ * import { inspect } from 'claim169';
839
+ *
840
+ * const meta = inspect(qrText);
841
+ * console.log(meta.issuer); // "https://issuer.example.com"
842
+ * console.log(meta.algorithm); // "EdDSA"
843
+ * console.log(meta.coseType); // "Sign1"
844
+ * ```
845
+ */
846
+ export function inspect(qrText) {
847
+ return wrapWasmCall(() => {
848
+ const raw = wasm.inspect(qrText);
849
+ return transformInspectResult(raw);
850
+ });
851
+ }
880
852
  //# sourceMappingURL=index.js.map