@multiplatform.one/keycloak 7.34.4 → 7.35.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.
Files changed (40) hide show
  1. package/dist/cjs/index.cjs +120 -70
  2. package/dist/cjs/index.native.cjs +283 -148
  3. package/dist/esm/index.js +78 -28
  4. package/dist/esm/index.native.js +270 -135
  5. package/package.json +9 -9
  6. package/src/betterAuth/expoAuthFlow.deadline.spec.ts +230 -0
  7. package/src/betterAuth/expoAuthFlow.native.ts +67 -27
  8. package/src/keycloak/base.ts +3 -2
  9. package/src/keycloak/context.ts +2 -2
  10. package/src/keycloak/index.ts +26 -13
  11. package/src/keycloak/login.error.spec.tsx +85 -0
  12. package/src/provider/KeycloakProvider.loading.spec.tsx +37 -0
  13. package/src/provider/KeycloakProvider.tsx +16 -9
  14. package/src/provider/authProvider/index.native.tsx +170 -108
  15. package/src/provider/authProvider/nonblocking.native.spec.tsx +303 -0
  16. package/src/session/authError.ts +30 -0
  17. package/src/session/index.native.ts +6 -1
  18. package/src/session/index.ts +11 -4
  19. package/types/betterAuth/expoAuthFlow.native.d.ts +3 -1
  20. package/types/betterAuth/expoAuthFlow.native.d.ts.map +1 -1
  21. package/types/keycloak/base.d.ts +1 -1
  22. package/types/keycloak/base.d.ts.map +1 -1
  23. package/types/keycloak/context.d.ts +2 -2
  24. package/types/keycloak/context.d.ts.map +1 -1
  25. package/types/keycloak/index.d.ts +1 -1
  26. package/types/keycloak/index.d.ts.map +1 -1
  27. package/types/keycloak/index.native.d.ts +1 -1
  28. package/types/keycloak/index.native.d.ts.map +1 -1
  29. package/types/keycloak/index.webext.d.ts +1 -1
  30. package/types/keycloak/index.webext.d.ts.map +1 -1
  31. package/types/provider/KeycloakProvider.d.ts +3 -2
  32. package/types/provider/KeycloakProvider.d.ts.map +1 -1
  33. package/types/provider/authProvider/index.native.d.ts +1 -1
  34. package/types/provider/authProvider/index.native.d.ts.map +1 -1
  35. package/types/session/authError.d.ts +7 -0
  36. package/types/session/authError.d.ts.map +1 -0
  37. package/types/session/index.d.ts +2 -0
  38. package/types/session/index.d.ts.map +1 -1
  39. package/types/session/index.native.d.ts +1 -0
  40. package/types/session/index.native.d.ts.map +1 -1
@@ -482,8 +482,9 @@ var BaseKeycloak = class {
482
482
  this._clear();
483
483
  if (this._keycloakClient) {
484
484
  await this._keycloakClient.login(options);
485
- } else {
486
- await this._login?.(options);
485
+ } else if (this._login) {
486
+ await this._login(options);
487
+ return;
487
488
  }
488
489
  this._sync();
489
490
  }
@@ -673,6 +674,32 @@ async function requestAccessToken(providerId, send, userId) {
673
674
  return second;
674
675
  }
675
676
 
677
+ // src/session/authError.ts
678
+ import { useSyncExternalStore } from "react";
679
+ var error;
680
+ var listeners = /* @__PURE__ */ new Set();
681
+ var AuthTimeoutError = class extends Error {
682
+ constructor(timeoutMs = 1e4) {
683
+ super(`Authentication request timed out after ${timeoutMs}ms`);
684
+ this.name = "AuthTimeoutError";
685
+ }
686
+ };
687
+ function setAuthError(next) {
688
+ if (error === next) return;
689
+ error = next;
690
+ for (const listener of listeners) listener();
691
+ }
692
+ function getAuthError() {
693
+ return error;
694
+ }
695
+ function subscribe(listener) {
696
+ listeners.add(listener);
697
+ return () => listeners.delete(listener);
698
+ }
699
+ function useAuthError() {
700
+ return useSyncExternalStore(subscribe, getAuthError, getAuthError);
701
+ }
702
+
676
703
  // src/betterAuth/expoAuthFlow.native.ts
677
704
  try {
678
705
  WebBrowser.maybeCompleteAuthSession?.();
@@ -813,24 +840,50 @@ var activeFlow = null;
813
840
  function getActiveExpoAuthFlow() {
814
841
  return activeFlow;
815
842
  }
816
- function createExpoAuthFlow(baseURL, scheme) {
843
+ function createExpoAuthFlow(baseURL, scheme, options) {
817
844
  const base = baseURL.replace(/\/$/, "");
818
845
  const origin = () => Linking.createURL("/", scheme ? { scheme } : void 0);
819
846
  async function authFetch(path, init) {
820
- const cookie = cookieHeader();
821
- const res = await fetch(`${base}/api/auth${path}`, {
822
- ...init,
823
- credentials: "omit",
824
- headers: {
825
- "Content-Type": "application/json",
826
- ...cookie ? { cookie } : {},
827
- "expo-origin": origin(),
828
- "x-skip-oauth-proxy": "true",
829
- ...init?.headers
830
- }
847
+ const controller = new AbortController();
848
+ const timeoutMs = options?.timeoutMs ?? 1e4;
849
+ let timer;
850
+ const deadline = new Promise((_resolve, reject) => {
851
+ timer = setTimeout(() => {
852
+ reject(new AuthTimeoutError(timeoutMs));
853
+ controller.abort();
854
+ }, timeoutMs);
831
855
  });
832
- absorbSetCookie(res.headers.get("set-cookie"));
833
- return res;
856
+ try {
857
+ const buffered = await Promise.race([
858
+ (async () => {
859
+ const cookie = cookieHeader();
860
+ const response = await fetch(`${base}/api/auth${path}`, {
861
+ ...init,
862
+ signal: controller.signal,
863
+ credentials: "omit",
864
+ headers: {
865
+ "Content-Type": "application/json",
866
+ ...cookie ? { cookie } : {},
867
+ "expo-origin": origin(),
868
+ "x-skip-oauth-proxy": "true",
869
+ ...init?.headers
870
+ }
871
+ });
872
+ const text = await response.text();
873
+ return { response, text };
874
+ })(),
875
+ deadline
876
+ ]);
877
+ absorbSetCookie(buffered.response.headers.get("set-cookie"));
878
+ return {
879
+ status: buffered.response.status,
880
+ ok: buffered.response.ok,
881
+ text: buffered.text,
882
+ json: () => buffered.text.trim() ? JSON.parse(buffered.text) : null
883
+ };
884
+ } finally {
885
+ clearTimeout(timer);
886
+ }
834
887
  }
835
888
  const flow = {
836
889
  async signIn(provider, callbackURL) {
@@ -840,10 +893,10 @@ function createExpoAuthFlow(baseURL, scheme) {
840
893
  body: JSON.stringify({ provider, callbackURL: to })
841
894
  });
842
895
  if (!res.ok) {
843
- const body = await res.text().catch(() => "");
896
+ const body = res.text;
844
897
  throw new Error(`sign-in failed (${res.status}): ${body.slice(0, 200)}`);
845
898
  }
846
- const data = await res.json();
899
+ const data = res.json();
847
900
  if (!data?.url) throw new Error("sign-in response had no authorization url");
848
901
  const params = new URLSearchParams({ authorizationURL: data.url });
849
902
  const oauthState = getOAuthState();
@@ -862,28 +915,31 @@ function createExpoAuthFlow(baseURL, scheme) {
862
915
  postLogoutRedirectUri || Linking.createURL("/"),
863
916
  "signed-out"
864
917
  );
918
+ let missingSso = false;
865
919
  try {
866
920
  const res = await authFetch(
867
921
  `/sign-out/sso?mode=json&callbackURL=${encodeURIComponent(to)}`,
868
922
  { method: "GET" }
869
923
  );
924
+ missingSso = res.status === 404 || res.status === 405;
870
925
  if (!res.ok) throw new Error(`sign-out/sso failed (${res.status})`);
871
- const data = await res.json().catch(() => null);
926
+ const data = res.json();
872
927
  if (data?.redirect && data.url) {
873
- await openAuthBrowser(data.url, to.split("?")[0], { timeoutMs: 12e4 }).catch(
874
- () => void 0
875
- );
928
+ await openAuthBrowser(data.url, to.split("?")[0], { timeoutMs: 12e4 });
876
929
  }
877
- } catch {
878
- await authFetch("/sign-out", { method: "POST", body: "{}" }).catch(() => void 0);
930
+ } catch (error2) {
931
+ const fallback = await authFetch("/sign-out", { method: "POST", body: "{}" });
932
+ if (!fallback.ok) throw new Error(`sign-out failed (${fallback.status})`);
933
+ if (!missingSso) throw error2;
879
934
  } finally {
880
935
  writeJar({});
881
936
  }
882
937
  },
883
938
  async getSession() {
884
939
  const res = await authFetch("/get-session");
885
- if (!res.ok) return null;
886
- const data = await res.json().catch(() => null);
940
+ if (res.status === 401) return null;
941
+ if (!res.ok) throw new Error(`get-session failed (${res.status})`);
942
+ const data = res.json();
887
943
  return data && Object.keys(data).length ? data : null;
888
944
  },
889
945
  async getAccessToken(providerId) {
@@ -893,7 +949,15 @@ function createExpoAuthFlow(baseURL, scheme) {
893
949
  method: "POST",
894
950
  body: JSON.stringify(body)
895
951
  });
896
- payload = await response.json().catch(() => null);
952
+ if (response.status >= 500) {
953
+ throw new Error(`get-access-token failed (${response.status})`);
954
+ }
955
+ try {
956
+ payload = response.json();
957
+ } catch (error2) {
958
+ if (response.ok) throw error2;
959
+ payload = null;
960
+ }
897
961
  return { status: response.status, body: payload };
898
962
  });
899
963
  if (res.status < 200 || res.status >= 300) return null;
@@ -1014,139 +1078,200 @@ import { useEffect as useEffect3, useMemo, useState } from "react";
1014
1078
  import { AppState as AppState2 } from "react-native";
1015
1079
  import * as Linking2 from "expo-linking";
1016
1080
 
1017
- // src/Loading.tsx
1018
- import { ActivityIndicator, Text as Text2, View } from "react-native";
1019
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1020
- function Loading({ loadingComponent }) {
1021
- const { debug } = useAuthConfig();
1022
- const LoadingComponent = loadingComponent;
1023
- if (typeof LoadingComponent === "undefined") {
1024
- return /* @__PURE__ */ jsxs(View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: [
1025
- /* @__PURE__ */ jsx3(ActivityIndicator, {}),
1026
- debug ? /* @__PURE__ */ jsx3(Text2, { children: "loading" }) : null
1027
- ] });
1028
- }
1029
- return /* @__PURE__ */ jsx3(LoadingComponent, {});
1030
- }
1031
-
1032
1081
  // src/session/index.native.ts
1033
- import { useSyncExternalStore } from "react";
1082
+ import { useSyncExternalStore as useSyncExternalStore2 } from "react";
1034
1083
  var state = { session: null, status: "loading" };
1035
- var listeners = /* @__PURE__ */ new Set();
1084
+ var listeners2 = /* @__PURE__ */ new Set();
1036
1085
  function setNativeSession(session, status) {
1037
1086
  state = {
1038
1087
  session,
1039
1088
  status: status ?? (session?.user ? "authenticated" : "unauthenticated")
1040
1089
  };
1041
- for (const l of listeners) l();
1090
+ for (const l of listeners2) l();
1042
1091
  }
1043
- function subscribe(listener) {
1044
- listeners.add(listener);
1045
- return () => listeners.delete(listener);
1092
+ function subscribe2(listener) {
1093
+ listeners2.add(listener);
1094
+ return () => listeners2.delete(listener);
1046
1095
  }
1047
1096
  async function getSession() {
1048
1097
  return state.session;
1049
1098
  }
1050
1099
  function useSession(_options) {
1051
- return useSyncExternalStore(
1052
- subscribe,
1100
+ const session = useSyncExternalStore2(
1101
+ subscribe2,
1053
1102
  () => state,
1054
1103
  () => state
1055
1104
  );
1105
+ const error2 = useAuthError();
1106
+ return { ...session, error: error2 };
1056
1107
  }
1057
1108
 
1058
1109
  // src/provider/authProvider/index.native.tsx
1059
- import { Fragment as Fragment3, jsx as jsx4 } from "react/jsx-runtime";
1110
+ import { Fragment as Fragment3, jsx as jsx3, jsxs } from "react/jsx-runtime";
1111
+ function createController(config, disabled, notify) {
1112
+ const flow = disabled ? null : createExpoAuthFlow(
1113
+ rewriteLoopbackHostForNative(config.betterAuthBaseUrl || "http://localhost:8000"),
1114
+ config.expoScheme
1115
+ );
1116
+ let active = true;
1117
+ let sequence = 0;
1118
+ let interactive = false;
1119
+ let session = null;
1120
+ const current = (request) => active && request === sequence;
1121
+ const controller = {
1122
+ keycloak: makeKeycloak(null),
1123
+ loading: !disabled,
1124
+ start() {
1125
+ active = true;
1126
+ if (!flow) {
1127
+ publish(null);
1128
+ } else if (!interactive) {
1129
+ void refresh().catch(() => void 0);
1130
+ }
1131
+ },
1132
+ stop() {
1133
+ active = false;
1134
+ sequence++;
1135
+ interactive = false;
1136
+ },
1137
+ refresh
1138
+ };
1139
+ function makeKeycloak(next) {
1140
+ const keycloak = new Keycloak(config, void 0, void 0, void 0, login, logout);
1141
+ if (next?.user) {
1142
+ keycloak.authenticated = true;
1143
+ keycloak.subject = next.user.id;
1144
+ keycloak.email = next.user.email ?? void 0;
1145
+ keycloak.username = next.user.name ?? void 0;
1146
+ }
1147
+ return keycloak;
1148
+ }
1149
+ function publish(next, error2) {
1150
+ session = next;
1151
+ controller.keycloak = makeKeycloak(next);
1152
+ controller.loading = false;
1153
+ setAuthError(error2);
1154
+ setNativeSession(next);
1155
+ notify();
1156
+ }
1157
+ function begin() {
1158
+ const request = ++sequence;
1159
+ controller.loading = true;
1160
+ setAuthError();
1161
+ setNativeSession(session, "loading");
1162
+ notify();
1163
+ return request;
1164
+ }
1165
+ async function probe(request) {
1166
+ const next = await flow.getSession();
1167
+ if (!current(request)) return;
1168
+ publish(
1169
+ next?.user ? {
1170
+ user: {
1171
+ id: next.user.id,
1172
+ name: next.user.name ?? null,
1173
+ email: next.user.email ?? null
1174
+ }
1175
+ } : null
1176
+ );
1177
+ }
1178
+ function fail(request, cause) {
1179
+ const error2 = cause instanceof Error ? cause : new Error(String(cause));
1180
+ if (current(request)) publish(null, error2);
1181
+ throw error2;
1182
+ }
1183
+ async function refresh() {
1184
+ if (!active || !flow || interactive) return;
1185
+ const request = begin();
1186
+ try {
1187
+ await probe(request);
1188
+ } catch (error2) {
1189
+ fail(request, error2);
1190
+ }
1191
+ }
1192
+ async function login(options) {
1193
+ if (!active || !flow) return void 0;
1194
+ interactive = true;
1195
+ const request = begin();
1196
+ try {
1197
+ await flow.signIn("keycloak", options.redirectUri || Linking2.createURL("/"));
1198
+ if (!current(request)) return void 0;
1199
+ clearKeycloakBearerToken();
1200
+ await probe(request);
1201
+ } catch (error2) {
1202
+ fail(request, error2);
1203
+ } finally {
1204
+ if (current(request)) interactive = false;
1205
+ }
1206
+ return void 0;
1207
+ }
1208
+ async function logout(options) {
1209
+ if (!active || !flow) return void 0;
1210
+ interactive = true;
1211
+ const request = ++sequence;
1212
+ clearKeycloakBearerToken();
1213
+ publish(null);
1214
+ try {
1215
+ const redirectUri = options.redirectUri?.includes("://") ? options.redirectUri : Linking2.createURL("/");
1216
+ await flow.signOut(redirectUri);
1217
+ } catch (error2) {
1218
+ fail(request, error2);
1219
+ } finally {
1220
+ if (current(request)) {
1221
+ clearKeycloakBearerToken();
1222
+ interactive = false;
1223
+ }
1224
+ }
1225
+ return void 0;
1226
+ }
1227
+ return controller;
1228
+ }
1060
1229
  function AuthProvider({
1061
1230
  children,
1062
1231
  disabled,
1063
1232
  keycloakConfig,
1064
- loadingComponent
1233
+ loadingComponent: LoadingComponent
1065
1234
  }) {
1066
- const [keycloak, setKeycloak] = useState();
1067
- const [isLoading, setIsLoading] = useState(true);
1068
- const serverBaseUrl = useMemo(() => {
1069
- return rewriteLoopbackHostForNative(
1070
- keycloakConfig.betterAuthBaseUrl || "http://localhost:8000"
1071
- );
1072
- }, [keycloakConfig]);
1073
- const scheme = useMemo(() => keycloakConfig.expoScheme, [keycloakConfig]);
1074
- const flow = useMemo(
1075
- () => disabled ? null : createExpoAuthFlow(serverBaseUrl, scheme),
1076
- [disabled, serverBaseUrl, scheme]
1235
+ const [, setRevision] = useState(0);
1236
+ const { url, realm, clientId, publicClientId, betterAuthBaseUrl, expoScheme } = keycloakConfig;
1237
+ const scopes = JSON.stringify(keycloakConfig.scopes);
1238
+ const controller = useMemo(
1239
+ () => createController(
1240
+ {
1241
+ url,
1242
+ realm,
1243
+ clientId,
1244
+ publicClientId,
1245
+ betterAuthBaseUrl,
1246
+ expoScheme,
1247
+ scopes: scopes ? JSON.parse(scopes) : void 0
1248
+ },
1249
+ disabled,
1250
+ () => setRevision((revision) => revision + 1)
1251
+ ),
1252
+ [url, realm, clientId, publicClientId, betterAuthBaseUrl, expoScheme, scopes, disabled]
1077
1253
  );
1078
1254
  useEffect3(() => {
1079
- if (disabled || !flow) {
1080
- setIsLoading(false);
1081
- return;
1082
- }
1083
- let alive = true;
1084
- const refresh = async () => {
1085
- let session = null;
1086
- try {
1087
- session = await flow.getSession();
1088
- } catch (err) {
1089
- console.error("[keycloak] native session check failed:", err);
1090
- }
1091
- const _keycloak = new Keycloak(
1092
- keycloakConfig,
1093
- void 0,
1094
- void 0,
1095
- void 0,
1096
- async (options) => {
1097
- await flow.signIn("keycloak", options.redirectUri || Linking2.createURL("/"));
1098
- clearKeycloakBearerToken();
1099
- await refresh();
1100
- return void 0;
1101
- },
1102
- async (options) => {
1103
- const redirectUri = options.redirectUri && options.redirectUri.includes("://") ? options.redirectUri : Linking2.createURL("/");
1104
- await flow.signOut(redirectUri);
1105
- clearKeycloakBearerToken();
1106
- await refresh();
1107
- return void 0;
1108
- }
1109
- );
1110
- if (session?.user) {
1111
- _keycloak.authenticated = true;
1112
- _keycloak.email = session.user.email || void 0;
1113
- _keycloak.username = session.user.name || void 0;
1114
- _keycloak.subject = session.user.id;
1115
- }
1116
- if (!alive) return;
1117
- setNativeSession(
1118
- session?.user ? {
1119
- user: {
1120
- id: session.user.id,
1121
- name: session.user.name ?? null,
1122
- email: session.user.email ?? null
1123
- }
1124
- } : null
1125
- );
1126
- setKeycloak(_keycloak);
1127
- };
1128
- refresh().finally(() => {
1129
- if (alive) setIsLoading(false);
1255
+ if (disabled) return;
1256
+ controller.start();
1257
+ const appSub = AppState2.addEventListener("change", (next) => {
1258
+ if (next === "active") void controller.refresh().catch(() => void 0);
1130
1259
  });
1131
- const onAppState = (next) => {
1132
- if (next === "active") refresh().catch(() => void 0);
1133
- };
1134
- const appSub = AppState2.addEventListener("change", onAppState);
1135
1260
  return () => {
1136
- alive = false;
1261
+ controller.stop();
1137
1262
  appSub.remove();
1138
1263
  };
1139
- }, [disabled, flow, keycloakConfig]);
1140
- if (disabled) return /* @__PURE__ */ jsx4(Fragment3, { children });
1141
- if (isLoading || !keycloak) {
1142
- return /* @__PURE__ */ jsx4(Loading, { loadingComponent });
1143
- }
1144
- return /* @__PURE__ */ jsx4(KeycloakConfigContext.Provider, { value: keycloakConfig, children: /* @__PURE__ */ jsx4(KeycloakContext.Provider, { value: keycloak, children: /* @__PURE__ */ jsx4(AfterAuth, { children }) }) });
1264
+ }, [controller, disabled]);
1265
+ if (disabled) return /* @__PURE__ */ jsx3(Fragment3, { children });
1266
+ return /* @__PURE__ */ jsx3(KeycloakConfigContext.Provider, { value: controller.keycloak.config, children: /* @__PURE__ */ jsxs(KeycloakContext.Provider, { value: controller.keycloak, children: [
1267
+ /* @__PURE__ */ jsx3(AfterAuth, { children }),
1268
+ controller.loading && LoadingComponent ? /* @__PURE__ */ jsx3(LoadingComponent, {}) : null
1269
+ ] }) });
1145
1270
  }
1146
1271
 
1147
1272
  // src/provider/KeycloakProvider.tsx
1148
1273
  import { useMemo as useMemo2 } from "react";
1149
- import { jsx as jsx5 } from "react/jsx-runtime";
1274
+ import { jsx as jsx4 } from "react/jsx-runtime";
1150
1275
  function KeycloakProvider({
1151
1276
  baseUrl,
1152
1277
  betterAuthBaseUrl,
@@ -1154,6 +1279,7 @@ function KeycloakProvider({
1154
1279
  clientId,
1155
1280
  expoScheme,
1156
1281
  loginRedirectUri,
1282
+ loadingComponent,
1157
1283
  debug,
1158
1284
  disabled,
1159
1285
  iframeSso,
@@ -1164,18 +1290,23 @@ function KeycloakProvider({
1164
1290
  () => ({ debug, disabled, iframeSso, loginRedirectUri }),
1165
1291
  [debug, disabled, iframeSso, loginRedirectUri]
1166
1292
  );
1167
- return /* @__PURE__ */ jsx5(AuthConfigContext.Provider, { value: authConfig, children: /* @__PURE__ */ jsx5(
1293
+ const keycloakConfig = useMemo2(
1294
+ () => ({
1295
+ clientId: clientId || "app",
1296
+ publicClientId,
1297
+ realm: realm || "main",
1298
+ url: baseUrl ?? "",
1299
+ betterAuthBaseUrl,
1300
+ expoScheme
1301
+ }),
1302
+ [clientId, publicClientId, realm, baseUrl, betterAuthBaseUrl, expoScheme]
1303
+ );
1304
+ return /* @__PURE__ */ jsx4(AuthConfigContext.Provider, { value: authConfig, children: /* @__PURE__ */ jsx4(
1168
1305
  AuthProvider,
1169
1306
  {
1170
1307
  disabled,
1171
- keycloakConfig: {
1172
- clientId: clientId || "app",
1173
- publicClientId,
1174
- realm: realm || "main",
1175
- url: baseUrl ?? "",
1176
- betterAuthBaseUrl,
1177
- expoScheme
1178
- },
1308
+ keycloakConfig,
1309
+ loadingComponent,
1179
1310
  children
1180
1311
  }
1181
1312
  ) });
@@ -1184,6 +1315,7 @@ export {
1184
1315
  AfterAuth,
1185
1316
  AuthConfigContext,
1186
1317
  AuthProvider,
1318
+ AuthTimeoutError,
1187
1319
  Authenticated,
1188
1320
  BaseKeycloak,
1189
1321
  Keycloak,
@@ -1191,14 +1323,17 @@ export {
1191
1323
  KeycloakProvider,
1192
1324
  defaultAuthConfig,
1193
1325
  getAllWalletAddresses,
1326
+ getAuthError,
1194
1327
  getKeycloakBearerToken,
1195
1328
  getSession,
1196
1329
  getWalletAddresses,
1197
1330
  getWalletsFromToken,
1198
1331
  hasWallets,
1199
1332
  isTokenExpired,
1333
+ setAuthError,
1200
1334
  setNativeSession,
1201
1335
  useAuthConfig,
1336
+ useAuthError,
1202
1337
  useKeycloak,
1203
1338
  useSession,
1204
1339
  useTokensFromQuery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/keycloak",
3
- "version": "7.34.4",
3
+ "version": "7.35.0",
4
4
  "description": "keycloak client for multiplatform.one ecosystem",
5
5
  "keywords": [
6
6
  "auth",
@@ -57,16 +57,16 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@better-auth/expo": "~1.6.33",
60
- "@multiplatform.one/keycloak-js": "^7.34.4",
61
- "@multiplatform.one/store": "^7.34.4",
60
+ "@multiplatform.one/keycloak-js": "^7.35.0",
61
+ "@multiplatform.one/store": "^7.35.0",
62
62
  "better-auth": "~1.6.33",
63
63
  "jwt-decode": "^4.0.0"
64
64
  },
65
65
  "devDependencies": {
66
- "@multiplatform.one/config": "7.34.4",
67
- "@multiplatform.one/logger": "7.34.4",
68
- "@multiplatform.one/platform": "7.34.4",
69
- "@multiplatform.one/test-utils": "7.34.4",
66
+ "@multiplatform.one/config": "7.35.0",
67
+ "@multiplatform.one/logger": "7.35.0",
68
+ "@multiplatform.one/platform": "7.35.0",
69
+ "@multiplatform.one/test-utils": "7.35.0",
70
70
  "@tamagui/build": "2.7.6",
71
71
  "@testing-library/jest-dom": "^7.0.1",
72
72
  "@testing-library/react": "^16.3.3",
@@ -80,8 +80,8 @@
80
80
  "vitest": "^4.1.5"
81
81
  },
82
82
  "peerDependencies": {
83
- "@multiplatform.one/logger": "^7.34.4",
84
- "@multiplatform.one/platform": "^7.34.4",
83
+ "@multiplatform.one/logger": "^7.35.0",
84
+ "@multiplatform.one/platform": "^7.35.0",
85
85
  "react": "^19.1.0",
86
86
  "react-native": ">=0.83.0"
87
87
  },