@calimero-network/mero-js 29.7.2 → 29.7.4

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.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  CalimeroError: () => CalimeroError,
40
40
  ClusterNotUpgraded: () => ClusterNotUpgraded,
41
41
  ConfirmCancelled: () => ConfirmCancelled,
42
+ ConfirmPromptBlocked: () => ConfirmPromptBlocked,
42
43
  ConfirmRequired: () => ConfirmRequired,
43
44
  ConsentStale: () => ConsentStale,
44
45
  DEFAULT_COLLATERAL_MIRROR: () => DEFAULT_COLLATERAL_MIRROR,
@@ -1511,6 +1512,13 @@ var ConfirmCancelled = class extends Error {
1511
1512
  this.name = "ConfirmCancelled";
1512
1513
  }
1513
1514
  };
1515
+ var ConfirmPromptBlocked = class extends Error {
1516
+ constructor(cause) {
1517
+ super("the passkey prompt was blocked by the browser or a password manager");
1518
+ this.cause = cause;
1519
+ this.name = "ConfirmPromptBlocked";
1520
+ }
1521
+ };
1514
1522
  var ArgsTooLarge = class extends CalimeroError {
1515
1523
  constructor(message, details = {}) {
1516
1524
  super(413, "ARGS_TOO_LARGE", message, details);
@@ -1717,17 +1725,36 @@ function cancelled(message) {
1717
1725
  error.name = "NotAllowedError";
1718
1726
  return error;
1719
1727
  }
1728
+ async function ask(method, options) {
1729
+ const container = navigator.credentials;
1730
+ const page = container[method];
1731
+ try {
1732
+ return await page.call(container, options);
1733
+ } catch (error) {
1734
+ const own = globalThis.CredentialsContainer?.prototype?.[method];
1735
+ if (!own || own === page || !stuck(error)) throw error;
1736
+ return own.call(container, options);
1737
+ }
1738
+ }
1739
+ function stuck(error) {
1740
+ return /request is already pending/i.test(
1741
+ error?.message?.toString() ?? ""
1742
+ );
1743
+ }
1720
1744
  function browserPasskey() {
1721
1745
  return {
1722
1746
  async create(options) {
1723
1747
  const o = options;
1724
- const cred = await navigator.credentials.create({
1748
+ const cred = await ask("create", {
1725
1749
  publicKey: {
1726
1750
  challenge: buf(fromB64url(o.challenge)),
1727
1751
  rp: o.rp,
1728
1752
  user: { ...o.user, id: buf(fromB64url(o.user.id)) },
1729
1753
  pubKeyCredParams: o.pubKeyCredParams,
1730
- excludeCredentials: (o.excludeCredentials ?? []).map((c) => ({ type: c.type, id: buf(fromB64url(c.id)) })),
1754
+ excludeCredentials: (o.excludeCredentials ?? []).map((c) => ({
1755
+ type: c.type,
1756
+ id: buf(fromB64url(c.id))
1757
+ })),
1731
1758
  authenticatorSelection: o.authenticatorSelection,
1732
1759
  attestation: "none",
1733
1760
  timeout: o.timeout
@@ -1740,13 +1767,16 @@ function browserPasskey() {
1740
1767
  clientDataJson: b64url(new Uint8Array(r.clientDataJSON))
1741
1768
  };
1742
1769
  },
1743
- async get(challenge, rpId, allowCredentials) {
1744
- const cred = await navigator.credentials.get({
1770
+ async get(challenge, rpId, allowCredentials, options) {
1771
+ const cred = await ask("get", {
1745
1772
  publicKey: {
1746
1773
  challenge: buf(challenge),
1747
1774
  rpId,
1748
- userVerification: "preferred",
1749
- allowCredentials: (allowCredentials ?? []).map((id) => ({ type: "public-key", id: buf(fromB64url(id)) }))
1775
+ userVerification: options?.userVerification ?? "preferred",
1776
+ allowCredentials: (allowCredentials ?? []).map((id) => ({
1777
+ type: "public-key",
1778
+ id: buf(fromB64url(id))
1779
+ }))
1750
1780
  }
1751
1781
  });
1752
1782
  if (!cred) throw cancelled("passkey sign-in was cancelled");
@@ -1966,6 +1996,19 @@ function pageDeployment(href) {
1966
1996
  return null;
1967
1997
  }
1968
1998
  }
1999
+ function userVerificationOf(named) {
2000
+ return named === "required" || named === "preferred" || named === "discouraged" ? named : "required";
2001
+ }
2002
+ function promptFailure(error) {
2003
+ const e = error;
2004
+ const name = e?.name;
2005
+ const message = typeof e?.message === "string" ? e.message : "";
2006
+ if (name === "InvalidStateError" || /not focused|already pending/i.test(message)) {
2007
+ return new ConfirmPromptBlocked(error);
2008
+ }
2009
+ if (name === "NotAllowedError" || name === "AbortError") return new ConfirmCancelled(error);
2010
+ return error;
2011
+ }
1969
2012
  function seg(value) {
1970
2013
  return encodeURIComponent(value);
1971
2014
  }
@@ -2743,11 +2786,11 @@ var CalimeroClient = class _CalimeroClient {
2743
2786
  const d = error.details;
2744
2787
  let assertion;
2745
2788
  try {
2746
- assertion = await passkey.get(fromB64url(d.challenge), d.rpId, d.allowCredentials);
2789
+ assertion = await passkey.get(fromB64url(d.challenge), d.rpId, d.allowCredentials, {
2790
+ userVerification: userVerificationOf(d.userVerification)
2791
+ });
2747
2792
  } catch (declined) {
2748
- const name = declined?.name;
2749
- if (name === "NotAllowedError" || name === "AbortError") throw new ConfirmCancelled(declined);
2750
- throw declined;
2793
+ throw promptFailure(declined);
2751
2794
  }
2752
2795
  return send({ ...body, confirm: { challengeId: d.challengeId, assertion } });
2753
2796
  }