oidc-spa 8.2.1 → 8.2.3

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 (94) hide show
  1. package/core/AuthResponse.d.ts +0 -5
  2. package/core/AuthResponse.js +0 -25
  3. package/core/AuthResponse.js.map +1 -1
  4. package/core/createOidc.d.ts +49 -16
  5. package/core/createOidc.js +97 -122
  6. package/core/createOidc.js.map +1 -1
  7. package/core/desiredPostLoginRedirectUrl.d.ts +4 -0
  8. package/core/desiredPostLoginRedirectUrl.js +12 -0
  9. package/core/desiredPostLoginRedirectUrl.js.map +1 -0
  10. package/core/diagnostic.d.ts +1 -1
  11. package/core/diagnostic.js +3 -3
  12. package/core/diagnostic.js.map +1 -1
  13. package/core/instancesThatCantUseIframes.d.ts +2 -0
  14. package/core/instancesThatCantUseIframes.js +20 -0
  15. package/core/instancesThatCantUseIframes.js.map +1 -0
  16. package/core/loginOrGoToAuthServer.d.ts +1 -0
  17. package/core/loginOrGoToAuthServer.js +3 -0
  18. package/core/loginOrGoToAuthServer.js.map +1 -1
  19. package/core/persistedAuthState.d.ts +1 -0
  20. package/core/persistedAuthState.js +14 -4
  21. package/core/persistedAuthState.js.map +1 -1
  22. package/esm/angular.d.ts +27 -4
  23. package/esm/angular.js +28 -6
  24. package/esm/angular.js.map +1 -1
  25. package/esm/core/AuthResponse.d.ts +0 -5
  26. package/esm/core/AuthResponse.js +0 -23
  27. package/esm/core/AuthResponse.js.map +1 -1
  28. package/esm/core/createOidc.d.ts +49 -16
  29. package/esm/core/createOidc.js +98 -123
  30. package/esm/core/createOidc.js.map +1 -1
  31. package/esm/core/desiredPostLoginRedirectUrl.d.ts +4 -0
  32. package/esm/core/desiredPostLoginRedirectUrl.js +8 -0
  33. package/esm/core/desiredPostLoginRedirectUrl.js.map +1 -0
  34. package/esm/core/diagnostic.d.ts +1 -1
  35. package/esm/core/diagnostic.js +3 -3
  36. package/esm/core/diagnostic.js.map +1 -1
  37. package/esm/core/instancesThatCantUseIframes.d.ts +2 -0
  38. package/esm/core/instancesThatCantUseIframes.js +16 -0
  39. package/esm/core/instancesThatCantUseIframes.js.map +1 -0
  40. package/esm/core/loginOrGoToAuthServer.d.ts +1 -0
  41. package/esm/core/loginOrGoToAuthServer.js +3 -0
  42. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  43. package/esm/core/persistedAuthState.d.ts +1 -0
  44. package/esm/core/persistedAuthState.js +14 -4
  45. package/esm/core/persistedAuthState.js.map +1 -1
  46. package/esm/keycloak/keycloak-js/Keycloak.d.ts +40 -0
  47. package/esm/keycloak/keycloak-js/Keycloak.js +2 -1
  48. package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
  49. package/esm/react/react.js +24 -2
  50. package/esm/react/react.js.map +1 -1
  51. package/esm/react-spa/createOidcSpaApi.js +26 -4
  52. package/esm/react-spa/createOidcSpaApi.js.map +1 -1
  53. package/esm/react-spa/types.d.ts +26 -3
  54. package/esm/tanstack-start/react/createOidcSpaApi.js +25 -3
  55. package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -1
  56. package/esm/tanstack-start/react/types.d.ts +26 -3
  57. package/esm/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +4 -4
  58. package/esm/tools/lazySessionStorage.js +83 -0
  59. package/esm/tools/lazySessionStorage.js.map +1 -0
  60. package/keycloak/keycloak-js/Keycloak.d.ts +40 -0
  61. package/keycloak/keycloak-js/Keycloak.js +2 -1
  62. package/keycloak/keycloak-js/Keycloak.js.map +1 -1
  63. package/package.json +5 -1
  64. package/react/react.js +24 -2
  65. package/react/react.js.map +1 -1
  66. package/react-spa/createOidcSpaApi.js +26 -4
  67. package/react-spa/createOidcSpaApi.js.map +1 -1
  68. package/react-spa/types.d.ts +26 -3
  69. package/src/angular.ts +72 -18
  70. package/src/core/AuthResponse.ts +0 -36
  71. package/src/core/createOidc.ts +160 -173
  72. package/src/core/desiredPostLoginRedirectUrl.ts +9 -0
  73. package/src/core/diagnostic.ts +4 -4
  74. package/src/core/instancesThatCantUseIframes.ts +24 -0
  75. package/src/core/loginOrGoToAuthServer.ts +5 -0
  76. package/src/core/persistedAuthState.ts +27 -5
  77. package/src/keycloak/keycloak-js/Keycloak.ts +43 -1
  78. package/src/react/react.tsx +32 -3
  79. package/src/react-spa/createOidcSpaApi.tsx +34 -5
  80. package/src/react-spa/types.tsx +26 -3
  81. package/src/tanstack-start/react/createOidcSpaApi.tsx +33 -4
  82. package/src/tanstack-start/react/types.tsx +26 -3
  83. package/src/tools/lazySessionStorage.ts +123 -0
  84. package/src/vite-plugin/manageOptimizedDeps.ts +4 -1
  85. package/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +4 -4
  86. package/tools/lazySessionStorage.js +86 -0
  87. package/tools/lazySessionStorage.js.map +1 -0
  88. package/vite-plugin/manageOptimizedDeps.js +3 -1
  89. package/vite-plugin/manageOptimizedDeps.js.map +1 -1
  90. package/esm/tools/EphemeralSessionStorage.js +0 -143
  91. package/esm/tools/EphemeralSessionStorage.js.map +0 -1
  92. package/src/tools/EphemeralSessionStorage.ts +0 -225
  93. package/tools/EphemeralSessionStorage.js +0 -146
  94. package/tools/EphemeralSessionStorage.js.map +0 -1
@@ -30,6 +30,7 @@ export function persistAuthState(params: {
30
30
  stateDescription: "logged in";
31
31
  idleSessionLifetimeInSeconds: number | undefined;
32
32
  refreshTokenExpirationTime: number | undefined;
33
+ serverDateNow: number;
33
34
  }
34
35
  | {
35
36
  stateDescription: "explicitly logged out";
@@ -56,14 +57,35 @@ export function persistAuthState(params: {
56
57
  __brand: "PersistedAuthState-v1",
57
58
  stateDescription: "logged in",
58
59
  untilTime: (() => {
59
- const { idleSessionLifetimeInSeconds, refreshTokenExpirationTime } =
60
- state;
60
+ const {
61
+ idleSessionLifetimeInSeconds,
62
+ refreshTokenExpirationTime,
63
+ serverDateNow
64
+ } = state;
65
+
66
+ const untilTime_real = (() => {
67
+ if (refreshTokenExpirationTime === undefined) {
68
+ return undefined;
69
+ }
70
+
71
+ const msBeforeExpirationOfTheSession =
72
+ refreshTokenExpirationTime - serverDateNow;
73
+
74
+ return Date.now() + msBeforeExpirationOfTheSession;
75
+ })();
76
+
77
+ const unitTime_userOverwrite = (() => {
78
+ if (idleSessionLifetimeInSeconds === undefined) {
79
+ return undefined;
80
+ }
61
81
 
62
- if (idleSessionLifetimeInSeconds !== undefined) {
63
82
  return Date.now() + idleSessionLifetimeInSeconds * 1000;
64
- }
83
+ })();
65
84
 
66
- return refreshTokenExpirationTime;
85
+ return Math.min(
86
+ untilTime_real ?? Number.POSITIVE_INFINITY,
87
+ unitTime_userOverwrite ?? Number.POSITIVE_INFINITY
88
+ );
67
89
  })()
68
90
  });
69
91
  case "explicitly logged out":
@@ -23,7 +23,48 @@ import { type StatefulEvt, createStatefulEvt } from "../../tools/StatefulEvt";
23
23
  import { readExpirationTimeInJwt } from "../../tools/readExpirationTimeInJwt";
24
24
 
25
25
  type ConstructorParams = KeycloakServerConfig & {
26
+ /**
27
+ * NOTE: This parameter is optional if you use the Vite plugin.
28
+ *
29
+ * This parameter let's you overwrite the value provided in
30
+ * oidcEarlyInit({ BASE_URL: xxx });
31
+ *
32
+ * What should you put in this parameter?
33
+ * - Vite project: `BASE_URL: import.meta.env.BASE_URL`
34
+ * - Create React App project: `BASE_URL: process.env.PUBLIC_URL`
35
+ * - Other: `BASE_URL: "/"` (Usually, or `/dashboard` if your app is not at the root of the domain)
36
+ */
26
37
  BASE_URL?: string;
38
+
39
+ /**
40
+ * Determines how session restoration is handled.
41
+ * Session restoration allows users to stay logged in between visits
42
+ * without needing to explicitly sign in each time.
43
+ *
44
+ * Options:
45
+ *
46
+ * - **"auto" (default)**:
47
+ * Automatically selects the best method.
48
+ * If the app’s domain shares a common parent domain with the authorization endpoint,
49
+ * an iframe is used for silent session restoration.
50
+ * Otherwise, a full-page redirect is used.
51
+ *
52
+ * - **"full page redirect"**:
53
+ * Forces full-page reloads for session restoration.
54
+ * Use this if your application is served with a restrictive CSP
55
+ * (e.g., `Content-Security-Policy: frame-ancestors "none"`)
56
+ * or `X-Frame-Options: DENY`, and you cannot modify those headers.
57
+ * This mode provides a slightly less seamless UX and will lead oidc-spa to
58
+ * store tokens in `localStorage` if multiple OIDC clients are used
59
+ * (e.g., your app communicates with several APIs).
60
+ *
61
+ * - **"iframe"**:
62
+ * Forces iframe-based session restoration.
63
+ * In development, if you go in your browser setting and allow your auth server’s domain
64
+ * to set third-party cookies this value will let you test your app
65
+ * with the local dev server as it will behave in production.
66
+ */
67
+ sessionRestorationMethod?: "iframe" | "full page redirect" | "auto";
27
68
  };
28
69
 
29
70
  /**
@@ -99,7 +140,8 @@ export class Keycloak {
99
140
  let hasCreateResolved = false;
100
141
 
101
142
  const oidcOrError = await createOidc({
102
- homeUrl: constructorParams.BASE_URL,
143
+ BASE_URL: constructorParams.BASE_URL,
144
+ sessionRestorationMethod: constructorParams.sessionRestorationMethod,
103
145
  issuerUri,
104
146
  clientId: this.#state.constructorParams.clientId,
105
147
  autoLogin,
@@ -15,6 +15,7 @@ import { id } from "../tools/tsafe/id";
15
15
  import type { ValueOrAsyncGetter } from "../tools/ValueOrAsyncGetter";
16
16
  import { Deferred } from "../tools/Deferred";
17
17
  import { toFullyQualifiedUrl } from "../tools/toFullyQualifiedUrl";
18
+ import { setDesiredPostLoginRedirectUrl } from "../core/desiredPostLoginRedirectUrl";
18
19
 
19
20
  export type OidcReact<DecodedIdToken extends Record<string, unknown>> =
20
21
  | OidcReact.NotLoggedIn
@@ -409,20 +410,48 @@ export function createReactOidc_dependencyInjection<
409
410
 
410
411
  const oidc = await getOidc();
411
412
 
413
+ const isUrlAlreadyReplaced =
414
+ window.location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
415
+
412
416
  if (!oidc.isUserLoggedIn) {
413
417
  if (cause === "preload") {
414
418
  throw new Error(
415
419
  "oidc-spa: User is not yet logged in. This is an expected error, nothing to be addressed."
416
420
  );
417
421
  }
418
- const doesCurrentHrefRequiresAuth =
419
- location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
420
422
 
421
423
  await oidc.login({
422
424
  redirectUrl,
423
- doesCurrentHrefRequiresAuth
425
+ doesCurrentHrefRequiresAuth: isUrlAlreadyReplaced
424
426
  });
425
427
  }
428
+
429
+ define_temporary_postLoginRedirectUrl: {
430
+ if (isUrlAlreadyReplaced) {
431
+ break define_temporary_postLoginRedirectUrl;
432
+ }
433
+
434
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: redirectUrl });
435
+
436
+ const history_pushState = history.pushState;
437
+ const history_replaceState = history.replaceState;
438
+
439
+ const onNavigated = () => {
440
+ history.pushState = history_pushState;
441
+ history.replaceState = history_replaceState;
442
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: undefined });
443
+ };
444
+
445
+ history.pushState = function pushState(...args) {
446
+ onNavigated();
447
+ return history_pushState.call(history, ...args);
448
+ };
449
+
450
+ history.replaceState = function replaceState(...args) {
451
+ onNavigated();
452
+ return history_replaceState.call(history, ...args);
453
+ };
454
+ }
426
455
  }
427
456
 
428
457
  async function getOidc(): Promise<Oidc<DecodedIdToken>> {
@@ -10,6 +10,7 @@ import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrow
10
10
  import { createStatefulEvt } from "../tools/StatefulEvt";
11
11
  import { id } from "../tools/tsafe/id";
12
12
  import { toFullyQualifiedUrl } from "../tools/toFullyQualifiedUrl";
13
+ import { setDesiredPostLoginRedirectUrl } from "../core/desiredPostLoginRedirectUrl";
13
14
 
14
15
  export function createOidcSpaApi<
15
16
  AutoLogin extends boolean,
@@ -390,7 +391,7 @@ export function createOidcSpaApi<
390
391
  transformUrlBeforeRedirect: paramsOfBootstrap.transformUrlBeforeRedirect,
391
392
  extraQueryParams: paramsOfBootstrap.extraQueryParams,
392
393
  extraTokenParams: paramsOfBootstrap.extraTokenParams,
393
- noIframe: paramsOfBootstrap.noIframe,
394
+ sessionRestorationMethod: paramsOfBootstrap.sessionRestorationMethod,
394
395
  debugLogs: paramsOfBootstrap.debugLogs,
395
396
  __unsafe_clientSecret: paramsOfBootstrap.__unsafe_clientSecret,
396
397
  __metadata: paramsOfBootstrap.__metadata,
@@ -440,25 +441,53 @@ export function createOidcSpaApi<
440
441
  });
441
442
  }
442
443
 
443
- return location.href;
444
+ return window.location.href;
444
445
  })();
445
446
 
446
447
  const oidc = await getOidc();
447
448
 
449
+ const isUrlAlreadyReplaced =
450
+ window.location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
451
+
448
452
  if (!oidc.isUserLoggedIn) {
449
453
  if (cause === "preload") {
450
454
  throw new Error(
451
455
  "oidc-spa: User is not yet logged in. This is an expected error, nothing to be addressed."
452
456
  );
453
457
  }
454
- const doesCurrentHrefRequiresAuth =
455
- location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
456
458
 
457
459
  await oidc.login({
458
460
  redirectUrl,
459
- doesCurrentHrefRequiresAuth
461
+ doesCurrentHrefRequiresAuth: isUrlAlreadyReplaced
460
462
  });
461
463
  }
464
+
465
+ define_temporary_postLoginRedirectUrl: {
466
+ if (isUrlAlreadyReplaced) {
467
+ break define_temporary_postLoginRedirectUrl;
468
+ }
469
+
470
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: redirectUrl });
471
+
472
+ const history_pushState = history.pushState;
473
+ const history_replaceState = history.replaceState;
474
+
475
+ const onNavigated = () => {
476
+ history.pushState = history_pushState;
477
+ history.replaceState = history_replaceState;
478
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: undefined });
479
+ };
480
+
481
+ history.pushState = function pushState(...args) {
482
+ onNavigated();
483
+ return history_pushState.call(history, ...args);
484
+ };
485
+
486
+ history.replaceState = function replaceState(...args) {
487
+ onNavigated();
488
+ return history_replaceState.call(history, ...args);
489
+ };
490
+ }
462
491
  }
463
492
 
464
493
  function OidcInitializationErrorGate(props: {
@@ -213,11 +213,34 @@ export namespace ParamsOfBootstrap {
213
213
  | (() => Record<string, string | undefined>);
214
214
 
215
215
  /**
216
- * Default: false
216
+ * Determines how session restoration is handled.
217
+ * Session restoration allows users to stay logged in between visits
218
+ * without needing to explicitly sign in each time.
217
219
  *
218
- * See: https://docs.oidc-spa.dev/v/v8/resources/iframe-related-issues
220
+ * Options:
221
+ *
222
+ * - **"auto" (default)**:
223
+ * Automatically selects the best method.
224
+ * If the app’s domain shares a common parent domain with the authorization endpoint,
225
+ * an iframe is used for silent session restoration.
226
+ * Otherwise, a full-page redirect is used.
227
+ *
228
+ * - **"full page redirect"**:
229
+ * Forces full-page reloads for session restoration.
230
+ * Use this if your application is served with a restrictive CSP
231
+ * (e.g., `Content-Security-Policy: frame-ancestors "none"`)
232
+ * or `X-Frame-Options: DENY`, and you cannot modify those headers.
233
+ * This mode provides a slightly less seamless UX and will lead oidc-spa to
234
+ * store tokens in `localStorage` if multiple OIDC clients are used
235
+ * (e.g., your app communicates with several APIs).
236
+ *
237
+ * - **"iframe"**:
238
+ * Forces iframe-based session restoration.
239
+ * In development, if you go in your browser setting and allow your auth server’s domain
240
+ * to set third-party cookies this value will let you test your app
241
+ * with the local dev server as it will behave in production.
219
242
  */
220
- noIframe?: boolean;
243
+ sessionRestorationMethod?: "iframe" | "full page redirect" | "auto";
221
244
 
222
245
  debugLogs?: boolean;
223
246
 
@@ -30,6 +30,7 @@ import { createServerFn, createMiddleware } from "@tanstack/react-start";
30
30
  import { getRequest, setResponseHeader, setResponseStatus } from "@tanstack/react-start/server";
31
31
  import { toFullyQualifiedUrl } from "../../tools/toFullyQualifiedUrl";
32
32
  import { UnifiedClientRetryForSsrLoadersError } from "./rfcUnifiedClientRetryForSsrLoaders/UnifiedClientRetryForSsrLoadersError";
33
+ import { setDesiredPostLoginRedirectUrl } from "../../core/desiredPostLoginRedirectUrl";
33
34
 
34
35
  export function createOidcSpaApi<
35
36
  AutoLogin extends boolean,
@@ -662,7 +663,7 @@ export function createOidcSpaApi<
662
663
  transformUrlBeforeRedirect: paramsOfBootstrap.transformUrlBeforeRedirect,
663
664
  extraQueryParams: paramsOfBootstrap.extraQueryParams,
664
665
  extraTokenParams: paramsOfBootstrap.extraTokenParams,
665
- noIframe: paramsOfBootstrap.noIframe,
666
+ sessionRestorationMethod: paramsOfBootstrap.sessionRestorationMethod,
666
667
  debugLogs: paramsOfBootstrap.debugLogs,
667
668
  __unsafe_clientSecret: paramsOfBootstrap.__unsafe_clientSecret,
668
669
  __metadata: paramsOfBootstrap.__metadata,
@@ -714,6 +715,9 @@ export function createOidcSpaApi<
714
715
 
715
716
  const oidc = await getOidc();
716
717
 
718
+ const isUrlAlreadyReplaced =
719
+ window.location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
720
+
717
721
  if (!oidc.isUserLoggedIn) {
718
722
  if (cause === "preload") {
719
723
  throw new Error(
@@ -724,14 +728,39 @@ export function createOidcSpaApi<
724
728
  ].join(" ")
725
729
  );
726
730
  }
727
- const doesCurrentHrefRequiresAuth =
728
- location.href.replace(/\/$/, "") === redirectUrl.replace(/\/$/, "");
729
731
 
730
732
  await oidc.login({
731
733
  redirectUrl,
732
- doesCurrentHrefRequiresAuth
734
+ doesCurrentHrefRequiresAuth: isUrlAlreadyReplaced
733
735
  });
734
736
  }
737
+
738
+ define_temporary_postLoginRedirectUrl: {
739
+ if (isUrlAlreadyReplaced) {
740
+ break define_temporary_postLoginRedirectUrl;
741
+ }
742
+
743
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: redirectUrl });
744
+
745
+ const history_pushState = history.pushState;
746
+ const history_replaceState = history.replaceState;
747
+
748
+ const onNavigated = () => {
749
+ history.pushState = history_pushState;
750
+ history.replaceState = history_replaceState;
751
+ setDesiredPostLoginRedirectUrl({ postLoginRedirectUrl: undefined });
752
+ };
753
+
754
+ history.pushState = function pushState(...args) {
755
+ onNavigated();
756
+ return history_pushState.call(history, ...args);
757
+ };
758
+
759
+ history.replaceState = function replaceState(...args) {
760
+ onNavigated();
761
+ return history_replaceState.call(history, ...args);
762
+ };
763
+ }
735
764
  }
736
765
 
737
766
  enforceLogin.__isOidcSpaEnforceLogin = true;
@@ -306,11 +306,34 @@ export namespace ParamsOfBootstrap {
306
306
  | (() => Record<string, string | undefined>);
307
307
 
308
308
  /**
309
- * Default: false
309
+ * Determines how session restoration is handled.
310
+ * Session restoration allows users to stay logged in between visits
311
+ * without needing to explicitly sign in each time.
310
312
  *
311
- * See: https://docs.oidc-spa.dev/v/v8/resources/iframe-related-issues
313
+ * Options:
314
+ *
315
+ * - **"auto" (default)**:
316
+ * Automatically selects the best method.
317
+ * If the app’s domain shares a common parent domain with the authorization endpoint,
318
+ * an iframe is used for silent session restoration.
319
+ * Otherwise, a full-page redirect is used.
320
+ *
321
+ * - **"full page redirect"**:
322
+ * Forces full-page reloads for session restoration.
323
+ * Use this if your application is served with a restrictive CSP
324
+ * (e.g., `Content-Security-Policy: frame-ancestors "none"`)
325
+ * or `X-Frame-Options: DENY`, and you cannot modify those headers.
326
+ * This mode provides a slightly less seamless UX and will lead oidc-spa to
327
+ * store tokens in `localStorage` if multiple OIDC clients are used
328
+ * (e.g., your app communicates with several APIs).
329
+ *
330
+ * - **"iframe"**:
331
+ * Forces iframe-based session restoration.
332
+ * In development, if you go in your browser setting and allow your auth server’s domain
333
+ * to set third-party cookies this value will let you test your app
334
+ * with the local dev server as it will behave in production.
312
335
  */
313
- noIframe?: boolean;
336
+ sessionRestorationMethod?: "iframe" | "full page redirect" | "auto";
314
337
 
315
338
  debugLogs?: boolean;
316
339
 
@@ -0,0 +1,123 @@
1
+ import { assert } from "../tools/tsafe/assert";
2
+
3
+ export type LazySessionStorage = {
4
+ // `Storage` methods, we don't use the type directly because it has [name: string]: any;
5
+ readonly length: number;
6
+ clear(): void;
7
+ getItem(key: string): string | null;
8
+ key(index: number): string | null;
9
+ removeItem(key: string): void;
10
+ setItem(key: string, value: string): void;
11
+
12
+ // Custom method
13
+ persistCurrentStateAndSubsequentChanges: () => void;
14
+ };
15
+
16
+ export function createLazySessionStorage(params: { storageId: string }): LazySessionStorage {
17
+ const { storageId } = params;
18
+
19
+ const sessionStoragePrefix = `lazy-session-storage:${storageId}:`;
20
+
21
+ const getSessionStorageKey = (key: string) => `${sessionStoragePrefix}${key}`;
22
+
23
+ const entries: { key: string; value: string }[] = [];
24
+
25
+ for (let i = 0; i < sessionStorage.length; i++) {
26
+ const key = sessionStorage.key(i);
27
+ assert(key !== null, "470498");
28
+
29
+ if (!key.startsWith(sessionStoragePrefix)) {
30
+ continue;
31
+ }
32
+
33
+ const value = sessionStorage.getItem(key);
34
+
35
+ assert(value !== null, "846771");
36
+
37
+ sessionStorage.removeItem(key);
38
+
39
+ entries.push({
40
+ key: key.slice(sessionStoragePrefix.length),
41
+ value
42
+ });
43
+ }
44
+
45
+ let isPersistenceEnabled = false;
46
+
47
+ const storage: LazySessionStorage = {
48
+ persistCurrentStateAndSubsequentChanges: () => {
49
+ isPersistenceEnabled = true;
50
+
51
+ for (let i = 0; i < storage.length; i++) {
52
+ const key = storage.key(i);
53
+ assert(key !== null, "803385");
54
+
55
+ const value = storage.getItem(key);
56
+
57
+ assert(value !== null, "777098");
58
+
59
+ storage.setItem(key, value);
60
+ }
61
+ },
62
+ get length() {
63
+ return entries.length;
64
+ },
65
+ key: index => {
66
+ const entry = entries[index];
67
+
68
+ if (entry === undefined) {
69
+ return null;
70
+ }
71
+
72
+ return entry.key;
73
+ },
74
+ removeItem: key => {
75
+ const entry = entries.find(entry => entry.key === key);
76
+
77
+ if (entry === undefined) {
78
+ return;
79
+ }
80
+
81
+ sessionStorage.removeItem(getSessionStorageKey(entry.key));
82
+
83
+ const index = entries.indexOf(entry);
84
+
85
+ entries.splice(index, 1);
86
+ },
87
+ clear: () => {
88
+ for (let i = 0; i < storage.length; i++) {
89
+ const key = storage.key(i);
90
+ assert(key !== null, "290875");
91
+ storage.removeItem(key);
92
+ }
93
+ },
94
+ getItem: key => {
95
+ const entry = entries.find(entry => entry.key === key);
96
+ if (entry === undefined) {
97
+ return null;
98
+ }
99
+ return entry.value;
100
+ },
101
+ setItem: (key, value) => {
102
+ if (isPersistenceEnabled) {
103
+ sessionStorage.setItem(getSessionStorageKey(key), value);
104
+ }
105
+
106
+ update: {
107
+ const entry = entries.find(entry => entry.key === key);
108
+
109
+ if (entry === undefined) {
110
+ break update;
111
+ }
112
+
113
+ entry.value = value;
114
+
115
+ return;
116
+ }
117
+
118
+ entries.push({ key, value });
119
+ }
120
+ };
121
+
122
+ return storage;
123
+ }
@@ -34,7 +34,8 @@ export function manageOptimizedDeps(params: {
34
34
  const moduleNames_include = [
35
35
  "oidc-spa/react-spa",
36
36
  "oidc-spa/entrypoint",
37
- "oidc-spa/keycloak"
37
+ "oidc-spa/keycloak",
38
+ "oidc-spa/core"
38
39
  ];
39
40
 
40
41
  for (const moduleName of moduleNames_include) {
@@ -55,6 +56,8 @@ export function manageOptimizedDeps(params: {
55
56
  moduleNames_include.push("zod");
56
57
  }
57
58
 
59
+ moduleNames_include.push("oidc-spa");
60
+
58
61
  ((userConfig.optimizeDeps ??= {}).include ??= []).push(...moduleNames_include);
59
62
  }
60
63
  break;
@@ -1,4 +1,4 @@
1
- export type EphemeralSessionStorage = {
1
+ export type LazySessionStorage = {
2
2
  readonly length: number;
3
3
  clear(): void;
4
4
  getItem(key: string): string | null;
@@ -7,6 +7,6 @@ export type EphemeralSessionStorage = {
7
7
  setItem(key: string, value: string): void;
8
8
  persistCurrentStateAndSubsequentChanges: () => void;
9
9
  };
10
- export declare function createEphemeralSessionStorage(params: {
11
- sessionStorageTtlMs: number;
12
- }): EphemeralSessionStorage;
10
+ export declare function createLazySessionStorage(params: {
11
+ storageId: string;
12
+ }): LazySessionStorage;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLazySessionStorage = createLazySessionStorage;
4
+ const assert_1 = require("../tools/tsafe/assert");
5
+ function createLazySessionStorage(params) {
6
+ const { storageId } = params;
7
+ const sessionStoragePrefix = `lazy-session-storage:${storageId}:`;
8
+ const getSessionStorageKey = (key) => `${sessionStoragePrefix}${key}`;
9
+ const entries = [];
10
+ for (let i = 0; i < sessionStorage.length; i++) {
11
+ const key = sessionStorage.key(i);
12
+ (0, assert_1.assert)(key !== null, "470498");
13
+ if (!key.startsWith(sessionStoragePrefix)) {
14
+ continue;
15
+ }
16
+ const value = sessionStorage.getItem(key);
17
+ (0, assert_1.assert)(value !== null, "846771");
18
+ sessionStorage.removeItem(key);
19
+ entries.push({
20
+ key: key.slice(sessionStoragePrefix.length),
21
+ value
22
+ });
23
+ }
24
+ let isPersistenceEnabled = false;
25
+ const storage = {
26
+ persistCurrentStateAndSubsequentChanges: () => {
27
+ isPersistenceEnabled = true;
28
+ for (let i = 0; i < storage.length; i++) {
29
+ const key = storage.key(i);
30
+ (0, assert_1.assert)(key !== null, "803385");
31
+ const value = storage.getItem(key);
32
+ (0, assert_1.assert)(value !== null, "777098");
33
+ storage.setItem(key, value);
34
+ }
35
+ },
36
+ get length() {
37
+ return entries.length;
38
+ },
39
+ key: index => {
40
+ const entry = entries[index];
41
+ if (entry === undefined) {
42
+ return null;
43
+ }
44
+ return entry.key;
45
+ },
46
+ removeItem: key => {
47
+ const entry = entries.find(entry => entry.key === key);
48
+ if (entry === undefined) {
49
+ return;
50
+ }
51
+ sessionStorage.removeItem(getSessionStorageKey(entry.key));
52
+ const index = entries.indexOf(entry);
53
+ entries.splice(index, 1);
54
+ },
55
+ clear: () => {
56
+ for (let i = 0; i < storage.length; i++) {
57
+ const key = storage.key(i);
58
+ (0, assert_1.assert)(key !== null, "290875");
59
+ storage.removeItem(key);
60
+ }
61
+ },
62
+ getItem: key => {
63
+ const entry = entries.find(entry => entry.key === key);
64
+ if (entry === undefined) {
65
+ return null;
66
+ }
67
+ return entry.value;
68
+ },
69
+ setItem: (key, value) => {
70
+ if (isPersistenceEnabled) {
71
+ sessionStorage.setItem(getSessionStorageKey(key), value);
72
+ }
73
+ update: {
74
+ const entry = entries.find(entry => entry.key === key);
75
+ if (entry === undefined) {
76
+ break update;
77
+ }
78
+ entry.value = value;
79
+ return;
80
+ }
81
+ entries.push({ key, value });
82
+ }
83
+ };
84
+ return storage;
85
+ }
86
+ //# sourceMappingURL=lazySessionStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazySessionStorage.js","sourceRoot":"","sources":["../src/tools/lazySessionStorage.ts"],"names":[],"mappings":"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"}
@@ -59,7 +59,8 @@ function manageOptimizedDeps(params) {
59
59
  const moduleNames_include = [
60
60
  "oidc-spa/react-spa",
61
61
  "oidc-spa/entrypoint",
62
- "oidc-spa/keycloak"
62
+ "oidc-spa/keycloak",
63
+ "oidc-spa/core"
63
64
  ];
64
65
  for (const moduleName of moduleNames_include) {
65
66
  (0, assert_1.assert)(moduleNames.includes(moduleName));
@@ -76,6 +77,7 @@ function manageOptimizedDeps(params) {
76
77
  if (isZodInstalled) {
77
78
  moduleNames_include.push("zod");
78
79
  }
80
+ moduleNames_include.push("oidc-spa");
79
81
  ((_b = (userConfig.optimizeDeps ?? (userConfig.optimizeDeps = {}))).include ?? (_b.include = [])).push(...moduleNames_include);
80
82
  }
81
83
  break;