@jmruthers/pace-core 0.5.181 → 0.5.182
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/CHANGELOG.md +1 -1
- package/README.md +16 -2
- package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
- package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
- package/dist/{DataTable-UA6CL4JI.js → DataTable-QAB34V6K.js} +14 -15
- package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
- package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
- package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
- package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
- package/dist/auth-BZOJqrdd.d.ts +49 -0
- package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
- package/dist/chunk-5DRSZLL2.js.map +1 -0
- package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
- package/dist/chunk-6C4YBBJM.js.map +1 -0
- package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
- package/dist/{chunk-HRO5HWN2.js → chunk-CSOFYHAG.js} +55 -162
- package/dist/chunk-CSOFYHAG.js.map +1 -0
- package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
- package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
- package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
- package/dist/chunk-FSFQFJCU.js.map +1 -0
- package/dist/chunk-FUEYYMX5.js +2296 -0
- package/dist/chunk-FUEYYMX5.js.map +1 -0
- package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
- package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
- package/dist/chunk-KQCRWDSA.js +1 -0
- package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
- package/dist/chunk-KUEN3HFB.js.map +1 -0
- package/dist/chunk-LMC26NLJ.js +84 -0
- package/dist/chunk-LMC26NLJ.js.map +1 -0
- package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
- package/dist/chunk-M7W4CP3M.js.map +1 -0
- package/dist/{chunk-HZLDFOE4.js → chunk-MI7HBHN3.js} +164 -243
- package/dist/chunk-MI7HBHN3.js.map +1 -0
- package/dist/{chunk-PPMP5J6T.js → chunk-PWAHJW4G.js} +180 -29
- package/dist/chunk-PWAHJW4G.js.map +1 -0
- package/dist/chunk-PWLANIRT.js +127 -0
- package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
- package/dist/chunk-QCDXODCA.js +75 -0
- package/dist/chunk-QCDXODCA.js.map +1 -0
- package/dist/{chunk-D7LCGMVS.js → chunk-QETLRQI6.js} +526 -887
- package/dist/chunk-QETLRQI6.js.map +1 -0
- package/dist/{chunk-5MT24GKJ.js → chunk-QUVSNGIP.js} +264 -262
- package/dist/chunk-QUVSNGIP.js.map +1 -0
- package/dist/chunk-QXHPKYJV.js +113 -0
- package/dist/chunk-QXHPKYJV.js.map +1 -0
- package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
- package/dist/chunk-R77UEZ4E.js.map +1 -0
- package/dist/{chunk-ZYTYSTO5.js → chunk-RA3JUFMW.js} +314 -161
- package/dist/chunk-RA3JUFMW.js.map +1 -0
- package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
- package/dist/chunk-SQGMNID3.js.map +1 -0
- package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
- package/dist/chunk-UHNYIBXL.js.map +1 -0
- package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
- package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
- package/dist/{chunk-VZ4VDGTB.js → chunk-W22JP75J.js} +5 -13
- package/dist/{chunk-VZ4VDGTB.js.map → chunk-W22JP75J.js.map} +1 -1
- package/dist/components.d.ts +12 -93
- package/dist/components.js +23 -106
- package/dist/components.js.map +1 -1
- package/dist/core-CUElvH_C.d.ts +164 -0
- package/dist/database.generated-CBmg2950.d.ts +8284 -0
- package/dist/event-CW5YB_2p.d.ts +239 -0
- package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
- package/dist/functions-D_kgHktt.d.ts +208 -0
- package/dist/hooks.d.ts +54 -7
- package/dist/hooks.js +204 -17
- package/dist/hooks.js.map +1 -1
- package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
- package/dist/index.d.ts +94 -261
- package/dist/index.js +314 -126
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +7 -8
- package/dist/providers.js +6 -13
- package/dist/rbac/index.d.ts +171 -101
- package/dist/rbac/index.js +23 -17
- package/dist/styles/index.d.ts +1 -3
- package/dist/styles/index.js +2 -17
- package/dist/theming/runtime.js +3 -3
- package/dist/types-UU913iLA.d.ts +102 -0
- package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
- package/dist/types.d.ts +88 -227
- package/dist/types.js +64 -112
- package/dist/types.js.map +1 -1
- package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
- package/dist/utils.d.ts +299 -13
- package/dist/utils.js +481 -55
- package/dist/utils.js.map +1 -1
- package/dist/validation-643vUDZW.d.ts +177 -0
- package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
- package/docs/README.md +9 -8
- package/docs/api/README.md +16 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +14 -14
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +29 -9
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +17 -17
- package/docs/api/enums/RBACErrorCode.md +228 -0
- package/docs/api/enums/RPCFunction.md +118 -0
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +2 -2
- package/docs/api/interfaces/CalendarProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +29 -3
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +2 -2
- package/docs/api/interfaces/DataTableColumn.md +6 -6
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +5 -5
- package/docs/api/interfaces/ExportOptions.md +4 -4
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +13 -13
- package/docs/api/interfaces/FileReference.md +12 -12
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +10 -10
- package/docs/api/interfaces/FileUploadProps.md +19 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +166 -0
- package/docs/api/interfaces/FormProps.md +113 -0
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
- package/docs/api/interfaces/InputProps.md +2 -2
- package/docs/api/interfaces/LabelProps.md +8 -8
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +17 -73
- package/docs/api/interfaces/NavigationMenuProps.md +38 -53
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +13 -13
- package/docs/api/interfaces/OrganisationContextType.md +21 -21
- package/docs/api/interfaces/OrganisationMembership.md +15 -15
- package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
- package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
- package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +50 -0
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
- package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
- package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
- package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
- package/docs/api/interfaces/RBACConfig.md +2 -2
- package/docs/api/interfaces/RBACContext.md +52 -0
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
- package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
- package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
- package/docs/api/interfaces/RBACResult.md +58 -0
- package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
- package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
- package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
- package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
- package/docs/api/interfaces/RBACRolesListParams.md +52 -0
- package/docs/api/interfaces/RBACRolesListResult.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +15 -2
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +43 -2
- package/docs/api/interfaces/TextareaProps.md +2 -2
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +4 -4
- package/docs/api/interfaces/UserProfile.md +7 -7
- package/docs/api/modules.md +484 -462
- package/docs/api-reference/components.md +186 -15
- package/docs/api-reference/deprecated.md +376 -0
- package/docs/api-reference/hooks.md +149 -19
- package/docs/api-reference/providers.md +61 -6
- package/docs/api-reference/rpc-functions.md +397 -0
- package/docs/api-reference/types.md +135 -78
- package/docs/api-reference/utilities.md +51 -380
- package/docs/architecture/README.md +49 -3
- package/docs/architecture/database-schema-requirements.md +40 -3
- package/docs/architecture/rbac-security-architecture.md +41 -4
- package/docs/architecture/services.md +127 -42
- package/docs/best-practices/README.md +51 -5
- package/docs/best-practices/accessibility.md +32 -3
- package/docs/best-practices/common-patterns.md +50 -3
- package/docs/best-practices/deployment.md +50 -4
- package/docs/best-practices/performance.md +50 -3
- package/docs/best-practices/security.md +94 -41
- package/docs/best-practices/testing.md +33 -4
- package/docs/core-concepts/authentication.md +5 -5
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +3 -3
- package/docs/core-concepts/permissions.md +3 -3
- package/docs/core-concepts/rbac-system.md +5 -5
- package/docs/documentation-index.md +30 -8
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +7 -5
- package/docs/getting-started/examples/basic-auth-app.md +3 -0
- package/docs/getting-started/examples/full-featured-app.md +5 -3
- package/docs/getting-started/faq.md +6 -6
- package/docs/getting-started/installation-guide.md +192 -13
- package/docs/getting-started/local-development.md +303 -0
- package/docs/getting-started/quick-reference.md +3 -3
- package/docs/getting-started/quick-start.md +517 -0
- package/docs/implementation-guides/app-layout.md +45 -3
- package/docs/implementation-guides/authentication.md +66 -7
- package/docs/implementation-guides/component-styling.md +53 -3
- package/docs/implementation-guides/data-tables.md +76 -7
- package/docs/implementation-guides/datatable-filtering.md +1 -2
- package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
- package/docs/implementation-guides/dynamic-colors.md +155 -4
- package/docs/implementation-guides/file-reference-system.md +72 -3
- package/docs/implementation-guides/file-upload-storage.md +72 -3
- package/docs/implementation-guides/forms.md +53 -3
- package/docs/implementation-guides/inactivity-tracking.md +53 -3
- package/docs/implementation-guides/large-datasets.md +1 -1
- package/docs/implementation-guides/navigation.md +55 -5
- package/docs/implementation-guides/organisation-security.md +72 -3
- package/docs/implementation-guides/performance.md +57 -1
- package/docs/implementation-guides/permission-enforcement.md +81 -8
- package/docs/implementation-guides/public-pages.md +560 -14
- package/docs/migration/MIGRATION_GUIDE.md +409 -50
- package/docs/migration/README.md +37 -3
- package/docs/migration/organisation-context-timing-fix.md +39 -4
- package/docs/migration/quick-migration-guide.md +41 -5
- package/docs/migration/rbac-migration.md +59 -3
- package/docs/migration/service-architecture.md +77 -14
- package/docs/rbac/README.md +79 -3
- package/docs/rbac/advanced-patterns.md +47 -3
- package/docs/rbac/api-reference.md +77 -8
- package/docs/rbac/event-based-apps.md +50 -5
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/examples.md +39 -3
- package/docs/rbac/getting-started.md +63 -4
- package/docs/rbac/quick-start.md +57 -5
- package/docs/rbac/rbac-rls-integration.md +68 -6
- package/docs/rbac/super-admin-guide.md +47 -3
- package/docs/rbac/troubleshooting.md +3 -3
- package/docs/security/README.md +68 -3
- package/docs/security/checklist.md +50 -3
- package/docs/standards/01-architecture-standard.md +39 -0
- package/docs/standards/02-api-and-rpc-standard.md +39 -0
- package/docs/standards/03-component-standard.md +32 -0
- package/docs/standards/04-code-style-standard.md +32 -0
- package/docs/standards/05-security-standard.md +30 -0
- package/docs/standards/06-testing-and-docs-standard.md +29 -0
- package/docs/standards/README.md +35 -0
- package/docs/styles/README.md +89 -8
- package/docs/testing/README.md +175 -24
- package/docs/troubleshooting/README.md +50 -3
- package/docs/troubleshooting/common-issues.md +271 -5
- package/docs/troubleshooting/debugging.md +54 -1
- package/docs/troubleshooting/migration.md +54 -1
- package/docs/troubleshooting/organisation-context-setup.md +29 -3
- package/docs/troubleshooting/styling-issues.md +246 -4
- package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
- package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
- package/{src/components/DataTable/examples → examples/DataTable}/HierarchicalExample.tsx +8 -6
- package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
- package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
- package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
- package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
- package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
- package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
- package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
- package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
- package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
- package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
- package/examples/README.md +81 -33
- package/examples/index.ts +14 -12
- package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
- package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
- package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
- package/package.json +21 -27
- package/src/__tests__/helpers/test-utils.tsx +29 -3
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
- package/src/components/Alert/Alert.test.tsx +2 -2
- package/src/components/Alert/Alert.tsx +4 -4
- package/src/components/Avatar/Avatar.test.tsx +17 -6
- package/src/components/Badge/Badge.test.tsx +1 -1
- package/src/components/Badge/Badge.tsx +2 -2
- package/src/components/Button/Button.test.tsx +2 -2
- package/src/components/Button/Button.tsx +11 -7
- package/src/components/Calendar/Calendar.test.tsx +41 -8
- package/src/components/Calendar/Calendar.tsx +39 -36
- package/src/components/Card/Card.tsx +51 -13
- package/src/components/Checkbox/Checkbox.test.tsx +36 -12
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
- package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
- package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
- package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
- package/src/components/DataTable/components/DataTableBody.tsx +10 -25
- package/src/components/DataTable/components/DataTableCore.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +3 -1
- package/src/components/DataTable/components/ImportModal.tsx +1 -1
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
- package/src/components/DataTable/core/ColumnFactory.ts +6 -6
- package/src/components/DataTable/core/DataTableContext.tsx +14 -10
- package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
- package/src/components/DataTable/core/PluginRegistry.ts +3 -3
- package/src/components/DataTable/core/StateManager.ts +12 -11
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
- package/src/components/DataTable/core/interfaces.ts +17 -17
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
- package/src/components/DataTable/types.ts +5 -5
- package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
- package/src/components/DataTable/utils/columnUtils.ts +3 -2
- package/src/components/DataTable/utils/debugTools.ts +1 -1
- package/src/components/DataTable/utils/exportUtils.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
- package/src/components/DataTable/utils/index.ts +0 -1
- package/src/components/DataTable/utils/performanceUtils.ts +9 -4
- package/src/components/Dialog/Dialog.test.tsx +49 -27
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
- package/src/components/EventSelector/EventSelector.test.tsx +60 -12
- package/src/components/EventSelector/EventSelector.tsx +38 -15
- package/src/components/EventSelector/index.ts +2 -2
- package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
- package/src/components/FileDisplay/FileDisplay.tsx +1 -0
- package/src/components/FileUpload/FileUpload.test.tsx +532 -152
- package/src/components/FileUpload/FileUpload.tsx +43 -8
- package/src/components/Footer/Footer.test.tsx +19 -14
- package/src/components/Form/Form.test.tsx +96 -14
- package/src/components/Form/Form.tsx +210 -1
- package/src/components/Form/index.ts +3 -7
- package/src/components/Header/Header.test.tsx +24 -17
- package/src/components/Header/Header.tsx +3 -1
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
- package/src/components/Input/Input.test.tsx +61 -36
- package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
- package/src/components/Label/Label.tsx +2 -3
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
- package/src/components/LoginForm/LoginForm.test.tsx +14 -13
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/LoginForm/index.ts +7 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
- package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
- package/src/components/NavigationMenu/index.ts +1 -1
- package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
- package/src/components/PaceAppLayout/test-setup.tsx +192 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
- package/src/components/PasswordChange/index.ts +2 -0
- package/src/components/Progress/Progress.test.tsx +11 -0
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Progress/index.ts +10 -0
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
- package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
- package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
- package/src/components/PublicLayout/index.ts +10 -28
- package/src/components/Select/Select.test.tsx +7 -7
- package/src/components/Select/Select.tsx +277 -11
- package/src/components/Select/index.ts +1 -2
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
- package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
- package/src/components/Tabs/Tabs.test.tsx +10 -9
- package/src/components/Tabs/Tabs.tsx +61 -33
- package/src/components/Textarea/Textarea.test.tsx +31 -18
- package/src/components/Toast/Toast.tsx +2 -2
- package/src/components/Tooltip/Tooltip.test.tsx +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +7 -6
- package/src/components/UserMenu/UserMenu.tsx +2 -2
- package/src/components/index.ts +5 -4
- package/src/constants/performance.ts +19 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
- package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
- package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
- package/src/hooks/index.ts +4 -0
- package/src/hooks/public/index.ts +2 -0
- package/src/hooks/public/usePublicEvent.ts +4 -6
- package/src/hooks/public/usePublicRouteParams.ts +1 -1
- package/src/hooks/services/useAuth.ts +2 -4
- package/src/hooks/services/useCurrentEvent.ts +1 -1
- package/src/hooks/useAppConfig.ts +1 -1
- package/src/hooks/useDataTablePerformance.ts +2 -2
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +51 -10
- package/src/hooks/useOrganisationPermissions.test.ts +3 -3
- package/src/hooks/useOrganisationPermissions.ts +1 -1
- package/src/hooks/useOrganisationSecurity.ts +2 -2
- package/src/hooks/usePermissionCache.test.ts +9 -9
- package/src/hooks/usePermissionCache.ts +2 -2
- package/src/index.ts +19 -12
- package/src/providers/OrganisationProvider.tsx +73 -9
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
- package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
- package/src/providers/__tests__/EventProvider.test.tsx +24 -15
- package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
- package/src/providers/index.ts +0 -3
- package/src/providers/services/AuthServiceProvider.tsx +2 -17
- package/src/providers/services/EventServiceProvider.tsx +11 -16
- package/src/providers/services/InactivityServiceProvider.tsx +9 -12
- package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
- package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
- package/src/rbac/adapters.tsx +1 -1
- package/src/rbac/api.ts +20 -4
- package/src/rbac/audit-enhanced.ts +47 -2
- package/src/rbac/audit.ts +47 -2
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.test.tsx +7 -6
- package/src/rbac/components/NavigationProvider.tsx +1 -1
- package/src/rbac/components/PagePermissionGuard.tsx +1 -1
- package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +1 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
- package/src/rbac/components/SecureDataProvider.tsx +1 -1
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/usePermissions.ts +31 -85
- package/src/rbac/hooks/useRBAC.test.ts +13 -1
- package/src/rbac/hooks/useRBAC.ts +13 -67
- package/src/rbac/hooks/useResolvedScope.ts +11 -0
- package/src/rbac/hooks/useSecureSupabase.ts +308 -0
- package/src/rbac/index.ts +3 -0
- package/src/rbac/secureClient.ts +53 -6
- package/src/rbac/security.ts +37 -1
- package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
- package/src/rbac/types.ts +3 -2
- package/src/services/AuthService.ts +33 -25
- package/src/services/EventService.ts +56 -44
- package/src/services/InactivityService.ts +33 -53
- package/src/services/OrganisationService.ts +36 -40
- package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
- package/src/services/__tests__/EventService.test.ts +67 -33
- package/src/services/interfaces/IEventService.ts +1 -1
- package/src/styles/core.css +2 -2
- package/src/styles/index.ts +1 -5
- package/src/types/__tests__/guards.test.ts +1 -1
- package/src/types/__tests__/type-validation.test.ts +0 -1
- package/src/types/auth.ts +42 -2
- package/src/types/core.ts +251 -0
- package/src/types/database.ts +11 -496
- package/src/types/event.ts +102 -0
- package/src/types/file-reference.ts +6 -4
- package/src/types/guards.ts +2 -1
- package/src/types/index.ts +48 -14
- package/src/types/lodash.debounce.d.ts +15 -0
- package/src/types/organisation.ts +14 -10
- package/src/types/supabase.ts +15 -17
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
- package/src/utils/app/appNameResolver.ts +1 -1
- package/src/utils/dynamic/dynamicUtils.ts +3 -2
- package/src/utils/file-reference/index.ts +25 -6
- package/src/utils/security/secureErrors.ts +1 -1
- package/src/utils/validation/index.ts +6 -12
- package/src/utils/validation/validationUtils.ts +0 -13
- package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
- package/dist/auth-DReDSLq9.d.ts +0 -16
- package/dist/chunk-3JI76CYK.js +0 -2444
- package/dist/chunk-3JI76CYK.js.map +0 -1
- package/dist/chunk-56XJ3TU6.js +0 -11
- package/dist/chunk-56XJ3TU6.js.map +0 -1
- package/dist/chunk-5MT24GKJ.js.map +0 -1
- package/dist/chunk-7QCC6MCP.js +0 -288
- package/dist/chunk-BESYRHQM.js.map +0 -1
- package/dist/chunk-BJPBT3CU.js +0 -21
- package/dist/chunk-BJPBT3CU.js.map +0 -1
- package/dist/chunk-BVYWGZVV.js.map +0 -1
- package/dist/chunk-CX5M4ZAG.js.map +0 -1
- package/dist/chunk-D7LCGMVS.js.map +0 -1
- package/dist/chunk-EGI6MUL6.js +0 -27
- package/dist/chunk-EGI6MUL6.js.map +0 -1
- package/dist/chunk-ERISIBYU.js.map +0 -1
- package/dist/chunk-HRO5HWN2.js.map +0 -1
- package/dist/chunk-HZLDFOE4.js.map +0 -1
- package/dist/chunk-JISYG63F.js +0 -70
- package/dist/chunk-JISYG63F.js.map +0 -1
- package/dist/chunk-LIMSTKYD.js +0 -61
- package/dist/chunk-LIMSTKYD.js.map +0 -1
- package/dist/chunk-OWAG3GSU.js.map +0 -1
- package/dist/chunk-PPMP5J6T.js.map +0 -1
- package/dist/chunk-Q5QRDWKI.js.map +0 -1
- package/dist/chunk-S5OFRT4M.js.map +0 -1
- package/dist/chunk-SBVILCCA.js.map +0 -1
- package/dist/chunk-TUMEWN34.js +0 -15
- package/dist/chunk-TUMEWN34.js.map +0 -1
- package/dist/chunk-XDNLUEXI.js +0 -138
- package/dist/chunk-XJ2HZOBU.js.map +0 -1
- package/dist/chunk-ZYTYSTO5.js.map +0 -1
- package/dist/chunk-ZZ2SS7NI.js +0 -237
- package/dist/chunk-ZZ2SS7NI.js.map +0 -1
- package/dist/database-C6jy7EOu.d.ts +0 -500
- package/dist/organisation-D6qRDtbF.d.ts +0 -93
- package/dist/schema-DTDZQe2u.d.ts +0 -28
- package/dist/unified-DQ4VcT7H.d.ts +0 -198
- package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
- package/dist/validation.d.ts +0 -47
- package/dist/validation.js +0 -24
- package/dist/validation.js.map +0 -1
- package/docs/DOCUMENTATION_AUDIT.md +0 -172
- package/docs/DOCUMENTATION_STANDARD.md +0 -137
- package/docs/api/classes/PublicErrorBoundary.md +0 -132
- package/docs/api/interfaces/EventLogoProps.md +0 -152
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
- package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
- package/docs/architecture/rpc-function-standards.md +0 -1106
- package/docs/getting-started/consuming-app-vite-config.md +0 -239
- package/docs/implementation-guides/event-theming-summary.md +0 -226
- package/docs/implementation-guides/public-pages-advanced.md +0 -1038
- package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
- package/docs/migration/v0.4.16-css-first-approach.md +0 -312
- package/docs/migration/v0.4.17-source-path-fix.md +0 -235
- package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
- package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
- package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
- package/docs/rbac/README-rbac-rls-integration.md +0 -374
- package/docs/styles/usage.md +0 -227
- package/docs/testing/visual-testing.md +0 -120
- package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
- package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
- package/docs/troubleshooting/database-view-compatibility.md +0 -125
- package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
- package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
- package/examples/RBAC/EventBasedApp.tsx +0 -239
- package/examples/RBAC/PermissionExample.tsx +0 -151
- package/examples/STRUCTURE.md +0 -125
- package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
- package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
- package/examples/components 2/index.ts +0 -11
- package/examples/features/index.ts +0 -12
- package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
- package/examples/features/rbac/index.ts +0 -13
- package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
- package/examples/public-pages/PublicEventPage.tsx +0 -274
- package/examples/public-pages/PublicPageApp.tsx +0 -308
- package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
- package/examples/public-pages/index.ts +0 -14
- package/src/__tests__/TEST_STANDARD.md +0 -1008
- package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
- package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
- package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
- package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
- package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
- package/src/components/Dialog/README.md +0 -804
- package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
- package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
- package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
- package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
- package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
- package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
- package/src/components/Dialog/utils/safeHtml.ts +0 -185
- package/src/components/EventSelector/types.ts +0 -79
- package/src/components/Form/FormErrorSummary.tsx +0 -113
- package/src/components/Form/FormField.tsx +0 -249
- package/src/components/Form/FormFieldset.tsx +0 -127
- package/src/components/Form/FormLiveRegion.tsx +0 -198
- package/src/components/Input/__mocks__/Input.tsx +0 -2
- package/src/components/NavigationMenu/types.ts +0 -85
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
- package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/ProtectedRoute/README.md +0 -164
- package/src/components/PublicLayout/EventLogo.tsx +0 -175
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
- package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
- package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
- package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
- package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
- package/src/components/Select/hooks.ts +0 -289
- package/src/hooks/useCounter.test.ts +0 -131
- package/src/hooks/useDebounce.test.ts +0 -375
- package/src/providers/AuthProvider.tsx +0 -15
- package/src/providers/EventProvider.tsx +0 -16
- package/src/providers/InactivityProvider.tsx +0 -15
- package/src/providers/OrganisationProvider.context.test.tsx +0 -169
- package/src/providers/UnifiedAuthProvider.tsx +0 -15
- package/src/types/theme.ts +0 -6
- package/src/types/unified.ts +0 -265
- package/src/utils/appConfig.ts +0 -47
- package/src/utils/appIdResolver.test.ts +0 -499
- package/src/utils/appIdResolver.ts +0 -130
- package/src/utils/appNameResolver.simple.test.ts +0 -212
- package/src/utils/appNameResolver.test.ts +0 -121
- package/src/utils/appNameResolver.ts +0 -191
- package/src/utils/audit.ts +0 -127
- package/src/utils/auth-utils.ts +0 -96
- package/src/utils/bundleAnalysis.ts +0 -129
- package/src/utils/debugLogger.ts +0 -67
- package/src/utils/deviceFingerprint.ts +0 -215
- package/src/utils/dynamicUtils.ts +0 -105
- package/src/utils/file-reference.test.ts +0 -788
- package/src/utils/file-reference.ts +0 -519
- package/src/utils/formatDate.test.ts +0 -237
- package/src/utils/formatting.ts +0 -170
- package/src/utils/lazyLoad.tsx +0 -44
- package/src/utils/logger.ts +0 -179
- package/src/utils/organisationContext.test.ts +0 -322
- package/src/utils/organisationContext.ts +0 -153
- package/src/utils/performanceBenchmark.ts +0 -64
- package/src/utils/performanceBudgets.ts +0 -110
- package/src/utils/permissionTypes.ts +0 -37
- package/src/utils/permissionUtils.test.ts +0 -393
- package/src/utils/permissionUtils.ts +0 -34
- package/src/utils/sanitization.ts +0 -264
- package/src/utils/schemaUtils.ts +0 -37
- package/src/utils/secureDataAccess.test.ts +0 -711
- package/src/utils/secureDataAccess.ts +0 -377
- package/src/utils/secureErrors.ts +0 -79
- package/src/utils/security.ts +0 -156
- package/src/utils/securityMonitor.ts +0 -45
- package/src/utils/sessionTracking.ts +0 -126
- package/src/utils/validation.ts +0 -111
- package/src/utils/validationUtils.ts +0 -120
- package/src/validation/index.ts +0 -12
- /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
- /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
- /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
- /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
- /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
- /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
- /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
- /package/examples/{RBAC → rbac}/index.ts +0 -0
package/dist/chunk-3JI76CYK.js
DELETED
|
@@ -1,2444 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
init_organisationContext,
|
|
3
|
-
init_secureStorage,
|
|
4
|
-
secureStorage,
|
|
5
|
-
setOrganisationContext
|
|
6
|
-
} from "./chunk-7QCC6MCP.js";
|
|
7
|
-
import {
|
|
8
|
-
createLogger,
|
|
9
|
-
init_logger,
|
|
10
|
-
logger
|
|
11
|
-
} from "./chunk-XDNLUEXI.js";
|
|
12
|
-
import {
|
|
13
|
-
__esm
|
|
14
|
-
} from "./chunk-PLDDJCW6.js";
|
|
15
|
-
|
|
16
|
-
// src/services/base/BaseService.ts
|
|
17
|
-
var BaseService;
|
|
18
|
-
var init_BaseService = __esm({
|
|
19
|
-
"src/services/base/BaseService.ts"() {
|
|
20
|
-
"use strict";
|
|
21
|
-
init_logger();
|
|
22
|
-
BaseService = class {
|
|
23
|
-
constructor() {
|
|
24
|
-
this.subscribers = [];
|
|
25
|
-
this.isInitialized = false;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Subscribe to state changes
|
|
29
|
-
* @param callback Function to call when state changes
|
|
30
|
-
* @returns Unsubscribe function
|
|
31
|
-
*/
|
|
32
|
-
subscribe(callback) {
|
|
33
|
-
this.subscribers.push(callback);
|
|
34
|
-
return () => {
|
|
35
|
-
const index = this.subscribers.indexOf(callback);
|
|
36
|
-
if (index > -1) {
|
|
37
|
-
this.subscribers.splice(index, 1);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Notify all subscribers of state changes
|
|
43
|
-
* This triggers React re-renders
|
|
44
|
-
*/
|
|
45
|
-
notify() {
|
|
46
|
-
this.subscribers.forEach((callback) => {
|
|
47
|
-
try {
|
|
48
|
-
callback();
|
|
49
|
-
} catch (error) {
|
|
50
|
-
logger.error("BaseService", "Error in subscriber callback:", error);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Initialize the service
|
|
56
|
-
* Override in subclasses to implement initialization logic
|
|
57
|
-
*/
|
|
58
|
-
async initialize() {
|
|
59
|
-
if (this.isInitialized) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
await this.doInitialize();
|
|
63
|
-
this.isInitialized = true;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Cleanup the service
|
|
67
|
-
* Override in subclasses to implement cleanup logic
|
|
68
|
-
*/
|
|
69
|
-
cleanup() {
|
|
70
|
-
this.subscribers = [];
|
|
71
|
-
this.doCleanup();
|
|
72
|
-
this.isInitialized = false;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Check if service is initialized
|
|
76
|
-
*/
|
|
77
|
-
getInitialized() {
|
|
78
|
-
return this.isInitialized;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Reset initialization state (allows re-initialization)
|
|
82
|
-
* Use when dependencies change and service needs to re-initialize
|
|
83
|
-
*/
|
|
84
|
-
resetInitialization() {
|
|
85
|
-
this.isInitialized = false;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// src/services/AuthService.ts
|
|
92
|
-
import { AuthError } from "@supabase/supabase-js";
|
|
93
|
-
var AuthService;
|
|
94
|
-
var init_AuthService = __esm({
|
|
95
|
-
"src/services/AuthService.ts"() {
|
|
96
|
-
"use strict";
|
|
97
|
-
init_BaseService();
|
|
98
|
-
init_logger();
|
|
99
|
-
AuthService = class extends BaseService {
|
|
100
|
-
constructor(supabaseClient, appName) {
|
|
101
|
-
super();
|
|
102
|
-
this.user = null;
|
|
103
|
-
this.session = null;
|
|
104
|
-
this.authLoading = false;
|
|
105
|
-
this.authError = null;
|
|
106
|
-
this.supabaseClient = null;
|
|
107
|
-
this.authStateSubscription = null;
|
|
108
|
-
this.sessionRestorationState = {
|
|
109
|
-
isRestoring: false,
|
|
110
|
-
restorationComplete: false,
|
|
111
|
-
restorationError: null
|
|
112
|
-
};
|
|
113
|
-
this.restorationTimeoutId = null;
|
|
114
|
-
this.restorationTimeoutMs = 5e3;
|
|
115
|
-
this.restorationStartTime = null;
|
|
116
|
-
this.appName = void 0;
|
|
117
|
-
this.supabaseClient = supabaseClient;
|
|
118
|
-
this.appName = appName;
|
|
119
|
-
}
|
|
120
|
-
// Auth state getters
|
|
121
|
-
getUser() {
|
|
122
|
-
return this.user;
|
|
123
|
-
}
|
|
124
|
-
getSession() {
|
|
125
|
-
return this.session;
|
|
126
|
-
}
|
|
127
|
-
isAuthenticated() {
|
|
128
|
-
return !!(this.user && this.session);
|
|
129
|
-
}
|
|
130
|
-
isLoading() {
|
|
131
|
-
return this.authLoading;
|
|
132
|
-
}
|
|
133
|
-
getError() {
|
|
134
|
-
return this.authError;
|
|
135
|
-
}
|
|
136
|
-
getSupabaseClient() {
|
|
137
|
-
return this.supabaseClient;
|
|
138
|
-
}
|
|
139
|
-
getSessionRestorationState() {
|
|
140
|
-
return { ...this.sessionRestorationState };
|
|
141
|
-
}
|
|
142
|
-
// Auth methods
|
|
143
|
-
async signIn(email, password) {
|
|
144
|
-
if (!this.supabaseClient) {
|
|
145
|
-
const error = new AuthError("Supabase client not available");
|
|
146
|
-
this.authError = error;
|
|
147
|
-
this.notify();
|
|
148
|
-
return { user: null, session: null, error };
|
|
149
|
-
}
|
|
150
|
-
try {
|
|
151
|
-
const { data, error } = await this.supabaseClient.auth.signInWithPassword({
|
|
152
|
-
email,
|
|
153
|
-
password: password || ""
|
|
154
|
-
});
|
|
155
|
-
if (error) {
|
|
156
|
-
this.authError = error;
|
|
157
|
-
this.user = null;
|
|
158
|
-
this.session = null;
|
|
159
|
-
} else {
|
|
160
|
-
this.authError = null;
|
|
161
|
-
this.user = data.user;
|
|
162
|
-
this.session = data.session;
|
|
163
|
-
}
|
|
164
|
-
this.notify();
|
|
165
|
-
return { user: data.user, session: data.session, error };
|
|
166
|
-
} catch (error) {
|
|
167
|
-
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
168
|
-
this.authError = authError;
|
|
169
|
-
this.user = null;
|
|
170
|
-
this.session = null;
|
|
171
|
-
this.notify();
|
|
172
|
-
return { user: null, session: null, error: authError };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
async signUp(email, password) {
|
|
176
|
-
if (!this.supabaseClient) {
|
|
177
|
-
const error = new AuthError("Supabase client not available");
|
|
178
|
-
this.authError = error;
|
|
179
|
-
this.notify();
|
|
180
|
-
return { user: null, session: null, error };
|
|
181
|
-
}
|
|
182
|
-
try {
|
|
183
|
-
const { data, error } = await this.supabaseClient.auth.signUp({
|
|
184
|
-
email,
|
|
185
|
-
password
|
|
186
|
-
});
|
|
187
|
-
if (error) {
|
|
188
|
-
this.authError = error;
|
|
189
|
-
this.user = null;
|
|
190
|
-
this.session = null;
|
|
191
|
-
} else {
|
|
192
|
-
this.authError = null;
|
|
193
|
-
this.user = data.user;
|
|
194
|
-
this.session = data.session;
|
|
195
|
-
}
|
|
196
|
-
this.notify();
|
|
197
|
-
return { user: data.user, session: data.session, error };
|
|
198
|
-
} catch (error) {
|
|
199
|
-
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
200
|
-
this.authError = authError;
|
|
201
|
-
this.user = null;
|
|
202
|
-
this.session = null;
|
|
203
|
-
this.notify();
|
|
204
|
-
return { user: null, session: null, error: authError };
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async signOut() {
|
|
208
|
-
if (!this.supabaseClient) {
|
|
209
|
-
const error = new AuthError("Supabase client not available");
|
|
210
|
-
this.authError = error;
|
|
211
|
-
this.notify();
|
|
212
|
-
return { user: null, session: null, error };
|
|
213
|
-
}
|
|
214
|
-
try {
|
|
215
|
-
const { error } = await this.supabaseClient.auth.signOut();
|
|
216
|
-
if (error) {
|
|
217
|
-
this.authError = error;
|
|
218
|
-
} else {
|
|
219
|
-
this.authError = null;
|
|
220
|
-
this.user = null;
|
|
221
|
-
this.session = null;
|
|
222
|
-
}
|
|
223
|
-
this.notify();
|
|
224
|
-
return { user: null, session: null, error };
|
|
225
|
-
} catch (error) {
|
|
226
|
-
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
227
|
-
this.authError = authError;
|
|
228
|
-
this.user = null;
|
|
229
|
-
this.session = null;
|
|
230
|
-
this.notify();
|
|
231
|
-
return { user: null, session: null, error: authError };
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
async resetPassword(email) {
|
|
235
|
-
if (!this.supabaseClient) {
|
|
236
|
-
const error = new AuthError("Supabase client not available");
|
|
237
|
-
this.authError = error;
|
|
238
|
-
this.notify();
|
|
239
|
-
return { user: null, session: null, error };
|
|
240
|
-
}
|
|
241
|
-
try {
|
|
242
|
-
const { error } = await this.supabaseClient.auth.resetPasswordForEmail(email);
|
|
243
|
-
if (error) {
|
|
244
|
-
this.authError = error;
|
|
245
|
-
} else {
|
|
246
|
-
this.authError = null;
|
|
247
|
-
}
|
|
248
|
-
this.notify();
|
|
249
|
-
return { user: null, session: null, error };
|
|
250
|
-
} catch (error) {
|
|
251
|
-
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
252
|
-
this.authError = authError;
|
|
253
|
-
this.notify();
|
|
254
|
-
return { user: null, session: null, error: authError };
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
async updatePassword(password) {
|
|
258
|
-
if (!this.supabaseClient) {
|
|
259
|
-
const error = new AuthError("Supabase client not available");
|
|
260
|
-
this.authError = error;
|
|
261
|
-
this.notify();
|
|
262
|
-
return { user: null, session: null, error };
|
|
263
|
-
}
|
|
264
|
-
try {
|
|
265
|
-
const { error } = await this.supabaseClient.auth.updateUser({
|
|
266
|
-
password
|
|
267
|
-
});
|
|
268
|
-
if (error) {
|
|
269
|
-
this.authError = error;
|
|
270
|
-
} else {
|
|
271
|
-
this.authError = null;
|
|
272
|
-
}
|
|
273
|
-
this.notify();
|
|
274
|
-
return { user: null, session: null, error };
|
|
275
|
-
} catch (error) {
|
|
276
|
-
const authError = error;
|
|
277
|
-
this.authError = authError;
|
|
278
|
-
this.notify();
|
|
279
|
-
return { user: null, session: null, error: authError };
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
async refreshSession() {
|
|
283
|
-
if (!this.supabaseClient) {
|
|
284
|
-
const error = new AuthError("Supabase client not available");
|
|
285
|
-
this.authError = error;
|
|
286
|
-
this.notify();
|
|
287
|
-
return { user: null, session: null, error };
|
|
288
|
-
}
|
|
289
|
-
try {
|
|
290
|
-
const { data, error } = await this.supabaseClient.auth.refreshSession();
|
|
291
|
-
if (error) {
|
|
292
|
-
this.authError = error;
|
|
293
|
-
this.user = null;
|
|
294
|
-
this.session = null;
|
|
295
|
-
} else {
|
|
296
|
-
this.authError = null;
|
|
297
|
-
if (data?.user && data?.session) {
|
|
298
|
-
this.user = data.user;
|
|
299
|
-
this.session = data.session;
|
|
300
|
-
} else {
|
|
301
|
-
this.user = null;
|
|
302
|
-
this.session = null;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
this.notify();
|
|
306
|
-
return {
|
|
307
|
-
user: data?.user && data?.session ? data.user : null,
|
|
308
|
-
session: data?.session ?? null,
|
|
309
|
-
error
|
|
310
|
-
};
|
|
311
|
-
} catch (error) {
|
|
312
|
-
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
313
|
-
this.authError = authError;
|
|
314
|
-
this.user = null;
|
|
315
|
-
this.session = null;
|
|
316
|
-
this.notify();
|
|
317
|
-
return { user: null, session: null, error: authError };
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
// Lifecycle methods
|
|
321
|
-
async initialize() {
|
|
322
|
-
await super.initialize();
|
|
323
|
-
await this.setupAuthStateListener();
|
|
324
|
-
await this.restoreSession();
|
|
325
|
-
}
|
|
326
|
-
cleanup() {
|
|
327
|
-
if (this.authStateSubscription && typeof this.authStateSubscription.unsubscribe === "function") {
|
|
328
|
-
this.authStateSubscription.unsubscribe();
|
|
329
|
-
this.authStateSubscription = null;
|
|
330
|
-
}
|
|
331
|
-
this.clearRestorationTimeout();
|
|
332
|
-
this.restorationStartTime = null;
|
|
333
|
-
this.sessionRestorationState = {
|
|
334
|
-
isRestoring: false,
|
|
335
|
-
restorationComplete: false,
|
|
336
|
-
restorationError: null
|
|
337
|
-
};
|
|
338
|
-
this.authLoading = false;
|
|
339
|
-
super.cleanup();
|
|
340
|
-
}
|
|
341
|
-
async doInitialize() {
|
|
342
|
-
this.setupErrorHandlers();
|
|
343
|
-
}
|
|
344
|
-
doCleanup() {
|
|
345
|
-
this.removeErrorHandlers();
|
|
346
|
-
}
|
|
347
|
-
startSessionRestoration() {
|
|
348
|
-
this.clearRestorationTimeout();
|
|
349
|
-
this.sessionRestorationState = {
|
|
350
|
-
isRestoring: true,
|
|
351
|
-
restorationComplete: false,
|
|
352
|
-
restorationError: null
|
|
353
|
-
};
|
|
354
|
-
this.authLoading = true;
|
|
355
|
-
this.restorationStartTime = Date.now();
|
|
356
|
-
logger.debug("AuthService", "Starting session restoration at", this.restorationStartTime);
|
|
357
|
-
this.notify();
|
|
358
|
-
this.restorationTimeoutId = setTimeout(() => {
|
|
359
|
-
logger.warn("AuthService", "Session restoration timed out after", this.restorationTimeoutMs, "ms");
|
|
360
|
-
const timeoutError = new Error(`Session restoration timed out after ${this.restorationTimeoutMs}ms`);
|
|
361
|
-
timeoutError.name = "SessionRestorationTimeoutError";
|
|
362
|
-
this.finishSessionRestoration(timeoutError);
|
|
363
|
-
}, this.restorationTimeoutMs);
|
|
364
|
-
}
|
|
365
|
-
finishSessionRestoration(error) {
|
|
366
|
-
if (!this.sessionRestorationState.isRestoring && !error) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
this.clearRestorationTimeout();
|
|
370
|
-
const completedAt = Date.now();
|
|
371
|
-
const duration = this.restorationStartTime ? completedAt - this.restorationStartTime : null;
|
|
372
|
-
this.restorationStartTime = null;
|
|
373
|
-
const restorationComplete = !error;
|
|
374
|
-
this.sessionRestorationState = {
|
|
375
|
-
isRestoring: false,
|
|
376
|
-
restorationComplete,
|
|
377
|
-
restorationError: error ?? null
|
|
378
|
-
};
|
|
379
|
-
this.authLoading = false;
|
|
380
|
-
if (error) {
|
|
381
|
-
logger.warn("AuthService", "Session restoration finished with error:", error, "duration(ms):", duration ?? "unknown");
|
|
382
|
-
} else {
|
|
383
|
-
logger.debug("AuthService", "Session restoration completed successfully in", duration ?? "unknown", "ms");
|
|
384
|
-
}
|
|
385
|
-
this.notify();
|
|
386
|
-
}
|
|
387
|
-
clearRestorationTimeout() {
|
|
388
|
-
if (this.restorationTimeoutId) {
|
|
389
|
-
clearTimeout(this.restorationTimeoutId);
|
|
390
|
-
this.restorationTimeoutId = null;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
async setupAuthStateListener() {
|
|
394
|
-
if (!this.supabaseClient) {
|
|
395
|
-
this.authLoading = false;
|
|
396
|
-
this.notify();
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
try {
|
|
400
|
-
this.authStateSubscription = this.supabaseClient.auth.onAuthStateChange(
|
|
401
|
-
(event, session) => {
|
|
402
|
-
try {
|
|
403
|
-
logger.debug("AuthService", "Auth state change event received:", event);
|
|
404
|
-
if (event === "SIGNED_OUT") {
|
|
405
|
-
this.session = null;
|
|
406
|
-
this.user = null;
|
|
407
|
-
this.authError = null;
|
|
408
|
-
if (session?.user) {
|
|
409
|
-
this.trackSession("logout", session).catch((err) => {
|
|
410
|
-
logger.warn("AuthService", "Failed to track logout session:", err);
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
} else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
|
|
414
|
-
this.session = session;
|
|
415
|
-
this.user = session?.user ?? null;
|
|
416
|
-
if (session) {
|
|
417
|
-
this.authError = null;
|
|
418
|
-
}
|
|
419
|
-
if (event === "SIGNED_IN" && session?.user) {
|
|
420
|
-
this.trackSession("login", session).catch((err) => {
|
|
421
|
-
logger.warn("AuthService", "Failed to track login session:", err);
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
} else if (event === "INITIAL_SESSION") {
|
|
425
|
-
if (session) {
|
|
426
|
-
this.session = session;
|
|
427
|
-
this.user = session.user ?? null;
|
|
428
|
-
this.authError = null;
|
|
429
|
-
const hasTimeoutError = this.sessionRestorationState.restorationError?.name === "SessionRestorationTimeoutError";
|
|
430
|
-
if (this.sessionRestorationState.isRestoring || this.sessionRestorationState.restorationError || hasTimeoutError && session) {
|
|
431
|
-
this.finishSessionRestoration();
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
if (this.sessionRestorationState.isRestoring) {
|
|
436
|
-
this.finishSessionRestoration();
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
this.authLoading = false;
|
|
441
|
-
this.notify();
|
|
442
|
-
} catch (error) {
|
|
443
|
-
logger.warn("AuthService", "Error in auth state change handler:", error);
|
|
444
|
-
this.authLoading = false;
|
|
445
|
-
this.notify();
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
);
|
|
449
|
-
} catch (error) {
|
|
450
|
-
logger.error("AuthService", "Failed to setup auth state listener:", error);
|
|
451
|
-
throw error;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
async restoreSession() {
|
|
455
|
-
if (!this.supabaseClient) {
|
|
456
|
-
const error = new Error("Supabase client not available during session restoration");
|
|
457
|
-
logger.error("AuthService", "Unable to restore session:", error);
|
|
458
|
-
this.finishSessionRestoration(error);
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
this.startSessionRestoration();
|
|
462
|
-
try {
|
|
463
|
-
logger.debug("AuthService", "Fetching existing session from Supabase");
|
|
464
|
-
let currentSession = null;
|
|
465
|
-
let sessionError = null;
|
|
466
|
-
try {
|
|
467
|
-
const { data, error } = await this.supabaseClient.auth.getSession();
|
|
468
|
-
currentSession = data?.session ?? null;
|
|
469
|
-
sessionError = error ?? null;
|
|
470
|
-
} catch (error) {
|
|
471
|
-
logger.debug("AuthService", "getSession unavailable, treating as no active session");
|
|
472
|
-
currentSession = null;
|
|
473
|
-
sessionError = null;
|
|
474
|
-
}
|
|
475
|
-
if (sessionError) {
|
|
476
|
-
logger.debug("AuthService", "getSession returned error, attempting to fetch user anyway");
|
|
477
|
-
this.authError = sessionError;
|
|
478
|
-
try {
|
|
479
|
-
const { data, error } = await this.supabaseClient.auth.getUser();
|
|
480
|
-
const currentUser = data?.user ?? null;
|
|
481
|
-
const userError = error ?? null;
|
|
482
|
-
if (currentUser) {
|
|
483
|
-
this.user = currentUser;
|
|
484
|
-
this.session = null;
|
|
485
|
-
}
|
|
486
|
-
if (userError && !this.authError) {
|
|
487
|
-
this.authError = userError;
|
|
488
|
-
}
|
|
489
|
-
} catch (getUserError) {
|
|
490
|
-
logger.debug("AuthService", "getUser also failed:", getUserError);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
if (currentSession) {
|
|
494
|
-
this.session = currentSession;
|
|
495
|
-
this.user = currentSession.user;
|
|
496
|
-
this.authError = null;
|
|
497
|
-
} else if (!sessionError) {
|
|
498
|
-
logger.debug("AuthService", "No active session found; treating as normal unauthenticated state");
|
|
499
|
-
this.session = null;
|
|
500
|
-
this.user = null;
|
|
501
|
-
this.authError = null;
|
|
502
|
-
}
|
|
503
|
-
this.finishSessionRestoration();
|
|
504
|
-
} catch (error) {
|
|
505
|
-
const restorationError = error instanceof Error ? error : new Error("Unknown error during auth initialization");
|
|
506
|
-
logger.error("AuthService", "Error during auth initialization:", restorationError);
|
|
507
|
-
if (restorationError instanceof AuthError) {
|
|
508
|
-
this.authError = restorationError;
|
|
509
|
-
}
|
|
510
|
-
this.finishSessionRestoration(restorationError);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* Automatically track user session using rbac_session_track
|
|
515
|
-
* This method is called automatically on SIGNED_IN and SIGNED_OUT events.
|
|
516
|
-
* It's non-blocking and failures are logged as warnings.
|
|
517
|
-
*/
|
|
518
|
-
async trackSession(sessionType, session) {
|
|
519
|
-
if (!this.supabaseClient || !session?.user) {
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
try {
|
|
523
|
-
let appId = void 0;
|
|
524
|
-
if (this.appName) {
|
|
525
|
-
const { data, error: error2 } = await this.supabaseClient.from("rbac_apps").select("id").eq("name", this.appName).eq("is_active", true).single();
|
|
526
|
-
if (!error2 && data) {
|
|
527
|
-
appId = data.id;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
const ipAddress = void 0;
|
|
531
|
-
const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : void 0;
|
|
532
|
-
const deviceFingerprint = void 0;
|
|
533
|
-
const { error } = await this.supabaseClient.rpc("rbac_session_track", {
|
|
534
|
-
p_user_id: session.user.id,
|
|
535
|
-
p_session_type: sessionType,
|
|
536
|
-
p_event_id: null,
|
|
537
|
-
// Event ID should come from context, not auth service
|
|
538
|
-
p_app_id: appId,
|
|
539
|
-
p_ip_address: ipAddress,
|
|
540
|
-
p_user_agent: userAgent,
|
|
541
|
-
p_device_fingerprint: deviceFingerprint
|
|
542
|
-
});
|
|
543
|
-
if (error) {
|
|
544
|
-
logger.warn("AuthService", `Failed to track ${sessionType} session:`, error);
|
|
545
|
-
} else {
|
|
546
|
-
logger.debug("AuthService", `Successfully tracked ${sessionType} session`);
|
|
547
|
-
}
|
|
548
|
-
} catch (error) {
|
|
549
|
-
logger.warn("AuthService", `Error tracking ${sessionType} session:`, error);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
setupErrorHandlers() {
|
|
553
|
-
if (typeof window === "undefined") return;
|
|
554
|
-
const handleError = (event) => {
|
|
555
|
-
if (event.error?.message?.includes("AuthSessionMissingError") || event.error?.message?.includes("Auth session missing")) {
|
|
556
|
-
logger.warn("AuthService", "Suppressing AuthSessionMissingError during logout");
|
|
557
|
-
event.preventDefault();
|
|
558
|
-
return false;
|
|
559
|
-
}
|
|
560
|
-
};
|
|
561
|
-
const handleUnhandledRejection = (event) => {
|
|
562
|
-
if (event.reason?.message?.includes("AuthSessionMissingError") || event.reason?.message?.includes("Auth session missing")) {
|
|
563
|
-
logger.warn("AuthService", "Suppressing unhandled AuthSessionMissingError");
|
|
564
|
-
event.preventDefault();
|
|
565
|
-
return false;
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
window.addEventListener("error", handleError);
|
|
569
|
-
window.addEventListener("unhandledrejection", handleUnhandledRejection);
|
|
570
|
-
}
|
|
571
|
-
removeErrorHandlers() {
|
|
572
|
-
if (typeof window === "undefined") return;
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
// src/providers/services/AuthServiceProvider.tsx
|
|
579
|
-
import { createContext, useContext, useMemo, useEffect, useState } from "react";
|
|
580
|
-
import { jsx } from "react/jsx-runtime";
|
|
581
|
-
function AuthServiceProvider({ children, supabaseClient, appName }) {
|
|
582
|
-
const authService = useMemo(
|
|
583
|
-
() => new AuthService(supabaseClient, appName),
|
|
584
|
-
[supabaseClient, appName]
|
|
585
|
-
);
|
|
586
|
-
const [sessionRestoration, setSessionRestoration] = useState(
|
|
587
|
-
() => authService.getSessionRestorationState()
|
|
588
|
-
);
|
|
589
|
-
useEffect(() => {
|
|
590
|
-
const unsubscribe = authService.subscribe(() => {
|
|
591
|
-
const restorationState = authService.getSessionRestorationState();
|
|
592
|
-
setSessionRestoration(restorationState);
|
|
593
|
-
const isDev = typeof import.meta !== "undefined" && (import.meta.env.DEV || import.meta.env.MODE === "development");
|
|
594
|
-
if (isDev) {
|
|
595
|
-
logger.debug("AuthServiceProvider", "Session restoration state updated", restorationState);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
return () => {
|
|
599
|
-
unsubscribe();
|
|
600
|
-
};
|
|
601
|
-
}, [authService]);
|
|
602
|
-
useEffect(() => {
|
|
603
|
-
authService.initialize().catch((error) => {
|
|
604
|
-
logger.error("AuthServiceProvider", "Failed to initialize auth service:", error);
|
|
605
|
-
});
|
|
606
|
-
return () => {
|
|
607
|
-
authService.cleanup();
|
|
608
|
-
};
|
|
609
|
-
}, [authService]);
|
|
610
|
-
const contextValue = useMemo(() => ({
|
|
611
|
-
authService,
|
|
612
|
-
sessionRestoration
|
|
613
|
-
}), [authService, sessionRestoration]);
|
|
614
|
-
return /* @__PURE__ */ jsx(AuthServiceContext.Provider, { value: contextValue, children });
|
|
615
|
-
}
|
|
616
|
-
var AuthServiceContext, useAuthService;
|
|
617
|
-
var init_AuthServiceProvider = __esm({
|
|
618
|
-
"src/providers/services/AuthServiceProvider.tsx"() {
|
|
619
|
-
"use strict";
|
|
620
|
-
init_AuthService();
|
|
621
|
-
init_logger();
|
|
622
|
-
AuthServiceContext = createContext(null);
|
|
623
|
-
useAuthService = () => {
|
|
624
|
-
const context = useContext(AuthServiceContext);
|
|
625
|
-
if (!context) {
|
|
626
|
-
throw new Error("useAuthService must be used within AuthServiceProvider");
|
|
627
|
-
}
|
|
628
|
-
return context.authService;
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
// src/services/OrganisationService.ts
|
|
634
|
-
var OrganisationService;
|
|
635
|
-
var init_OrganisationService = __esm({
|
|
636
|
-
"src/services/OrganisationService.ts"() {
|
|
637
|
-
"use strict";
|
|
638
|
-
init_BaseService();
|
|
639
|
-
init_organisationContext();
|
|
640
|
-
init_logger();
|
|
641
|
-
OrganisationService = class extends BaseService {
|
|
642
|
-
constructor(supabaseClient, user, session) {
|
|
643
|
-
super();
|
|
644
|
-
this._selectedOrganisation = null;
|
|
645
|
-
this._organisations = [];
|
|
646
|
-
this._userMemberships = [];
|
|
647
|
-
this._roleMapState = /* @__PURE__ */ new Map();
|
|
648
|
-
this._isLoading = false;
|
|
649
|
-
this._error = null;
|
|
650
|
-
this._isContextReady = false;
|
|
651
|
-
this.retryCount = 0;
|
|
652
|
-
// Dependencies
|
|
653
|
-
this.supabaseClient = null;
|
|
654
|
-
this.user = null;
|
|
655
|
-
this.session = null;
|
|
656
|
-
// Internal state management
|
|
657
|
-
this.isLoadingRef = false;
|
|
658
|
-
this.lastLoadTimeRef = 0;
|
|
659
|
-
this.hasFailedRef = false;
|
|
660
|
-
this.abortControllerRef = null;
|
|
661
|
-
this.supabaseClient = supabaseClient;
|
|
662
|
-
this.user = user;
|
|
663
|
-
this.session = session;
|
|
664
|
-
}
|
|
665
|
-
// Interface implementation
|
|
666
|
-
getSelectedOrganisation() {
|
|
667
|
-
return this._selectedOrganisation;
|
|
668
|
-
}
|
|
669
|
-
getOrganisations() {
|
|
670
|
-
return this._organisations;
|
|
671
|
-
}
|
|
672
|
-
getUserMemberships() {
|
|
673
|
-
return this._userMemberships;
|
|
674
|
-
}
|
|
675
|
-
isLoading() {
|
|
676
|
-
return this._isLoading;
|
|
677
|
-
}
|
|
678
|
-
getError() {
|
|
679
|
-
return this._error;
|
|
680
|
-
}
|
|
681
|
-
hasValidOrganisationContext() {
|
|
682
|
-
return !!(this._selectedOrganisation && !this._isLoading && !this._error && this._isContextReady);
|
|
683
|
-
}
|
|
684
|
-
isContextReady() {
|
|
685
|
-
return this._isContextReady;
|
|
686
|
-
}
|
|
687
|
-
// Additional methods for testing
|
|
688
|
-
setSelectedOrganisation(organisation) {
|
|
689
|
-
this._selectedOrganisation = organisation;
|
|
690
|
-
if (organisation) {
|
|
691
|
-
localStorage.setItem("pace-core-selected-organisation", JSON.stringify(organisation));
|
|
692
|
-
this.setDatabaseOrganisationContext(organisation);
|
|
693
|
-
} else {
|
|
694
|
-
localStorage.removeItem("pace-core-selected-organisation");
|
|
695
|
-
this._isContextReady = false;
|
|
696
|
-
}
|
|
697
|
-
this.notify();
|
|
698
|
-
}
|
|
699
|
-
// For testing: expose dependencies
|
|
700
|
-
getDependencies() {
|
|
701
|
-
return {
|
|
702
|
-
user: this.user,
|
|
703
|
-
session: this.session,
|
|
704
|
-
supabaseClient: this.supabaseClient
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
// For testing: manually set state
|
|
708
|
-
setTestState(organisations, memberships, roleMap, selectedOrg = null) {
|
|
709
|
-
this._organisations = organisations;
|
|
710
|
-
this._userMemberships = memberships;
|
|
711
|
-
this._roleMapState = roleMap;
|
|
712
|
-
if (selectedOrg) {
|
|
713
|
-
this._selectedOrganisation = selectedOrg;
|
|
714
|
-
} else if (organisations.length > 0) {
|
|
715
|
-
this._selectedOrganisation = organisations[0];
|
|
716
|
-
}
|
|
717
|
-
this._isLoading = false;
|
|
718
|
-
this._error = null;
|
|
719
|
-
this.notify();
|
|
720
|
-
}
|
|
721
|
-
// Update dependencies
|
|
722
|
-
updateDependencies(user, session) {
|
|
723
|
-
const wasAuthenticated = !!(this.user && this.session);
|
|
724
|
-
const isAuthenticated = !!(user && session);
|
|
725
|
-
this.user = user;
|
|
726
|
-
this.session = session;
|
|
727
|
-
if (wasAuthenticated && !isAuthenticated) {
|
|
728
|
-
this.isInitialized = false;
|
|
729
|
-
}
|
|
730
|
-
this.notify();
|
|
731
|
-
}
|
|
732
|
-
// Organisation methods
|
|
733
|
-
async switchOrganisation(orgId) {
|
|
734
|
-
if (!this.validateOrganisationAccess(orgId)) {
|
|
735
|
-
throw new Error(`User does not have access to organisation ${orgId}`);
|
|
736
|
-
}
|
|
737
|
-
const targetOrg = this._organisations.find((org) => org.id === orgId);
|
|
738
|
-
if (!targetOrg) {
|
|
739
|
-
throw new Error(`Organisation ${orgId} not found in user's organisations`);
|
|
740
|
-
}
|
|
741
|
-
this._selectedOrganisation = targetOrg;
|
|
742
|
-
localStorage.setItem("pace-core-selected-organisation", JSON.stringify(targetOrg));
|
|
743
|
-
await this.setDatabaseOrganisationContext(targetOrg);
|
|
744
|
-
this.notify();
|
|
745
|
-
}
|
|
746
|
-
getUserRole(orgId) {
|
|
747
|
-
const targetOrgId = orgId || this._selectedOrganisation?.id;
|
|
748
|
-
if (!targetOrgId) return "no_access";
|
|
749
|
-
return this._roleMapState.get(targetOrgId) || "no_access";
|
|
750
|
-
}
|
|
751
|
-
validateOrganisationAccess(orgId) {
|
|
752
|
-
return this._userMemberships.some(
|
|
753
|
-
(m) => m.organisation_id === orgId && m.status === "active" && m.revoked_at === null
|
|
754
|
-
);
|
|
755
|
-
}
|
|
756
|
-
async refreshOrganisations() {
|
|
757
|
-
if (!this.user || !this.session || !this.supabaseClient) return;
|
|
758
|
-
this._isLoading = true;
|
|
759
|
-
this.notify();
|
|
760
|
-
await this.loadUserOrganisations();
|
|
761
|
-
}
|
|
762
|
-
ensureOrganisationContext() {
|
|
763
|
-
if (!this._selectedOrganisation) {
|
|
764
|
-
throw new Error("Organisation context is required but not available");
|
|
765
|
-
}
|
|
766
|
-
return this._selectedOrganisation;
|
|
767
|
-
}
|
|
768
|
-
isOrganisationSecure() {
|
|
769
|
-
return !!(this._selectedOrganisation && this.user);
|
|
770
|
-
}
|
|
771
|
-
getPrimaryOrganisation() {
|
|
772
|
-
const rolePriority = ["org_admin", "leader", "member"];
|
|
773
|
-
for (const role of rolePriority) {
|
|
774
|
-
const membership = this._userMemberships.find((m) => m.role === role);
|
|
775
|
-
if (membership) {
|
|
776
|
-
return this._organisations.find((org) => org.id === membership.organisation_id) || null;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return null;
|
|
780
|
-
}
|
|
781
|
-
buildOrganisationHierarchy(orgs) {
|
|
782
|
-
const orgMap = /* @__PURE__ */ new Map();
|
|
783
|
-
orgs.forEach((org) => orgMap.set(org.id, org));
|
|
784
|
-
const roots = [];
|
|
785
|
-
orgs.forEach((org) => {
|
|
786
|
-
if (!org.parent_id) {
|
|
787
|
-
roots.push({
|
|
788
|
-
organisation: org,
|
|
789
|
-
children: [],
|
|
790
|
-
depth: 0
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
|
-
return roots;
|
|
795
|
-
}
|
|
796
|
-
// Lifecycle methods
|
|
797
|
-
async initialize() {
|
|
798
|
-
await super.initialize();
|
|
799
|
-
if (!this.isLoadingRef) {
|
|
800
|
-
await this.loadUserOrganisations();
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
cleanup() {
|
|
804
|
-
this.isLoadingRef = false;
|
|
805
|
-
this.hasFailedRef = false;
|
|
806
|
-
this.lastLoadTimeRef = 0;
|
|
807
|
-
if (this.abortControllerRef) {
|
|
808
|
-
this.abortControllerRef = null;
|
|
809
|
-
}
|
|
810
|
-
this._selectedOrganisation = null;
|
|
811
|
-
this._organisations = [];
|
|
812
|
-
this._userMemberships = [];
|
|
813
|
-
this._roleMapState = /* @__PURE__ */ new Map();
|
|
814
|
-
this._isLoading = false;
|
|
815
|
-
this._error = null;
|
|
816
|
-
this._isContextReady = false;
|
|
817
|
-
super.cleanup();
|
|
818
|
-
}
|
|
819
|
-
async doInitialize() {
|
|
820
|
-
}
|
|
821
|
-
doCleanup() {
|
|
822
|
-
}
|
|
823
|
-
async setDatabaseOrganisationContext(organisation) {
|
|
824
|
-
if (!this.supabaseClient || !this.session) {
|
|
825
|
-
logger.warn("OrganisationService", "No Supabase client or session available for setting organisation context");
|
|
826
|
-
this._isContextReady = false;
|
|
827
|
-
this.notify();
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
try {
|
|
831
|
-
logger.debug("OrganisationService", "Setting database organisation context for:", organisation.id);
|
|
832
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
833
|
-
setTimeout(() => reject(new Error("Context setting timeout after 5 seconds")), 5e3);
|
|
834
|
-
});
|
|
835
|
-
const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);
|
|
836
|
-
await Promise.race([contextPromise, timeoutPromise]);
|
|
837
|
-
logger.debug("OrganisationService", "Database organisation context set successfully");
|
|
838
|
-
this._isContextReady = true;
|
|
839
|
-
this.notify();
|
|
840
|
-
} catch (error) {
|
|
841
|
-
logger.error("OrganisationService", "Failed to set database organisation context:", error);
|
|
842
|
-
this._isContextReady = true;
|
|
843
|
-
this.notify();
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
async loadUserOrganisations() {
|
|
847
|
-
const callId = Math.random().toString(36).substr(2, 9);
|
|
848
|
-
logger.debug("OrganisationService", `Starting loadUserOrganisations call ${callId}`);
|
|
849
|
-
if (!this.user || !this.session || !this.supabaseClient) {
|
|
850
|
-
this._selectedOrganisation = null;
|
|
851
|
-
this._organisations = [];
|
|
852
|
-
this._userMemberships = [];
|
|
853
|
-
this._isLoading = false;
|
|
854
|
-
this._error = null;
|
|
855
|
-
this.notify();
|
|
856
|
-
return;
|
|
857
|
-
}
|
|
858
|
-
if (this.isLoadingRef) {
|
|
859
|
-
logger.debug("OrganisationService", "Already loading, skipping duplicate load");
|
|
860
|
-
this._isLoading = true;
|
|
861
|
-
this.notify();
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
const now = Date.now();
|
|
865
|
-
if (now - this.lastLoadTimeRef < 2e3) {
|
|
866
|
-
logger.debug("OrganisationService", "Too soon since last load, skipping");
|
|
867
|
-
if (this._organisations.length > 0 || this._selectedOrganisation) {
|
|
868
|
-
this._isLoading = false;
|
|
869
|
-
} else {
|
|
870
|
-
this._isLoading = true;
|
|
871
|
-
}
|
|
872
|
-
this.notify();
|
|
873
|
-
return;
|
|
874
|
-
}
|
|
875
|
-
if (this.abortControllerRef) {
|
|
876
|
-
this.abortControllerRef.abort();
|
|
877
|
-
}
|
|
878
|
-
this.abortControllerRef = new AbortController();
|
|
879
|
-
const abortSignal = this.abortControllerRef.signal;
|
|
880
|
-
this.lastLoadTimeRef = now;
|
|
881
|
-
this.isLoadingRef = true;
|
|
882
|
-
this._isLoading = true;
|
|
883
|
-
this._error = null;
|
|
884
|
-
this.notify();
|
|
885
|
-
try {
|
|
886
|
-
logger.debug("OrganisationService", "Supabase client ready:", {
|
|
887
|
-
isConnected: !!this.supabaseClient,
|
|
888
|
-
hasAuth: !!this.supabaseClient.auth,
|
|
889
|
-
hasRpc: !!this.supabaseClient.rpc
|
|
890
|
-
});
|
|
891
|
-
let memberships, membershipError;
|
|
892
|
-
try {
|
|
893
|
-
logger.debug("OrganisationService", "Making RPC call to data_user_organisation_roles_get...");
|
|
894
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
895
|
-
const timeoutId = setTimeout(() => reject(new Error("RPC call timeout after 10 seconds")), 1e4);
|
|
896
|
-
abortSignal.addEventListener("abort", () => {
|
|
897
|
-
clearTimeout(timeoutId);
|
|
898
|
-
reject(new Error("Request aborted"));
|
|
899
|
-
});
|
|
900
|
-
});
|
|
901
|
-
const rpcPromise = this.supabaseClient.rpc("data_user_organisation_roles_get", {
|
|
902
|
-
p_user_id: this.user.id,
|
|
903
|
-
p_organisation_id: null
|
|
904
|
-
});
|
|
905
|
-
if (abortSignal.aborted) {
|
|
906
|
-
throw new Error("Request aborted");
|
|
907
|
-
}
|
|
908
|
-
const result = await Promise.race([rpcPromise, timeoutPromise]);
|
|
909
|
-
logger.debug("OrganisationService", "RPC call completed:", {
|
|
910
|
-
hasData: !!result.data,
|
|
911
|
-
hasError: !!result.error,
|
|
912
|
-
dataLength: result.data?.length || 0,
|
|
913
|
-
errorMessage: result.error?.message || "No error"
|
|
914
|
-
});
|
|
915
|
-
memberships = result.data?.filter(
|
|
916
|
-
(role) => ["org_admin", "leader", "member"].includes(role.role)
|
|
917
|
-
) || [];
|
|
918
|
-
membershipError = result.error;
|
|
919
|
-
} catch (queryError) {
|
|
920
|
-
membershipError = queryError;
|
|
921
|
-
}
|
|
922
|
-
if (membershipError) {
|
|
923
|
-
logger.error("OrganisationService", "Error loading memberships:", membershipError);
|
|
924
|
-
if (membershipError.message?.includes("timeout")) {
|
|
925
|
-
logger.debug("OrganisationService", "RPC timed out, trying direct database query as fallback...");
|
|
926
|
-
try {
|
|
927
|
-
if (abortSignal.aborted) {
|
|
928
|
-
throw new Error("Request aborted");
|
|
929
|
-
}
|
|
930
|
-
const { data: fallbackData, error: fallbackError } = await this.supabaseClient.from("rbac_organisation_roles").select(`
|
|
931
|
-
id,
|
|
932
|
-
user_id,
|
|
933
|
-
organisation_id,
|
|
934
|
-
role,
|
|
935
|
-
status,
|
|
936
|
-
granted_at,
|
|
937
|
-
granted_by,
|
|
938
|
-
revoked_at,
|
|
939
|
-
revoked_by,
|
|
940
|
-
notes,
|
|
941
|
-
created_at,
|
|
942
|
-
updated_at,
|
|
943
|
-
organisations!inner(
|
|
944
|
-
id,
|
|
945
|
-
name,
|
|
946
|
-
display_name,
|
|
947
|
-
subscription_tier,
|
|
948
|
-
settings,
|
|
949
|
-
is_active,
|
|
950
|
-
parent_id,
|
|
951
|
-
created_at,
|
|
952
|
-
updated_at
|
|
953
|
-
)
|
|
954
|
-
`).eq("user_id", this.user.id).eq("status", "active").is("revoked_at", null).in("role", ["org_admin", "leader", "member"]);
|
|
955
|
-
if (fallbackError) {
|
|
956
|
-
logger.error("OrganisationService", "Fallback query also failed:", fallbackError);
|
|
957
|
-
throw membershipError;
|
|
958
|
-
}
|
|
959
|
-
logger.debug("OrganisationService", "Fallback query successful, got", fallbackData?.length || 0, "memberships");
|
|
960
|
-
memberships = fallbackData || [];
|
|
961
|
-
membershipError = null;
|
|
962
|
-
} catch (fallbackErr) {
|
|
963
|
-
logger.error("OrganisationService", "Fallback query failed:", fallbackErr);
|
|
964
|
-
throw membershipError;
|
|
965
|
-
}
|
|
966
|
-
} else {
|
|
967
|
-
throw membershipError;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
if (!memberships || memberships.length === 0) {
|
|
971
|
-
throw new Error("User has no active organisation memberships");
|
|
972
|
-
}
|
|
973
|
-
const organisationIds = memberships.map((m) => m.organisation_id).filter((id) => {
|
|
974
|
-
if (!id || typeof id !== "string") {
|
|
975
|
-
logger.warn("OrganisationService", "Invalid organisation ID (not string):", id);
|
|
976
|
-
return false;
|
|
977
|
-
}
|
|
978
|
-
const trimmedId = id.trim();
|
|
979
|
-
if (trimmedId === "") {
|
|
980
|
-
logger.warn("OrganisationService", "Empty organisation ID found");
|
|
981
|
-
return false;
|
|
982
|
-
}
|
|
983
|
-
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);
|
|
984
|
-
if (!isValidUuid) {
|
|
985
|
-
logger.warn("OrganisationService", "Invalid UUID format:", trimmedId);
|
|
986
|
-
}
|
|
987
|
-
return isValidUuid;
|
|
988
|
-
});
|
|
989
|
-
if (organisationIds.length === 0) {
|
|
990
|
-
logger.warn("OrganisationService", "No valid organisation IDs found in memberships:", memberships);
|
|
991
|
-
throw new Error("No valid organisation IDs found in memberships");
|
|
992
|
-
}
|
|
993
|
-
if (abortSignal.aborted) {
|
|
994
|
-
throw new Error("Request aborted");
|
|
995
|
-
}
|
|
996
|
-
const { data: allOrganisations, error: orgError } = await this.supabaseClient.from("organisations").select("id, name, display_name, subscription_tier, settings, is_active, parent_id, created_at, updated_at");
|
|
997
|
-
if (orgError) {
|
|
998
|
-
logger.error("OrganisationService", "Error loading organisations:", orgError);
|
|
999
|
-
throw orgError;
|
|
1000
|
-
}
|
|
1001
|
-
const organisations = allOrganisations?.filter(
|
|
1002
|
-
(org) => organisationIds.includes(org.id)
|
|
1003
|
-
) || [];
|
|
1004
|
-
const roleMap = /* @__PURE__ */ new Map();
|
|
1005
|
-
memberships?.forEach((membership) => {
|
|
1006
|
-
roleMap.set(membership.organisation_id, membership.role);
|
|
1007
|
-
});
|
|
1008
|
-
const orgs = organisations;
|
|
1009
|
-
const activeOrgs = orgs.filter((org) => org.is_active);
|
|
1010
|
-
if (activeOrgs.length === 0) {
|
|
1011
|
-
throw new Error("User has no access to active organisations");
|
|
1012
|
-
}
|
|
1013
|
-
this._organisations = activeOrgs;
|
|
1014
|
-
this._userMemberships = memberships;
|
|
1015
|
-
this._roleMapState = roleMap;
|
|
1016
|
-
let initialOrg = null;
|
|
1017
|
-
try {
|
|
1018
|
-
const persistedOrgString = localStorage.getItem("pace-core-selected-organisation");
|
|
1019
|
-
if (persistedOrgString) {
|
|
1020
|
-
const persistedOrg = JSON.parse(persistedOrgString);
|
|
1021
|
-
if (persistedOrg.id && typeof persistedOrg.id === "string" && persistedOrg.id.trim() !== "") {
|
|
1022
|
-
const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
|
|
1023
|
-
if (validPersistedOrg) {
|
|
1024
|
-
initialOrg = validPersistedOrg;
|
|
1025
|
-
} else {
|
|
1026
|
-
logger.warn("OrganisationService", "Persisted organisation not found in active orgs, clearing cache");
|
|
1027
|
-
localStorage.removeItem("pace-core-selected-organisation");
|
|
1028
|
-
}
|
|
1029
|
-
} else {
|
|
1030
|
-
logger.warn("OrganisationService", "Invalid persisted organisation ID, clearing cache");
|
|
1031
|
-
localStorage.removeItem("pace-core-selected-organisation");
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
} catch (storageError) {
|
|
1035
|
-
logger.warn("OrganisationService", "Failed to restore persisted organisation:", storageError);
|
|
1036
|
-
localStorage.removeItem("pace-core-selected-organisation");
|
|
1037
|
-
}
|
|
1038
|
-
if (!initialOrg) {
|
|
1039
|
-
const adminMembership = memberships.find((m) => m.role === "org_admin");
|
|
1040
|
-
if (adminMembership) {
|
|
1041
|
-
const foundOrg = organisations.find((org) => org.id === adminMembership.organisation_id);
|
|
1042
|
-
if (foundOrg) {
|
|
1043
|
-
initialOrg = foundOrg;
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
if (!initialOrg) {
|
|
1048
|
-
initialOrg = activeOrgs[0];
|
|
1049
|
-
}
|
|
1050
|
-
if (!initialOrg) {
|
|
1051
|
-
throw new Error("No valid organisation found for user");
|
|
1052
|
-
}
|
|
1053
|
-
this._selectedOrganisation = initialOrg;
|
|
1054
|
-
localStorage.setItem("pace-core-selected-organisation", JSON.stringify(initialOrg));
|
|
1055
|
-
await this.setDatabaseOrganisationContext(initialOrg);
|
|
1056
|
-
this.retryCount = 0;
|
|
1057
|
-
this.hasFailedRef = false;
|
|
1058
|
-
} catch (err) {
|
|
1059
|
-
logger.error("OrganisationService", "Failed to load organisations:", err);
|
|
1060
|
-
this._error = err;
|
|
1061
|
-
this.retryCount = this.retryCount + 1;
|
|
1062
|
-
this.hasFailedRef = true;
|
|
1063
|
-
this.clearAllCachedData();
|
|
1064
|
-
} finally {
|
|
1065
|
-
this.isLoadingRef = false;
|
|
1066
|
-
this._isLoading = false;
|
|
1067
|
-
this.abortControllerRef = null;
|
|
1068
|
-
this.notify();
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
clearAllCachedData() {
|
|
1072
|
-
localStorage.removeItem("pace-core-selected-organisation");
|
|
1073
|
-
localStorage.removeItem("pace-core-organisation-context");
|
|
1074
|
-
this._selectedOrganisation = null;
|
|
1075
|
-
this._organisations = [];
|
|
1076
|
-
this._userMemberships = [];
|
|
1077
|
-
this._roleMapState = /* @__PURE__ */ new Map();
|
|
1078
|
-
this.retryCount = 0;
|
|
1079
|
-
this._isContextReady = false;
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
|
-
// src/providers/services/OrganisationServiceProvider.tsx
|
|
1086
|
-
import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2, useEffect as useEffect2, useRef } from "react";
|
|
1087
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1088
|
-
function OrganisationServiceProvider({
|
|
1089
|
-
children,
|
|
1090
|
-
supabaseClient,
|
|
1091
|
-
user,
|
|
1092
|
-
session
|
|
1093
|
-
}) {
|
|
1094
|
-
const organisationServiceRef = useRef(null);
|
|
1095
|
-
if (!organisationServiceRef.current) {
|
|
1096
|
-
organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);
|
|
1097
|
-
}
|
|
1098
|
-
const organisationService = organisationServiceRef.current;
|
|
1099
|
-
useEffect2(() => {
|
|
1100
|
-
organisationService.updateDependencies(user, session);
|
|
1101
|
-
let isMounted = true;
|
|
1102
|
-
organisationService.initialize().catch((error) => {
|
|
1103
|
-
if (isMounted) {
|
|
1104
|
-
logger.error("OrganisationServiceProvider", "Failed to initialize organisation service:", error);
|
|
1105
|
-
}
|
|
1106
|
-
});
|
|
1107
|
-
return () => {
|
|
1108
|
-
isMounted = false;
|
|
1109
|
-
};
|
|
1110
|
-
}, [organisationService, user, session]);
|
|
1111
|
-
const contextValue = useMemo2(() => ({
|
|
1112
|
-
organisationService
|
|
1113
|
-
}), [organisationService]);
|
|
1114
|
-
return /* @__PURE__ */ jsx2(OrganisationServiceContext.Provider, { value: contextValue, children });
|
|
1115
|
-
}
|
|
1116
|
-
var OrganisationServiceContext, useOrganisationService;
|
|
1117
|
-
var init_OrganisationServiceProvider = __esm({
|
|
1118
|
-
"src/providers/services/OrganisationServiceProvider.tsx"() {
|
|
1119
|
-
"use strict";
|
|
1120
|
-
init_OrganisationService();
|
|
1121
|
-
init_logger();
|
|
1122
|
-
OrganisationServiceContext = createContext2(null);
|
|
1123
|
-
useOrganisationService = () => {
|
|
1124
|
-
const context = useContext2(OrganisationServiceContext);
|
|
1125
|
-
if (!context) {
|
|
1126
|
-
throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
|
|
1127
|
-
}
|
|
1128
|
-
return context.organisationService;
|
|
1129
|
-
};
|
|
1130
|
-
}
|
|
1131
|
-
});
|
|
1132
|
-
|
|
1133
|
-
// src/services/EventService.ts
|
|
1134
|
-
var EventService;
|
|
1135
|
-
var init_EventService = __esm({
|
|
1136
|
-
"src/services/EventService.ts"() {
|
|
1137
|
-
"use strict";
|
|
1138
|
-
init_BaseService();
|
|
1139
|
-
init_logger();
|
|
1140
|
-
init_secureStorage();
|
|
1141
|
-
EventService = class extends BaseService {
|
|
1142
|
-
constructor(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
|
|
1143
|
-
super();
|
|
1144
|
-
this.events = [];
|
|
1145
|
-
this.selectedEvent = null;
|
|
1146
|
-
this._isLoading = false;
|
|
1147
|
-
// Start as false to avoid blocking UI
|
|
1148
|
-
this.error = null;
|
|
1149
|
-
// Dependencies
|
|
1150
|
-
this.supabaseClient = null;
|
|
1151
|
-
this.user = null;
|
|
1152
|
-
this.session = null;
|
|
1153
|
-
this.appName = "";
|
|
1154
|
-
this.selectedOrganisation = null;
|
|
1155
|
-
this.setSelectedEventId = null;
|
|
1156
|
-
// Internal state management
|
|
1157
|
-
this.isInitializedRef = false;
|
|
1158
|
-
this.isFetchingRef = false;
|
|
1159
|
-
this.hasAutoSelectedRef = false;
|
|
1160
|
-
this.userClearedEventRef = false;
|
|
1161
|
-
this.supabaseClient = supabaseClient;
|
|
1162
|
-
this.user = user;
|
|
1163
|
-
this.session = session;
|
|
1164
|
-
this.appName = appName;
|
|
1165
|
-
this.selectedOrganisation = selectedOrganisation;
|
|
1166
|
-
this.setSelectedEventId = setSelectedEventId;
|
|
1167
|
-
}
|
|
1168
|
-
// Helper method to get user-scoped storage key
|
|
1169
|
-
getStorageKey(userId) {
|
|
1170
|
-
if (!userId) {
|
|
1171
|
-
return "pace-core-selected-event-no-user";
|
|
1172
|
-
}
|
|
1173
|
-
return `pace-core-selected-event-${userId}`;
|
|
1174
|
-
}
|
|
1175
|
-
// Update dependencies
|
|
1176
|
-
async updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
|
|
1177
|
-
const previousOrgId = this.selectedOrganisation?.id;
|
|
1178
|
-
const newOrgId = selectedOrganisation?.id;
|
|
1179
|
-
const previousUserId = this.user?.id || null;
|
|
1180
|
-
const newUserId = user?.id || null;
|
|
1181
|
-
if (previousUserId !== newUserId) {
|
|
1182
|
-
if (previousUserId !== null) {
|
|
1183
|
-
await this.clearEventSelectionForUser(previousUserId);
|
|
1184
|
-
}
|
|
1185
|
-
if (newUserId === null) {
|
|
1186
|
-
this.selectedEvent = null;
|
|
1187
|
-
this.setSelectedEventId?.(null);
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
this.supabaseClient = supabaseClient;
|
|
1191
|
-
this.user = user;
|
|
1192
|
-
this.session = session;
|
|
1193
|
-
this.appName = appName;
|
|
1194
|
-
this.selectedOrganisation = selectedOrganisation;
|
|
1195
|
-
this.setSelectedEventId = setSelectedEventId;
|
|
1196
|
-
if (previousOrgId !== newOrgId) {
|
|
1197
|
-
this.resetInitialization();
|
|
1198
|
-
this.isInitializedRef = false;
|
|
1199
|
-
this.isFetchingRef = false;
|
|
1200
|
-
if (previousOrgId !== null && newOrgId !== previousOrgId) {
|
|
1201
|
-
this.events = [];
|
|
1202
|
-
this.selectedEvent = null;
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
this.notify();
|
|
1206
|
-
}
|
|
1207
|
-
// Event state getters
|
|
1208
|
-
getEvents() {
|
|
1209
|
-
return this.events;
|
|
1210
|
-
}
|
|
1211
|
-
getSelectedEvent() {
|
|
1212
|
-
return this.selectedEvent;
|
|
1213
|
-
}
|
|
1214
|
-
isLoading() {
|
|
1215
|
-
return this._isLoading;
|
|
1216
|
-
}
|
|
1217
|
-
getError() {
|
|
1218
|
-
return this.error;
|
|
1219
|
-
}
|
|
1220
|
-
// Event methods
|
|
1221
|
-
setSelectedEvent(event) {
|
|
1222
|
-
if (event) {
|
|
1223
|
-
try {
|
|
1224
|
-
if (this.selectedOrganisation && event.organisation_id !== this.selectedOrganisation.id) {
|
|
1225
|
-
logger.error("EventService", "Event organisation_id does not match selected organisation", {
|
|
1226
|
-
eventOrganisationId: event.organisation_id,
|
|
1227
|
-
selectedOrganisationId: this.selectedOrganisation.id,
|
|
1228
|
-
eventName: event.event_name
|
|
1229
|
-
});
|
|
1230
|
-
return;
|
|
1231
|
-
}
|
|
1232
|
-
} catch (error) {
|
|
1233
|
-
logger.error("EventService", "Error during event validation:", error);
|
|
1234
|
-
}
|
|
1235
|
-
this.selectedEvent = event;
|
|
1236
|
-
this.setSelectedEventId?.(event.event_id);
|
|
1237
|
-
this.persistEventSelection(event.event_id).catch((error) => {
|
|
1238
|
-
logger.warn("EventService", "Failed to persist event selection:", error);
|
|
1239
|
-
});
|
|
1240
|
-
this.userClearedEventRef = false;
|
|
1241
|
-
} else {
|
|
1242
|
-
this.selectedEvent = null;
|
|
1243
|
-
this.setSelectedEventId?.(null);
|
|
1244
|
-
this.clearEventSelection().catch((error) => {
|
|
1245
|
-
logger.warn("EventService", "Failed to clear event selection:", error);
|
|
1246
|
-
});
|
|
1247
|
-
this.hasAutoSelectedRef = false;
|
|
1248
|
-
this.userClearedEventRef = true;
|
|
1249
|
-
}
|
|
1250
|
-
this.notify();
|
|
1251
|
-
}
|
|
1252
|
-
async refreshEvents() {
|
|
1253
|
-
this.isInitializedRef = false;
|
|
1254
|
-
this.isFetchingRef = false;
|
|
1255
|
-
await this.fetchEvents();
|
|
1256
|
-
}
|
|
1257
|
-
async loadPersistedEvent(events) {
|
|
1258
|
-
try {
|
|
1259
|
-
const userId = this.user?.id || null;
|
|
1260
|
-
if (!userId) {
|
|
1261
|
-
return false;
|
|
1262
|
-
}
|
|
1263
|
-
const storageKey = this.getStorageKey(userId);
|
|
1264
|
-
const persistedEventId = await secureStorage.getItem(storageKey);
|
|
1265
|
-
if (persistedEventId && events.length > 0) {
|
|
1266
|
-
const persistedEvent = events.find((event) => event.event_id === persistedEventId);
|
|
1267
|
-
if (persistedEvent) {
|
|
1268
|
-
this.setSelectedEvent(persistedEvent);
|
|
1269
|
-
return true;
|
|
1270
|
-
} else {
|
|
1271
|
-
await secureStorage.removeItem(storageKey);
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
} catch (error) {
|
|
1275
|
-
logger.warn("EventService", "Failed to load persisted event:", error);
|
|
1276
|
-
}
|
|
1277
|
-
return false;
|
|
1278
|
-
}
|
|
1279
|
-
/**
|
|
1280
|
-
* Restore persisted event after login screen has rendered
|
|
1281
|
-
* This should be called explicitly from login page component
|
|
1282
|
-
*
|
|
1283
|
-
* @returns Promise<boolean> - true if event was successfully restored, false otherwise
|
|
1284
|
-
*/
|
|
1285
|
-
async restorePersistedEvent() {
|
|
1286
|
-
if (this.events.length === 0) {
|
|
1287
|
-
return false;
|
|
1288
|
-
}
|
|
1289
|
-
return await this.loadPersistedEvent(this.events);
|
|
1290
|
-
}
|
|
1291
|
-
async persistEventSelection(eventId) {
|
|
1292
|
-
try {
|
|
1293
|
-
const userId = this.user?.id || null;
|
|
1294
|
-
const storageKey = this.getStorageKey(userId);
|
|
1295
|
-
await secureStorage.setItem(storageKey, eventId, { encrypt: true });
|
|
1296
|
-
} catch (error) {
|
|
1297
|
-
logger.warn("EventService", "Failed to persist event selection:", error);
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
async clearEventSelection() {
|
|
1301
|
-
try {
|
|
1302
|
-
const userId = this.user?.id || null;
|
|
1303
|
-
const storageKey = this.getStorageKey(userId);
|
|
1304
|
-
await secureStorage.removeItem(storageKey);
|
|
1305
|
-
this.selectedEvent = null;
|
|
1306
|
-
this.setSelectedEventId?.(null);
|
|
1307
|
-
} catch (error) {
|
|
1308
|
-
logger.warn("EventService", "Failed to clear event selection:", error);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
/**
|
|
1312
|
-
* Clear event selection for a specific user (used when user logs out or changes)
|
|
1313
|
-
*/
|
|
1314
|
-
async clearEventSelectionForUser(userId) {
|
|
1315
|
-
try {
|
|
1316
|
-
if (!userId) return;
|
|
1317
|
-
const storageKey = this.getStorageKey(userId);
|
|
1318
|
-
await secureStorage.removeItem(storageKey);
|
|
1319
|
-
} catch (error) {
|
|
1320
|
-
logger.warn("EventService", "Failed to clear event selection for user:", error);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
autoSelectNextEvent(events) {
|
|
1324
|
-
const nextEvent = this.getNextEventByDate(events);
|
|
1325
|
-
if (nextEvent) {
|
|
1326
|
-
this.setSelectedEvent(nextEvent);
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
// Lifecycle methods
|
|
1330
|
-
async initialize() {
|
|
1331
|
-
await super.initialize();
|
|
1332
|
-
try {
|
|
1333
|
-
if (typeof sessionStorage !== "undefined") {
|
|
1334
|
-
sessionStorage.removeItem("pace-core-selected-event");
|
|
1335
|
-
}
|
|
1336
|
-
if (typeof localStorage !== "undefined") {
|
|
1337
|
-
localStorage.removeItem("pace-core-selected-event");
|
|
1338
|
-
localStorage.removeItem("_sec_pace-core-selected-event");
|
|
1339
|
-
}
|
|
1340
|
-
} catch (error) {
|
|
1341
|
-
logger.warn("EventService", "Failed to clean up old storage keys:", error);
|
|
1342
|
-
}
|
|
1343
|
-
await this.fetchEvents(false);
|
|
1344
|
-
}
|
|
1345
|
-
cleanup() {
|
|
1346
|
-
super.cleanup();
|
|
1347
|
-
}
|
|
1348
|
-
async doInitialize() {
|
|
1349
|
-
await this.fetchEvents();
|
|
1350
|
-
}
|
|
1351
|
-
doCleanup() {
|
|
1352
|
-
}
|
|
1353
|
-
async fetchEvents(skipLoadPersisted = false) {
|
|
1354
|
-
if (!this.user || !this.session || !this.supabaseClient || !this.appName || !this.selectedOrganisation) {
|
|
1355
|
-
this.notify();
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
this._isLoading = true;
|
|
1359
|
-
this.notify();
|
|
1360
|
-
if (this.isFetchingRef) {
|
|
1361
|
-
return;
|
|
1362
|
-
}
|
|
1363
|
-
this.isFetchingRef = true;
|
|
1364
|
-
let isMounted = true;
|
|
1365
|
-
try {
|
|
1366
|
-
logger.debug("EventService", "Fetching events with params:", {
|
|
1367
|
-
p_user_id: this.user.id,
|
|
1368
|
-
p_organisation_id: this.selectedOrganisation.id,
|
|
1369
|
-
p_app_name: this.appName
|
|
1370
|
-
});
|
|
1371
|
-
const { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
|
|
1372
|
-
p_user_id: this.user.id,
|
|
1373
|
-
p_organisation_id: this.selectedOrganisation.id,
|
|
1374
|
-
p_app_name: this.appName
|
|
1375
|
-
});
|
|
1376
|
-
logger.debug("EventService", "RPC call completed:", {
|
|
1377
|
-
hasData: !!data,
|
|
1378
|
-
dataLength: Array.isArray(data) ? data.length : 0,
|
|
1379
|
-
hasError: !!rpcError,
|
|
1380
|
-
errorMessage: rpcError?.message || "No error"
|
|
1381
|
-
});
|
|
1382
|
-
if (rpcError) {
|
|
1383
|
-
logger.error("EventService", "RPC error fetching events:", rpcError);
|
|
1384
|
-
throw new Error(rpcError.message || "Failed to fetch events");
|
|
1385
|
-
}
|
|
1386
|
-
if (isMounted) {
|
|
1387
|
-
const eventsData = data || [];
|
|
1388
|
-
const transformedEvents = eventsData.map((event) => ({
|
|
1389
|
-
id: event.event_id,
|
|
1390
|
-
// Use event_id as the primary id
|
|
1391
|
-
event_id: event.event_id,
|
|
1392
|
-
event_name: event.event_name,
|
|
1393
|
-
event_code: event.event_code,
|
|
1394
|
-
event_date: event.event_date,
|
|
1395
|
-
event_venue: event.event_venue,
|
|
1396
|
-
event_participants: event.event_participants,
|
|
1397
|
-
event_colours: event.event_colours,
|
|
1398
|
-
event_logo: "",
|
|
1399
|
-
// No logo field in event table
|
|
1400
|
-
organisation_id: event.organisation_id,
|
|
1401
|
-
is_visible: event.is_visible,
|
|
1402
|
-
// Legacy compatibility
|
|
1403
|
-
name: event.event_name,
|
|
1404
|
-
start_date: event.event_date
|
|
1405
|
-
}));
|
|
1406
|
-
this.events = transformedEvents;
|
|
1407
|
-
this.error = null;
|
|
1408
|
-
this.hasAutoSelectedRef = false;
|
|
1409
|
-
if (!skipLoadPersisted) {
|
|
1410
|
-
const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
|
|
1411
|
-
if (!persistedEventLoaded && !this.userClearedEventRef) {
|
|
1412
|
-
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
1413
|
-
if (nextEvent) {
|
|
1414
|
-
this.hasAutoSelectedRef = true;
|
|
1415
|
-
this.setSelectedEvent(nextEvent);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
} else {
|
|
1419
|
-
if (!this.userClearedEventRef) {
|
|
1420
|
-
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
1421
|
-
if (nextEvent) {
|
|
1422
|
-
this.hasAutoSelectedRef = true;
|
|
1423
|
-
this.setSelectedEvent(nextEvent);
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
} catch (err) {
|
|
1429
|
-
logger.error("EventService", "Error fetching events:", err);
|
|
1430
|
-
const _error = err instanceof Error ? err : new Error("Unknown error occurred");
|
|
1431
|
-
if (isMounted) {
|
|
1432
|
-
this.error = _error;
|
|
1433
|
-
this.events = [];
|
|
1434
|
-
}
|
|
1435
|
-
} finally {
|
|
1436
|
-
if (isMounted) {
|
|
1437
|
-
this._isLoading = false;
|
|
1438
|
-
}
|
|
1439
|
-
this.isFetchingRef = false;
|
|
1440
|
-
this.notify();
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
getNextEventByDate(events) {
|
|
1444
|
-
const eventsToUse = events || this.events;
|
|
1445
|
-
if (!eventsToUse || eventsToUse.length === 0) {
|
|
1446
|
-
return null;
|
|
1447
|
-
}
|
|
1448
|
-
const now = /* @__PURE__ */ new Date();
|
|
1449
|
-
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
|
1450
|
-
const futureEvents = eventsToUse.filter((event) => {
|
|
1451
|
-
if (!event.event_date) return false;
|
|
1452
|
-
const eventDate = new Date(event.event_date);
|
|
1453
|
-
const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
|
|
1454
|
-
return startOfEventDate >= startOfToday;
|
|
1455
|
-
});
|
|
1456
|
-
if (futureEvents.length > 0) {
|
|
1457
|
-
const sortedFutureEvents = futureEvents.sort((a, b) => {
|
|
1458
|
-
const dateA = new Date(a.event_date);
|
|
1459
|
-
const dateB = new Date(b.event_date);
|
|
1460
|
-
return dateA.getTime() - dateB.getTime();
|
|
1461
|
-
});
|
|
1462
|
-
return sortedFutureEvents[0];
|
|
1463
|
-
}
|
|
1464
|
-
const pastEvents = eventsToUse.filter((event) => {
|
|
1465
|
-
if (!event.event_date) return false;
|
|
1466
|
-
const eventDate = new Date(event.event_date);
|
|
1467
|
-
const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
|
|
1468
|
-
return startOfEventDate < startOfToday;
|
|
1469
|
-
});
|
|
1470
|
-
if (pastEvents.length > 0) {
|
|
1471
|
-
const sortedPastEvents = pastEvents.sort((a, b) => {
|
|
1472
|
-
const dateA = new Date(a.event_date);
|
|
1473
|
-
const dateB = new Date(b.event_date);
|
|
1474
|
-
return dateB.getTime() - dateA.getTime();
|
|
1475
|
-
});
|
|
1476
|
-
return sortedPastEvents[0];
|
|
1477
|
-
}
|
|
1478
|
-
return null;
|
|
1479
|
-
}
|
|
1480
|
-
};
|
|
1481
|
-
}
|
|
1482
|
-
});
|
|
1483
|
-
|
|
1484
|
-
// src/providers/services/EventServiceProvider.tsx
|
|
1485
|
-
import { createContext as createContext3, useContext as useContext3, useMemo as useMemo3, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
1486
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1487
|
-
function EventServiceProvider({
|
|
1488
|
-
children,
|
|
1489
|
-
supabaseClient,
|
|
1490
|
-
user,
|
|
1491
|
-
session,
|
|
1492
|
-
appName,
|
|
1493
|
-
selectedOrganisation,
|
|
1494
|
-
setSelectedEventId
|
|
1495
|
-
}) {
|
|
1496
|
-
const eventServiceRef = useRef2(null);
|
|
1497
|
-
if (!eventServiceRef.current) {
|
|
1498
|
-
eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1499
|
-
}
|
|
1500
|
-
const eventService = eventServiceRef.current;
|
|
1501
|
-
useEffect3(() => {
|
|
1502
|
-
let isMounted = true;
|
|
1503
|
-
const updateAndInitialize = async () => {
|
|
1504
|
-
await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1505
|
-
if (!isMounted) return;
|
|
1506
|
-
await eventService.initialize().catch((error) => {
|
|
1507
|
-
if (isMounted) {
|
|
1508
|
-
logger.error("EventServiceProvider", "Failed to initialize event service:", error);
|
|
1509
|
-
}
|
|
1510
|
-
});
|
|
1511
|
-
};
|
|
1512
|
-
updateAndInitialize();
|
|
1513
|
-
return () => {
|
|
1514
|
-
isMounted = false;
|
|
1515
|
-
};
|
|
1516
|
-
}, [eventService, supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);
|
|
1517
|
-
const contextValue = useMemo3(() => ({
|
|
1518
|
-
eventService
|
|
1519
|
-
}), [eventService]);
|
|
1520
|
-
return /* @__PURE__ */ jsx3(EventServiceContext.Provider, { value: contextValue, children });
|
|
1521
|
-
}
|
|
1522
|
-
var EventServiceContext, useEventService;
|
|
1523
|
-
var init_EventServiceProvider = __esm({
|
|
1524
|
-
"src/providers/services/EventServiceProvider.tsx"() {
|
|
1525
|
-
"use strict";
|
|
1526
|
-
init_EventService();
|
|
1527
|
-
init_logger();
|
|
1528
|
-
EventServiceContext = createContext3(null);
|
|
1529
|
-
useEventService = () => {
|
|
1530
|
-
const context = useContext3(EventServiceContext);
|
|
1531
|
-
if (!context) {
|
|
1532
|
-
throw new Error("useEventService must be used within EventServiceProvider");
|
|
1533
|
-
}
|
|
1534
|
-
return context.eventService;
|
|
1535
|
-
};
|
|
1536
|
-
}
|
|
1537
|
-
});
|
|
1538
|
-
|
|
1539
|
-
// src/services/InactivityService.ts
|
|
1540
|
-
var InactivityService;
|
|
1541
|
-
var init_InactivityService = __esm({
|
|
1542
|
-
"src/services/InactivityService.ts"() {
|
|
1543
|
-
"use strict";
|
|
1544
|
-
init_BaseService();
|
|
1545
|
-
init_logger();
|
|
1546
|
-
InactivityService = class extends BaseService {
|
|
1547
|
-
constructor(supabaseClient, user, session, idleTimeoutMs = 30 * 60 * 1e3, warnBeforeMs = 60 * 1e3, onIdleLogout) {
|
|
1548
|
-
super();
|
|
1549
|
-
this._showInactivityWarning = false;
|
|
1550
|
-
this._inactivityTimeRemaining = 0;
|
|
1551
|
-
this._isIdle = false;
|
|
1552
|
-
this._timeRemaining = 0;
|
|
1553
|
-
this._showWarning = false;
|
|
1554
|
-
this._isTracking = false;
|
|
1555
|
-
// Dependencies
|
|
1556
|
-
this.supabaseClient = null;
|
|
1557
|
-
this.user = null;
|
|
1558
|
-
this.session = null;
|
|
1559
|
-
this.idleTimeoutMs = 30 * 60 * 1e3;
|
|
1560
|
-
// 30 minutes
|
|
1561
|
-
this.warnBeforeMs = 60 * 1e3;
|
|
1562
|
-
// 60 seconds
|
|
1563
|
-
this.onIdleLogout = null;
|
|
1564
|
-
// Internal state management
|
|
1565
|
-
this.inactivityTracker = null;
|
|
1566
|
-
this.isInactivityEnabled = true;
|
|
1567
|
-
this.supabaseClient = supabaseClient;
|
|
1568
|
-
this.user = user;
|
|
1569
|
-
this.session = session;
|
|
1570
|
-
this.idleTimeoutMs = idleTimeoutMs;
|
|
1571
|
-
this.warnBeforeMs = warnBeforeMs;
|
|
1572
|
-
this.onIdleLogout = onIdleLogout;
|
|
1573
|
-
this._timeRemaining = idleTimeoutMs;
|
|
1574
|
-
}
|
|
1575
|
-
// Interface implementation
|
|
1576
|
-
isIdle() {
|
|
1577
|
-
return this._isIdle;
|
|
1578
|
-
}
|
|
1579
|
-
getTimeRemaining() {
|
|
1580
|
-
return this._timeRemaining;
|
|
1581
|
-
}
|
|
1582
|
-
isWarningShown() {
|
|
1583
|
-
return this._showWarning;
|
|
1584
|
-
}
|
|
1585
|
-
isTracking() {
|
|
1586
|
-
return this._isTracking;
|
|
1587
|
-
}
|
|
1588
|
-
getShowInactivityWarning() {
|
|
1589
|
-
return this._showInactivityWarning;
|
|
1590
|
-
}
|
|
1591
|
-
getInactivityTimeRemaining() {
|
|
1592
|
-
return this._inactivityTimeRemaining;
|
|
1593
|
-
}
|
|
1594
|
-
// Additional getter methods that tests expect
|
|
1595
|
-
getIsIdle() {
|
|
1596
|
-
return this._isIdle;
|
|
1597
|
-
}
|
|
1598
|
-
getIsTracking() {
|
|
1599
|
-
return this._isTracking;
|
|
1600
|
-
}
|
|
1601
|
-
getShowWarning() {
|
|
1602
|
-
return this._showWarning;
|
|
1603
|
-
}
|
|
1604
|
-
// Additional methods for testing
|
|
1605
|
-
setShowInactivityWarning(value) {
|
|
1606
|
-
this._showInactivityWarning = value;
|
|
1607
|
-
this.notify();
|
|
1608
|
-
}
|
|
1609
|
-
setInactivityTimeRemaining(value) {
|
|
1610
|
-
this._inactivityTimeRemaining = value;
|
|
1611
|
-
this.notify();
|
|
1612
|
-
}
|
|
1613
|
-
setIsIdle(value) {
|
|
1614
|
-
this._isIdle = value;
|
|
1615
|
-
this.notify();
|
|
1616
|
-
}
|
|
1617
|
-
setTimeRemaining(value) {
|
|
1618
|
-
this._timeRemaining = value;
|
|
1619
|
-
this.notify();
|
|
1620
|
-
}
|
|
1621
|
-
setShowWarning(value) {
|
|
1622
|
-
this._showWarning = value;
|
|
1623
|
-
this.notify();
|
|
1624
|
-
}
|
|
1625
|
-
setIsTracking(value) {
|
|
1626
|
-
this._isTracking = value;
|
|
1627
|
-
this.notify();
|
|
1628
|
-
}
|
|
1629
|
-
triggerWarning(timeRemaining) {
|
|
1630
|
-
this._showInactivityWarning = true;
|
|
1631
|
-
this._inactivityTimeRemaining = Math.ceil(timeRemaining / 1e3);
|
|
1632
|
-
this._showWarning = true;
|
|
1633
|
-
this.notify();
|
|
1634
|
-
}
|
|
1635
|
-
triggerIdle() {
|
|
1636
|
-
this._isIdle = true;
|
|
1637
|
-
this.handleIdleLogout();
|
|
1638
|
-
this.notify();
|
|
1639
|
-
}
|
|
1640
|
-
// Update dependencies
|
|
1641
|
-
updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout) {
|
|
1642
|
-
this.supabaseClient = supabaseClient;
|
|
1643
|
-
this.user = user;
|
|
1644
|
-
this.session = session;
|
|
1645
|
-
if (idleTimeoutMs !== void 0) this.idleTimeoutMs = idleTimeoutMs;
|
|
1646
|
-
if (warnBeforeMs !== void 0) this.warnBeforeMs = warnBeforeMs;
|
|
1647
|
-
if (onIdleLogout !== void 0) this.onIdleLogout = onIdleLogout;
|
|
1648
|
-
this.notify();
|
|
1649
|
-
}
|
|
1650
|
-
// Inactivity methods
|
|
1651
|
-
resetActivity() {
|
|
1652
|
-
if (this.inactivityTracker) {
|
|
1653
|
-
this.inactivityTracker.resetActivity();
|
|
1654
|
-
}
|
|
1655
|
-
this._isIdle = false;
|
|
1656
|
-
this._showWarning = false;
|
|
1657
|
-
this._showInactivityWarning = false;
|
|
1658
|
-
this._inactivityTimeRemaining = 0;
|
|
1659
|
-
this._timeRemaining = this.idleTimeoutMs;
|
|
1660
|
-
this.notify();
|
|
1661
|
-
}
|
|
1662
|
-
startTracking() {
|
|
1663
|
-
if (this.inactivityTracker) {
|
|
1664
|
-
this.inactivityTracker.startTracking();
|
|
1665
|
-
}
|
|
1666
|
-
this._isTracking = true;
|
|
1667
|
-
this.notify();
|
|
1668
|
-
}
|
|
1669
|
-
stopTracking() {
|
|
1670
|
-
if (this.inactivityTracker) {
|
|
1671
|
-
this.inactivityTracker.stopTracking();
|
|
1672
|
-
}
|
|
1673
|
-
this._isTracking = false;
|
|
1674
|
-
this.notify();
|
|
1675
|
-
}
|
|
1676
|
-
async handleIdleLogout() {
|
|
1677
|
-
this._showInactivityWarning = false;
|
|
1678
|
-
this._inactivityTimeRemaining = 0;
|
|
1679
|
-
this.stopTracking();
|
|
1680
|
-
try {
|
|
1681
|
-
if (this.supabaseClient) {
|
|
1682
|
-
await this.supabaseClient.auth.signOut();
|
|
1683
|
-
}
|
|
1684
|
-
} catch (error) {
|
|
1685
|
-
logger.error("InactivityService", "Error during idle logout:", error);
|
|
1686
|
-
}
|
|
1687
|
-
this.onIdleLogout?.("inactivity");
|
|
1688
|
-
this.notify();
|
|
1689
|
-
}
|
|
1690
|
-
handleStaySignedIn() {
|
|
1691
|
-
this._showInactivityWarning = false;
|
|
1692
|
-
this._inactivityTimeRemaining = 0;
|
|
1693
|
-
this.resetActivity();
|
|
1694
|
-
this.notify();
|
|
1695
|
-
}
|
|
1696
|
-
async handleSignOutNow() {
|
|
1697
|
-
this._showInactivityWarning = false;
|
|
1698
|
-
this._inactivityTimeRemaining = 0;
|
|
1699
|
-
this.stopTracking();
|
|
1700
|
-
try {
|
|
1701
|
-
if (this.supabaseClient) {
|
|
1702
|
-
await this.supabaseClient.auth.signOut();
|
|
1703
|
-
}
|
|
1704
|
-
} catch (error) {
|
|
1705
|
-
logger.error("InactivityService", "Error during manual sign out:", error);
|
|
1706
|
-
}
|
|
1707
|
-
this.onIdleLogout?.("inactivity");
|
|
1708
|
-
this.notify();
|
|
1709
|
-
}
|
|
1710
|
-
// Lifecycle methods
|
|
1711
|
-
async initialize() {
|
|
1712
|
-
await super.initialize();
|
|
1713
|
-
await this.setupInactivityTracker();
|
|
1714
|
-
}
|
|
1715
|
-
cleanup() {
|
|
1716
|
-
if (this.inactivityTracker) {
|
|
1717
|
-
this.inactivityTracker.cleanup?.();
|
|
1718
|
-
this.inactivityTracker = null;
|
|
1719
|
-
}
|
|
1720
|
-
this._isTracking = false;
|
|
1721
|
-
this._isIdle = false;
|
|
1722
|
-
this._showWarning = false;
|
|
1723
|
-
this._showInactivityWarning = false;
|
|
1724
|
-
this._timeRemaining = 0;
|
|
1725
|
-
this._inactivityTimeRemaining = 0;
|
|
1726
|
-
super.cleanup();
|
|
1727
|
-
}
|
|
1728
|
-
async doInitialize() {
|
|
1729
|
-
if (typeof window !== "undefined") {
|
|
1730
|
-
const isProduction = import.meta.env.MODE === "production";
|
|
1731
|
-
if (isProduction) {
|
|
1732
|
-
logger.warn("InactivityService", "Inactivity feature enabled in production");
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
doCleanup() {
|
|
1737
|
-
}
|
|
1738
|
-
async setupInactivityTracker() {
|
|
1739
|
-
if (typeof window === "undefined") return;
|
|
1740
|
-
this.isInactivityEnabled = this.user && this.session;
|
|
1741
|
-
if (!this.isInactivityEnabled) {
|
|
1742
|
-
return;
|
|
1743
|
-
}
|
|
1744
|
-
try {
|
|
1745
|
-
const { useInactivityTracker } = await import("./useInactivityTracker-TO6ZOF35.js");
|
|
1746
|
-
this.inactivityTracker = {
|
|
1747
|
-
isIdle: false,
|
|
1748
|
-
timeRemaining: 0,
|
|
1749
|
-
showWarning: false,
|
|
1750
|
-
isTracking: false,
|
|
1751
|
-
resetActivity: () => {
|
|
1752
|
-
this._isIdle = false;
|
|
1753
|
-
this._timeRemaining = 0;
|
|
1754
|
-
this._showWarning = false;
|
|
1755
|
-
this.notify();
|
|
1756
|
-
},
|
|
1757
|
-
startTracking: () => {
|
|
1758
|
-
this._isTracking = true;
|
|
1759
|
-
this.notify();
|
|
1760
|
-
},
|
|
1761
|
-
stopTracking: () => {
|
|
1762
|
-
this._isTracking = false;
|
|
1763
|
-
this.notify();
|
|
1764
|
-
},
|
|
1765
|
-
cleanup: () => {
|
|
1766
|
-
this._isTracking = false;
|
|
1767
|
-
this._isIdle = false;
|
|
1768
|
-
this._showWarning = false;
|
|
1769
|
-
this._timeRemaining = 0;
|
|
1770
|
-
}
|
|
1771
|
-
};
|
|
1772
|
-
this.setupEventHandlers();
|
|
1773
|
-
} catch (error) {
|
|
1774
|
-
logger.error("InactivityService", "Failed to setup inactivity tracker:", error);
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
setupEventHandlers() {
|
|
1778
|
-
if (typeof window === "undefined") return;
|
|
1779
|
-
let idleTimer = null;
|
|
1780
|
-
let warningTimer = null;
|
|
1781
|
-
let lastActivity = Date.now();
|
|
1782
|
-
const resetTimers = () => {
|
|
1783
|
-
lastActivity = Date.now();
|
|
1784
|
-
if (idleTimer) {
|
|
1785
|
-
clearTimeout(idleTimer);
|
|
1786
|
-
idleTimer = null;
|
|
1787
|
-
}
|
|
1788
|
-
if (warningTimer) {
|
|
1789
|
-
clearTimeout(warningTimer);
|
|
1790
|
-
warningTimer = null;
|
|
1791
|
-
}
|
|
1792
|
-
this._showInactivityWarning = false;
|
|
1793
|
-
this._inactivityTimeRemaining = 0;
|
|
1794
|
-
this._isIdle = false;
|
|
1795
|
-
this._showWarning = false;
|
|
1796
|
-
this.notify();
|
|
1797
|
-
};
|
|
1798
|
-
const startIdleTimer = () => {
|
|
1799
|
-
if (idleTimer) {
|
|
1800
|
-
clearTimeout(idleTimer);
|
|
1801
|
-
}
|
|
1802
|
-
idleTimer = setTimeout(() => {
|
|
1803
|
-
this._isIdle = true;
|
|
1804
|
-
this._showWarning = true;
|
|
1805
|
-
this.notify();
|
|
1806
|
-
warningTimer = setTimeout(() => {
|
|
1807
|
-
this.handleIdleLogout();
|
|
1808
|
-
}, this.warnBeforeMs);
|
|
1809
|
-
}, this.idleTimeoutMs - this.warnBeforeMs);
|
|
1810
|
-
};
|
|
1811
|
-
const startWarningTimer = () => {
|
|
1812
|
-
if (warningTimer) {
|
|
1813
|
-
clearTimeout(warningTimer);
|
|
1814
|
-
}
|
|
1815
|
-
warningTimer = setTimeout(() => {
|
|
1816
|
-
this.handleIdleLogout();
|
|
1817
|
-
}, this.warnBeforeMs);
|
|
1818
|
-
};
|
|
1819
|
-
const activityEvents = ["mousedown", "mousemove", "keypress", "scroll", "touchstart", "click"];
|
|
1820
|
-
const handleActivity = () => {
|
|
1821
|
-
resetTimers();
|
|
1822
|
-
startIdleTimer();
|
|
1823
|
-
};
|
|
1824
|
-
activityEvents.forEach((event) => {
|
|
1825
|
-
document.addEventListener(event, handleActivity, true);
|
|
1826
|
-
});
|
|
1827
|
-
startIdleTimer();
|
|
1828
|
-
this.inactivityTracker.cleanup = () => {
|
|
1829
|
-
if (idleTimer) {
|
|
1830
|
-
clearTimeout(idleTimer);
|
|
1831
|
-
idleTimer = null;
|
|
1832
|
-
}
|
|
1833
|
-
if (warningTimer) {
|
|
1834
|
-
clearTimeout(warningTimer);
|
|
1835
|
-
warningTimer = null;
|
|
1836
|
-
}
|
|
1837
|
-
activityEvents.forEach((event) => {
|
|
1838
|
-
document.removeEventListener(event, handleActivity, true);
|
|
1839
|
-
});
|
|
1840
|
-
this._isTracking = false;
|
|
1841
|
-
this._isIdle = false;
|
|
1842
|
-
this._showWarning = false;
|
|
1843
|
-
this._timeRemaining = 0;
|
|
1844
|
-
this._showInactivityWarning = false;
|
|
1845
|
-
this._inactivityTimeRemaining = 0;
|
|
1846
|
-
};
|
|
1847
|
-
this._isTracking = true;
|
|
1848
|
-
this.notify();
|
|
1849
|
-
}
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
|
-
});
|
|
1853
|
-
|
|
1854
|
-
// src/providers/services/InactivityServiceProvider.tsx
|
|
1855
|
-
import { createContext as createContext4, useContext as useContext4, useMemo as useMemo4, useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
1856
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1857
|
-
function InactivityServiceProvider({
|
|
1858
|
-
children,
|
|
1859
|
-
supabaseClient,
|
|
1860
|
-
user,
|
|
1861
|
-
session,
|
|
1862
|
-
idleTimeoutMs = 30 * 60 * 1e3,
|
|
1863
|
-
warnBeforeMs = 60 * 1e3,
|
|
1864
|
-
onIdleLogout
|
|
1865
|
-
}) {
|
|
1866
|
-
const inactivityServiceRef = useRef3(null);
|
|
1867
|
-
if (!inactivityServiceRef.current) {
|
|
1868
|
-
inactivityServiceRef.current = new InactivityService(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
|
|
1869
|
-
}
|
|
1870
|
-
const inactivityService = inactivityServiceRef.current;
|
|
1871
|
-
useEffect4(() => {
|
|
1872
|
-
inactivityService.updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
|
|
1873
|
-
let isMounted = true;
|
|
1874
|
-
inactivityService.initialize().catch((error) => {
|
|
1875
|
-
if (isMounted) {
|
|
1876
|
-
logger.error("InactivityServiceProvider", "Failed to initialize inactivity service:", error);
|
|
1877
|
-
}
|
|
1878
|
-
});
|
|
1879
|
-
return () => {
|
|
1880
|
-
isMounted = false;
|
|
1881
|
-
};
|
|
1882
|
-
}, [inactivityService, supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout]);
|
|
1883
|
-
const contextValue = useMemo4(() => ({
|
|
1884
|
-
inactivityService
|
|
1885
|
-
}), [inactivityService]);
|
|
1886
|
-
return /* @__PURE__ */ jsx4(InactivityServiceContext.Provider, { value: contextValue, children });
|
|
1887
|
-
}
|
|
1888
|
-
var InactivityServiceContext, useInactivityService;
|
|
1889
|
-
var init_InactivityServiceProvider = __esm({
|
|
1890
|
-
"src/providers/services/InactivityServiceProvider.tsx"() {
|
|
1891
|
-
"use strict";
|
|
1892
|
-
init_InactivityService();
|
|
1893
|
-
init_logger();
|
|
1894
|
-
InactivityServiceContext = createContext4(null);
|
|
1895
|
-
useInactivityService = () => {
|
|
1896
|
-
const context = useContext4(InactivityServiceContext);
|
|
1897
|
-
if (!context) {
|
|
1898
|
-
throw new Error("useInactivityService must be used within InactivityServiceProvider");
|
|
1899
|
-
}
|
|
1900
|
-
return context.inactivityService;
|
|
1901
|
-
};
|
|
1902
|
-
}
|
|
1903
|
-
});
|
|
1904
|
-
|
|
1905
|
-
// src/hooks/services/useAuthService.ts
|
|
1906
|
-
import { useContext as useContext5, useReducer, useEffect as useEffect5 } from "react";
|
|
1907
|
-
function useAuthService2() {
|
|
1908
|
-
const context = useContext5(AuthServiceContext);
|
|
1909
|
-
if (!context) {
|
|
1910
|
-
throw new Error("useAuthService must be used within AuthServiceProvider");
|
|
1911
|
-
}
|
|
1912
|
-
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
1913
|
-
useEffect5(() => {
|
|
1914
|
-
return context.authService.subscribe(() => forceUpdate());
|
|
1915
|
-
}, [context.authService]);
|
|
1916
|
-
return context.authService;
|
|
1917
|
-
}
|
|
1918
|
-
var init_useAuthService = __esm({
|
|
1919
|
-
"src/hooks/services/useAuthService.ts"() {
|
|
1920
|
-
"use strict";
|
|
1921
|
-
init_AuthServiceProvider();
|
|
1922
|
-
}
|
|
1923
|
-
});
|
|
1924
|
-
|
|
1925
|
-
// src/hooks/services/useOrganisationService.ts
|
|
1926
|
-
import { useContext as useContext6, useReducer as useReducer2, useEffect as useEffect6 } from "react";
|
|
1927
|
-
function useOrganisationService2() {
|
|
1928
|
-
const context = useContext6(OrganisationServiceContext);
|
|
1929
|
-
if (!context) {
|
|
1930
|
-
throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
|
|
1931
|
-
}
|
|
1932
|
-
const [, forceUpdate] = useReducer2((x) => x + 1, 0);
|
|
1933
|
-
useEffect6(() => {
|
|
1934
|
-
return context.organisationService.subscribe(() => forceUpdate());
|
|
1935
|
-
}, [context.organisationService]);
|
|
1936
|
-
return context.organisationService;
|
|
1937
|
-
}
|
|
1938
|
-
var init_useOrganisationService = __esm({
|
|
1939
|
-
"src/hooks/services/useOrganisationService.ts"() {
|
|
1940
|
-
"use strict";
|
|
1941
|
-
init_OrganisationServiceProvider();
|
|
1942
|
-
}
|
|
1943
|
-
});
|
|
1944
|
-
|
|
1945
|
-
// src/hooks/services/useEventService.ts
|
|
1946
|
-
import { useContext as useContext7, useReducer as useReducer3, useEffect as useEffect7 } from "react";
|
|
1947
|
-
function useEventService2() {
|
|
1948
|
-
const context = useContext7(EventServiceContext);
|
|
1949
|
-
if (!context) {
|
|
1950
|
-
throw new Error("useEventService must be used within EventServiceProvider");
|
|
1951
|
-
}
|
|
1952
|
-
const [, forceUpdate] = useReducer3((x) => x + 1, 0);
|
|
1953
|
-
useEffect7(() => {
|
|
1954
|
-
return context.eventService.subscribe(() => forceUpdate());
|
|
1955
|
-
}, [context.eventService]);
|
|
1956
|
-
return context.eventService;
|
|
1957
|
-
}
|
|
1958
|
-
var init_useEventService = __esm({
|
|
1959
|
-
"src/hooks/services/useEventService.ts"() {
|
|
1960
|
-
"use strict";
|
|
1961
|
-
init_EventServiceProvider();
|
|
1962
|
-
}
|
|
1963
|
-
});
|
|
1964
|
-
|
|
1965
|
-
// src/hooks/services/useInactivityService.ts
|
|
1966
|
-
import { useContext as useContext8, useReducer as useReducer4, useEffect as useEffect8 } from "react";
|
|
1967
|
-
function useInactivityService2() {
|
|
1968
|
-
const context = useContext8(InactivityServiceContext);
|
|
1969
|
-
if (!context) {
|
|
1970
|
-
throw new Error("useInactivityService must be used within InactivityServiceProvider");
|
|
1971
|
-
}
|
|
1972
|
-
const [, forceUpdate] = useReducer4((x) => x + 1, 0);
|
|
1973
|
-
useEffect8(() => {
|
|
1974
|
-
return context.inactivityService.subscribe(() => forceUpdate());
|
|
1975
|
-
}, [context.inactivityService]);
|
|
1976
|
-
return context.inactivityService;
|
|
1977
|
-
}
|
|
1978
|
-
var init_useInactivityService = __esm({
|
|
1979
|
-
"src/hooks/services/useInactivityService.ts"() {
|
|
1980
|
-
"use strict";
|
|
1981
|
-
init_InactivityServiceProvider();
|
|
1982
|
-
}
|
|
1983
|
-
});
|
|
1984
|
-
|
|
1985
|
-
// src/hooks/useSessionRestoration.ts
|
|
1986
|
-
import { useContext as useContext9, useMemo as useMemo5, useEffect as useEffect9, useState as useState2 } from "react";
|
|
1987
|
-
function useSessionRestoration() {
|
|
1988
|
-
const context = useContext9(AuthServiceContext);
|
|
1989
|
-
if (!context) {
|
|
1990
|
-
throw new Error("useSessionRestoration must be used within AuthServiceProvider");
|
|
1991
|
-
}
|
|
1992
|
-
const { sessionRestoration } = context;
|
|
1993
|
-
const [hasTimedOut, setHasTimedOut] = useState2(false);
|
|
1994
|
-
useEffect9(() => {
|
|
1995
|
-
let timeoutHandle = null;
|
|
1996
|
-
if (sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError) {
|
|
1997
|
-
setHasTimedOut(false);
|
|
1998
|
-
timeoutHandle = setTimeout(() => {
|
|
1999
|
-
log.warn("Session restoration timed out");
|
|
2000
|
-
setHasTimedOut(true);
|
|
2001
|
-
}, SESSION_RESTORATION_TIMEOUT_MS);
|
|
2002
|
-
} else {
|
|
2003
|
-
setHasTimedOut(false);
|
|
2004
|
-
}
|
|
2005
|
-
return () => {
|
|
2006
|
-
if (timeoutHandle) {
|
|
2007
|
-
clearTimeout(timeoutHandle);
|
|
2008
|
-
}
|
|
2009
|
-
};
|
|
2010
|
-
}, [
|
|
2011
|
-
sessionRestoration.isRestoring,
|
|
2012
|
-
sessionRestoration.restorationComplete,
|
|
2013
|
-
sessionRestoration.restorationError
|
|
2014
|
-
]);
|
|
2015
|
-
return useMemo5(() => ({
|
|
2016
|
-
...sessionRestoration,
|
|
2017
|
-
hasTimedOut,
|
|
2018
|
-
timeoutMs: SESSION_RESTORATION_TIMEOUT_MS
|
|
2019
|
-
}), [sessionRestoration, hasTimedOut]);
|
|
2020
|
-
}
|
|
2021
|
-
var log, SESSION_RESTORATION_TIMEOUT_MS;
|
|
2022
|
-
var init_useSessionRestoration = __esm({
|
|
2023
|
-
"src/hooks/useSessionRestoration.ts"() {
|
|
2024
|
-
"use strict";
|
|
2025
|
-
init_AuthServiceProvider();
|
|
2026
|
-
init_logger();
|
|
2027
|
-
log = createLogger("useSessionRestoration");
|
|
2028
|
-
SESSION_RESTORATION_TIMEOUT_MS = 5e3;
|
|
2029
|
-
}
|
|
2030
|
-
});
|
|
2031
|
-
|
|
2032
|
-
// src/providers/services/UnifiedAuthProvider.tsx
|
|
2033
|
-
import { createContext as createContext5, useContext as useContext10, useMemo as useMemo6, useCallback, useRef as useRef4 } from "react";
|
|
2034
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
2035
|
-
function UnifiedAuthContextProvider({
|
|
2036
|
-
children,
|
|
2037
|
-
appName,
|
|
2038
|
-
appConfig = { requires_event: true },
|
|
2039
|
-
// Default to requiring events
|
|
2040
|
-
...props
|
|
2041
|
-
}) {
|
|
2042
|
-
const authService = useAuthService2();
|
|
2043
|
-
const organisationService = useOrganisationService2();
|
|
2044
|
-
const inactivityService = useInactivityService2();
|
|
2045
|
-
const sessionRestorationState = useSessionRestoration();
|
|
2046
|
-
const {
|
|
2047
|
-
hasTimedOut: sessionRestorationTimedOut,
|
|
2048
|
-
timeoutMs: sessionRestorationTimeoutMs,
|
|
2049
|
-
isRestoring,
|
|
2050
|
-
restorationComplete,
|
|
2051
|
-
restorationError
|
|
2052
|
-
} = sessionRestorationState;
|
|
2053
|
-
const sessionRestoration = useMemo6(() => ({
|
|
2054
|
-
isRestoring,
|
|
2055
|
-
restorationComplete,
|
|
2056
|
-
restorationError
|
|
2057
|
-
}), [isRestoring, restorationComplete, restorationError]);
|
|
2058
|
-
let eventService;
|
|
2059
|
-
try {
|
|
2060
|
-
eventService = useEventService2();
|
|
2061
|
-
} catch (error) {
|
|
2062
|
-
eventService = {
|
|
2063
|
-
getEvents: () => [],
|
|
2064
|
-
getSelectedEvent: () => null,
|
|
2065
|
-
isLoading: () => false,
|
|
2066
|
-
getError: () => null,
|
|
2067
|
-
setSelectedEvent: () => {
|
|
2068
|
-
},
|
|
2069
|
-
refreshEvents: async () => {
|
|
2070
|
-
}
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
const currentUser = authService.getUser();
|
|
2074
|
-
const currentSession = authService.getSession();
|
|
2075
|
-
const isAuth = !!(currentUser && currentSession);
|
|
2076
|
-
const authLoading = authService.isLoading();
|
|
2077
|
-
const orgLoading = organisationService.isLoading();
|
|
2078
|
-
const eventLoading = eventService.isLoading();
|
|
2079
|
-
const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;
|
|
2080
|
-
const totalLoading = restorationLoading || authLoading || orgLoading || eventLoading;
|
|
2081
|
-
const authError = authService.getError();
|
|
2082
|
-
const supabase = authService.getSupabaseClient();
|
|
2083
|
-
const selectedOrganisation = organisationService.getSelectedOrganisation();
|
|
2084
|
-
const organisations = organisationService.getOrganisations();
|
|
2085
|
-
const userMemberships = organisationService.getUserMemberships();
|
|
2086
|
-
const organisationError = organisationService.getError();
|
|
2087
|
-
const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();
|
|
2088
|
-
const isContextReady = organisationService.isContextReady();
|
|
2089
|
-
const events = eventService.getEvents();
|
|
2090
|
-
const selectedEvent = eventService.getSelectedEvent();
|
|
2091
|
-
const eventError = eventService.getError();
|
|
2092
|
-
const showInactivityWarning = inactivityService.getShowInactivityWarning();
|
|
2093
|
-
const inactivityTimeRemaining = inactivityService.getInactivityTimeRemaining();
|
|
2094
|
-
const isIdle = inactivityService.isIdle();
|
|
2095
|
-
const timeRemaining = inactivityService.getTimeRemaining();
|
|
2096
|
-
const showWarning = inactivityService.isWarningShown();
|
|
2097
|
-
const isTracking = inactivityService.isTracking();
|
|
2098
|
-
const hasErrors = !!(authError || organisationError || eventError || sessionRestoration.restorationError);
|
|
2099
|
-
const signIn = useCallback((email, password) => authService.signIn(email, password), [authService]);
|
|
2100
|
-
const signUp = useCallback((email, password) => authService.signUp(email, password), [authService]);
|
|
2101
|
-
const signOut = useCallback(() => authService.signOut(), [authService]);
|
|
2102
|
-
const resetPassword = useCallback((email) => authService.resetPassword(email), [authService]);
|
|
2103
|
-
const updatePassword = useCallback((password) => authService.updatePassword(password), [authService]);
|
|
2104
|
-
const refreshSession = useCallback(() => authService.refreshSession(), [authService]);
|
|
2105
|
-
const switchOrganisation = useCallback((orgId) => organisationService.switchOrganisation(orgId), [organisationService]);
|
|
2106
|
-
const getUserRole = useCallback((orgId) => organisationService.getUserRole(orgId), [organisationService]);
|
|
2107
|
-
const validateOrganisationAccess = useCallback((orgId) => organisationService.validateOrganisationAccess(orgId), [organisationService]);
|
|
2108
|
-
const refreshOrganisations = useCallback(() => organisationService.refreshOrganisations(), [organisationService]);
|
|
2109
|
-
const ensureOrganisationContext = useCallback(() => organisationService.ensureOrganisationContext(), [organisationService]);
|
|
2110
|
-
const isOrganisationSecure = useCallback(() => organisationService.isOrganisationSecure(), [organisationService]);
|
|
2111
|
-
const getPrimaryOrganisation = useCallback(() => organisationService.getPrimaryOrganisation(), [organisationService]);
|
|
2112
|
-
const setSelectedEvent = useCallback((event) => eventService.setSelectedEvent(event), [eventService]);
|
|
2113
|
-
const refreshEvents = useCallback(() => eventService.refreshEvents(), [eventService]);
|
|
2114
|
-
const resetActivity = useCallback(() => inactivityService.resetActivity(), [inactivityService]);
|
|
2115
|
-
const startTracking = useCallback(() => inactivityService.startTracking(), [inactivityService]);
|
|
2116
|
-
const stopTracking = useCallback(() => inactivityService.stopTracking(), [inactivityService]);
|
|
2117
|
-
const handleIdleLogout = useCallback(() => inactivityService.handleIdleLogout(), [inactivityService]);
|
|
2118
|
-
const handleStaySignedIn = useCallback(() => inactivityService.handleStaySignedIn(), [inactivityService]);
|
|
2119
|
-
const handleSignOutNow = useCallback(() => inactivityService.handleSignOutNow(), [inactivityService]);
|
|
2120
|
-
const prevStateRef = useRef4(null);
|
|
2121
|
-
const isDev = import.meta.env.DEV || import.meta.env.MODE === "development";
|
|
2122
|
-
if (isDev) {
|
|
2123
|
-
const currentState = {
|
|
2124
|
-
isAuthenticated: isAuth,
|
|
2125
|
-
userEmail: currentUser?.email,
|
|
2126
|
-
totalLoading
|
|
2127
|
-
};
|
|
2128
|
-
const prevState = prevStateRef.current;
|
|
2129
|
-
if (!prevState || prevState.isAuthenticated !== currentState.isAuthenticated || prevState.userEmail !== currentState.userEmail || prevState.totalLoading !== currentState.totalLoading) {
|
|
2130
|
-
logger.debug("UnifiedAuthContext", "Auth state changed:", {
|
|
2131
|
-
isAuthenticated: isAuth,
|
|
2132
|
-
user: currentUser?.email,
|
|
2133
|
-
session: currentSession ? "exists" : "null",
|
|
2134
|
-
totalLoading,
|
|
2135
|
-
authLoading,
|
|
2136
|
-
orgLoading,
|
|
2137
|
-
eventLoading,
|
|
2138
|
-
orgContextReady: isContextReady,
|
|
2139
|
-
sessionRestoration,
|
|
2140
|
-
sessionRestorationTimedOut
|
|
2141
|
-
});
|
|
2142
|
-
prevStateRef.current = currentState;
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
const contextValue = useMemo6(() => {
|
|
2146
|
-
return {
|
|
2147
|
-
// Auth state
|
|
2148
|
-
user: currentUser,
|
|
2149
|
-
session: currentSession,
|
|
2150
|
-
isAuthenticated: isAuth,
|
|
2151
|
-
authLoading,
|
|
2152
|
-
authError,
|
|
2153
|
-
error: authError,
|
|
2154
|
-
// Alias for backward compatibility
|
|
2155
|
-
supabase,
|
|
2156
|
-
// Auth methods
|
|
2157
|
-
signIn,
|
|
2158
|
-
signUp,
|
|
2159
|
-
signOut,
|
|
2160
|
-
resetPassword,
|
|
2161
|
-
updatePassword,
|
|
2162
|
-
refreshSession,
|
|
2163
|
-
// Organisation state
|
|
2164
|
-
selectedOrganisation,
|
|
2165
|
-
organisations,
|
|
2166
|
-
userMemberships,
|
|
2167
|
-
organisationLoading: orgLoading,
|
|
2168
|
-
organisationError,
|
|
2169
|
-
hasValidOrganisationContext,
|
|
2170
|
-
isContextReady,
|
|
2171
|
-
// Organisation methods
|
|
2172
|
-
switchOrganisation,
|
|
2173
|
-
getUserRole,
|
|
2174
|
-
validateOrganisationAccess,
|
|
2175
|
-
refreshOrganisations,
|
|
2176
|
-
ensureOrganisationContext,
|
|
2177
|
-
isOrganisationSecure,
|
|
2178
|
-
getPrimaryOrganisation,
|
|
2179
|
-
// Event state
|
|
2180
|
-
events,
|
|
2181
|
-
selectedEvent,
|
|
2182
|
-
eventLoading,
|
|
2183
|
-
eventError,
|
|
2184
|
-
// Event methods
|
|
2185
|
-
setSelectedEvent,
|
|
2186
|
-
refreshEvents,
|
|
2187
|
-
// Inactivity state
|
|
2188
|
-
showInactivityWarning,
|
|
2189
|
-
inactivityTimeRemaining,
|
|
2190
|
-
isIdle,
|
|
2191
|
-
timeRemaining,
|
|
2192
|
-
showWarning,
|
|
2193
|
-
isTracking,
|
|
2194
|
-
// Inactivity methods
|
|
2195
|
-
resetActivity,
|
|
2196
|
-
startTracking,
|
|
2197
|
-
stopTracking,
|
|
2198
|
-
handleIdleLogout,
|
|
2199
|
-
handleStaySignedIn,
|
|
2200
|
-
handleSignOutNow,
|
|
2201
|
-
// Additional unified properties
|
|
2202
|
-
appName,
|
|
2203
|
-
appConfig,
|
|
2204
|
-
isLoading: totalLoading,
|
|
2205
|
-
hasErrors,
|
|
2206
|
-
sessionRestoration,
|
|
2207
|
-
sessionRestorationTimedOut,
|
|
2208
|
-
sessionRestorationTimeoutMs
|
|
2209
|
-
};
|
|
2210
|
-
}, [
|
|
2211
|
-
// All primitive values extracted from services
|
|
2212
|
-
// Note: Arrays/objects from services are stable references (same reference unless data changes)
|
|
2213
|
-
currentUser,
|
|
2214
|
-
currentSession,
|
|
2215
|
-
isAuth,
|
|
2216
|
-
authLoading,
|
|
2217
|
-
authError,
|
|
2218
|
-
supabase,
|
|
2219
|
-
selectedOrganisation,
|
|
2220
|
-
organisations,
|
|
2221
|
-
userMemberships,
|
|
2222
|
-
orgLoading,
|
|
2223
|
-
organisationError,
|
|
2224
|
-
hasValidOrganisationContext,
|
|
2225
|
-
isContextReady,
|
|
2226
|
-
events,
|
|
2227
|
-
selectedEvent,
|
|
2228
|
-
eventLoading,
|
|
2229
|
-
eventError,
|
|
2230
|
-
showInactivityWarning,
|
|
2231
|
-
inactivityTimeRemaining,
|
|
2232
|
-
isIdle,
|
|
2233
|
-
timeRemaining,
|
|
2234
|
-
showWarning,
|
|
2235
|
-
isTracking,
|
|
2236
|
-
totalLoading,
|
|
2237
|
-
hasErrors,
|
|
2238
|
-
appName,
|
|
2239
|
-
appConfig,
|
|
2240
|
-
sessionRestoration,
|
|
2241
|
-
sessionRestorationTimedOut,
|
|
2242
|
-
sessionRestorationTimeoutMs,
|
|
2243
|
-
// Stable function references from useCallback (services are stable, so callbacks are too)
|
|
2244
|
-
signIn,
|
|
2245
|
-
signUp,
|
|
2246
|
-
signOut,
|
|
2247
|
-
resetPassword,
|
|
2248
|
-
updatePassword,
|
|
2249
|
-
refreshSession,
|
|
2250
|
-
switchOrganisation,
|
|
2251
|
-
getUserRole,
|
|
2252
|
-
validateOrganisationAccess,
|
|
2253
|
-
refreshOrganisations,
|
|
2254
|
-
ensureOrganisationContext,
|
|
2255
|
-
isOrganisationSecure,
|
|
2256
|
-
getPrimaryOrganisation,
|
|
2257
|
-
setSelectedEvent,
|
|
2258
|
-
refreshEvents,
|
|
2259
|
-
resetActivity,
|
|
2260
|
-
startTracking,
|
|
2261
|
-
stopTracking,
|
|
2262
|
-
handleIdleLogout,
|
|
2263
|
-
handleStaySignedIn,
|
|
2264
|
-
handleSignOutNow
|
|
2265
|
-
]);
|
|
2266
|
-
return /* @__PURE__ */ jsx5(UnifiedAuthContext.Provider, { value: contextValue, children });
|
|
2267
|
-
}
|
|
2268
|
-
function EventServiceProviderWrapper({
|
|
2269
|
-
children,
|
|
2270
|
-
supabaseClient,
|
|
2271
|
-
user,
|
|
2272
|
-
session,
|
|
2273
|
-
appName
|
|
2274
|
-
}) {
|
|
2275
|
-
const organisationService = useOrganisationService2();
|
|
2276
|
-
const selectedOrganisation = organisationService.getSelectedOrganisation();
|
|
2277
|
-
return /* @__PURE__ */ jsx5(
|
|
2278
|
-
EventServiceProvider,
|
|
2279
|
-
{
|
|
2280
|
-
supabaseClient,
|
|
2281
|
-
user,
|
|
2282
|
-
session,
|
|
2283
|
-
appName,
|
|
2284
|
-
selectedOrganisation,
|
|
2285
|
-
setSelectedEventId: () => {
|
|
2286
|
-
},
|
|
2287
|
-
children
|
|
2288
|
-
}
|
|
2289
|
-
);
|
|
2290
|
-
}
|
|
2291
|
-
function ServiceAwareProviders({
|
|
2292
|
-
children,
|
|
2293
|
-
supabaseClient,
|
|
2294
|
-
appName,
|
|
2295
|
-
appConfig,
|
|
2296
|
-
persistState,
|
|
2297
|
-
enablePersistence,
|
|
2298
|
-
requireOrganisationContext,
|
|
2299
|
-
idleTimeoutMs,
|
|
2300
|
-
warnBeforeMs,
|
|
2301
|
-
onIdleLogout,
|
|
2302
|
-
renderInactivityWarning,
|
|
2303
|
-
dangerouslyDisableInactivity
|
|
2304
|
-
}) {
|
|
2305
|
-
const authService = useAuthService2();
|
|
2306
|
-
return /* @__PURE__ */ jsx5(
|
|
2307
|
-
OrganisationServiceProvider,
|
|
2308
|
-
{
|
|
2309
|
-
supabaseClient,
|
|
2310
|
-
user: authService.getUser(),
|
|
2311
|
-
session: authService.getSession(),
|
|
2312
|
-
children: /* @__PURE__ */ jsx5(
|
|
2313
|
-
EventServiceProviderWrapper,
|
|
2314
|
-
{
|
|
2315
|
-
supabaseClient,
|
|
2316
|
-
user: authService.getUser(),
|
|
2317
|
-
session: authService.getSession(),
|
|
2318
|
-
appName,
|
|
2319
|
-
children: /* @__PURE__ */ jsx5(
|
|
2320
|
-
InactivityServiceProvider,
|
|
2321
|
-
{
|
|
2322
|
-
supabaseClient,
|
|
2323
|
-
user: authService.getUser(),
|
|
2324
|
-
session: authService.getSession(),
|
|
2325
|
-
idleTimeoutMs,
|
|
2326
|
-
warnBeforeMs,
|
|
2327
|
-
onIdleLogout,
|
|
2328
|
-
children: /* @__PURE__ */ jsx5(
|
|
2329
|
-
UnifiedAuthContextProvider,
|
|
2330
|
-
{
|
|
2331
|
-
appName,
|
|
2332
|
-
appConfig,
|
|
2333
|
-
supabaseClient,
|
|
2334
|
-
persistState,
|
|
2335
|
-
enablePersistence,
|
|
2336
|
-
requireOrganisationContext,
|
|
2337
|
-
idleTimeoutMs,
|
|
2338
|
-
warnBeforeMs,
|
|
2339
|
-
onIdleLogout,
|
|
2340
|
-
renderInactivityWarning,
|
|
2341
|
-
dangerouslyDisableInactivity,
|
|
2342
|
-
children
|
|
2343
|
-
}
|
|
2344
|
-
)
|
|
2345
|
-
}
|
|
2346
|
-
)
|
|
2347
|
-
}
|
|
2348
|
-
)
|
|
2349
|
-
}
|
|
2350
|
-
);
|
|
2351
|
-
}
|
|
2352
|
-
function UnifiedAuthProvider({
|
|
2353
|
-
children,
|
|
2354
|
-
supabaseClient,
|
|
2355
|
-
appName,
|
|
2356
|
-
appConfig = { requires_event: true },
|
|
2357
|
-
// Default to requiring events
|
|
2358
|
-
persistState = true,
|
|
2359
|
-
enablePersistence,
|
|
2360
|
-
requireOrganisationContext = true,
|
|
2361
|
-
idleTimeoutMs = 30 * 60 * 1e3,
|
|
2362
|
-
// 30 minutes
|
|
2363
|
-
warnBeforeMs = 60 * 1e3,
|
|
2364
|
-
// 60 seconds
|
|
2365
|
-
onIdleLogout,
|
|
2366
|
-
renderInactivityWarning,
|
|
2367
|
-
dangerouslyDisableInactivity = false
|
|
2368
|
-
}) {
|
|
2369
|
-
return /* @__PURE__ */ jsx5(AuthServiceProvider, { supabaseClient, appName, children: /* @__PURE__ */ jsx5(
|
|
2370
|
-
ServiceAwareProviders,
|
|
2371
|
-
{
|
|
2372
|
-
supabaseClient,
|
|
2373
|
-
appName,
|
|
2374
|
-
appConfig,
|
|
2375
|
-
persistState,
|
|
2376
|
-
enablePersistence,
|
|
2377
|
-
requireOrganisationContext,
|
|
2378
|
-
idleTimeoutMs,
|
|
2379
|
-
warnBeforeMs,
|
|
2380
|
-
onIdleLogout,
|
|
2381
|
-
renderInactivityWarning,
|
|
2382
|
-
dangerouslyDisableInactivity,
|
|
2383
|
-
children
|
|
2384
|
-
}
|
|
2385
|
-
) });
|
|
2386
|
-
}
|
|
2387
|
-
var UnifiedAuthContext, useUnifiedAuth;
|
|
2388
|
-
var init_UnifiedAuthProvider = __esm({
|
|
2389
|
-
"src/providers/services/UnifiedAuthProvider.tsx"() {
|
|
2390
|
-
"use strict";
|
|
2391
|
-
init_AuthServiceProvider();
|
|
2392
|
-
init_OrganisationServiceProvider();
|
|
2393
|
-
init_EventServiceProvider();
|
|
2394
|
-
init_InactivityServiceProvider();
|
|
2395
|
-
init_useAuthService();
|
|
2396
|
-
init_useOrganisationService();
|
|
2397
|
-
init_useEventService();
|
|
2398
|
-
init_useInactivityService();
|
|
2399
|
-
init_useSessionRestoration();
|
|
2400
|
-
init_logger();
|
|
2401
|
-
UnifiedAuthContext = createContext5(void 0);
|
|
2402
|
-
useUnifiedAuth = () => {
|
|
2403
|
-
const context = useContext10(UnifiedAuthContext);
|
|
2404
|
-
if (!context) {
|
|
2405
|
-
logger.error("useUnifiedAuth", "useUnifiedAuth must be used within a UnifiedAuthProvider");
|
|
2406
|
-
throw new Error("useUnifiedAuth must be used within a UnifiedAuthProvider");
|
|
2407
|
-
}
|
|
2408
|
-
return context;
|
|
2409
|
-
};
|
|
2410
|
-
}
|
|
2411
|
-
});
|
|
2412
|
-
|
|
2413
|
-
export {
|
|
2414
|
-
AuthServiceContext,
|
|
2415
|
-
AuthServiceProvider,
|
|
2416
|
-
useAuthService,
|
|
2417
|
-
init_AuthServiceProvider,
|
|
2418
|
-
OrganisationServiceContext,
|
|
2419
|
-
OrganisationServiceProvider,
|
|
2420
|
-
useOrganisationService,
|
|
2421
|
-
init_OrganisationServiceProvider,
|
|
2422
|
-
EventServiceContext,
|
|
2423
|
-
EventServiceProvider,
|
|
2424
|
-
useEventService,
|
|
2425
|
-
init_EventServiceProvider,
|
|
2426
|
-
InactivityServiceContext,
|
|
2427
|
-
InactivityServiceProvider,
|
|
2428
|
-
useInactivityService,
|
|
2429
|
-
init_InactivityServiceProvider,
|
|
2430
|
-
useAuthService2,
|
|
2431
|
-
init_useAuthService,
|
|
2432
|
-
useOrganisationService2,
|
|
2433
|
-
init_useOrganisationService,
|
|
2434
|
-
useEventService2,
|
|
2435
|
-
init_useEventService,
|
|
2436
|
-
useInactivityService2,
|
|
2437
|
-
init_useInactivityService,
|
|
2438
|
-
useSessionRestoration,
|
|
2439
|
-
init_useSessionRestoration,
|
|
2440
|
-
useUnifiedAuth,
|
|
2441
|
-
UnifiedAuthProvider,
|
|
2442
|
-
init_UnifiedAuthProvider
|
|
2443
|
-
};
|
|
2444
|
-
//# sourceMappingURL=chunk-3JI76CYK.js.map
|