@oxyhq/services 13.1.0 → 13.1.2

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 (35) hide show
  1. package/lib/commonjs/ui/components/SettingsIcon.js.map +1 -1
  2. package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
  3. package/lib/commonjs/ui/context/OxyContext.js +17 -45
  4. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  5. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  6. package/lib/commonjs/ui/utils/activeAuthuser.js +14 -35
  7. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
  8. package/lib/module/ui/components/SettingsIcon.js.map +1 -1
  9. package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
  10. package/lib/module/ui/context/OxyContext.js +17 -45
  11. package/lib/module/ui/context/OxyContext.js.map +1 -1
  12. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  13. package/lib/module/ui/utils/activeAuthuser.js +14 -35
  14. package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
  15. package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts +2 -1
  16. package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts.map +1 -1
  17. package/lib/typescript/commonjs/ui/components/payment/types.d.ts +3 -1
  18. package/lib/typescript/commonjs/ui/components/payment/types.d.ts.map +1 -1
  19. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  20. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
  21. package/lib/typescript/module/ui/components/SettingsIcon.d.ts +2 -1
  22. package/lib/typescript/module/ui/components/SettingsIcon.d.ts.map +1 -1
  23. package/lib/typescript/module/ui/components/payment/types.d.ts +3 -1
  24. package/lib/typescript/module/ui/components/payment/types.d.ts.map +1 -1
  25. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  26. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
  27. package/package.json +1 -1
  28. package/src/ui/components/ProfileMenu.tsx +1 -1
  29. package/src/ui/components/SettingsIcon.tsx +2 -2
  30. package/src/ui/components/fileManagement/FileViewer.tsx +1 -1
  31. package/src/ui/components/payment/types.ts +3 -1
  32. package/src/ui/context/OxyContext.tsx +17 -45
  33. package/src/ui/screens/FeedbackScreen.tsx +3 -3
  34. package/src/ui/utils/activeAuthuser.ts +14 -34
  35. package/src/ui/utils/__tests__/activeAuthuser.test.ts +0 -75
@@ -30,22 +30,8 @@ import {
30
30
 
31
31
  const ACTIVE_AUTHUSER_KEY = 'oxy_active_authuser';
32
32
 
33
- /**
34
- * Safely resolve `window.localStorage`, returning `null` when it is
35
- * unavailable. The PROPERTY ACCESS itself (`window.localStorage`) can throw a
36
- * `SecurityError` synchronously in opaque-origin / sandboxed iframes or when
37
- * storage is disabled — even `typeof window.localStorage` evaluates the getter
38
- * and throws. Every read/write in this module routes through here so the getter
39
- * throw is caught once, at the source, and callers stay clean. Returns `null`
40
- * off-web and on any access failure (fail safe).
41
- */
42
- function getLocalStorage(): Storage | null {
43
- if (typeof window === 'undefined') return null;
44
- try {
45
- return window.localStorage ?? null;
46
- } catch {
47
- return null;
48
- }
33
+ function hasLocalStorage(): boolean {
34
+ return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
49
35
  }
50
36
 
51
37
  function getSessionStorage(): Storage | null {
@@ -65,12 +51,11 @@ function getSessionStorage(): Storage | null {
65
51
  * fall back to deterministic selection (lowest authuser).
66
52
  */
67
53
  export function readActiveAuthuser(): number | null {
68
- const storage = getLocalStorage();
69
- if (!storage) {
54
+ if (!hasLocalStorage()) {
70
55
  return null;
71
56
  }
72
57
  try {
73
- const raw = storage.getItem(ACTIVE_AUTHUSER_KEY);
58
+ const raw = window.localStorage.getItem(ACTIVE_AUTHUSER_KEY);
74
59
  if (raw === null) return null;
75
60
  const parsed = Number.parseInt(raw, 10);
76
61
  if (!Number.isFinite(parsed) || parsed < 0) return null;
@@ -86,11 +71,10 @@ export function readActiveAuthuser(): number | null {
86
71
  * this succeeding — it is best-effort UX persistence, not authoritative.
87
72
  */
88
73
  export function writeActiveAuthuser(authuser: number): void {
74
+ if (!hasLocalStorage()) return;
89
75
  if (!Number.isFinite(authuser) || authuser < 0) return;
90
- const storage = getLocalStorage();
91
- if (!storage) return;
92
76
  try {
93
- storage.setItem(ACTIVE_AUTHUSER_KEY, String(authuser));
77
+ window.localStorage.setItem(ACTIVE_AUTHUSER_KEY, String(authuser));
94
78
  } catch {
95
79
  // Best-effort persistence; swallow QuotaExceededError / SecurityError.
96
80
  }
@@ -102,10 +86,9 @@ export function writeActiveAuthuser(authuser: number): void {
102
86
  * cleared slot.
103
87
  */
104
88
  export function clearActiveAuthuser(): void {
105
- const storage = getLocalStorage();
106
- if (!storage) return;
89
+ if (!hasLocalStorage()) return;
107
90
  try {
108
- storage.removeItem(ACTIVE_AUTHUSER_KEY);
91
+ window.localStorage.removeItem(ACTIVE_AUTHUSER_KEY);
109
92
  } catch {
110
93
  // Best-effort.
111
94
  }
@@ -120,10 +103,9 @@ export function clearActiveAuthuser(): void {
120
103
  * failure (best-effort).
121
104
  */
122
105
  export function markSignedOut(): void {
123
- const storage = getLocalStorage();
124
- if (!storage) return;
106
+ if (!hasLocalStorage()) return;
125
107
  try {
126
- storage.setItem(ssoSignedOutKey(window.location.origin), '1');
108
+ window.localStorage.setItem(ssoSignedOutKey(window.location.origin), '1');
127
109
  } catch {
128
110
  // Best-effort; swallow QuotaExceededError / SecurityError (private mode).
129
111
  }
@@ -136,10 +118,9 @@ export function markSignedOut(): void {
136
118
  * state. No-ops on native / storage failure.
137
119
  */
138
120
  export function clearSignedOut(): void {
139
- const storage = getLocalStorage();
140
- if (!storage) return;
121
+ if (!hasLocalStorage()) return;
141
122
  try {
142
- storage.removeItem(ssoSignedOutKey(window.location.origin));
123
+ window.localStorage.removeItem(ssoSignedOutKey(window.location.origin));
143
124
  } catch {
144
125
  // Best-effort.
145
126
  }
@@ -153,9 +134,8 @@ export function clearSignedOut(): void {
153
134
  * `fedcm-silent` and `silent-iframe` cold-boot steps.
154
135
  */
155
136
  export function isSilentRestoreSuppressed(): boolean {
156
- const storage = getLocalStorage();
157
- if (!storage) return false;
158
- return silentRestoreSuppressed(storage, window.location.origin);
137
+ if (!hasLocalStorage()) return false;
138
+ return silentRestoreSuppressed(window.localStorage, window.location.origin);
159
139
  }
160
140
 
161
141
  /**
@@ -1,75 +0,0 @@
1
- /**
2
- * Fail-safe guarantees for the web `activeAuthuser` storage helpers.
3
- *
4
- * The PROPERTY ACCESS `window.localStorage` can throw a `SecurityError`
5
- * synchronously in opaque-origin / sandboxed iframes or when storage is
6
- * disabled — not just `getItem`/`setItem`. These helpers run during cold boot
7
- * (and feed render-phase gate values in the providers), so they MUST never
8
- * propagate that throw: reads fail safe to a benign default and writes no-op.
9
- */
10
-
11
- import {
12
- readActiveAuthuser,
13
- writeActiveAuthuser,
14
- clearActiveAuthuser,
15
- markSignedOut,
16
- clearSignedOut,
17
- isSilentRestoreSuppressed,
18
- } from '../activeAuthuser';
19
-
20
- describe('activeAuthuser helpers — localStorage fail-safe', () => {
21
- const realDescriptor = Object.getOwnPropertyDescriptor(window, 'localStorage');
22
-
23
- afterEach(() => {
24
- if (realDescriptor) {
25
- Object.defineProperty(window, 'localStorage', realDescriptor);
26
- }
27
- window.localStorage?.clear?.();
28
- });
29
-
30
- /** Replace the `localStorage` accessor so reading the property throws. */
31
- function makeLocalStorageGetterThrow(): void {
32
- Object.defineProperty(window, 'localStorage', {
33
- configurable: true,
34
- get() {
35
- throw new DOMException('denied', 'SecurityError');
36
- },
37
- });
38
- }
39
-
40
- it('readActiveAuthuser returns null (never throws) when the getter throws', () => {
41
- makeLocalStorageGetterThrow();
42
- expect(() => readActiveAuthuser()).not.toThrow();
43
- expect(readActiveAuthuser()).toBeNull();
44
- });
45
-
46
- it('isSilentRestoreSuppressed returns false (never throws) when the getter throws', () => {
47
- makeLocalStorageGetterThrow();
48
- expect(() => isSilentRestoreSuppressed()).not.toThrow();
49
- expect(isSilentRestoreSuppressed()).toBe(false);
50
- });
51
-
52
- it('writeActiveAuthuser / clearActiveAuthuser / markSignedOut / clearSignedOut no-op when the getter throws', () => {
53
- makeLocalStorageGetterThrow();
54
- expect(() => {
55
- writeActiveAuthuser(2);
56
- clearActiveAuthuser();
57
- markSignedOut();
58
- clearSignedOut();
59
- }).not.toThrow();
60
- });
61
-
62
- it('round-trips normally when storage works (zero behavior change)', () => {
63
- writeActiveAuthuser(3);
64
- expect(readActiveAuthuser()).toBe(3);
65
-
66
- expect(isSilentRestoreSuppressed()).toBe(false);
67
- markSignedOut();
68
- expect(isSilentRestoreSuppressed()).toBe(true);
69
- clearSignedOut();
70
- expect(isSilentRestoreSuppressed()).toBe(false);
71
-
72
- clearActiveAuthuser();
73
- expect(readActiveAuthuser()).toBeNull();
74
- });
75
- });