@jmruthers/pace-core 0.5.43 → 0.5.45

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 (140) hide show
  1. package/dist/{DataTable-BGK2YF7A.js → DataTable-PWLLTSP7.js} +5 -5
  2. package/dist/{UnifiedAuthProvider-DGQsy-vY.d.ts → UnifiedAuthProvider-CQNiemcB.d.ts} +2 -2
  3. package/dist/{chunk-BLZBTCBT.js → chunk-2T6QEWMI.js} +2 -2
  4. package/dist/{chunk-DNAASEYY.js → chunk-3FAB54BI.js} +4 -4
  5. package/dist/{chunk-37LRETMD.js → chunk-3PNBACK3.js} +2 -2
  6. package/dist/{chunk-ZSLTSF55.js → chunk-6AQ7X3EE.js} +5 -5
  7. package/dist/{chunk-X4Y4KT5T.js → chunk-D4X7PPGX.js} +3 -3
  8. package/dist/{chunk-SAB5UT2E.js → chunk-FZ7EBWOT.js} +3 -3
  9. package/dist/{chunk-B3MGS7VR.js → chunk-GIISFLMP.js} +3 -3
  10. package/dist/{chunk-RL267HOF.js → chunk-NYF3CUNC.js} +2 -2
  11. package/dist/{chunk-P27KH7XF.js → chunk-OQ6DTLZ6.js} +156 -196
  12. package/dist/chunk-OQ6DTLZ6.js.map +1 -0
  13. package/dist/{chunk-APHGXR2D.js → chunk-VCHXOYD5.js} +3 -3
  14. package/dist/components.d.ts +1 -1
  15. package/dist/components.js +7 -7
  16. package/dist/hooks.js +4 -4
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +10 -10
  19. package/dist/providers.d.ts +1 -1
  20. package/dist/providers.js +3 -3
  21. package/dist/rbac/index.js +5 -5
  22. package/dist/utils.js +1 -1
  23. package/docs/api/classes/ErrorBoundary.md +1 -1
  24. package/docs/api/classes/InvalidScopeError.md +1 -1
  25. package/docs/api/classes/MissingUserContextError.md +1 -1
  26. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  27. package/docs/api/classes/PermissionDeniedError.md +1 -1
  28. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  29. package/docs/api/classes/RBACAuditManager.md +1 -1
  30. package/docs/api/classes/RBACCache.md +1 -1
  31. package/docs/api/classes/RBACEngine.md +1 -1
  32. package/docs/api/classes/RBACError.md +1 -1
  33. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  34. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  35. package/docs/api/interfaces/AggregateConfig.md +1 -1
  36. package/docs/api/interfaces/ButtonProps.md +1 -1
  37. package/docs/api/interfaces/CardProps.md +1 -1
  38. package/docs/api/interfaces/ColorPalette.md +1 -1
  39. package/docs/api/interfaces/ColorShade.md +1 -1
  40. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  41. package/docs/api/interfaces/DataTableAction.md +1 -1
  42. package/docs/api/interfaces/DataTableColumn.md +1 -1
  43. package/docs/api/interfaces/DataTableProps.md +1 -1
  44. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  45. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  46. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  47. package/docs/api/interfaces/EventContextType.md +1 -1
  48. package/docs/api/interfaces/EventLogoProps.md +1 -1
  49. package/docs/api/interfaces/EventProviderProps.md +1 -1
  50. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  51. package/docs/api/interfaces/FileUploadProps.md +1 -1
  52. package/docs/api/interfaces/FooterProps.md +1 -1
  53. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  54. package/docs/api/interfaces/InputProps.md +1 -1
  55. package/docs/api/interfaces/LabelProps.md +1 -1
  56. package/docs/api/interfaces/LoginFormProps.md +1 -1
  57. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  58. package/docs/api/interfaces/NavigationContextType.md +1 -1
  59. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  60. package/docs/api/interfaces/NavigationItem.md +1 -1
  61. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  62. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  63. package/docs/api/interfaces/Organisation.md +1 -1
  64. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  65. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  66. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  67. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  68. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  69. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  70. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  71. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  72. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  73. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  74. package/docs/api/interfaces/PaletteData.md +1 -1
  75. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  76. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  77. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  78. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  79. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  80. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  81. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  82. package/docs/api/interfaces/RBACConfig.md +1 -1
  83. package/docs/api/interfaces/RBACContextType.md +1 -1
  84. package/docs/api/interfaces/RBACLogger.md +1 -1
  85. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  86. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  87. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  88. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  89. package/docs/api/interfaces/RouteConfig.md +1 -1
  90. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  91. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  92. package/docs/api/interfaces/StorageConfig.md +1 -1
  93. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  94. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  95. package/docs/api/interfaces/StorageListOptions.md +1 -1
  96. package/docs/api/interfaces/StorageListResult.md +1 -1
  97. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  98. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  99. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  100. package/docs/api/interfaces/StyleImport.md +1 -1
  101. package/docs/api/interfaces/ToastActionElement.md +1 -1
  102. package/docs/api/interfaces/ToastProps.md +1 -1
  103. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  104. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  105. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  106. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  107. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  108. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  109. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  110. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  111. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  112. package/docs/api/interfaces/UserEventAccess.md +1 -1
  113. package/docs/api/interfaces/UserMenuProps.md +1 -1
  114. package/docs/api/interfaces/UserProfile.md +1 -1
  115. package/docs/api/modules.md +3 -3
  116. package/package.json +1 -1
  117. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +756 -0
  118. package/src/components/DataTable/__tests__/DataTable.test.tsx +880 -0
  119. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +702 -0
  120. package/src/components/PrintButton/__tests__/PrintButton.test.tsx +271 -0
  121. package/src/providers/AuthProvider.tsx +131 -230
  122. package/src/providers/OrganisationProvider.tsx +72 -10
  123. package/src/providers/__tests__/AuthProvider.test.tsx +619 -0
  124. package/src/providers/__tests__/EventProvider.test.tsx +190 -0
  125. package/src/providers/__tests__/InactivityProvider.test.tsx +645 -0
  126. package/src/providers/__tests__/OrganisationProvider.test.tsx +343 -0
  127. package/src/providers/__tests__/README.md +167 -0
  128. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +581 -0
  129. package/src/rbac/__tests__/rbac-core.test.tsx +277 -0
  130. package/dist/chunk-P27KH7XF.js.map +0 -1
  131. /package/dist/{DataTable-BGK2YF7A.js.map → DataTable-PWLLTSP7.js.map} +0 -0
  132. /package/dist/{chunk-BLZBTCBT.js.map → chunk-2T6QEWMI.js.map} +0 -0
  133. /package/dist/{chunk-DNAASEYY.js.map → chunk-3FAB54BI.js.map} +0 -0
  134. /package/dist/{chunk-37LRETMD.js.map → chunk-3PNBACK3.js.map} +0 -0
  135. /package/dist/{chunk-ZSLTSF55.js.map → chunk-6AQ7X3EE.js.map} +0 -0
  136. /package/dist/{chunk-X4Y4KT5T.js.map → chunk-D4X7PPGX.js.map} +0 -0
  137. /package/dist/{chunk-SAB5UT2E.js.map → chunk-FZ7EBWOT.js.map} +0 -0
  138. /package/dist/{chunk-B3MGS7VR.js.map → chunk-GIISFLMP.js.map} +0 -0
  139. /package/dist/{chunk-RL267HOF.js.map → chunk-NYF3CUNC.js.map} +0 -0
  140. /package/dist/{chunk-APHGXR2D.js.map → chunk-VCHXOYD5.js.map} +0 -0
@@ -49,262 +49,174 @@ function AuthProvider({ children, supabaseClient }) {
49
49
  };
50
50
  }, []);
51
51
  useEffect(() => {
52
- if (!supabaseClient) return;
53
- const loadInitialUser = async (retryCount = 0) => {
52
+ if (!supabaseClient) {
53
+ setAuthLoading(false);
54
+ return;
55
+ }
56
+ let isMounted = true;
57
+ const initializeAuth = async () => {
54
58
  try {
55
- DebugLogger.log("AuthProvider", `Loading initial user (attempt ${retryCount + 1})...`);
56
- const response = await supabaseClient.auth.getUser();
57
- const { data: { user: initialUser }, error } = response || { data: { user: null }, error: null };
58
- if (error) {
59
- console.warn("Failed to get initial user:", error);
60
- if (retryCount === 0 && (error.message?.includes("network") || error.message?.includes("timeout"))) {
61
- console.log("AuthProvider: Retrying initial user load due to network error...");
62
- setTimeout(() => loadInitialUser(1), 1e3);
63
- return;
59
+ DebugLogger.log("AuthProvider", "Initializing authentication...");
60
+ const { data: { session: currentSession }, error: sessionError } = await supabaseClient.auth.getSession();
61
+ if (sessionError) {
62
+ console.warn("[AuthProvider] Error getting current session:", sessionError);
63
+ }
64
+ if (currentSession && isMounted) {
65
+ DebugLogger.log("AuthProvider", "Session restored from storage:", currentSession.user?.email);
66
+ setSession(currentSession);
67
+ setUser(currentSession.user);
68
+ setAuthError(null);
69
+ } else if (isMounted) {
70
+ DebugLogger.log("AuthProvider", "No session found in storage");
71
+ const { data: { user: currentUser }, error: userError } = await supabaseClient.auth.getUser();
72
+ if (userError) {
73
+ DebugLogger.log("AuthProvider", "No user found:", userError.message);
74
+ } else if (currentUser && isMounted) {
75
+ DebugLogger.log("AuthProvider", "User found without session:", currentUser.email);
76
+ setUser(currentUser);
64
77
  }
65
- setAuthLoading(false);
66
- return;
67
78
  }
68
- if (initialUser) {
69
- DebugLogger.log("AuthProvider", "Initial user loaded successfully:", initialUser.email);
70
- setUser(initialUser);
71
- } else {
72
- DebugLogger.log("AuthProvider", "No initial user found");
79
+ if (isMounted) {
80
+ setAuthLoading(false);
73
81
  }
74
- setAuthLoading(false);
75
82
  } catch (error) {
76
- console.error("Error loading initial user:", error);
77
- if (retryCount === 0 && (error instanceof Error && (error.message.includes("network") || error.message.includes("timeout")))) {
78
- console.log("AuthProvider: Retrying initial user load due to network error...");
79
- setTimeout(() => loadInitialUser(1), 1e3);
80
- return;
83
+ console.error("[AuthProvider] Error during auth initialization:", error);
84
+ if (isMounted) {
85
+ setAuthLoading(false);
81
86
  }
82
- setAuthLoading(false);
83
87
  }
84
88
  };
85
- const timeoutId = setTimeout(() => {
86
- if (authLoading && !user && !session) {
87
- loadInitialUser();
88
- }
89
- }, 100);
90
- return () => clearTimeout(timeoutId);
91
- }, [supabaseClient, authLoading, user, session]);
92
- useEffect(() => {
93
- if (!supabaseClient) {
94
- setAuthLoading(false);
95
- return;
96
- }
97
- const timeoutId = setTimeout(() => {
98
- if (authLoading) {
99
- console.warn("AuthProvider: Auth loading timeout reached - this may indicate a network issue or slow auth response");
100
- setAuthLoading(false);
101
- setAuthError(new AuthError("Authentication timeout - please try refreshing the page"));
102
- }
103
- }, 1e4);
104
- try {
105
- DebugLogger.log("AuthProvider", "Setting up auth state change listener...");
106
- const authStateChange = supabaseClient.auth.onAuthStateChange(
107
- (event, session2) => {
108
- try {
109
- DebugLogger.log("AuthProvider", "Auth state changed:", event, session2?.user?.email);
110
- clearTimeout(timeoutId);
111
- if (event === "SIGNED_OUT") {
112
- DebugLogger.log("AuthProvider", "User signed out, clearing all state");
113
- setSession(null);
114
- setUser(null);
115
- setAuthLoading(false);
89
+ const { data: { subscription } } = supabaseClient.auth.onAuthStateChange(
90
+ (event, session2) => {
91
+ if (!isMounted) return;
92
+ try {
93
+ DebugLogger.log("AuthProvider", "Auth state changed:", event, session2?.user?.email);
94
+ if (event === "SIGNED_OUT") {
95
+ DebugLogger.log("AuthProvider", "User signed out, clearing all state");
96
+ setSession(null);
97
+ setUser(null);
98
+ setAuthError(null);
99
+ } else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
100
+ DebugLogger.log("AuthProvider", "User signed in or token refreshed");
101
+ setSession(session2);
102
+ setUser(session2?.user ?? null);
103
+ if (session2) {
116
104
  setAuthError(null);
117
- } else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
118
- DebugLogger.log("AuthProvider", "User signed in or token refreshed");
105
+ }
106
+ } else if (event === "INITIAL_SESSION") {
107
+ DebugLogger.log("AuthProvider", "Initial session event");
108
+ if (session2) {
119
109
  setSession(session2);
120
- setUser(session2?.user ?? null);
121
- setAuthLoading(false);
122
- if (session2) {
123
- setAuthError(null);
124
- }
125
- } else {
126
- if (session2) {
127
- setSession(session2);
128
- setUser(session2.user ?? null);
129
- setAuthLoading(false);
130
- if (session2) {
131
- setAuthError(null);
132
- }
133
- }
110
+ setUser(session2.user ?? null);
111
+ setAuthError(null);
134
112
  }
135
- } catch (error) {
136
- console.warn("[AuthProvider] Error in auth state change handler:", error);
113
+ }
114
+ setAuthLoading(false);
115
+ } catch (error) {
116
+ console.warn("[AuthProvider] Error in auth state change handler:", error);
117
+ if (isMounted) {
137
118
  setAuthLoading(false);
138
119
  }
139
120
  }
140
- );
141
- const subscription = authStateChange?.data?.subscription || authStateChange;
142
- return () => {
143
- clearTimeout(timeoutId);
144
- if (subscription && typeof subscription.unsubscribe === "function") {
145
- DebugLogger.log("AuthProvider", "Cleaning up auth state listener");
146
- subscription.unsubscribe();
147
- }
148
- };
149
- } catch (error) {
150
- console.error("AuthProvider: Error setting up auth state change listener:", error);
151
- if (error instanceof Error && !error.message.includes("No API key found") && !error.message.includes("AuthSessionMissingError") && !error.message.includes("Auth session missing")) {
152
- setAuthError(error);
153
121
  }
154
- setAuthLoading(false);
155
- clearTimeout(timeoutId);
156
- return () => {
157
- };
158
- }
122
+ );
123
+ initializeAuth();
124
+ return () => {
125
+ isMounted = false;
126
+ subscription?.unsubscribe();
127
+ };
159
128
  }, [supabaseClient]);
160
129
  const signIn = useCallback(async (email, password) => {
161
130
  if (!supabaseClient) {
162
- const error = new Error("No Supabase client provided");
163
- setAuthError(error);
164
- return { error };
131
+ return { error: new AuthError("Supabase client not available") };
165
132
  }
166
- setAuthLoading(true);
167
- setAuthError(null);
168
133
  try {
169
- const { error } = await supabaseClient.auth.signInWithPassword({ email, password: password || "" });
170
- if (error) {
171
- setAuthError(error);
172
- }
134
+ const { error } = await supabaseClient.auth.signInWithPassword({
135
+ email,
136
+ password: password || ""
137
+ });
138
+ return { error };
139
+ } catch (error) {
173
140
  return { error };
174
- } catch (err) {
175
- const authError2 = err;
176
- setAuthError(authError2);
177
- return { error: authError2 };
178
- } finally {
179
- setAuthLoading(false);
180
141
  }
181
142
  }, [supabaseClient]);
182
143
  const signUp = useCallback(async (email, password) => {
183
144
  if (!supabaseClient) {
184
- const error = new Error("No Supabase client provided");
185
- setAuthError(error);
186
- return { error };
145
+ return { error: new AuthError("Supabase client not available") };
187
146
  }
188
- setAuthError(null);
189
147
  try {
190
- const { error } = await supabaseClient.auth.signUp({ email, password });
191
- if (error) {
192
- setAuthError(error);
193
- }
148
+ const { error } = await supabaseClient.auth.signUp({
149
+ email,
150
+ password
151
+ });
152
+ return { error };
153
+ } catch (error) {
194
154
  return { error };
195
- } catch (err) {
196
- const authError2 = err;
197
- setAuthError(authError2);
198
- return { error: authError2 };
199
155
  }
200
156
  }, [supabaseClient]);
201
157
  const signOut = useCallback(async () => {
202
- DebugLogger.log("AuthProvider", "signOut called");
203
- setAuthLoading(false);
204
158
  if (!supabaseClient) {
205
- DebugLogger.log("AuthProvider", "No supabase client, clearing state manually");
206
- setUser(null);
207
- setSession(null);
208
- setAuthError(null);
209
- return { error: null };
159
+ return { error: new AuthError("Supabase client not available") };
210
160
  }
211
- DebugLogger.log("AuthProvider", "Pre-clearing state before signOut call");
212
- setUser(null);
213
- setSession(null);
214
- setAuthError(null);
215
161
  try {
216
- DebugLogger.log("AuthProvider", "Calling supabase signOut");
217
- const signOutPromise = supabaseClient.auth.signOut();
218
- const timeoutPromise = new Promise(
219
- (_, reject) => setTimeout(() => reject(new Error("SignOut timeout")), 3e3)
220
- );
221
- const { error } = await Promise.race([signOutPromise, timeoutPromise]);
222
- if (error && !error.message?.includes("SignOut timeout")) {
223
- console.error("[AuthProvider] signOut error:", error);
224
- }
225
- DebugLogger.log("AuthProvider", "signOut process completed");
226
- return { error: null };
227
- } catch (err) {
228
- console.warn("[AuthProvider] signOut exception (ignored):", err);
229
- return { error: null };
162
+ const { error } = await supabaseClient.auth.signOut();
163
+ return { error };
164
+ } catch (error) {
165
+ return { error };
230
166
  }
231
167
  }, [supabaseClient]);
232
168
  const resetPassword = useCallback(async (email) => {
233
169
  if (!supabaseClient) {
234
- const error = new Error("No Supabase client provided");
235
- setAuthError(error);
236
- return { error };
170
+ return { error: new AuthError("Supabase client not available") };
237
171
  }
238
- setAuthError(null);
239
172
  try {
240
173
  const { error } = await supabaseClient.auth.resetPasswordForEmail(email);
241
- if (error) {
242
- setAuthError(error);
243
- }
244
174
  return { error };
245
- } catch (err) {
246
- const authError2 = err;
247
- setAuthError(authError2);
248
- return { error: authError2 };
175
+ } catch (error) {
176
+ return { error };
249
177
  }
250
178
  }, [supabaseClient]);
251
179
  const updatePassword = useCallback(async (password) => {
252
- if (!supabaseClient) return { error: new AuthError("Supabase client not available.", 500) };
253
- const { error } = await supabaseClient.auth.updateUser({ password });
254
- if (error) {
255
- setAuthError(error);
180
+ if (!supabaseClient) {
181
+ return { error: new AuthError("Supabase client not available") };
182
+ }
183
+ try {
184
+ const { error } = await supabaseClient.auth.updateUser({
185
+ password
186
+ });
187
+ return { error };
188
+ } catch (error) {
189
+ return { error };
256
190
  }
257
- return { error };
258
191
  }, [supabaseClient]);
259
192
  const refreshSession = useCallback(async () => {
260
193
  if (!supabaseClient) {
261
- const error = new Error("No Supabase client provided");
262
- setAuthError(error);
263
- return { error };
194
+ return { error: new AuthError("Supabase client not available") };
264
195
  }
265
- setAuthError(null);
266
196
  try {
267
197
  const { error } = await supabaseClient.auth.refreshSession();
268
- if (error) {
269
- setAuthError(error);
270
- }
271
198
  return { error };
272
- } catch (err) {
273
- const authError2 = err;
274
- setAuthError(authError2);
275
- return { error: authError2 };
199
+ } catch (error) {
200
+ return { error };
276
201
  }
277
202
  }, [supabaseClient]);
278
- const isAuthenticated = !!user;
279
203
  const contextValue = useMemo(() => ({
280
204
  user,
281
205
  session,
282
- isAuthenticated,
206
+ isAuthenticated: !!user && !!session,
283
207
  authLoading,
284
208
  authError,
285
209
  error: authError,
286
210
  // Alias for backward compatibility
287
211
  supabase: supabaseClient || null,
212
+ // Ensure null instead of undefined
288
213
  signIn,
289
214
  signUp,
290
215
  signOut,
291
216
  resetPassword,
292
217
  updatePassword,
293
218
  refreshSession
294
- }), [
295
- user,
296
- session,
297
- isAuthenticated,
298
- authLoading,
299
- authError,
300
- supabaseClient,
301
- signIn,
302
- signUp,
303
- signOut,
304
- resetPassword,
305
- updatePassword,
306
- refreshSession
307
- ]);
219
+ }), [user, session, authLoading, authError, supabaseClient, signIn, signUp, signOut, resetPassword, updatePassword, refreshSession]);
308
220
  return /* @__PURE__ */ jsx(AuthContext.Provider, { value: contextValue, children });
309
221
  }
310
222
  var AuthContext, useAuth;
@@ -7430,6 +7342,10 @@ function OrganisationProvider({ children }) {
7430
7342
  setError(null);
7431
7343
  return;
7432
7344
  }
7345
+ if (isLoading) {
7346
+ DebugLogger.log("OrganisationProvider", "Already loading, skipping duplicate load");
7347
+ return;
7348
+ }
7433
7349
  setIsLoading(true);
7434
7350
  setError(null);
7435
7351
  try {
@@ -7463,10 +7379,32 @@ function OrganisationProvider({ children }) {
7463
7379
  if (!memberships || memberships.length === 0) {
7464
7380
  throw new Error("User has no active organisation memberships");
7465
7381
  }
7466
- const organisationIds = memberships.map((m) => m.organisation_id).filter((id) => id && id.trim() !== "" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id));
7382
+ memberships.forEach((membership, index) => {
7383
+ if (!membership.organisation_id || membership.organisation_id.trim() === "") {
7384
+ console.warn(`[OrganisationProvider] Membership ${index} has invalid organisation_id:`, membership);
7385
+ }
7386
+ });
7387
+ const organisationIds = memberships.map((m) => m.organisation_id).filter((id) => {
7388
+ if (!id || typeof id !== "string") {
7389
+ console.warn("[OrganisationProvider] Invalid organisation ID (not string):", id);
7390
+ return false;
7391
+ }
7392
+ const trimmedId = id.trim();
7393
+ if (trimmedId === "") {
7394
+ console.warn("[OrganisationProvider] Empty organisation ID found");
7395
+ return false;
7396
+ }
7397
+ const isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(trimmedId);
7398
+ if (!isValidUuid) {
7399
+ console.warn("[OrganisationProvider] Invalid UUID format:", trimmedId);
7400
+ }
7401
+ return isValidUuid;
7402
+ });
7467
7403
  if (organisationIds.length === 0) {
7404
+ console.warn("[OrganisationProvider] No valid organisation IDs found in memberships:", memberships);
7468
7405
  throw new Error("No valid organisation IDs found in memberships");
7469
7406
  }
7407
+ DebugLogger.log("OrganisationProvider", "Valid organisation IDs:", organisationIds);
7470
7408
  const { data: organisations2, error: orgError } = await supabase.from("organisations").select("id, name, display_name, subscription_tier, settings, is_active, parent_id, created_at, updated_at").in("id", organisationIds);
7471
7409
  if (orgError) {
7472
7410
  console.error("[OrganisationProvider] Error loading organisations:", orgError);
@@ -7490,14 +7428,23 @@ function OrganisationProvider({ children }) {
7490
7428
  const persistedOrgString = localStorage.getItem(STORAGE_KEYS2.SELECTED_ORGANISATION);
7491
7429
  if (persistedOrgString) {
7492
7430
  const persistedOrg = JSON.parse(persistedOrgString);
7493
- const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
7494
- if (validPersistedOrg) {
7495
- initialOrg = validPersistedOrg;
7496
- DebugLogger.log("OrganisationProvider", "Restored persisted organisation:", initialOrg.display_name);
7431
+ if (persistedOrg.id && typeof persistedOrg.id === "string" && persistedOrg.id.trim() !== "") {
7432
+ const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
7433
+ if (validPersistedOrg) {
7434
+ initialOrg = validPersistedOrg;
7435
+ DebugLogger.log("OrganisationProvider", "Restored persisted organisation:", initialOrg.display_name);
7436
+ } else {
7437
+ console.warn("[OrganisationProvider] Persisted organisation not found in active orgs, clearing cache");
7438
+ localStorage.removeItem(STORAGE_KEYS2.SELECTED_ORGANISATION);
7439
+ }
7440
+ } else {
7441
+ console.warn("[OrganisationProvider] Invalid persisted organisation ID, clearing cache");
7442
+ localStorage.removeItem(STORAGE_KEYS2.SELECTED_ORGANISATION);
7497
7443
  }
7498
7444
  }
7499
7445
  } catch (storageError) {
7500
7446
  console.warn("[OrganisationProvider] Failed to restore persisted organisation:", storageError);
7447
+ localStorage.removeItem(STORAGE_KEYS2.SELECTED_ORGANISATION);
7501
7448
  }
7502
7449
  if (!initialOrg) {
7503
7450
  const adminMembership = memberships.find((m) => m.role === "org_admin");
@@ -7535,8 +7482,21 @@ function OrganisationProvider({ children }) {
7535
7482
  }
7536
7483
  }, [user, session, supabase]);
7537
7484
  useEffect7(() => {
7538
- loadUserOrganisations();
7539
- }, [loadUserOrganisations]);
7485
+ if (user && session && supabase && !isLoading) {
7486
+ DebugLogger.log("OrganisationProvider", "Authentication stable, loading organizations...");
7487
+ loadUserOrganisations();
7488
+ } else if (!user && !session) {
7489
+ DebugLogger.log("OrganisationProvider", "No authentication, clearing organization state");
7490
+ setSelectedOrganisation(null);
7491
+ setOrganisations([]);
7492
+ setUserMemberships([]);
7493
+ setRoleMapState(/* @__PURE__ */ new Map());
7494
+ setIsLoading(false);
7495
+ setError(null);
7496
+ localStorage.removeItem(STORAGE_KEYS2.SELECTED_ORGANISATION);
7497
+ localStorage.removeItem(STORAGE_KEYS2.ORGANISATION_CONTEXT);
7498
+ }
7499
+ }, [user, session, supabase, isLoading, loadUserOrganisations]);
7540
7500
  const handleLogoutAndRedirect = useCallback7(async () => {
7541
7501
  try {
7542
7502
  await signOut();
@@ -7730,8 +7690,8 @@ var init_OrganisationProvider = __esm({
7730
7690
  });
7731
7691
 
7732
7692
  export {
7733
- useAuth,
7734
7693
  AuthProvider,
7694
+ useAuth,
7735
7695
  init_AuthProvider,
7736
7696
  useRBAC,
7737
7697
  RBACProvider,
@@ -7785,4 +7745,4 @@ lodash/lodash.js:
7785
7745
  * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
7786
7746
  *)
7787
7747
  */
7788
- //# sourceMappingURL=chunk-P27KH7XF.js.map
7748
+ //# sourceMappingURL=chunk-OQ6DTLZ6.js.map