@jmruthers/pace-core 0.5.189 → 0.5.190
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/core-usage-manifest.json +0 -4
- package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
- package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
- package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
- package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
- package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
- package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
- package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
- package/dist/chunk-4QYC5L4K.js.map +1 -0
- package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
- package/dist/chunk-73HSNNOQ.js.map +1 -0
- package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
- package/dist/chunk-DZWK57KZ.js.map +1 -0
- package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
- package/dist/chunk-HQVPB5MZ.js.map +1 -0
- package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
- package/dist/chunk-HW3OVDUF.js.map +1 -0
- package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
- package/dist/chunk-I7PSE6JW.js.map +1 -0
- package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
- package/dist/chunk-J2XXC7R5.js.map +1 -0
- package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
- package/dist/chunk-NIU6J6OX.js.map +1 -0
- package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
- package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
- package/dist/chunk-RUYZKXOD.js.map +1 -0
- package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
- package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
- package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
- package/dist/chunk-STYK4OH2.js.map +1 -0
- package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
- package/dist/chunk-VVBAW5A5.js.map +1 -0
- package/dist/chunk-Y4BUBBHD.js +614 -0
- package/dist/chunk-Y4BUBBHD.js.map +1 -0
- package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
- package/dist/chunk-ZSAAAMVR.js.map +1 -0
- package/dist/components.d.ts +3 -4
- package/dist/components.js +19 -19
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
- package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
- package/dist/hooks.d.ts +10 -5
- package/dist/hooks.js +14 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.js +79 -69
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +76 -12
- package/dist/rbac/index.js +12 -9
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
- package/dist/utils.js +16 -16
- package/docs/README.md +2 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +2 -2
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +2 -2
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +4 -4
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +2 -2
- package/docs/api/classes/SecureSupabaseClient.md +21 -16
- package/docs/api/classes/StorageUtils.md +7 -4
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +20 -6
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +62 -16
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +2 -2
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +26 -12
- package/docs/api/interfaces/FileUploadProps.md +30 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +3 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +4 -4
- package/docs/api/interfaces/StorageFileInfo.md +7 -7
- package/docs/api/interfaces/StorageFileMetadata.md +25 -14
- package/docs/api/interfaces/StorageListOptions.md +22 -9
- package/docs/api/interfaces/StorageListResult.md +4 -4
- package/docs/api/interfaces/StorageUploadOptions.md +21 -8
- package/docs/api/interfaces/StorageUploadResult.md +6 -6
- package/docs/api/interfaces/StorageUrlOptions.md +19 -6
- 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 +1 -1
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +151 -92
- package/docs/api-reference/components.md +15 -7
- package/docs/api-reference/providers.md +2 -2
- package/docs/api-reference/rpc-functions.md +1 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/deployment.md +8 -8
- package/docs/getting-started/examples/README.md +2 -2
- package/docs/getting-started/installation-guide.md +4 -4
- package/docs/getting-started/quick-start.md +3 -3
- package/docs/migration/MIGRATION_GUIDE.md +3 -3
- package/docs/rbac/compliance/compliance-guide.md +2 -2
- package/docs/rbac/event-based-apps.md +2 -2
- package/docs/rbac/getting-started.md +2 -2
- package/docs/rbac/quick-start.md +2 -2
- package/docs/security/README.md +4 -4
- package/docs/standards/07-rbac-and-rls-standard.md +430 -7
- package/docs/troubleshooting/README.md +2 -2
- package/docs/troubleshooting/migration.md +3 -3
- package/package.json +1 -3
- package/scripts/check-pace-core-compliance.cjs +1 -1
- package/scripts/check-pace-core-compliance.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +301 -0
- package/src/__tests__/public-recipe-view.test.ts +9 -9
- package/src/__tests__/rls-policies.test.ts +197 -61
- package/src/components/AddressField/AddressField.test.tsx +42 -0
- package/src/components/AddressField/AddressField.tsx +71 -60
- package/src/components/AddressField/README.md +1 -0
- package/src/components/Alert/Alert.test.tsx +50 -10
- package/src/components/Alert/Alert.tsx +5 -3
- package/src/components/Avatar/Avatar.test.tsx +95 -43
- package/src/components/Avatar/Avatar.tsx +16 -16
- package/src/components/Button/Button.test.tsx +2 -1
- package/src/components/Button/Button.tsx +3 -3
- package/src/components/Calendar/Calendar.test.tsx +53 -37
- package/src/components/Calendar/Calendar.tsx +409 -82
- package/src/components/Card/Card.test.tsx +7 -4
- package/src/components/Card/Card.tsx +3 -6
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +5 -5
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
- package/src/components/DataTable/components/DataTableBody.tsx +12 -12
- package/src/components/DataTable/components/DataTableCore.tsx +3 -3
- package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
- package/src/components/DataTable/components/EditableRow.tsx +2 -2
- package/src/components/DataTable/components/EmptyState.tsx +3 -3
- package/src/components/DataTable/components/GroupHeader.tsx +2 -2
- package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
- package/src/components/DataTable/components/ImportModal.tsx +4 -4
- package/src/components/DataTable/components/LoadingState.tsx +1 -1
- package/src/components/DataTable/components/PaginationControls.tsx +11 -11
- package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
- package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
- package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/EventSelector/EventSelector.tsx +7 -7
- package/src/components/FileDisplay/FileDisplay.tsx +291 -179
- package/src/components/FileUpload/FileUpload.tsx +7 -4
- package/src/components/Header/Header.test.tsx +28 -0
- package/src/components/Header/Header.tsx +22 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
- package/src/components/PaceAppLayout/test-setup.tsx +1 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
- package/src/components/Progress/Progress.test.tsx +18 -19
- package/src/components/Progress/Progress.tsx +31 -32
- package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
- package/src/components/Select/Select.tsx +5 -5
- package/src/components/Switch/Switch.test.tsx +2 -1
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.test.tsx +8 -2
- package/src/components/UserMenu/UserMenu.tsx +3 -3
- package/src/eslint-rules/pace-core-compliance.cjs +0 -2
- package/src/eslint-rules/pace-core-compliance.js +0 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
- package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
- package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
- package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
- package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
- package/src/hooks/index.ts +1 -1
- package/src/hooks/public/usePublicEvent.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.ts +173 -87
- package/src/hooks/useAppConfig.ts +24 -5
- package/src/hooks/useFileDisplay.ts +297 -34
- package/src/hooks/useFileReference.ts +56 -11
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useInactivityTracker.ts +16 -7
- package/src/hooks/usePermissionCache.test.ts +85 -8
- package/src/hooks/useQueryCache.ts +21 -0
- package/src/hooks/useSecureDataAccess.test.ts +80 -35
- package/src/hooks/useSecureDataAccess.ts +80 -37
- package/src/providers/services/EventServiceProvider.tsx +37 -17
- package/src/providers/services/InactivityServiceProvider.tsx +4 -4
- package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
- package/src/rbac/api.ts +240 -36
- package/src/rbac/cache-invalidation.ts +21 -7
- package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
- package/src/rbac/components/NavigationGuard.tsx +23 -63
- package/src/rbac/components/NavigationProvider.test.tsx +52 -23
- package/src/rbac/components/NavigationProvider.tsx +13 -11
- package/src/rbac/components/PagePermissionGuard.tsx +77 -203
- package/src/rbac/components/PagePermissionProvider.tsx +13 -11
- package/src/rbac/components/PermissionEnforcer.tsx +24 -62
- package/src/rbac/components/RoleBasedRouter.tsx +14 -12
- package/src/rbac/components/SecureDataProvider.tsx +13 -11
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
- package/src/rbac/engine.ts +4 -2
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/useCan.test.ts +101 -53
- package/src/rbac/hooks/usePermissions.ts +108 -41
- package/src/rbac/hooks/useRBAC.test.ts +11 -3
- package/src/rbac/hooks/useRBAC.ts +83 -40
- package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
- package/src/rbac/hooks/useResolvedScope.ts +128 -70
- package/src/rbac/hooks/useSecureSupabase.ts +36 -19
- package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
- package/src/rbac/request-deduplication.ts +1 -1
- package/src/rbac/secureClient.ts +72 -12
- package/src/rbac/security.ts +29 -23
- package/src/rbac/types.ts +10 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
- package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
- package/src/rbac/utils/contextValidator.ts +288 -0
- package/src/rbac/utils/eventContext.ts +48 -2
- package/src/services/EventService.ts +165 -21
- package/src/services/OrganisationService.ts +37 -2
- package/src/services/__tests__/EventService.test.ts +26 -21
- package/src/types/file-reference.ts +13 -10
- package/src/utils/app/appNameResolver.test.ts +346 -73
- package/src/utils/context/superAdminOverride.ts +58 -0
- package/src/utils/file-reference/index.ts +61 -33
- package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
- package/src/utils/storage/helpers.test.ts +1 -1
- package/src/utils/storage/helpers.ts +38 -19
- package/src/utils/storage/types.ts +15 -8
- package/src/utils/validation/__tests__/csrf.test.ts +105 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
- package/src/vite-env.d.ts +2 -2
- package/dist/chunk-3GOZZZYH.js.map +0 -1
- package/dist/chunk-DDM4CCYT.js.map +0 -1
- package/dist/chunk-E7UAOUMY.js +0 -75
- package/dist/chunk-E7UAOUMY.js.map +0 -1
- package/dist/chunk-F2IMUDXZ.js.map +0 -1
- package/dist/chunk-HEHYGYOX.js.map +0 -1
- package/dist/chunk-IM4QE42D.js.map +0 -1
- package/dist/chunk-MX64ZF6I.js.map +0 -1
- package/dist/chunk-SAUPYVLF.js.map +0 -1
- package/dist/chunk-THRPYOFK.js.map +0 -1
- package/dist/chunk-UCQSRW7Z.js.map +0 -1
- package/dist/chunk-VGZZXKBR.js.map +0 -1
- package/dist/chunk-YGPFYGA6.js.map +0 -1
- package/dist/chunk-YHCN776L.js.map +0 -1
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
- /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
- /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
- /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Supabase Test Fixtures
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module TestFixtures/Supabase
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* Shared Supabase client fixtures and mock data generators for tests.
|
|
8
|
+
* Reduces repeated mock setup across test files.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { createMockSupabaseClient, createMockQueryBuilder } from '../helpers/supabaseMock';
|
|
12
|
+
import type { User, Session } from '@supabase/supabase-js';
|
|
13
|
+
import { TEST_FIXTURES } from './test-data';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a standard mock Supabase client with common RBAC mocks
|
|
17
|
+
*/
|
|
18
|
+
export function createTestSupabaseClient(overrides: {
|
|
19
|
+
user?: User;
|
|
20
|
+
session?: Session;
|
|
21
|
+
rpcResponses?: Record<string, any>;
|
|
22
|
+
tableData?: Record<string, any[]>;
|
|
23
|
+
} = {}) {
|
|
24
|
+
const mockUser = overrides.user || {
|
|
25
|
+
id: TEST_FIXTURES.users.basic.id,
|
|
26
|
+
email: TEST_FIXTURES.users.basic.email,
|
|
27
|
+
user_metadata: {},
|
|
28
|
+
app_metadata: {},
|
|
29
|
+
aud: 'authenticated',
|
|
30
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
31
|
+
} as User;
|
|
32
|
+
|
|
33
|
+
const mockSession = overrides.session || {
|
|
34
|
+
access_token: 'test-access-token',
|
|
35
|
+
refresh_token: 'test-refresh-token',
|
|
36
|
+
expires_at: Date.now() + 3600000,
|
|
37
|
+
expires_in: 3600,
|
|
38
|
+
token_type: 'bearer',
|
|
39
|
+
user: mockUser,
|
|
40
|
+
} as Session;
|
|
41
|
+
|
|
42
|
+
const client = createMockSupabaseClient();
|
|
43
|
+
if (!overrides.tableData) {
|
|
44
|
+
throw new Error('createTestSupabaseClient requires tableData overrides for tests');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// Setup auth mocks
|
|
49
|
+
vi.spyOn(client.auth, 'getSession').mockResolvedValue({
|
|
50
|
+
data: { session: mockSession },
|
|
51
|
+
error: null
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
vi.spyOn(client.auth, 'getUser').mockResolvedValue({
|
|
55
|
+
data: { user: mockUser },
|
|
56
|
+
error: null
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Setup default RPC responses
|
|
60
|
+
const defaultRpcResponses: Record<string, any> = {
|
|
61
|
+
rbac_page_access_check: { data: true, error: null },
|
|
62
|
+
rbac_permissions_get: {
|
|
63
|
+
data: [
|
|
64
|
+
{
|
|
65
|
+
permission_type: 'organisation_access',
|
|
66
|
+
role_name: 'member',
|
|
67
|
+
context_id: TEST_FIXTURES.organisations.basic.id
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
error: null
|
|
71
|
+
},
|
|
72
|
+
rbac_access_validate: {
|
|
73
|
+
data: [{
|
|
74
|
+
has_access: true,
|
|
75
|
+
access_level: 'organisation',
|
|
76
|
+
context_id: TEST_FIXTURES.organisations.basic.id
|
|
77
|
+
}],
|
|
78
|
+
error: null
|
|
79
|
+
},
|
|
80
|
+
...overrides.rpcResponses
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
client.rpc.mockImplementation((functionName: string, params?: any) => {
|
|
84
|
+
const response = defaultRpcResponses[functionName];
|
|
85
|
+
if (response) {
|
|
86
|
+
// If response is a function, call it with params
|
|
87
|
+
if (typeof response === 'function') {
|
|
88
|
+
return response(params);
|
|
89
|
+
}
|
|
90
|
+
return Promise.resolve(response);
|
|
91
|
+
}
|
|
92
|
+
return Promise.resolve({ data: null, error: null });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Setup default table data
|
|
96
|
+
// CRITICAL: Capture organisations from overrides BEFORE any processing
|
|
97
|
+
// This ensures we use the exact organisations provided, not defaults
|
|
98
|
+
const organisationsData = overrides.tableData?.organisations
|
|
99
|
+
? [...overrides.tableData.organisations] // Create a copy to avoid mutations
|
|
100
|
+
: [TEST_FIXTURES.organisations.basic];
|
|
101
|
+
|
|
102
|
+
// Ensure all organisations have is_active: true (required by OrganisationService)
|
|
103
|
+
// But preserve all other properties including name
|
|
104
|
+
const processedOrganisations = organisationsData.map((org: any) => {
|
|
105
|
+
// If is_active is already set, return org as-is to preserve all properties including name
|
|
106
|
+
if (org.is_active !== undefined) {
|
|
107
|
+
return org;
|
|
108
|
+
}
|
|
109
|
+
// Only add is_active if missing, preserving all other properties
|
|
110
|
+
return {
|
|
111
|
+
...org, // Preserve ALL existing properties including name
|
|
112
|
+
is_active: true
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const defaultTableData: Record<string, any> = {
|
|
117
|
+
organisations: processedOrganisations, // Use processed organisations
|
|
118
|
+
event: overrides.tableData?.event ?? [TEST_FIXTURES.events.basic],
|
|
119
|
+
rbac_global_roles: overrides.tableData?.rbac_global_roles ?? [],
|
|
120
|
+
rbac_apps: overrides.tableData?.rbac_apps ?? [{ id: 'app-123', name: 'TEST_APP', is_active: true }],
|
|
121
|
+
rbac_app_pages: overrides.tableData?.rbac_app_pages ?? [{ id: 'page-123', page_name: 'dashboard', app_id: 'app-123' }],
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Apply any additional table data that wasn't explicitly handled above
|
|
125
|
+
if (overrides.tableData) {
|
|
126
|
+
for (const [key, value] of Object.entries(overrides.tableData)) {
|
|
127
|
+
if (!(key in defaultTableData)) {
|
|
128
|
+
defaultTableData[key] = value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Mock from() to return a builder that resolves with table-specific data
|
|
134
|
+
// CRITICAL: Capture processedOrganisations in closure to ensure it's always used
|
|
135
|
+
const organisationsForMock = processedOrganisations;
|
|
136
|
+
|
|
137
|
+
// Override the from() mock completely - don't use the default one from createMockSupabaseClient
|
|
138
|
+
client.from = vi.fn().mockImplementation((table: string) => {
|
|
139
|
+
// For organisations table, always use the captured processedOrganisations
|
|
140
|
+
// This ensures we use the correct organisations even if defaultTableData is modified
|
|
141
|
+
let tableData: any;
|
|
142
|
+
if (table === 'organisations') {
|
|
143
|
+
tableData = organisationsForMock;
|
|
144
|
+
} else {
|
|
145
|
+
tableData = defaultTableData[table as keyof typeof defaultTableData];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Ensure data is always an array
|
|
149
|
+
const data = Array.isArray(tableData) ? tableData : (tableData ? [tableData] : []);
|
|
150
|
+
// Create response in the format Supabase returns: { data: [...], error: null }
|
|
151
|
+
const response = { data, error: null };
|
|
152
|
+
|
|
153
|
+
// Create a fresh builder for each call to ensure data is correct
|
|
154
|
+
// We'll completely override the builder to use our response
|
|
155
|
+
// IMPORTANT: All chainable methods must return the builder itself (not 'this')
|
|
156
|
+
const builder: any = {};
|
|
157
|
+
|
|
158
|
+
// Define chainable methods that return the builder
|
|
159
|
+
const chainableMethods = ['select', 'insert', 'update', 'delete', 'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'like', 'ilike', 'in', 'not', 'is', 'or', 'and', 'filter', 'match', 'order', 'offset'];
|
|
160
|
+
chainableMethods.forEach(method => {
|
|
161
|
+
builder[method] = vi.fn().mockReturnValue(builder);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Methods that resolve with data
|
|
165
|
+
builder.limit = vi.fn().mockResolvedValue(response);
|
|
166
|
+
builder.single = vi.fn().mockResolvedValue({ data: data[0] || null, error: null });
|
|
167
|
+
builder.maybeSingle = vi.fn().mockResolvedValue({ data: data[0] || null, error: null });
|
|
168
|
+
|
|
169
|
+
// Thenable interface - CRITICAL: must resolve with the correct response
|
|
170
|
+
builder.then = vi.fn().mockImplementation((resolve, reject) => {
|
|
171
|
+
Promise.resolve(response).then(resolve, reject);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
builder.catch = vi.fn().mockImplementation((onRejected) => {
|
|
175
|
+
return Promise.resolve(response).catch(onRejected);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
builder.finally = vi.fn().mockImplementation((onFinally) => {
|
|
179
|
+
return Promise.resolve(response).finally(onFinally);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
builder.range = vi.fn().mockImplementation((min: number, max: number) => {
|
|
183
|
+
// Return a thenable builder that resolves with the sliced data
|
|
184
|
+
const rangedData = data.slice(min, max + 1);
|
|
185
|
+
const rangedResponse = { data: rangedData, error: null };
|
|
186
|
+
const rangedBuilder = Object.assign({}, builder);
|
|
187
|
+
rangedBuilder.then = vi.fn().mockImplementation((resolve, reject) => {
|
|
188
|
+
Promise.resolve(rangedResponse).then(resolve, reject);
|
|
189
|
+
});
|
|
190
|
+
rangedBuilder.catch = vi.fn().mockImplementation((onRejected) => {
|
|
191
|
+
return Promise.resolve(rangedResponse).catch(onRejected);
|
|
192
|
+
});
|
|
193
|
+
rangedBuilder.finally = vi.fn().mockImplementation((onFinally) => {
|
|
194
|
+
return Promise.resolve(rangedResponse).finally(onFinally);
|
|
195
|
+
});
|
|
196
|
+
// Ensure chainable methods still work
|
|
197
|
+
chainableMethods.forEach(method => {
|
|
198
|
+
rangedBuilder[method] = vi.fn().mockReturnValue(rangedBuilder);
|
|
199
|
+
});
|
|
200
|
+
return rangedBuilder;
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
return builder;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return client;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Creates mock user data
|
|
211
|
+
*/
|
|
212
|
+
export function createMockUser(overrides: Partial<User> = {}): User {
|
|
213
|
+
return {
|
|
214
|
+
id: TEST_FIXTURES.users.basic.id,
|
|
215
|
+
email: TEST_FIXTURES.users.basic.email,
|
|
216
|
+
user_metadata: {},
|
|
217
|
+
app_metadata: {},
|
|
218
|
+
aud: 'authenticated',
|
|
219
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
220
|
+
...overrides
|
|
221
|
+
} as User;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates mock session data
|
|
226
|
+
*/
|
|
227
|
+
export function createMockSession(user?: User, overrides: Partial<Session> = {}): Session {
|
|
228
|
+
const mockUser = user || createMockUser();
|
|
229
|
+
return {
|
|
230
|
+
access_token: 'test-access-token',
|
|
231
|
+
refresh_token: 'test-refresh-token',
|
|
232
|
+
expires_at: Date.now() + 3600000,
|
|
233
|
+
expires_in: 3600,
|
|
234
|
+
token_type: 'bearer',
|
|
235
|
+
user: mockUser,
|
|
236
|
+
...overrides
|
|
237
|
+
} as Session;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Creates mock organisation data
|
|
242
|
+
*/
|
|
243
|
+
export function createMockOrganisation(overrides: Partial<typeof TEST_FIXTURES.organisations.basic> & { is_active?: boolean; display_name?: string; name?: string } = {}) {
|
|
244
|
+
// Extract name from overrides if provided, otherwise use default
|
|
245
|
+
const orgName = overrides.name ?? TEST_FIXTURES.organisations.basic.name;
|
|
246
|
+
const displayName = overrides.display_name ?? orgName;
|
|
247
|
+
|
|
248
|
+
// Build the organisation object, ensuring overrides take precedence
|
|
249
|
+
return {
|
|
250
|
+
...TEST_FIXTURES.organisations.basic,
|
|
251
|
+
// Set required fields with defaults
|
|
252
|
+
is_active: true, // Required by OrganisationService - only active orgs are used
|
|
253
|
+
subscription_tier: 'basic',
|
|
254
|
+
settings: {},
|
|
255
|
+
parent_id: null,
|
|
256
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
257
|
+
updated_at: '2023-01-01T00:00:00Z',
|
|
258
|
+
// Apply name and display_name (these should come before overrides to ensure they're set)
|
|
259
|
+
name: orgName, // Explicitly set name (used by UI components)
|
|
260
|
+
display_name: displayName, // display_name defaults to name
|
|
261
|
+
// Apply all overrides last to ensure they take precedence (including name if provided)
|
|
262
|
+
...overrides
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Creates mock event data
|
|
268
|
+
*/
|
|
269
|
+
export function createMockEvent(overrides: Partial<typeof TEST_FIXTURES.events.basic> = {}) {
|
|
270
|
+
return {
|
|
271
|
+
...TEST_FIXTURES.events.basic,
|
|
272
|
+
...overrides
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Creates a Supabase client configured for organisation-scoped data access tests
|
|
278
|
+
*/
|
|
279
|
+
export function createOrganisationScopedSupabaseClient(organisationId: string) {
|
|
280
|
+
return createTestSupabaseClient({
|
|
281
|
+
tableData: {
|
|
282
|
+
organisations: [createMockOrganisation({ id: organisationId })],
|
|
283
|
+
event: [createMockEvent({ organisation_id: organisationId })]
|
|
284
|
+
},
|
|
285
|
+
rpcResponses: {
|
|
286
|
+
rbac_permissions_get: {
|
|
287
|
+
data: [{
|
|
288
|
+
permission_type: 'organisation_access',
|
|
289
|
+
role_name: 'member',
|
|
290
|
+
context_id: organisationId
|
|
291
|
+
}],
|
|
292
|
+
error: null
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Re-export vi for convenience
|
|
299
|
+
import { vi } from 'vitest';
|
|
300
|
+
export { vi };
|
|
301
|
+
|
|
@@ -19,10 +19,10 @@ const TEST_TIMEOUT = 5000;
|
|
|
19
19
|
const PERFORMANCE_THRESHOLD = 500; // 500ms for public view queries
|
|
20
20
|
|
|
21
21
|
// Check if we're using real test-db (via environment variables)
|
|
22
|
-
const USE_REAL_DB = !!(process.env.SUPABASE_URL && process.env.
|
|
22
|
+
const USE_REAL_DB = !!(process.env.SUPABASE_URL && process.env.VITE_SUPABASE_PUBLISHABLE_KEY);
|
|
23
23
|
const TEST_SUPABASE_URL = process.env.SUPABASE_URL || process.env.VITE_SUPABASE_URL;
|
|
24
|
-
const
|
|
25
|
-
const TEST_SUPABASE_SERVICE_ROLE_KEY = process.env.
|
|
24
|
+
const TEST_SUPABASE_PUBLISHABLE_KEY = process.env.VITE_SUPABASE_PUBLISHABLE_KEY;
|
|
25
|
+
const TEST_SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
26
26
|
|
|
27
27
|
let anonClient: SupabaseClient<Database>;
|
|
28
28
|
let authenticatedClient: SupabaseClient<Database>;
|
|
@@ -43,14 +43,14 @@ const privateEvent = {
|
|
|
43
43
|
organisation_id: 'org-1' as any
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
describe.skipIf(!USE_REAL_DB || !TEST_SUPABASE_URL || !
|
|
46
|
+
describe.skipIf(!USE_REAL_DB || !TEST_SUPABASE_URL || !TEST_SUPABASE_PUBLISHABLE_KEY)('Public Recipe View - Anonymous Access', () => {
|
|
47
47
|
beforeEach(() => {
|
|
48
|
-
if (USE_REAL_DB && TEST_SUPABASE_URL &&
|
|
49
|
-
anonClient = createClient<Database>(TEST_SUPABASE_URL,
|
|
50
|
-
authenticatedClient = createClient<Database>(TEST_SUPABASE_URL, TEST_SUPABASE_SERVICE_ROLE_KEY ||
|
|
48
|
+
if (USE_REAL_DB && TEST_SUPABASE_URL && TEST_SUPABASE_PUBLISHABLE_KEY) {
|
|
49
|
+
anonClient = createClient<Database>(TEST_SUPABASE_URL, TEST_SUPABASE_PUBLISHABLE_KEY);
|
|
50
|
+
authenticatedClient = createClient<Database>(TEST_SUPABASE_URL, TEST_SUPABASE_SERVICE_ROLE_KEY || TEST_SUPABASE_PUBLISHABLE_KEY);
|
|
51
51
|
} else {
|
|
52
52
|
// This should not happen due to skipIf, but provide fallback
|
|
53
|
-
throw new Error('Test database credentials not available. Set SUPABASE_URL and
|
|
53
|
+
throw new Error('Test database credentials not available. Set SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY environment variables.');
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -172,7 +172,7 @@ describe.skipIf(!USE_REAL_DB || !TEST_SUPABASE_URL || !TEST_SUPABASE_ANON_KEY)('
|
|
|
172
172
|
});
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
describe.skipIf(!USE_REAL_DB || !TEST_SUPABASE_URL || !
|
|
175
|
+
describe.skipIf(!USE_REAL_DB || !TEST_SUPABASE_URL || !TEST_SUPABASE_PUBLISHABLE_KEY)('Public Recipe View - Authenticated Access', () => {
|
|
176
176
|
it('should allow authenticated users to view public recipes', async () => {
|
|
177
177
|
const { data, error } = await authenticatedClient
|
|
178
178
|
.from('public_recipe_details')
|