@finueva/auth 0.10.1 → 0.11.1

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.js CHANGED
@@ -383,6 +383,109 @@ function parseJSON(value, options = { strict: true }) {
383
383
  return betterJSONParse(value, options);
384
384
  }
385
385
  //#endregion
386
+ //#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_fc032d4b6d0d0a5be5267474da10b212/node_modules/better-auth/dist/client/query.mjs
387
+ const isServer$1 = () => typeof window === "undefined";
388
+ function isAuthQueryStateEqual(a, b) {
389
+ return isJsonEqual(a.data, b.data) && a.error === b.error && a.isPending === b.isPending && a.isRefetching === b.isRefetching && a.refetch === b.refetch;
390
+ }
391
+ const useAuthQuery = (initializedAtom, path, $fetch, options) => {
392
+ const value = atom({
393
+ data: null,
394
+ error: null,
395
+ isPending: true,
396
+ isRefetching: false,
397
+ refetch: (queryParams) => fn(queryParams)
398
+ });
399
+ withEquality(value, isAuthQueryStateEqual);
400
+ const fn = async (queryParams) => {
401
+ return new Promise((resolve) => {
402
+ const opts = typeof options === "function" ? options({
403
+ data: value.get().data,
404
+ error: value.get().error,
405
+ isPending: value.get().isPending
406
+ }) : options;
407
+ $fetch(path, {
408
+ ...opts,
409
+ query: {
410
+ ...opts?.query,
411
+ ...queryParams?.query
412
+ },
413
+ async onSuccess(context) {
414
+ const current = value.get();
415
+ const stableData = current.data != null && context.data != null && isJsonEqual(current.data, context.data) ? current.data : context.data;
416
+ value.set({
417
+ data: stableData,
418
+ error: null,
419
+ isPending: false,
420
+ isRefetching: false,
421
+ refetch: value.value.refetch
422
+ });
423
+ await opts?.onSuccess?.(context);
424
+ },
425
+ async onError(context) {
426
+ const { request } = context;
427
+ const retryAttempts = typeof request.retry === "number" ? request.retry : request.retry?.attempts;
428
+ const retryAttempt = request.retryAttempt || 0;
429
+ if (retryAttempts && retryAttempt < retryAttempts) return;
430
+ const isUnauthorized = context.error.status === 401;
431
+ value.set({
432
+ error: context.error,
433
+ data: isUnauthorized ? null : value.get().data,
434
+ isPending: false,
435
+ isRefetching: false,
436
+ refetch: value.value.refetch
437
+ });
438
+ await opts?.onError?.(context);
439
+ },
440
+ async onRequest(context) {
441
+ const currentValue = value.get();
442
+ value.set({
443
+ isPending: currentValue.data === null,
444
+ data: currentValue.data,
445
+ error: null,
446
+ isRefetching: true,
447
+ refetch: value.value.refetch
448
+ });
449
+ await opts?.onRequest?.(context);
450
+ }
451
+ }).catch((error) => {
452
+ value.set({
453
+ error,
454
+ data: value.get().data,
455
+ isPending: false,
456
+ isRefetching: false,
457
+ refetch: value.value.refetch
458
+ });
459
+ }).finally(() => {
460
+ resolve(void 0);
461
+ });
462
+ });
463
+ };
464
+ initializedAtom = Array.isArray(initializedAtom) ? initializedAtom : [initializedAtom];
465
+ let isInitialized = false;
466
+ const cleanups = [];
467
+ for (const initAtom of initializedAtom) {
468
+ const unbind = initAtom.subscribe(async () => {
469
+ if (isServer$1()) return;
470
+ if (isInitialized) await fn();
471
+ else onMount(value, () => {
472
+ const timeoutId = setTimeout(async () => {
473
+ if (!isInitialized) {
474
+ isInitialized = true;
475
+ await fn();
476
+ }
477
+ }, 0);
478
+ return () => {
479
+ for (const u of cleanups) u();
480
+ clearTimeout(timeoutId);
481
+ };
482
+ });
483
+ });
484
+ cleanups.push(unbind);
485
+ }
486
+ return value;
487
+ };
488
+ //#endregion
386
489
  //#region ../../node_modules/.pnpm/better-auth@1.6.22_drizzle-kit@0.31.10_drizzle-orm@0.45.2_@libsql+client@0.17.4_kysely@_fc032d4b6d0d0a5be5267474da10b212/node_modules/better-auth/dist/client/session-refresh.mjs
387
490
  const now = () => Math.floor(Date.now() / 1e3);
388
491
  const FOCUS_REFETCH_RATE_LIMIT_SECONDS = 5;
@@ -564,6 +667,15 @@ Object.freeze({
564
667
  }
565
668
  });
566
669
  //#endregion
670
+ //#region ../../node_modules/.pnpm/@better-auth+core@1.6.22_@better-auth+utils@0.4.2_@better-fetch+fetch@1.3.1_better-call_17975d57218030f5a353914665f207d6/node_modules/@better-auth/core/dist/utils/error-codes.mjs
671
+ function defineErrorCodes(codes) {
672
+ return Object.fromEntries(Object.entries(codes).map(([key, value]) => [key, {
673
+ code: key,
674
+ message: value,
675
+ toString: () => key
676
+ }]));
677
+ }
678
+ //#endregion
567
679
  //#region ../../node_modules/.pnpm/better-call@1.3.7_zod@4.4.3/node_modules/better-call/dist/error.mjs
568
680
  function isErrorStackTraceLimitWritable() {
569
681
  const desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit");
@@ -1635,7 +1747,551 @@ function createAuthClient$1(options) {
1635
1747
  }, $fetch, pluginPathMethods, pluginsAtoms, atomListeners);
1636
1748
  }
1637
1749
  //#endregion
1638
- //#region ../../node_modules/.pnpm/@chiballc+utils@2.5.0_@hono+zod-openapi@1.5.1_hono@4.13.0_zod@4.4.3__hono@4.13.0_magic-_deb761a9672ce7cf69932b564bd2142d/node_modules/@chiballc/utils/dist/index.mjs
1750
+ //#region ../../node_modules/.pnpm/@better-auth+passkey@1.6.22_@better-auth+core@1.6.22_@better-auth+utils@0.4.2_@better-f_9dcb641568b0468b4b3f2fd37291240f/node_modules/@better-auth/passkey/dist/version-uW-pDlTC.mjs
1751
+ const PASSKEY_ERROR_CODES = defineErrorCodes({
1752
+ CHALLENGE_NOT_FOUND: "Challenge not found",
1753
+ YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: "You are not allowed to register this passkey",
1754
+ FAILED_TO_VERIFY_REGISTRATION: "Failed to verify registration",
1755
+ PASSKEY_NOT_FOUND: "Passkey not found",
1756
+ AUTHENTICATION_FAILED: "Authentication failed",
1757
+ UNABLE_TO_CREATE_SESSION: "Unable to create session",
1758
+ FAILED_TO_UPDATE_PASSKEY: "Failed to update passkey",
1759
+ PREVIOUSLY_REGISTERED: "Previously registered",
1760
+ REGISTRATION_CANCELLED: "Registration cancelled",
1761
+ AUTH_CANCELLED: "Auth cancelled",
1762
+ UNKNOWN_ERROR: "Unknown error",
1763
+ SESSION_REQUIRED: "Passkey registration requires an authenticated session",
1764
+ RESOLVE_USER_REQUIRED: "Passkey registration requires either an authenticated session or a resolveUser callback when requireSession is false",
1765
+ RESOLVED_USER_INVALID: "Resolved user is invalid"
1766
+ });
1767
+ const PACKAGE_VERSION = "1.6.22";
1768
+ //#endregion
1769
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/bufferToBase64URLString.js
1770
+ function bufferToBase64URLString(buffer) {
1771
+ const bytes = new Uint8Array(buffer);
1772
+ let str = "";
1773
+ for (const charCode of bytes) str += String.fromCharCode(charCode);
1774
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1775
+ }
1776
+ //#endregion
1777
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/base64URLStringToBuffer.js
1778
+ function base64URLStringToBuffer(base64URLString) {
1779
+ const base64 = base64URLString.replace(/-/g, "+").replace(/_/g, "/");
1780
+ const padLength = (4 - base64.length % 4) % 4;
1781
+ const padded = base64.padEnd(base64.length + padLength, "=");
1782
+ const binary = atob(padded);
1783
+ const buffer = new ArrayBuffer(binary.length);
1784
+ const bytes = new Uint8Array(buffer);
1785
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
1786
+ return buffer;
1787
+ }
1788
+ //#endregion
1789
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthn.js
1790
+ function browserSupportsWebAuthn() {
1791
+ return _browserSupportsWebAuthnInternals.stubThis(globalThis?.PublicKeyCredential !== void 0 && typeof globalThis.PublicKeyCredential === "function");
1792
+ }
1793
+ const _browserSupportsWebAuthnInternals = { stubThis: (value) => value };
1794
+ //#endregion
1795
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/toPublicKeyCredentialDescriptor.js
1796
+ function toPublicKeyCredentialDescriptor(descriptor) {
1797
+ const { id } = descriptor;
1798
+ return {
1799
+ ...descriptor,
1800
+ id: base64URLStringToBuffer(id),
1801
+ transports: descriptor.transports
1802
+ };
1803
+ }
1804
+ //#endregion
1805
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/isValidDomain.js
1806
+ function isValidDomain(hostname) {
1807
+ return hostname === "localhost" || /^((xn--[a-z0-9-]+|[a-z0-9]+(-[a-z0-9]+)*)\.)+([a-z]{2,}|xn--[a-z0-9-]+)$/i.test(hostname);
1808
+ }
1809
+ //#endregion
1810
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnError.js
1811
+ var WebAuthnError = class extends Error {
1812
+ constructor({ message, code, cause, name }) {
1813
+ super(message, { cause });
1814
+ Object.defineProperty(this, "code", {
1815
+ enumerable: true,
1816
+ configurable: true,
1817
+ writable: true,
1818
+ value: void 0
1819
+ });
1820
+ this.name = name ?? cause.name;
1821
+ this.code = code;
1822
+ }
1823
+ };
1824
+ //#endregion
1825
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/identifyRegistrationError.js
1826
+ function identifyRegistrationError({ error, options }) {
1827
+ const { publicKey } = options;
1828
+ if (!publicKey) throw Error("options was missing required publicKey property");
1829
+ if (error.name === "AbortError") {
1830
+ if (options.signal instanceof AbortSignal) return new WebAuthnError({
1831
+ message: "Registration ceremony was sent an abort signal",
1832
+ code: "ERROR_CEREMONY_ABORTED",
1833
+ cause: error
1834
+ });
1835
+ } else if (error.name === "ConstraintError") {
1836
+ if (publicKey.authenticatorSelection?.requireResidentKey === true) return new WebAuthnError({
1837
+ message: "Discoverable credentials were required but no available authenticator supported it",
1838
+ code: "ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",
1839
+ cause: error
1840
+ });
1841
+ else if (options.mediation === "conditional" && publicKey.authenticatorSelection?.userVerification === "required") return new WebAuthnError({
1842
+ message: "User verification was required during automatic registration but it could not be performed",
1843
+ code: "ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",
1844
+ cause: error
1845
+ });
1846
+ else if (publicKey.authenticatorSelection?.userVerification === "required") return new WebAuthnError({
1847
+ message: "User verification was required but no available authenticator supported it",
1848
+ code: "ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",
1849
+ cause: error
1850
+ });
1851
+ } else if (error.name === "InvalidStateError") return new WebAuthnError({
1852
+ message: "The authenticator was previously registered",
1853
+ code: "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",
1854
+ cause: error
1855
+ });
1856
+ else if (error.name === "NotAllowedError") return new WebAuthnError({
1857
+ message: error.message,
1858
+ code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
1859
+ cause: error
1860
+ });
1861
+ else if (error.name === "NotSupportedError") {
1862
+ if (publicKey.pubKeyCredParams.filter((param) => param.type === "public-key").length === 0) return new WebAuthnError({
1863
+ message: "No entry in pubKeyCredParams was of type \"public-key\"",
1864
+ code: "ERROR_MALFORMED_PUBKEYCREDPARAMS",
1865
+ cause: error
1866
+ });
1867
+ return new WebAuthnError({
1868
+ message: "No available authenticator supported any of the specified pubKeyCredParams algorithms",
1869
+ code: "ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",
1870
+ cause: error
1871
+ });
1872
+ } else if (error.name === "SecurityError") {
1873
+ const effectiveDomain = globalThis.location.hostname;
1874
+ if (!isValidDomain(effectiveDomain)) return new WebAuthnError({
1875
+ message: `${globalThis.location.hostname} is an invalid domain`,
1876
+ code: "ERROR_INVALID_DOMAIN",
1877
+ cause: error
1878
+ });
1879
+ else if (publicKey.rp.id !== effectiveDomain) return new WebAuthnError({
1880
+ message: `The RP ID "${publicKey.rp.id}" is invalid for this domain`,
1881
+ code: "ERROR_INVALID_RP_ID",
1882
+ cause: error
1883
+ });
1884
+ } else if (error.name === "TypeError") {
1885
+ if (publicKey.user.id.byteLength < 1 || publicKey.user.id.byteLength > 64) return new WebAuthnError({
1886
+ message: "User ID was not between 1 and 64 characters",
1887
+ code: "ERROR_INVALID_USER_ID_LENGTH",
1888
+ cause: error
1889
+ });
1890
+ } else if (error.name === "UnknownError") return new WebAuthnError({
1891
+ message: "The authenticator was unable to process the specified options, or could not create a new credential",
1892
+ code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
1893
+ cause: error
1894
+ });
1895
+ return error;
1896
+ }
1897
+ //#endregion
1898
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/webAuthnAbortService.js
1899
+ var BaseWebAuthnAbortService = class {
1900
+ constructor() {
1901
+ Object.defineProperty(this, "controller", {
1902
+ enumerable: true,
1903
+ configurable: true,
1904
+ writable: true,
1905
+ value: void 0
1906
+ });
1907
+ }
1908
+ createNewAbortSignal() {
1909
+ if (this.controller) {
1910
+ const abortError = new Error("Cancelling existing WebAuthn API call for new one");
1911
+ abortError.name = "AbortError";
1912
+ this.controller.abort(abortError);
1913
+ }
1914
+ const newController = new AbortController();
1915
+ this.controller = newController;
1916
+ return newController.signal;
1917
+ }
1918
+ cancelCeremony() {
1919
+ if (this.controller) {
1920
+ const abortError = new Error("Manually cancelling existing WebAuthn API call");
1921
+ abortError.name = "AbortError";
1922
+ this.controller.abort(abortError);
1923
+ this.controller = void 0;
1924
+ }
1925
+ }
1926
+ };
1927
+ const WebAuthnAbortService = new BaseWebAuthnAbortService();
1928
+ //#endregion
1929
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/toAuthenticatorAttachment.js
1930
+ const attachments = ["cross-platform", "platform"];
1931
+ function toAuthenticatorAttachment(attachment) {
1932
+ if (!attachment) return;
1933
+ if (attachments.indexOf(attachment) < 0) return;
1934
+ return attachment;
1935
+ }
1936
+ //#endregion
1937
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/methods/startRegistration.js
1938
+ async function startRegistration(options) {
1939
+ if (!options.optionsJSON && options.challenge) {
1940
+ console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
1941
+ options = { optionsJSON: options };
1942
+ }
1943
+ const { optionsJSON, useAutoRegister = false } = options;
1944
+ if (!browserSupportsWebAuthn()) throw new Error("WebAuthn is not supported in this browser");
1945
+ const publicKey = {
1946
+ ...optionsJSON,
1947
+ challenge: base64URLStringToBuffer(optionsJSON.challenge),
1948
+ user: {
1949
+ ...optionsJSON.user,
1950
+ id: base64URLStringToBuffer(optionsJSON.user.id)
1951
+ },
1952
+ excludeCredentials: optionsJSON.excludeCredentials?.map(toPublicKeyCredentialDescriptor)
1953
+ };
1954
+ const createOptions = {};
1955
+ if (useAutoRegister) createOptions.mediation = "conditional";
1956
+ createOptions.publicKey = publicKey;
1957
+ createOptions.signal = WebAuthnAbortService.createNewAbortSignal();
1958
+ let credential;
1959
+ try {
1960
+ credential = await navigator.credentials.create(createOptions);
1961
+ } catch (err) {
1962
+ throw identifyRegistrationError({
1963
+ error: err,
1964
+ options: createOptions
1965
+ });
1966
+ }
1967
+ if (!credential) throw new Error("Registration was not completed");
1968
+ const { id, rawId, response, type } = credential;
1969
+ let transports = void 0;
1970
+ if (typeof response.getTransports === "function") transports = response.getTransports();
1971
+ let responsePublicKeyAlgorithm = void 0;
1972
+ if (typeof response.getPublicKeyAlgorithm === "function") try {
1973
+ responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm();
1974
+ } catch (error) {
1975
+ warnOnBrokenImplementation("getPublicKeyAlgorithm()", error);
1976
+ }
1977
+ let responsePublicKey = void 0;
1978
+ if (typeof response.getPublicKey === "function") try {
1979
+ const _publicKey = response.getPublicKey();
1980
+ if (_publicKey !== null) responsePublicKey = bufferToBase64URLString(_publicKey);
1981
+ } catch (error) {
1982
+ warnOnBrokenImplementation("getPublicKey()", error);
1983
+ }
1984
+ let responseAuthenticatorData;
1985
+ if (typeof response.getAuthenticatorData === "function") try {
1986
+ responseAuthenticatorData = bufferToBase64URLString(response.getAuthenticatorData());
1987
+ } catch (error) {
1988
+ warnOnBrokenImplementation("getAuthenticatorData()", error);
1989
+ }
1990
+ return {
1991
+ id,
1992
+ rawId: bufferToBase64URLString(rawId),
1993
+ response: {
1994
+ attestationObject: bufferToBase64URLString(response.attestationObject),
1995
+ clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
1996
+ transports,
1997
+ publicKeyAlgorithm: responsePublicKeyAlgorithm,
1998
+ publicKey: responsePublicKey,
1999
+ authenticatorData: responseAuthenticatorData
2000
+ },
2001
+ type,
2002
+ clientExtensionResults: credential.getClientExtensionResults(),
2003
+ authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
2004
+ };
2005
+ }
2006
+ function warnOnBrokenImplementation(methodName, cause) {
2007
+ console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${methodName}. You should report this error to them.\n`, cause);
2008
+ }
2009
+ //#endregion
2010
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/browserSupportsWebAuthnAutofill.js
2011
+ function browserSupportsWebAuthnAutofill() {
2012
+ if (!browserSupportsWebAuthn()) return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
2013
+ const globalPublicKeyCredential = globalThis.PublicKeyCredential;
2014
+ if (globalPublicKeyCredential?.isConditionalMediationAvailable === void 0) return _browserSupportsWebAuthnAutofillInternals.stubThis(new Promise((resolve) => resolve(false)));
2015
+ return _browserSupportsWebAuthnAutofillInternals.stubThis(globalPublicKeyCredential.isConditionalMediationAvailable());
2016
+ }
2017
+ const _browserSupportsWebAuthnAutofillInternals = { stubThis: (value) => value };
2018
+ //#endregion
2019
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/helpers/identifyAuthenticationError.js
2020
+ function identifyAuthenticationError({ error, options }) {
2021
+ const { publicKey } = options;
2022
+ if (!publicKey) throw Error("options was missing required publicKey property");
2023
+ if (error.name === "AbortError") {
2024
+ if (options.signal instanceof AbortSignal) return new WebAuthnError({
2025
+ message: "Authentication ceremony was sent an abort signal",
2026
+ code: "ERROR_CEREMONY_ABORTED",
2027
+ cause: error
2028
+ });
2029
+ } else if (error.name === "NotAllowedError") return new WebAuthnError({
2030
+ message: error.message,
2031
+ code: "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",
2032
+ cause: error
2033
+ });
2034
+ else if (error.name === "SecurityError") {
2035
+ const effectiveDomain = globalThis.location.hostname;
2036
+ if (!isValidDomain(effectiveDomain)) return new WebAuthnError({
2037
+ message: `${globalThis.location.hostname} is an invalid domain`,
2038
+ code: "ERROR_INVALID_DOMAIN",
2039
+ cause: error
2040
+ });
2041
+ else if (publicKey.rpId !== effectiveDomain) return new WebAuthnError({
2042
+ message: `The RP ID "${publicKey.rpId}" is invalid for this domain`,
2043
+ code: "ERROR_INVALID_RP_ID",
2044
+ cause: error
2045
+ });
2046
+ } else if (error.name === "UnknownError") return new WebAuthnError({
2047
+ message: "The authenticator was unable to process the specified options, or could not create a new assertion signature",
2048
+ code: "ERROR_AUTHENTICATOR_GENERAL_ERROR",
2049
+ cause: error
2050
+ });
2051
+ return error;
2052
+ }
2053
+ //#endregion
2054
+ //#region ../../node_modules/.pnpm/@simplewebauthn+browser@13.3.0/node_modules/@simplewebauthn/browser/esm/methods/startAuthentication.js
2055
+ async function startAuthentication(options) {
2056
+ if (!options.optionsJSON && options.challenge) {
2057
+ console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information.");
2058
+ options = { optionsJSON: options };
2059
+ }
2060
+ const { optionsJSON, useBrowserAutofill = false, verifyBrowserAutofillInput = true } = options;
2061
+ if (!browserSupportsWebAuthn()) throw new Error("WebAuthn is not supported in this browser");
2062
+ let allowCredentials;
2063
+ if (optionsJSON.allowCredentials?.length !== 0) allowCredentials = optionsJSON.allowCredentials?.map(toPublicKeyCredentialDescriptor);
2064
+ const publicKey = {
2065
+ ...optionsJSON,
2066
+ challenge: base64URLStringToBuffer(optionsJSON.challenge),
2067
+ allowCredentials
2068
+ };
2069
+ const getOptions = {};
2070
+ if (useBrowserAutofill) {
2071
+ if (!await browserSupportsWebAuthnAutofill()) throw Error("Browser does not support WebAuthn autofill");
2072
+ if (document.querySelectorAll("input[autocomplete$='webauthn']").length < 1 && verifyBrowserAutofillInput) throw Error("No <input> with \"webauthn\" as the only or last value in its `autocomplete` attribute was detected");
2073
+ getOptions.mediation = "conditional";
2074
+ publicKey.allowCredentials = [];
2075
+ }
2076
+ getOptions.publicKey = publicKey;
2077
+ getOptions.signal = WebAuthnAbortService.createNewAbortSignal();
2078
+ let credential;
2079
+ try {
2080
+ credential = await navigator.credentials.get(getOptions);
2081
+ } catch (err) {
2082
+ throw identifyAuthenticationError({
2083
+ error: err,
2084
+ options: getOptions
2085
+ });
2086
+ }
2087
+ if (!credential) throw new Error("Authentication was not completed");
2088
+ const { id, rawId, response, type } = credential;
2089
+ let userHandle = void 0;
2090
+ if (response.userHandle) userHandle = bufferToBase64URLString(response.userHandle);
2091
+ return {
2092
+ id,
2093
+ rawId: bufferToBase64URLString(rawId),
2094
+ response: {
2095
+ authenticatorData: bufferToBase64URLString(response.authenticatorData),
2096
+ clientDataJSON: bufferToBase64URLString(response.clientDataJSON),
2097
+ signature: bufferToBase64URLString(response.signature),
2098
+ userHandle
2099
+ },
2100
+ type,
2101
+ clientExtensionResults: credential.getClientExtensionResults(),
2102
+ authenticatorAttachment: toAuthenticatorAttachment(credential.authenticatorAttachment)
2103
+ };
2104
+ }
2105
+ //#endregion
2106
+ //#region ../../node_modules/.pnpm/@better-auth+passkey@1.6.22_@better-auth+core@1.6.22_@better-auth+utils@0.4.2_@better-f_9dcb641568b0468b4b3f2fd37291240f/node_modules/@better-auth/passkey/dist/client.mjs
2107
+ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
2108
+ const signInPasskey = async (opts, options) => {
2109
+ const response = await $fetch("/passkey/generate-authenticate-options", {
2110
+ method: "GET",
2111
+ throw: false
2112
+ });
2113
+ if (!response.data) return response;
2114
+ const mergedExtensions = response.data.extensions || opts?.extensions ? {
2115
+ ...response.data.extensions || {},
2116
+ ...opts?.extensions || {}
2117
+ } : void 0;
2118
+ let res;
2119
+ try {
2120
+ res = await startAuthentication({
2121
+ optionsJSON: {
2122
+ ...response.data,
2123
+ extensions: mergedExtensions
2124
+ },
2125
+ useBrowserAutofill: opts?.autoFill
2126
+ });
2127
+ } catch (err) {
2128
+ return {
2129
+ data: null,
2130
+ error: {
2131
+ code: err instanceof WebAuthnError ? err.code : "AUTH_CANCELLED",
2132
+ message: PASSKEY_ERROR_CODES.AUTH_CANCELLED.message,
2133
+ status: 400,
2134
+ statusText: "BAD_REQUEST"
2135
+ }
2136
+ };
2137
+ }
2138
+ try {
2139
+ const { clientExtensionResults, ...responseBody } = res;
2140
+ const verified = await $fetch("/passkey/verify-authentication", {
2141
+ body: { response: responseBody },
2142
+ ...opts?.fetchOptions,
2143
+ ...options,
2144
+ method: "POST",
2145
+ throw: false
2146
+ });
2147
+ $listPasskeys.set(Math.random());
2148
+ $store.notify("$sessionSignal");
2149
+ if (opts?.returnWebAuthnResponse) return {
2150
+ ...verified,
2151
+ webauthn: {
2152
+ response: res,
2153
+ clientExtensionResults
2154
+ }
2155
+ };
2156
+ return verified;
2157
+ } catch (err) {
2158
+ console.error(`[Better Auth] Error verifying passkey`, err);
2159
+ return {
2160
+ data: null,
2161
+ error: {
2162
+ code: "AUTH_CANCELLED",
2163
+ message: PASSKEY_ERROR_CODES.AUTH_CANCELLED.message,
2164
+ status: 400,
2165
+ statusText: "BAD_REQUEST"
2166
+ }
2167
+ };
2168
+ }
2169
+ };
2170
+ const registerPasskey = async (opts, fetchOpts) => {
2171
+ const options = await $fetch("/passkey/generate-register-options", {
2172
+ method: "GET",
2173
+ query: {
2174
+ ...opts?.authenticatorAttachment && { authenticatorAttachment: opts.authenticatorAttachment },
2175
+ ...opts?.name && { name: opts.name },
2176
+ ...opts?.context && { context: opts.context }
2177
+ },
2178
+ throw: false
2179
+ });
2180
+ if (!options.data) return options;
2181
+ try {
2182
+ const mergedExtensions = options.data.extensions || opts?.extensions ? {
2183
+ ...options.data.extensions || {},
2184
+ ...opts?.extensions || {}
2185
+ } : void 0;
2186
+ const res = await startRegistration({
2187
+ optionsJSON: {
2188
+ ...options.data,
2189
+ extensions: mergedExtensions
2190
+ },
2191
+ useAutoRegister: opts?.useAutoRegister
2192
+ });
2193
+ const { clientExtensionResults, ...responseBody } = res;
2194
+ const verified = await $fetch("/passkey/verify-registration", {
2195
+ ...opts?.fetchOptions,
2196
+ ...fetchOpts,
2197
+ body: {
2198
+ response: responseBody,
2199
+ name: opts?.name
2200
+ },
2201
+ method: "POST",
2202
+ throw: false
2203
+ });
2204
+ if (!verified.data) return verified;
2205
+ $listPasskeys.set(Math.random());
2206
+ if (opts?.returnWebAuthnResponse) return {
2207
+ ...verified,
2208
+ webauthn: {
2209
+ response: res,
2210
+ clientExtensionResults
2211
+ }
2212
+ };
2213
+ return verified;
2214
+ } catch (e) {
2215
+ if (e instanceof WebAuthnError) {
2216
+ if (e.code === "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED") return {
2217
+ data: null,
2218
+ error: {
2219
+ code: e.code,
2220
+ message: PASSKEY_ERROR_CODES.PREVIOUSLY_REGISTERED.message,
2221
+ status: 400,
2222
+ statusText: "BAD_REQUEST"
2223
+ }
2224
+ };
2225
+ if (e.code === "ERROR_CEREMONY_ABORTED") return {
2226
+ data: null,
2227
+ error: {
2228
+ code: e.code,
2229
+ message: PASSKEY_ERROR_CODES.REGISTRATION_CANCELLED.message,
2230
+ status: 400,
2231
+ statusText: "BAD_REQUEST"
2232
+ }
2233
+ };
2234
+ return {
2235
+ data: null,
2236
+ error: {
2237
+ code: e.code,
2238
+ message: e.message,
2239
+ status: 400,
2240
+ statusText: "BAD_REQUEST"
2241
+ }
2242
+ };
2243
+ }
2244
+ return {
2245
+ data: null,
2246
+ error: {
2247
+ code: "UNKNOWN_ERROR",
2248
+ message: e instanceof Error ? e.message : PASSKEY_ERROR_CODES.UNKNOWN_ERROR.message,
2249
+ status: 500,
2250
+ statusText: "INTERNAL_SERVER_ERROR"
2251
+ }
2252
+ };
2253
+ }
2254
+ };
2255
+ return {
2256
+ signIn: { passkey: signInPasskey },
2257
+ passkey: { addPasskey: registerPasskey },
2258
+ $Infer: {}
2259
+ };
2260
+ };
2261
+ const passkeyClient = () => {
2262
+ const $listPasskeys = atom();
2263
+ return {
2264
+ id: "passkey",
2265
+ version: PACKAGE_VERSION,
2266
+ $InferServerPlugin: {},
2267
+ getActions: ($fetch, $store) => getPasskeyActions($fetch, {
2268
+ $listPasskeys,
2269
+ $store
2270
+ }),
2271
+ getAtoms($fetch) {
2272
+ return {
2273
+ listPasskeys: useAuthQuery($listPasskeys, "/passkey/list-user-passkeys", $fetch, { method: "GET" }),
2274
+ $listPasskeys
2275
+ };
2276
+ },
2277
+ pathMethods: {
2278
+ "/passkey/register": "POST",
2279
+ "/passkey/authenticate": "POST"
2280
+ },
2281
+ atomListeners: [{
2282
+ matcher(path) {
2283
+ return path === "/passkey/verify-registration" || path === "/passkey/delete-passkey" || path === "/passkey/update-passkey" || path === "/sign-out";
2284
+ },
2285
+ signal: "$listPasskeys"
2286
+ }, {
2287
+ matcher: (path) => path === "/passkey/verify-authentication",
2288
+ signal: "$sessionSignal"
2289
+ }],
2290
+ $ERROR_CODES: PASSKEY_ERROR_CODES
2291
+ };
2292
+ };
2293
+ //#endregion
2294
+ //#region ../../node_modules/.pnpm/@chiballc+utils@2.5.1_@hono+zod-openapi@1.5.1_hono@4.13.0_zod@4.4.3__hono@4.13.0_magic-_dfcdb59639d9fe73412dad0223379a88/node_modules/@chiballc/utils/dist/index.mjs
1639
2295
  function isPromise(arg) {
1640
2296
  return arg && typeof arg.then === "function";
1641
2297
  }
@@ -1895,6 +2551,9 @@ const messages = {
1895
2551
  auth_request_rate_limited: "Authentication requests are temporarily limited.",
1896
2552
  state_conflict: "The authentication state conflicts with the request.",
1897
2553
  access_denied: "Access is denied.",
2554
+ platform_target_unavailable: "The platform administration target is unavailable.",
2555
+ platform_quorum_unavailable: "Platform administration quorum is unavailable.",
2556
+ platform_recovery_required: "Platform administration requires separate recovery.",
1898
2557
  identity_authority_unavailable: "Authentication is temporarily unavailable."
1899
2558
  };
1900
2559
  var AuthError = class extends Error {
@@ -2639,6 +3298,187 @@ function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
2639
3298
  if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
2640
3299
  return fromOrganizationReadAuthorityError(value, status);
2641
3300
  }
3301
+ function normalizePlatformRoleChangeRecentAuthenticationInput(value) {
3302
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "changeReference,expectedGlobalRevision,expectedTargetRevision,idempotencyKey,reasonCategory,requestedRoles,targetUserId") throw new TypeError("recent authentication input is invalid");
3303
+ if (!isId(value.targetUserId)) throw new TypeError("targetUserId is invalid");
3304
+ if (!Array.isArray(value.requestedRoles) || value.requestedRoles.length < 1 || value.requestedRoles.length > 2 || value.requestedRoles.some((role) => role !== "administrator" && role !== "investigator") || new Set(value.requestedRoles).size !== value.requestedRoles.length) throw new TypeError("requestedRoles is invalid");
3305
+ for (const field of ["expectedTargetRevision", "expectedGlobalRevision"]) if (!Number.isSafeInteger(value[field]) || value[field] < 0 || value[field] >= Number.MAX_SAFE_INTEGER) throw new TypeError(`${field} is invalid`);
3306
+ if (!(typeof value.reasonCategory === "string" && [
3307
+ "initial_bootstrap",
3308
+ "personnel_change",
3309
+ "privilege_review",
3310
+ "quorum_recovery",
3311
+ "security_response"
3312
+ ].includes(value.reasonCategory))) throw new TypeError("reasonCategory is invalid");
3313
+ for (const field of ["changeReference", "idempotencyKey"]) if (typeof value[field] !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value[field])) throw new TypeError(`${field} is invalid`);
3314
+ return {
3315
+ action: "platform_role_change",
3316
+ targetUserId: value.targetUserId,
3317
+ requestedRoles: [...value.requestedRoles].sort(),
3318
+ expectedTargetRevision: value.expectedTargetRevision,
3319
+ expectedGlobalRevision: value.expectedGlobalRevision,
3320
+ reasonCategory: value.reasonCategory,
3321
+ changeReference: value.changeReference,
3322
+ idempotencyKey: value.idempotencyKey
3323
+ };
3324
+ }
3325
+ function normalizeOrganizationManualRoleChangeInput(value) {
3326
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "expectedActorAuthorityRevision,expectedTargetAuthorityRevision,idempotencyKey,requestedManualRole") throw new TypeError("organization manual role input is invalid");
3327
+ if (value.requestedManualRole !== "owner" && value.requestedManualRole !== "admin" && value.requestedManualRole !== "member") throw new TypeError("requestedManualRole is invalid");
3328
+ const expectedActorAuthorityRevision = normalizeAuthorityRevision(value.expectedActorAuthorityRevision, "expectedActorAuthorityRevision");
3329
+ const expectedTargetAuthorityRevision = normalizeAuthorityRevision(value.expectedTargetAuthorityRevision, "expectedTargetAuthorityRevision", true);
3330
+ return {
3331
+ requestedManualRole: value.requestedManualRole,
3332
+ expectedActorAuthorityRevision,
3333
+ expectedTargetAuthorityRevision,
3334
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
3335
+ };
3336
+ }
3337
+ function normalizeOrganizationOwnershipTransferInput(value) {
3338
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "expectedActorAuthorityRevision,expectedOutgoingOwnerAuthorityRevision,expectedSuccessorAuthorityRevision,idempotencyKey,outgoingOwnerMembershipId,outgoingOwnerRole,successorMembershipId") throw new TypeError("organization ownership transfer input is invalid");
3339
+ if (!isId(value.outgoingOwnerMembershipId) || !isId(value.successorMembershipId)) throw new TypeError("ownership transfer membership is invalid");
3340
+ if (value.outgoingOwnerMembershipId === value.successorMembershipId) throw new TypeError("ownership transfer memberships must differ");
3341
+ if (value.outgoingOwnerRole !== "admin" && value.outgoingOwnerRole !== "member") throw new TypeError("outgoingOwnerRole is invalid");
3342
+ return {
3343
+ outgoingOwnerMembershipId: value.outgoingOwnerMembershipId,
3344
+ successorMembershipId: value.successorMembershipId,
3345
+ outgoingOwnerRole: value.outgoingOwnerRole,
3346
+ expectedActorAuthorityRevision: normalizeAuthorityRevision(value.expectedActorAuthorityRevision, "expectedActorAuthorityRevision"),
3347
+ expectedOutgoingOwnerAuthorityRevision: normalizeAuthorityRevision(value.expectedOutgoingOwnerAuthorityRevision, "expectedOutgoingOwnerAuthorityRevision", true),
3348
+ expectedSuccessorAuthorityRevision: normalizeAuthorityRevision(value.expectedSuccessorAuthorityRevision, "expectedSuccessorAuthorityRevision", true),
3349
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
3350
+ };
3351
+ }
3352
+ function normalizeOrganizationManualRoleChangeResult(value) {
3353
+ exact(value, [
3354
+ "status",
3355
+ "memberId",
3356
+ "manualRole",
3357
+ "role",
3358
+ "authorityRevision"
3359
+ ]);
3360
+ if (value.status !== "applied") throw authorityUnavailable();
3361
+ return {
3362
+ status: "applied",
3363
+ ...normalizeOrganizationAuthorityMemberOutcome(value, true)
3364
+ };
3365
+ }
3366
+ function normalizeOrganizationOwnershipTransferResult(value) {
3367
+ exact(value, [
3368
+ "status",
3369
+ "outgoingOwner",
3370
+ "successor"
3371
+ ]);
3372
+ if (value.status !== "applied") throw authorityUnavailable();
3373
+ return {
3374
+ status: "applied",
3375
+ outgoingOwner: normalizeOrganizationAuthorityMemberOutcome(value.outgoingOwner),
3376
+ successor: normalizeOrganizationAuthorityMemberOutcome(value.successor)
3377
+ };
3378
+ }
3379
+ function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = false) {
3380
+ exact(value, [
3381
+ "memberId",
3382
+ "manualRole",
3383
+ "role",
3384
+ "authorityRevision",
3385
+ ...includesStatus ? ["status"] : []
3386
+ ]);
3387
+ if (!isId(value.memberId) || value.manualRole !== "owner" && value.manualRole !== "admin" && value.manualRole !== "member" || value.role !== "owner" && value.role !== "admin" && value.role !== "member") throw authorityUnavailable();
3388
+ return {
3389
+ memberId: value.memberId,
3390
+ manualRole: value.manualRole,
3391
+ role: value.role,
3392
+ authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
3393
+ };
3394
+ }
3395
+ function normalizeAuthorityRevision(value, name, incremented = false) {
3396
+ if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER - (incremented ? 1 : 0)) throw new TypeError(`${name} is invalid`);
3397
+ return value;
3398
+ }
3399
+ function normalizeAuthorityResultRevision(value) {
3400
+ if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
3401
+ return value;
3402
+ }
3403
+ function normalizeAuthorityIdempotencyKey(value) {
3404
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)) throw new TypeError("idempotencyKey is invalid");
3405
+ return value;
3406
+ }
3407
+ function normalizePlatformBootstrapRoleChangeInput(value) {
3408
+ const request = normalizePlatformRoleChangeRecentAuthenticationInput(value);
3409
+ if (request.reasonCategory !== "initial_bootstrap" || !request.requestedRoles.includes("administrator")) throw new TypeError("platform first approval input is invalid");
3410
+ return request;
3411
+ }
3412
+ function normalizePlatformRoleApproval(value) {
3413
+ exact(value, [
3414
+ "status",
3415
+ "targetUserId",
3416
+ "targetRevision",
3417
+ "globalRevision",
3418
+ "roles"
3419
+ ]);
3420
+ if (value.status !== "awaiting_second_approval" && value.status !== "applied" || !isId(value.targetUserId)) throw authorityUnavailable();
3421
+ if (!Number.isSafeInteger(value.targetRevision) || value.targetRevision < 0) throw authorityUnavailable();
3422
+ if (!Number.isSafeInteger(value.globalRevision) || value.globalRevision < 0) throw authorityUnavailable();
3423
+ if (!Array.isArray(value.roles) || value.status === "awaiting_second_approval" && value.roles.length !== 0 || value.status === "applied" && !(value.roles.length === 1 && value.roles[0] === "administrator" || value.roles.length === 2 && value.roles[0] === "administrator" && value.roles[1] === "investigator")) throw authorityUnavailable();
3424
+ if (value.status === "applied") return {
3425
+ status: "applied",
3426
+ targetUserId: value.targetUserId,
3427
+ targetRevision: value.targetRevision,
3428
+ globalRevision: value.globalRevision,
3429
+ roles: value.roles
3430
+ };
3431
+ return {
3432
+ status: "awaiting_second_approval",
3433
+ targetUserId: value.targetUserId,
3434
+ targetRevision: value.targetRevision,
3435
+ globalRevision: value.globalRevision,
3436
+ roles: []
3437
+ };
3438
+ }
3439
+ function normalizePlatformStatus(value) {
3440
+ exact(value, [
3441
+ "eligible",
3442
+ "globalRevision",
3443
+ "roles"
3444
+ ]);
3445
+ if (typeof value.eligible !== "boolean") throw authorityUnavailable();
3446
+ if (!Number.isSafeInteger(value.globalRevision) || value.globalRevision < 0 || value.globalRevision >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
3447
+ if (!Array.isArray(value.roles) || !(value.roles.length === 0 || value.roles.length === 1 && (value.roles[0] === "administrator" || value.roles[0] === "investigator") || value.roles.length === 2 && value.roles[0] === "administrator" && value.roles[1] === "investigator") || !value.eligible && value.roles.length !== 0) throw authorityUnavailable();
3448
+ return {
3449
+ eligible: value.eligible,
3450
+ globalRevision: value.globalRevision,
3451
+ roles: value.roles
3452
+ };
3453
+ }
3454
+ function normalizeRecentAuthenticationStatus(value) {
3455
+ exact(value, ["status"]);
3456
+ if (value.status !== "pending" && value.status !== "ready") throw authorityUnavailable();
3457
+ return { status: value.status };
3458
+ }
3459
+ function fromRecentAuthenticationError(value, status, retryAfter) {
3460
+ if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
3461
+ if (status === 401) return new AuthError("authentication_required", 401);
3462
+ if (status === 403) return new AuthError("request_origin_denied", 403);
3463
+ if (status === 409) return new AuthError("state_conflict", 409);
3464
+ if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
3465
+ return authorityUnavailable();
3466
+ }
3467
+ function fromPlatformAdministrationError(value, status, retryAfter) {
3468
+ const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
3469
+ if (status === 400 && code === "BAD_REQUEST") return new AuthError("invalid_request", 400);
3470
+ if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
3471
+ if (status === 403 && code === "FORBIDDEN") return new AuthError("access_denied", 403);
3472
+ if (status === 404 && code === "NOT_FOUND") return new AuthError("platform_target_unavailable", 404);
3473
+ if (status === 409 && code === "CONFLICT") return new AuthError("state_conflict", 409);
3474
+ if (status === 409 && code === "QUORUM_UNAVAILABLE") return new AuthError("platform_quorum_unavailable", 409);
3475
+ if (status === 413 && code === "REQUEST_TOO_LONG") return new AuthError("invalid_request", 413);
3476
+ if (status === 415 && code === "UNSUPPORTED_MEDIA_TYPE") return new AuthError("invalid_request", 415);
3477
+ if (status === 422 && code === "RECOVERY_REQUIRED") return new AuthError("platform_recovery_required", 422);
3478
+ if (status === 429 && code === "RATE_LIMITED") return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
3479
+ if (status === 503 && code === "SERVICE_UNAVAILABLE") return authorityUnavailable();
3480
+ return authorityUnavailable();
3481
+ }
2642
3482
  function fromInvitationAuthorityError(value, status) {
2643
3483
  const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
2644
3484
  if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
@@ -3580,6 +4420,8 @@ function byteLength(value) {
3580
4420
  //#endregion
3581
4421
  //#region src/client.ts
3582
4422
  const REFRESH_WINDOW_MS = 120 * 1e3;
4423
+ const RECENT_AUTHENTICATION_BROWSER_HEADER = "x-finueva-recent-auth-browser";
4424
+ const RECENT_AUTHENTICATION_REQUEST_HEADER = "x-finueva-recent-auth-request";
3583
4425
  function createAuthClient(options) {
3584
4426
  const authOrigin = normalizeOrigin(options.authOrigin, "authOrigin");
3585
4427
  const appOrigin = normalizeOrigin(options.appOrigin, "appOrigin");
@@ -3596,7 +4438,8 @@ function createAuthClient(options) {
3596
4438
  credentials: "include",
3597
4439
  retry: 0,
3598
4440
  timeout: timeoutMs
3599
- }
4441
+ },
4442
+ plugins: [passkeyClient()]
3600
4443
  });
3601
4444
  const persistence = createSessionPersistence(options.persistence, authOrigin, now, timeoutMs);
3602
4445
  const authStateListeners = new Set();
@@ -3608,6 +4451,12 @@ function createAuthClient(options) {
3608
4451
  let selectedWorkspaceKey;
3609
4452
  let credentialGeneration = 0;
3610
4453
  let authorityGeneration = 0;
4454
+ let platformStatusReadEpoch = 0;
4455
+ let sessionAuthorityEpoch = 0;
4456
+ let sessionAuthorityObserved = false;
4457
+ let recentAuthenticationBrowserToken;
4458
+ let recentAuthenticationStartAttempt;
4459
+ let recentAuthenticationStartRequest;
3611
4460
  let sessionReadEpoch = 0;
3612
4461
  let activeAccountMutationGeneration;
3613
4462
  let invitationAbort;
@@ -3621,6 +4470,10 @@ function createAuthClient(options) {
3621
4470
  let signalRefreshPending = false;
3622
4471
  let signalRefreshScheduled = false;
3623
4472
  let signalRefreshRequest;
4473
+ function advanceAuthorityGeneration() {
4474
+ recentAuthenticationStartAttempt = void 0;
4475
+ return ++authorityGeneration;
4476
+ }
3624
4477
  function setAuthState(state) {
3625
4478
  authState = state;
3626
4479
  for (const listener of authStateListeners) try {
@@ -3726,7 +4579,11 @@ function createAuthClient(options) {
3726
4579
  }
3727
4580
  function updateSession(session) {
3728
4581
  const unboundCredential = !sessionId && (credential || credentialRequests.size > 0);
4582
+ const changedSession = sessionId === void 0 ? !sessionAuthorityObserved || session !== null : !session || session.id !== sessionId || session.user.id !== sessionUserId;
3729
4583
  if (!session || unboundCredential || sessionId && (session.id !== sessionId || session.user.id !== sessionUserId)) clearCredential();
4584
+ if (changedSession || recentAuthenticationStartAttempt && (recentAuthenticationStartAttempt.sessionId !== session?.id || recentAuthenticationStartAttempt.userId !== session?.user.id)) recentAuthenticationStartAttempt = void 0;
4585
+ if (changedSession) sessionAuthorityEpoch += 1;
4586
+ sessionAuthorityObserved = true;
3730
4587
  sessionId = session?.id;
3731
4588
  sessionUserId = session?.user.id;
3732
4589
  return session;
@@ -3755,10 +4612,10 @@ function createAuthClient(options) {
3755
4612
  }
3756
4613
  function signOut() {
3757
4614
  if (signOutRequest) return signOutRequest;
3758
- if (activeAccountMutationGeneration !== void 0) return Promise.reject(new AuthError("state_conflict", 409));
4615
+ if (activeAccountMutationGeneration !== void 0 || recentAuthenticationStartRequest) return Promise.reject(new AuthError("state_conflict", 409));
3759
4616
  const pendingInvitation = invitationRequest;
3760
4617
  invitationAbort?.abort();
3761
- const generation = ++authorityGeneration;
4618
+ const generation = advanceAuthorityGeneration();
3762
4619
  sessionReadEpoch += 1;
3763
4620
  clearCredential();
3764
4621
  sessionId = void 0;
@@ -3803,10 +4660,10 @@ function createAuthClient(options) {
3803
4660
  return request;
3804
4661
  }
3805
4662
  async function runAccountMutation(operation) {
3806
- if (signOutRequest || activeAccountMutationGeneration !== void 0) throw new AuthError("state_conflict", 409);
4663
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || recentAuthenticationStartRequest) throw new AuthError("state_conflict", 409);
3807
4664
  const pendingInvitation = invitationRequest;
3808
4665
  invitationAbort?.abort();
3809
- const generation = ++authorityGeneration;
4666
+ const generation = advanceAuthorityGeneration();
3810
4667
  sessionReadEpoch += 1;
3811
4668
  activeAccountMutationGeneration = generation;
3812
4669
  clearCredential();
@@ -3873,8 +4730,138 @@ function createAuthClient(options) {
3873
4730
  throw error;
3874
4731
  }
3875
4732
  }
4733
+ function assertRecentAuthenticationOrigin() {
4734
+ if (appOrigin !== authOrigin) throw new TypeError("recent authentication requires the exact Auth Origin");
4735
+ }
4736
+ function assertPlatformAdministrationOrigin() {
4737
+ if (appOrigin !== authOrigin) throw new TypeError("platform administration requires the exact Auth Origin");
4738
+ }
4739
+ async function startRecentAuthentication(body) {
4740
+ assertRecentAuthenticationOrigin();
4741
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
4742
+ if (recentAuthenticationStartRequest) throw new AuthError("state_conflict", 409);
4743
+ const generation = authorityGeneration;
4744
+ recentAuthenticationBrowserToken ??= createOpaqueToken();
4745
+ const normalizedInput = JSON.stringify(body);
4746
+ const attempt = recentAuthenticationStartAttempt?.input === normalizedInput ? recentAuthenticationStartAttempt : {
4747
+ input: normalizedInput,
4748
+ requestToken: createOpaqueToken(),
4749
+ sessionId,
4750
+ userId: sessionUserId
4751
+ };
4752
+ recentAuthenticationStartAttempt = attempt;
4753
+ const request = (async () => {
4754
+ try {
4755
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/recent-authentication"), {
4756
+ fetch: fetchImpl,
4757
+ timeoutMs,
4758
+ method: "POST",
4759
+ headers: {
4760
+ "content-type": "application/json",
4761
+ [RECENT_AUTHENTICATION_BROWSER_HEADER]: recentAuthenticationBrowserToken,
4762
+ [RECENT_AUTHENTICATION_REQUEST_HEADER]: attempt.requestToken
4763
+ },
4764
+ body,
4765
+ mapError: fromRecentAuthenticationError
4766
+ });
4767
+ if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
4768
+ const status = normalizeRecentAuthenticationStatus(value);
4769
+ if (recentAuthenticationStartAttempt === attempt) recentAuthenticationStartAttempt = void 0;
4770
+ return status;
4771
+ } catch (error) {
4772
+ if (recentAuthenticationStartAttempt === attempt && (!(error instanceof AuthError) || error.code !== "identity_authority_unavailable")) recentAuthenticationStartAttempt = void 0;
4773
+ throw error;
4774
+ }
4775
+ })();
4776
+ recentAuthenticationStartRequest = request;
4777
+ try {
4778
+ return await request;
4779
+ } finally {
4780
+ if (recentAuthenticationStartRequest === request) recentAuthenticationStartRequest = void 0;
4781
+ }
4782
+ }
3876
4783
  return {
3877
4784
  _type: "browser",
4785
+ async getPlatformStatus() {
4786
+ assertPlatformAdministrationOrigin();
4787
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
4788
+ const generation = authorityGeneration;
4789
+ const readEpoch = ++platformStatusReadEpoch;
4790
+ const sessionEpoch = sessionAuthorityEpoch;
4791
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/platform/status"), {
4792
+ fetch: fetchImpl,
4793
+ timeoutMs,
4794
+ method: "POST",
4795
+ headers: { "content-type": "application/json" },
4796
+ body: {},
4797
+ mapError: fromPlatformAdministrationError
4798
+ });
4799
+ if (generation !== authorityGeneration || readEpoch !== platformStatusReadEpoch || sessionEpoch !== sessionAuthorityEpoch) throw new AuthError("state_conflict", 409);
4800
+ return normalizePlatformStatus(value);
4801
+ },
4802
+ async startPlatformRoleChangeRecentAuthentication(input) {
4803
+ return startRecentAuthentication(normalizePlatformRoleChangeRecentAuthenticationInput(input));
4804
+ },
4805
+ async startOrganizationOwnerRoleChangeRecentAuthentication(organizationId, targetMembershipId, input) {
4806
+ return startRecentAuthentication({
4807
+ action: "organization_owner_role_change",
4808
+ organizationId: normalizeIdInput(organizationId),
4809
+ targetMembershipId: normalizeIdInput(targetMembershipId),
4810
+ ...normalizeOrganizationManualRoleChangeInput(input)
4811
+ });
4812
+ },
4813
+ async startOrganizationOwnershipTransferRecentAuthentication(organizationId, input) {
4814
+ return startRecentAuthentication({
4815
+ action: "organization_ownership_transfer",
4816
+ organizationId: normalizeIdInput(organizationId),
4817
+ ...normalizeOrganizationOwnershipTransferInput(input)
4818
+ });
4819
+ },
4820
+ async approveBootstrapPlatformRoleChange(input) {
4821
+ assertRecentAuthenticationOrigin();
4822
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
4823
+ const body = normalizePlatformBootstrapRoleChangeInput(input);
4824
+ const generation = authorityGeneration;
4825
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/platform/role-approvals"), {
4826
+ fetch: fetchImpl,
4827
+ timeoutMs,
4828
+ method: "POST",
4829
+ headers: { "content-type": "application/json" },
4830
+ body,
4831
+ mapError: fromPlatformAdministrationError
4832
+ });
4833
+ if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
4834
+ return normalizePlatformRoleApproval(value);
4835
+ },
4836
+ async verifyRecentAuthenticationWithPasskey() {
4837
+ assertRecentAuthenticationOrigin();
4838
+ if (!(await runAccountMutation(async () => {
4839
+ const verification = await betterAuth.signIn.passkey({ autoFill: false });
4840
+ if (verification.error) throw fromRecentAuthenticationError(void 0, verification.error.status);
4841
+ })).session) throw new AuthError("authentication_required", 401);
4842
+ },
4843
+ async addPasskey() {
4844
+ assertRecentAuthenticationOrigin();
4845
+ if (!(await runAccountMutation(async () => {
4846
+ const registration = await betterAuth.passkey.addPasskey({ context: createOpaqueToken() });
4847
+ if (registration.error) throw fromAccountAuthorityError(registration.error, registration.error.status);
4848
+ })).session) throw new AuthError("authentication_required", 401);
4849
+ },
4850
+ async getRecentAuthenticationStatus() {
4851
+ assertRecentAuthenticationOrigin();
4852
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
4853
+ const generation = authorityGeneration;
4854
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/recent-authentication/status"), {
4855
+ fetch: fetchImpl,
4856
+ timeoutMs,
4857
+ method: "POST",
4858
+ headers: { "content-type": "application/json" },
4859
+ body: {},
4860
+ mapError: fromRecentAuthenticationError
4861
+ });
4862
+ if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
4863
+ return normalizeRecentAuthenticationStatus(value);
4864
+ },
3878
4865
  acceptInvitation(input) {
3879
4866
  let invitation;
3880
4867
  try {
@@ -3882,8 +4869,8 @@ function createAuthClient(options) {
3882
4869
  } catch (error) {
3883
4870
  return Promise.reject(error);
3884
4871
  }
3885
- if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) return Promise.reject(new AuthError("state_conflict", 409));
3886
- const generation = ++authorityGeneration;
4872
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest || recentAuthenticationStartRequest) return Promise.reject(new AuthError("state_conflict", 409));
4873
+ const generation = advanceAuthorityGeneration();
3887
4874
  const controller = new AbortController();
3888
4875
  clearCredential();
3889
4876
  const request = (async () => {
@@ -3989,6 +4976,39 @@ function createAuthClient(options) {
3989
4976
  if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
3990
4977
  return normalizeOrganizationTeamDisplay(value);
3991
4978
  },
4979
+ async changeOrganizationMemberManualRole(organizationId, targetMembershipId, input) {
4980
+ const organization = normalizeIdInput(organizationId);
4981
+ const target = normalizeIdInput(targetMembershipId);
4982
+ const body = normalizeOrganizationManualRoleChangeInput(input);
4983
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
4984
+ const generation = authorityGeneration;
4985
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", organization, "members", target, "manual-role"), {
4986
+ fetch: fetchImpl,
4987
+ timeoutMs,
4988
+ method: "POST",
4989
+ headers: { "content-type": "application/json" },
4990
+ body,
4991
+ mapError: fromOrganizationMutationAuthorityError
4992
+ });
4993
+ if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
4994
+ return normalizeOrganizationManualRoleChangeResult(value);
4995
+ },
4996
+ async transferOrganizationOwnership(organizationId, input) {
4997
+ const organization = normalizeIdInput(organizationId);
4998
+ const body = normalizeOrganizationOwnershipTransferInput(input);
4999
+ if (signOutRequest || activeAccountMutationGeneration !== void 0 || invitationRequest) throw new AuthError("state_conflict", 409);
5000
+ const generation = authorityGeneration;
5001
+ const value = await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", organization, "ownership-transfer"), {
5002
+ fetch: fetchImpl,
5003
+ timeoutMs,
5004
+ method: "POST",
5005
+ headers: { "content-type": "application/json" },
5006
+ body,
5007
+ mapError: fromOrganizationMutationAuthorityError
5008
+ });
5009
+ if (generation !== authorityGeneration) throw new AuthError("state_conflict", 409);
5010
+ return normalizeOrganizationOwnershipTransferResult(value);
5011
+ },
3992
5012
  async listOrganizationMembers(organizationId, input) {
3993
5013
  return organizationRead(`${normalizeIdInput(organizationId)}/members`, input, normalizeOrganizationMembers);
3994
5014
  },
@@ -4138,5 +5158,12 @@ function createAuthClient(options) {
4138
5158
  }
4139
5159
  };
4140
5160
  }
5161
+ function createOpaqueToken() {
5162
+ const bytes = new Uint8Array(32);
5163
+ globalThis.crypto.getRandomValues(bytes);
5164
+ let binary = "";
5165
+ for (const byte of bytes) binary += String.fromCharCode(byte);
5166
+ return globalThis.btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
5167
+ }
4141
5168
  //#endregion
4142
5169
  export { AuthError, createAuthClient };