decane-connect-kit 2.29.2 → 2.30.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.cjs CHANGED
@@ -42,6 +42,7 @@ __export(errors_exports, {
42
42
  InvalidApiKeyError: () => InvalidApiKeyError,
43
43
  InvalidPinError: () => InvalidPinError,
44
44
  InvalidRecoveryFileError: () => InvalidRecoveryFileError,
45
+ LoginInUseError: () => LoginInUseError,
45
46
  NetworkError: () => NetworkError,
46
47
  NewDeviceError: () => NewDeviceError,
47
48
  OriginNotAllowedError: () => OriginNotAllowedError,
@@ -64,7 +65,7 @@ __export(errors_exports, {
64
65
  WrongPasswordError: () => WrongPasswordError,
65
66
  WrongUnlockPasswordError: () => WrongUnlockPasswordError
66
67
  });
67
- var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, InvalidAccessTokenError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError, WalletExistsError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
68
+ var DecaneConnectError, InvalidApiKeyError, OriginNotAllowedError, SessionExpiredError, UnlockRequiredError, ReconnectRequiredError, UserCancelledError, WebAuthnNotSupportedError, InvalidPinError, CallSequenceError, NetworkError, ShareCorruptedError, ProvisioningTimeoutError, NewDeviceError, StaleDeviceShareError, PromptPinNotConfiguredError, PromptPasswordNotConfiguredError, WrongUnlockPasswordError, InvalidAccessTokenError, UnlockTokenRejectedError, AttestationError, RecoveryFailedError, InvalidRecoveryFileError, WrongPasswordError, RecoveryWalletMismatchError, ExportNotAuthorizedError, LoginInUseError, WalletExistsError, WalletEnrolmentError, ProvisioningRateLimitedError, EnclaveHttpError;
68
69
  var init_errors = __esm({
69
70
  "src/social/errors.ts"() {
70
71
  "use strict";
@@ -213,6 +214,11 @@ var init_errors = __esm({
213
214
  super("EXPORT_NOT_AUTHORIZED", "Export requires a fresh security check", true);
214
215
  }
215
216
  };
217
+ LoginInUseError = class extends DecaneConnectError {
218
+ constructor(message = "That login already opens another account. It was not linked.") {
219
+ super("LOGIN_IN_USE", message);
220
+ }
221
+ };
216
222
  WalletExistsError = class extends DecaneConnectError {
217
223
  constructor() {
218
224
  super("WALLET_EXISTS", "This account already has a wallet; opening it instead.", true);
@@ -266,6 +272,7 @@ __export(index_exports, {
266
272
  InvalidApiKeyError: () => InvalidApiKeyError,
267
273
  InvalidPinError: () => InvalidPinError,
268
274
  InvalidRecoveryFileError: () => InvalidRecoveryFileError,
275
+ LoginInUseError: () => LoginInUseError,
269
276
  MIN_PASSWORD_LENGTH: () => MIN_PASSWORD_LENGTH,
270
277
  NetworkError: () => NetworkError,
271
278
  NewDeviceError: () => NewDeviceError,
@@ -2118,7 +2125,9 @@ var ERROR_MAP = {
2118
2125
  // generic failure message.
2119
2126
  UNAUTHORIZED: ReconnectRequiredError,
2120
2127
  // A restorable wallet already exists: the client provisions instead of creating.
2121
- WALLET_EXISTS: WalletExistsError
2128
+ WALLET_EXISTS: WalletExistsError,
2129
+ // linkWithToken(): the login already opens another account.
2130
+ LOGIN_IN_USE: LoginInUseError
2122
2131
  };
2123
2132
  var REQUEST_TIMEOUT_MS = 3e4;
2124
2133
  var ApiClient = class {
@@ -2287,6 +2296,23 @@ var ApiClient = class {
2287
2296
  body: JSON.stringify(providerId ? { token, providerId } : { token })
2288
2297
  });
2289
2298
  }
2299
+ /** Attach a login from the project's own provider to the signed-in account. */
2300
+ async linkExternal(jwt, token, providerId) {
2301
+ return this._request("/auth/link/external", {
2302
+ method: "POST",
2303
+ headers: { Authorization: `Bearer ${jwt}` },
2304
+ body: JSON.stringify(providerId ? { token, providerId } : { token })
2305
+ });
2306
+ }
2307
+ async listLinkedLogins(jwt) {
2308
+ return this._request("/auth/link/external", { method: "GET", headers: { Authorization: `Bearer ${jwt}` } });
2309
+ }
2310
+ async unlinkLogin(jwt, id) {
2311
+ await this._request(`/auth/link/external/${encodeURIComponent(id)}`, {
2312
+ method: "DELETE",
2313
+ headers: { Authorization: `Bearer ${jwt}` }
2314
+ });
2315
+ }
2290
2316
  /**
2291
2317
  * Returns null when this user has no server-registered passkey, which is the
2292
2318
  * expected answer for wallets created before passkey sign-in existed or for
@@ -4954,6 +4980,20 @@ async function createDecaneConnect(config) {
4954
4980
  const result = await api.authExternal(token, opts?.providerId);
4955
4981
  return handleAuthResult(result);
4956
4982
  },
4983
+ async linkWithToken(token, opts) {
4984
+ if (!token) throw new CallSequenceError("linkWithToken requires a token");
4985
+ if (!auth) throw new ReconnectRequiredError();
4986
+ const result = await api.linkExternal(auth.jwt, token, opts?.providerId);
4987
+ return result.id ? { alreadyLinked: result.alreadyLinked, id: result.id } : { alreadyLinked: result.alreadyLinked };
4988
+ },
4989
+ async listLinkedLogins() {
4990
+ if (!auth) throw new ReconnectRequiredError();
4991
+ return (await api.listLinkedLogins(auth.jwt)).logins;
4992
+ },
4993
+ async unlinkLogin(id) {
4994
+ if (!auth) throw new ReconnectRequiredError();
4995
+ await api.unlinkLogin(auth.jwt, id);
4996
+ },
4957
4997
  async connectWithAccessToken(token) {
4958
4998
  const claims = decodeAccessToken(token);
4959
4999
  if (!claims) throw new InvalidAccessTokenError("not a Decane access token");
@@ -7035,6 +7075,21 @@ function DecaneKit({ config, children }) {
7035
7075
  throw e;
7036
7076
  }
7037
7077
  }, [clearPhase]);
7078
+ const linkWithToken = (0, import_react5.useCallback)(async (token, opts) => {
7079
+ const sdk = socialRef.current;
7080
+ if (!sdk) throw new Error("Social sign-in not configured");
7081
+ return sdk.linkWithToken(token, opts);
7082
+ }, []);
7083
+ const listLinkedLogins = (0, import_react5.useCallback)(async () => {
7084
+ const sdk = socialRef.current;
7085
+ if (!sdk) throw new Error("Social sign-in not configured");
7086
+ return sdk.listLinkedLogins();
7087
+ }, []);
7088
+ const unlinkLogin = (0, import_react5.useCallback)(async (id) => {
7089
+ const sdk = socialRef.current;
7090
+ if (!sdk) throw new Error("Social sign-in not configured");
7091
+ await sdk.unlinkLogin(id);
7092
+ }, []);
7038
7093
  const connectWithToken = (0, import_react5.useCallback)(async (token, opts) => {
7039
7094
  const sdk = socialRef.current;
7040
7095
  if (!sdk) throw new Error("Social sign-in not configured");
@@ -7252,6 +7307,9 @@ function DecaneKit({ config, children }) {
7252
7307
  verifyPhoneCode: verifyPhoneCode2,
7253
7308
  connectWithToken,
7254
7309
  connectWithAccessToken,
7310
+ linkWithToken,
7311
+ listLinkedLogins,
7312
+ unlinkLogin,
7255
7313
  customAuthLabel: customAuthConfig?.label,
7256
7314
  connectWithCustomAuth: customAuthConfig ? connectWithCustomAuth : void 0,
7257
7315
  socialUnlock,
@@ -7368,6 +7426,9 @@ function useSocialAuth() {
7368
7426
  verifyPhoneCode: verifyPhoneCode2,
7369
7427
  connectWithToken,
7370
7428
  connectWithAccessToken,
7429
+ linkWithToken,
7430
+ listLinkedLogins,
7431
+ unlinkLogin,
7371
7432
  customAuthLabel,
7372
7433
  connectWithCustomAuth,
7373
7434
  signInWithPasskey: ctxSignInWithPasskey,
@@ -7571,6 +7632,11 @@ function useSocialAuth() {
7571
7632
  confirmPhoneCode,
7572
7633
  signInWithToken,
7573
7634
  signInWithAccessToken,
7635
+ // Linked logins: while signed in, attach a login from your own auth (a
7636
+ // phone number your backend verified, say) so it opens this same wallet.
7637
+ linkWithToken,
7638
+ listLinkedLogins,
7639
+ unlinkLogin,
7574
7640
  signInWithCustomAuth: connectWithCustomAuth ? signInWithCustomAuth : void 0,
7575
7641
  signInWithPasskey,
7576
7642
  unlock,
@@ -8125,6 +8191,7 @@ function useSignTypedData() {
8125
8191
  InvalidApiKeyError,
8126
8192
  InvalidPinError,
8127
8193
  InvalidRecoveryFileError,
8194
+ LoginInUseError,
8128
8195
  MIN_PASSWORD_LENGTH,
8129
8196
  NetworkError,
8130
8197
  NewDeviceError,