@alneas/appkit-react 0.1.0 → 0.2.0
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 +53 -0
- package/README.md +85 -15
- package/consumer-ai/SKILL.md +12 -0
- package/consumer-ai/api-index.json +103754 -0
- package/consumer-ai/package-context.json +409 -0
- package/dist/ai/action/ExecutionHistory.cjs.map +1 -1
- package/dist/ai/action/ExecutionHistory.d.cts +32 -2
- package/dist/ai/action/ExecutionHistory.d.ts +32 -2
- package/dist/ai/action/ExecutionHistory.js.map +1 -1
- package/dist/ai/action/ScreenActionContext.cjs.map +1 -1
- package/dist/ai/action/ScreenActionContext.d.cts +15 -2
- package/dist/ai/action/ScreenActionContext.d.ts +15 -2
- package/dist/ai/action/ScreenActionContext.js.map +1 -1
- package/dist/ai/action/context.cjs.map +1 -1
- package/dist/ai/action/context.d.cts +19 -3
- package/dist/ai/action/context.d.ts +19 -3
- package/dist/ai/action/context.js.map +1 -1
- package/dist/ai/action/types.d.cts +35 -3
- package/dist/ai/action/types.d.ts +35 -3
- package/dist/ai/action/use-execution-session.cjs.map +1 -1
- package/dist/ai/action/use-execution-session.d.cts +17 -1
- package/dist/ai/action/use-execution-session.d.ts +17 -1
- package/dist/ai/action/use-execution-session.js.map +1 -1
- package/dist/ai/action/use-screen-action-registry.cjs.map +1 -1
- package/dist/ai/action/use-screen-action-registry.d.cts +77 -8
- package/dist/ai/action/use-screen-action-registry.d.ts +77 -8
- package/dist/ai/action/use-screen-action-registry.js.map +1 -1
- package/dist/ai/action/use-screen-action.cjs.map +1 -1
- package/dist/ai/action/use-screen-action.d.cts +23 -6
- package/dist/ai/action/use-screen-action.d.ts +23 -6
- package/dist/ai/action/use-screen-action.js.map +1 -1
- package/dist/ai/action/use-screen-context.cjs.map +1 -1
- package/dist/ai/action/use-screen-context.d.cts +42 -5
- package/dist/ai/action/use-screen-context.d.ts +42 -5
- package/dist/ai/action/use-screen-context.js.map +1 -1
- package/dist/ai/ai-chat/transport.cjs.map +1 -1
- package/dist/ai/ai-chat/transport.d.cts +35 -8
- package/dist/ai/ai-chat/transport.d.ts +35 -8
- package/dist/ai/ai-chat/transport.js.map +1 -1
- package/dist/ai/generative-ui/GenerativeUIRenderer.cjs.map +1 -1
- package/dist/ai/generative-ui/GenerativeUIRenderer.d.cts +21 -3
- package/dist/ai/generative-ui/GenerativeUIRenderer.d.ts +21 -3
- package/dist/ai/generative-ui/GenerativeUIRenderer.js.map +1 -1
- package/dist/ai/generative-ui/error-boundary.cjs.map +1 -1
- package/dist/ai/generative-ui/error-boundary.d.cts +98 -2
- package/dist/ai/generative-ui/error-boundary.d.ts +98 -2
- package/dist/ai/generative-ui/error-boundary.js.map +1 -1
- package/dist/ai/generative-ui/registry.cjs.map +1 -1
- package/dist/ai/generative-ui/registry.d.cts +96 -7
- package/dist/ai/generative-ui/registry.d.ts +96 -7
- package/dist/ai/generative-ui/registry.js.map +1 -1
- package/dist/ai/proposal/ProposalFieldReview.cjs.map +1 -1
- package/dist/ai/proposal/ProposalFieldReview.d.cts +170 -8
- package/dist/ai/proposal/ProposalFieldReview.d.ts +170 -8
- package/dist/ai/proposal/ProposalFieldReview.js.map +1 -1
- package/dist/ai/proposal/types.d.cts +97 -26
- package/dist/ai/proposal/types.d.ts +97 -26
- package/dist/ai/proposal/use-proposal-batch-review.cjs.map +1 -1
- package/dist/ai/proposal/use-proposal-batch-review.d.cts +133 -7
- package/dist/ai/proposal/use-proposal-batch-review.d.ts +133 -7
- package/dist/ai/proposal/use-proposal-batch-review.js.map +1 -1
- package/dist/ai/proposal/use-proposal-review.cjs.map +1 -1
- package/dist/ai/proposal/use-proposal-review.d.cts +47 -5
- package/dist/ai/proposal/use-proposal-review.d.ts +47 -5
- package/dist/ai/proposal/use-proposal-review.js.map +1 -1
- package/dist/avatar.svg +1 -0
- package/dist/consumer-ai/SKILL.md +6 -0
- package/dist/consumer-ai/api-index.json +103754 -0
- package/dist/consumer-ai/package-context.json +5 -3
- package/dist/mockServiceWorker.js +361 -0
- package/dist/styles.css +1 -1
- package/dist/tools/components/auth/AuthForms.cjs.map +1 -1
- package/dist/tools/components/auth/AuthForms.d.cts +131 -81
- package/dist/tools/components/auth/AuthForms.d.ts +131 -81
- package/dist/tools/components/auth/AuthForms.js.map +1 -1
- package/dist/tools/components/auth/AuthGuard.cjs.map +1 -1
- package/dist/tools/components/auth/AuthGuard.d.cts +31 -4
- package/dist/tools/components/auth/AuthGuard.d.ts +31 -4
- package/dist/tools/components/auth/AuthGuard.js.map +1 -1
- package/dist/tools/components/auth/AuthProvider.cjs.map +1 -1
- package/dist/tools/components/auth/AuthProvider.d.cts +39 -42
- package/dist/tools/components/auth/AuthProvider.d.ts +39 -42
- package/dist/tools/components/auth/AuthProvider.js.map +1 -1
- package/dist/tools/components/auth/ProtectedRoute.cjs.map +1 -1
- package/dist/tools/components/auth/ProtectedRoute.d.cts +75 -60
- package/dist/tools/components/auth/ProtectedRoute.d.ts +75 -60
- package/dist/tools/components/auth/ProtectedRoute.js.map +1 -1
- package/dist/tools/components/auth/SignInButton.cjs.map +1 -1
- package/dist/tools/components/auth/SignInButton.d.cts +26 -18
- package/dist/tools/components/auth/SignInButton.d.ts +26 -18
- package/dist/tools/components/auth/SignInButton.js.map +1 -1
- package/dist/tools/components/auth/UserProfileProvider.cjs.map +1 -1
- package/dist/tools/components/auth/UserProfileProvider.d.cts +48 -20
- package/dist/tools/components/auth/UserProfileProvider.d.ts +48 -20
- package/dist/tools/components/auth/UserProfileProvider.js.map +1 -1
- package/dist/tools/components/auth/adapters/better-auth-adapter.cjs.map +1 -1
- package/dist/tools/components/auth/adapters/better-auth-adapter.d.cts +371 -51
- package/dist/tools/components/auth/adapters/better-auth-adapter.d.ts +371 -51
- package/dist/tools/components/auth/adapters/better-auth-adapter.js.map +1 -1
- package/dist/tools/components/auth/adapters/mock-adapter.cjs.map +1 -1
- package/dist/tools/components/auth/adapters/mock-adapter.d.cts +149 -28
- package/dist/tools/components/auth/adapters/mock-adapter.d.ts +149 -28
- package/dist/tools/components/auth/adapters/mock-adapter.js.map +1 -1
- package/dist/tools/components/auth/auth-session.cjs.map +1 -1
- package/dist/tools/components/auth/auth-session.d.cts +147 -1
- package/dist/tools/components/auth/auth-session.d.ts +147 -1
- package/dist/tools/components/auth/auth-session.js.map +1 -1
- package/dist/tools/components/auth/session-cache.cjs.map +1 -1
- package/dist/tools/components/auth/session-cache.d.cts +88 -24
- package/dist/tools/components/auth/session-cache.d.ts +88 -24
- package/dist/tools/components/auth/session-cache.js.map +1 -1
- package/dist/tools/components/auth/types.cjs.map +1 -1
- package/dist/tools/components/auth/types.d.cts +329 -106
- package/dist/tools/components/auth/types.d.ts +329 -106
- package/dist/tools/components/auth/types.js.map +1 -1
- package/dist/tools/components/auth/useAuth.cjs.map +1 -1
- package/dist/tools/components/auth/useAuth.d.cts +110 -17
- package/dist/tools/components/auth/useAuth.d.ts +110 -17
- package/dist/tools/components/auth/useAuth.js.map +1 -1
- package/dist/tools/components/auth/useAuthGuard.cjs.map +1 -1
- package/dist/tools/components/auth/useAuthGuard.d.cts +49 -38
- package/dist/tools/components/auth/useAuthGuard.d.ts +49 -38
- package/dist/tools/components/auth/useAuthGuard.js.map +1 -1
- package/dist/tools/components/auth/useRoleCheck.cjs.map +1 -1
- package/dist/tools/components/auth/useRoleCheck.d.cts +48 -1
- package/dist/tools/components/auth/useRoleCheck.d.ts +48 -1
- package/dist/tools/components/auth/useRoleCheck.js.map +1 -1
- package/dist/tools/components/auth/useUserProfile.cjs.map +1 -1
- package/dist/tools/components/auth/useUserProfile.d.cts +66 -1
- package/dist/tools/components/auth/useUserProfile.d.ts +66 -1
- package/dist/tools/components/auth/useUserProfile.js.map +1 -1
- package/dist/tools/components/barcode/BarcodeGenerator.cjs.map +1 -1
- package/dist/tools/components/barcode/BarcodeGenerator.d.cts +32 -18
- package/dist/tools/components/barcode/BarcodeGenerator.d.ts +32 -18
- package/dist/tools/components/barcode/BarcodeGenerator.js.map +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.cjs +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.cjs.map +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.d.cts +20 -13
- package/dist/tools/components/barcode/QRCodeGenerator.d.ts +20 -13
- package/dist/tools/components/barcode/QRCodeGenerator.js +1 -1
- package/dist/tools/components/barcode/QRCodeGenerator.js.map +1 -1
- package/dist/tools/components/barcode/QRCodeScanner.cjs.map +1 -1
- package/dist/tools/components/barcode/QRCodeScanner.d.cts +32 -1
- package/dist/tools/components/barcode/QRCodeScanner.d.ts +32 -1
- package/dist/tools/components/barcode/QRCodeScanner.js.map +1 -1
- package/dist/tools/components/calendar/ResourceCalendar.cjs.map +1 -1
- package/dist/tools/components/calendar/ResourceCalendar.d.cts +17 -42
- package/dist/tools/components/calendar/ResourceCalendar.d.ts +17 -42
- package/dist/tools/components/calendar/ResourceCalendar.js.map +1 -1
- package/dist/tools/components/calendar/views/ResourceView.cjs +1 -1
- package/dist/tools/components/calendar/views/ResourceView.cjs.map +1 -1
- package/dist/tools/components/calendar/views/ResourceView.js +2 -2
- package/dist/tools/components/calendar/views/ResourceView.js.map +1 -1
- package/dist/tools/components/chart/ComposedChart.cjs.map +1 -1
- package/dist/tools/components/chart/ComposedChart.d.cts +54 -1
- package/dist/tools/components/chart/ComposedChart.d.ts +54 -1
- package/dist/tools/components/chart/ComposedChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleAreaChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleAreaChart.d.cts +41 -1
- package/dist/tools/components/chart/SimpleAreaChart.d.ts +41 -1
- package/dist/tools/components/chart/SimpleAreaChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleBarChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleBarChart.d.cts +34 -24
- package/dist/tools/components/chart/SimpleBarChart.d.ts +34 -24
- package/dist/tools/components/chart/SimpleBarChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleLineChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleLineChart.d.cts +31 -28
- package/dist/tools/components/chart/SimpleLineChart.d.ts +31 -28
- package/dist/tools/components/chart/SimpleLineChart.js.map +1 -1
- package/dist/tools/components/chart/SimplePieChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimplePieChart.d.cts +28 -22
- package/dist/tools/components/chart/SimplePieChart.d.ts +28 -22
- package/dist/tools/components/chart/SimplePieChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleRadarChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleRadarChart.d.cts +38 -1
- package/dist/tools/components/chart/SimpleRadarChart.d.ts +38 -1
- package/dist/tools/components/chart/SimpleRadarChart.js.map +1 -1
- package/dist/tools/components/chart/SimpleScatterChart.cjs.map +1 -1
- package/dist/tools/components/chart/SimpleScatterChart.d.cts +44 -1
- package/dist/tools/components/chart/SimpleScatterChart.d.ts +44 -1
- package/dist/tools/components/chart/SimpleScatterChart.js.map +1 -1
- package/dist/tools/components/chart/StackedBarChart.cjs.map +1 -1
- package/dist/tools/components/chart/StackedBarChart.d.cts +38 -1
- package/dist/tools/components/chart/StackedBarChart.d.ts +38 -1
- package/dist/tools/components/chart/StackedBarChart.js.map +1 -1
- package/dist/tools/components/data-table/data-table.cjs +1 -1
- package/dist/tools/components/data-table/data-table.cjs.map +1 -1
- package/dist/tools/components/data-table/data-table.js +286 -263
- package/dist/tools/components/data-table/data-table.js.map +1 -1
- package/dist/tools/components/data-table/table-utils.cjs.map +1 -1
- package/dist/tools/components/data-table/table-utils.d.cts +45 -35
- package/dist/tools/components/data-table/table-utils.d.ts +45 -35
- package/dist/tools/components/data-table/table-utils.js.map +1 -1
- package/dist/tools/components/editable-table/editable-table.cjs +1 -1
- package/dist/tools/components/editable-table/editable-table.cjs.map +1 -1
- package/dist/tools/components/editable-table/editable-table.js +15 -2
- package/dist/tools/components/editable-table/editable-table.js.map +1 -1
- package/dist/tools/components/error/ErrorDialog.cjs +1 -1
- package/dist/tools/components/error/ErrorDialog.cjs.map +1 -1
- package/dist/tools/components/error/ErrorDialog.js +1 -1
- package/dist/tools/components/error/ErrorDialog.js.map +1 -1
- package/dist/tools/components/error/ErrorInline.cjs +1 -1
- package/dist/tools/components/error/ErrorInline.cjs.map +1 -1
- package/dist/tools/components/error/ErrorInline.js +1 -1
- package/dist/tools/components/error/ErrorInline.js.map +1 -1
- package/dist/tools/components/error/ErrorNotification.cjs +1 -1
- package/dist/tools/components/error/ErrorNotification.cjs.map +1 -1
- package/dist/tools/components/error/ErrorNotification.js +10 -10
- package/dist/tools/components/error/ErrorNotification.js.map +1 -1
- package/dist/tools/components/file-browser/FilePreview.cjs +1 -1
- package/dist/tools/components/file-browser/FilePreview.cjs.map +1 -1
- package/dist/tools/components/file-browser/FilePreview.js +28 -26
- package/dist/tools/components/file-browser/FilePreview.js.map +1 -1
- package/dist/tools/components/filter/filter.cjs.map +1 -1
- package/dist/tools/components/filter/filter.d.cts +23 -34
- package/dist/tools/components/filter/filter.d.ts +23 -34
- package/dist/tools/components/filter/filter.js.map +1 -1
- package/dist/tools/components/form/EnhancedDetailPage.cjs.map +1 -1
- package/dist/tools/components/form/EnhancedDetailPage.d.cts +47 -42
- package/dist/tools/components/form/EnhancedDetailPage.d.ts +47 -42
- package/dist/tools/components/form/EnhancedDetailPage.js.map +1 -1
- package/dist/tools/components/form/form-grid.cjs.map +1 -1
- package/dist/tools/components/form/form-grid.d.cts +44 -22
- package/dist/tools/components/form/form-grid.d.ts +44 -22
- package/dist/tools/components/form/form-grid.js.map +1 -1
- package/dist/tools/components/gantt/GanttChart.cjs +1 -1
- package/dist/tools/components/gantt/GanttChart.cjs.map +1 -1
- package/dist/tools/components/gantt/GanttChart.d.cts +20 -1
- package/dist/tools/components/gantt/GanttChart.d.ts +20 -1
- package/dist/tools/components/gantt/GanttChart.js +3 -0
- package/dist/tools/components/gantt/GanttChart.js.map +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.cjs +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.cjs.map +1 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.js +2 -1
- package/dist/tools/components/gantt/components/GanttTaskBar.js.map +1 -1
- package/dist/tools/components/header/header.cjs +1 -1
- package/dist/tools/components/header/header.cjs.map +1 -1
- package/dist/tools/components/header/header.d.cts +103 -40
- package/dist/tools/components/header/header.d.ts +103 -40
- package/dist/tools/components/header/header.js +1 -1
- package/dist/tools/components/header/header.js.map +1 -1
- package/dist/tools/components/i18n/LanguageSwitcher.cjs.map +1 -1
- package/dist/tools/components/i18n/LanguageSwitcher.d.cts +18 -14
- package/dist/tools/components/i18n/LanguageSwitcher.d.ts +18 -14
- package/dist/tools/components/i18n/LanguageSwitcher.js.map +1 -1
- package/dist/tools/components/kanban/KanbanBoard.cjs +1 -1
- package/dist/tools/components/kanban/KanbanBoard.cjs.map +1 -1
- package/dist/tools/components/kanban/KanbanBoard.d.cts +16 -34
- package/dist/tools/components/kanban/KanbanBoard.d.ts +16 -34
- package/dist/tools/components/kanban/KanbanBoard.js +3 -0
- package/dist/tools/components/kanban/KanbanBoard.js.map +1 -1
- package/dist/tools/components/kanban/KanbanColumn.cjs +1 -1
- package/dist/tools/components/kanban/KanbanColumn.cjs.map +1 -1
- package/dist/tools/components/kanban/KanbanColumn.js +1 -1
- package/dist/tools/components/kanban/KanbanColumn.js.map +1 -1
- package/dist/tools/components/kanban/kanban-compound.cjs +1 -1
- package/dist/tools/components/kanban/kanban-compound.cjs.map +1 -1
- package/dist/tools/components/kanban/kanban-compound.js +4 -1
- package/dist/tools/components/kanban/kanban-compound.js.map +1 -1
- package/dist/tools/components/kanban/kanban-primitives.cjs +1 -1
- package/dist/tools/components/kanban/kanban-primitives.cjs.map +1 -1
- package/dist/tools/components/kanban/kanban-primitives.js +0 -1
- package/dist/tools/components/kanban/kanban-primitives.js.map +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.cjs +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.cjs.map +1 -1
- package/dist/tools/components/priority-queue/PriorityCard.js +3 -1
- package/dist/tools/components/priority-queue/PriorityCard.js.map +1 -1
- package/dist/tools/components/sidebar/SmartSidebar.cjs.map +1 -1
- package/dist/tools/components/sidebar/SmartSidebar.d.cts +41 -43
- package/dist/tools/components/sidebar/SmartSidebar.d.ts +41 -43
- package/dist/tools/components/sidebar/SmartSidebar.js.map +1 -1
- package/dist/tools/components/splash/SplashScreen.cjs.map +1 -1
- package/dist/tools/components/splash/SplashScreen.d.cts +43 -68
- package/dist/tools/components/splash/SplashScreen.d.ts +43 -68
- package/dist/tools/components/splash/SplashScreen.js.map +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.cjs +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.cjs.map +1 -1
- package/dist/tools/components/workflow/WorkflowStatusPanel.js +2 -2
- package/dist/tools/components/workflow/WorkflowStatusPanel.js.map +1 -1
- package/dist/tools/lib/data-access/data-access-context.cjs.map +1 -1
- package/dist/tools/lib/data-access/data-access-context.d.cts +15 -6
- package/dist/tools/lib/data-access/data-access-context.d.ts +15 -6
- package/dist/tools/lib/data-access/data-access-context.js.map +1 -1
- package/dist/tools/lib/data-access/react-query-provider.cjs.map +1 -1
- package/dist/tools/lib/data-access/react-query-provider.d.cts +19 -2
- package/dist/tools/lib/data-access/react-query-provider.d.ts +19 -2
- package/dist/tools/lib/data-access/react-query-provider.js.map +1 -1
- package/dist/tools/lib/data-access/react-query.cjs.map +1 -1
- package/dist/tools/lib/data-access/react-query.d.cts +365 -90
- package/dist/tools/lib/data-access/react-query.d.ts +365 -90
- package/dist/tools/lib/data-access/react-query.js.map +1 -1
- package/dist/tools/lib/error/AppError.cjs.map +1 -1
- package/dist/tools/lib/error/AppError.d.cts +157 -63
- package/dist/tools/lib/error/AppError.d.ts +157 -63
- package/dist/tools/lib/error/AppError.js.map +1 -1
- package/dist/tools/lib/hooks/useAsyncWithTimeout.cjs.map +1 -1
- package/dist/tools/lib/hooks/useAsyncWithTimeout.d.cts +79 -26
- package/dist/tools/lib/hooks/useAsyncWithTimeout.d.ts +79 -26
- package/dist/tools/lib/hooks/useAsyncWithTimeout.js.map +1 -1
- package/dist/tools/lib/hooks/useError.cjs.map +1 -1
- package/dist/tools/lib/hooks/useError.d.cts +51 -16
- package/dist/tools/lib/hooks/useError.d.ts +51 -16
- package/dist/tools/lib/hooks/useError.js.map +1 -1
- package/dist/tools/lib/schema/ajv.cjs +1 -1
- package/dist/tools/lib/schema/ajv.cjs.map +1 -1
- package/dist/tools/lib/schema/ajv.d.cts +19 -8
- package/dist/tools/lib/schema/ajv.d.ts +19 -8
- package/dist/tools/lib/schema/ajv.js +2 -1
- package/dist/tools/lib/schema/ajv.js.map +1 -1
- package/dist/tools/lib/state/error-store.cjs.map +1 -1
- package/dist/tools/lib/state/error-store.d.cts +61 -10
- package/dist/tools/lib/state/error-store.d.ts +61 -10
- package/dist/tools/lib/state/error-store.js.map +1 -1
- package/dist/tools/lib/state/store-factory.cjs.map +1 -1
- package/dist/tools/lib/state/store-factory.d.cts +25 -4
- package/dist/tools/lib/state/store-factory.d.ts +25 -4
- package/dist/tools/lib/state/store-factory.js.map +1 -1
- package/dist/tools/lib/state/ui-store.cjs.map +1 -1
- package/dist/tools/lib/state/ui-store.d.cts +39 -0
- package/dist/tools/lib/state/ui-store.d.ts +39 -0
- package/dist/tools/lib/state/ui-store.js.map +1 -1
- package/dist/ui/components/theme/theme-context.cjs.map +1 -1
- package/dist/ui/components/theme/theme-context.d.cts +171 -1
- package/dist/ui/components/theme/theme-context.d.ts +171 -1
- package/dist/ui/components/theme/theme-context.js.map +1 -1
- package/dist/ui/components/theme/theme-provider.cjs.map +1 -1
- package/dist/ui/components/theme/theme-provider.d.cts +31 -19
- package/dist/ui/components/theme/theme-provider.d.ts +31 -19
- package/dist/ui/components/theme/theme-provider.js.map +1 -1
- package/dist/ui/components/theme/theme-script.cjs.map +1 -1
- package/dist/ui/components/theme/theme-script.d.cts +16 -1
- package/dist/ui/components/theme/theme-script.d.ts +16 -1
- package/dist/ui/components/theme/theme-script.js.map +1 -1
- package/dist/ui/components/theme/theme-switcher.cjs +1 -1
- package/dist/ui/components/theme/theme-switcher.cjs.map +1 -1
- package/dist/ui/components/theme/theme-switcher.d.cts +82 -13
- package/dist/ui/components/theme/theme-switcher.d.ts +82 -13
- package/dist/ui/components/theme/theme-switcher.js +8 -0
- package/dist/ui/components/theme/theme-switcher.js.map +1 -1
- package/dist/ui/components/ui/accordion.cjs.map +1 -1
- package/dist/ui/components/ui/accordion.d.cts +60 -0
- package/dist/ui/components/ui/accordion.d.ts +60 -0
- package/dist/ui/components/ui/accordion.js.map +1 -1
- package/dist/ui/components/ui/adjustable-pane.cjs.map +1 -1
- package/dist/ui/components/ui/adjustable-pane.d.cts +44 -26
- package/dist/ui/components/ui/adjustable-pane.d.ts +44 -26
- package/dist/ui/components/ui/adjustable-pane.js.map +1 -1
- package/dist/ui/components/ui/alert-dialog.cjs.map +1 -1
- package/dist/ui/components/ui/alert-dialog.d.cts +179 -2
- package/dist/ui/components/ui/alert-dialog.d.ts +179 -2
- package/dist/ui/components/ui/alert-dialog.js.map +1 -1
- package/dist/ui/components/ui/alert.cjs.map +1 -1
- package/dist/ui/components/ui/alert.d.cts +52 -4
- package/dist/ui/components/ui/alert.d.ts +52 -4
- package/dist/ui/components/ui/alert.js.map +1 -1
- package/dist/ui/components/ui/aspect-ratio.cjs.map +1 -1
- package/dist/ui/components/ui/aspect-ratio.d.cts +16 -1
- package/dist/ui/components/ui/aspect-ratio.d.ts +16 -1
- package/dist/ui/components/ui/aspect-ratio.js.map +1 -1
- package/dist/ui/components/ui/avatar.cjs.map +1 -1
- package/dist/ui/components/ui/avatar.d.cts +87 -3
- package/dist/ui/components/ui/avatar.d.ts +87 -3
- package/dist/ui/components/ui/avatar.js.map +1 -1
- package/dist/ui/components/ui/badge-components.cjs.map +1 -1
- package/dist/ui/components/ui/badge-components.d.cts +13 -1
- package/dist/ui/components/ui/badge-components.d.ts +13 -1
- package/dist/ui/components/ui/badge-components.js.map +1 -1
- package/dist/ui/components/ui/badge-variants.cjs.map +1 -1
- package/dist/ui/components/ui/badge-variants.d.cts +15 -0
- package/dist/ui/components/ui/badge-variants.d.ts +15 -0
- package/dist/ui/components/ui/badge-variants.js.map +1 -1
- package/dist/ui/components/ui/breadcrumb.cjs.map +1 -1
- package/dist/ui/components/ui/breadcrumb.d.cts +91 -7
- package/dist/ui/components/ui/breadcrumb.d.ts +91 -7
- package/dist/ui/components/ui/breadcrumb.js.map +1 -1
- package/dist/ui/components/ui/button-components.cjs.map +1 -1
- package/dist/ui/components/ui/button-components.d.cts +18 -6
- package/dist/ui/components/ui/button-components.d.ts +18 -6
- package/dist/ui/components/ui/button-components.js.map +1 -1
- package/dist/ui/components/ui/button-group-components.cjs.map +1 -1
- package/dist/ui/components/ui/button-group-components.d.cts +39 -3
- package/dist/ui/components/ui/button-group-components.d.ts +39 -3
- package/dist/ui/components/ui/button-group-components.js.map +1 -1
- package/dist/ui/components/ui/button-group-variants.cjs.map +1 -1
- package/dist/ui/components/ui/button-group-variants.d.cts +15 -0
- package/dist/ui/components/ui/button-group-variants.d.ts +15 -0
- package/dist/ui/components/ui/button-group-variants.js.map +1 -1
- package/dist/ui/components/ui/button-variants.cjs.map +1 -1
- package/dist/ui/components/ui/button-variants.d.cts +13 -2
- package/dist/ui/components/ui/button-variants.d.ts +13 -2
- package/dist/ui/components/ui/button-variants.js.map +1 -1
- package/dist/ui/components/ui/card.cjs.map +1 -1
- package/dist/ui/components/ui/card.d.cts +106 -2
- package/dist/ui/components/ui/card.d.ts +106 -2
- package/dist/ui/components/ui/card.js.map +1 -1
- package/dist/ui/components/ui/checkbox-group.cjs.map +1 -1
- package/dist/ui/components/ui/checkbox-group.d.cts +13 -1
- package/dist/ui/components/ui/checkbox-group.d.ts +13 -1
- package/dist/ui/components/ui/checkbox-group.js.map +1 -1
- package/dist/ui/components/ui/checkbox.cjs.map +1 -1
- package/dist/ui/components/ui/checkbox.d.cts +17 -6
- package/dist/ui/components/ui/checkbox.d.ts +17 -6
- package/dist/ui/components/ui/checkbox.js.map +1 -1
- package/dist/ui/components/ui/collapsible.cjs.map +1 -1
- package/dist/ui/components/ui/collapsible.d.cts +39 -3
- package/dist/ui/components/ui/collapsible.d.ts +39 -3
- package/dist/ui/components/ui/collapsible.js.map +1 -1
- package/dist/ui/components/ui/combobox-components.cjs.map +1 -1
- package/dist/ui/components/ui/combobox-components.d.cts +209 -14
- package/dist/ui/components/ui/combobox-components.d.ts +209 -14
- package/dist/ui/components/ui/combobox-components.js.map +1 -1
- package/dist/ui/components/ui/combobox-hooks.cjs.map +1 -1
- package/dist/ui/components/ui/combobox-hooks.d.cts +13 -1
- package/dist/ui/components/ui/combobox-hooks.d.ts +13 -1
- package/dist/ui/components/ui/combobox-hooks.js.map +1 -1
- package/dist/ui/components/ui/command.cjs.map +1 -1
- package/dist/ui/components/ui/command.d.cts +132 -9
- package/dist/ui/components/ui/command.d.ts +132 -9
- package/dist/ui/components/ui/command.js.map +1 -1
- package/dist/ui/components/ui/context-menu.cjs.map +1 -1
- package/dist/ui/components/ui/context-menu.d.cts +233 -2
- package/dist/ui/components/ui/context-menu.d.ts +233 -2
- package/dist/ui/components/ui/context-menu.js.map +1 -1
- package/dist/ui/components/ui/dialog.cjs.map +1 -1
- package/dist/ui/components/ui/dialog.d.cts +157 -5
- package/dist/ui/components/ui/dialog.d.ts +157 -5
- package/dist/ui/components/ui/dialog.js.map +1 -1
- package/dist/ui/components/ui/drawer.cjs.map +1 -1
- package/dist/ui/components/ui/drawer.d.cts +130 -10
- package/dist/ui/components/ui/drawer.d.ts +130 -10
- package/dist/ui/components/ui/drawer.js.map +1 -1
- package/dist/ui/components/ui/dropdown-menu.cjs.map +1 -1
- package/dist/ui/components/ui/dropdown-menu.d.cts +225 -6
- package/dist/ui/components/ui/dropdown-menu.d.ts +225 -6
- package/dist/ui/components/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/components/ui/empty.cjs.map +1 -1
- package/dist/ui/components/ui/empty.d.cts +78 -6
- package/dist/ui/components/ui/empty.d.ts +78 -6
- package/dist/ui/components/ui/empty.js.map +1 -1
- package/dist/ui/components/ui/field.cjs.map +1 -1
- package/dist/ui/components/ui/field.d.cts +180 -6
- package/dist/ui/components/ui/field.d.ts +180 -6
- package/dist/ui/components/ui/field.js.map +1 -1
- package/dist/ui/components/ui/file-icon.cjs.map +1 -1
- package/dist/ui/components/ui/file-icon.d.cts +32 -4
- package/dist/ui/components/ui/file-icon.d.ts +32 -4
- package/dist/ui/components/ui/file-icon.js.map +1 -1
- package/dist/ui/components/ui/hover-card.cjs.map +1 -1
- package/dist/ui/components/ui/hover-card.d.cts +39 -3
- package/dist/ui/components/ui/hover-card.d.ts +39 -3
- package/dist/ui/components/ui/hover-card.js.map +1 -1
- package/dist/ui/components/ui/input-group.cjs.map +1 -1
- package/dist/ui/components/ui/input-group.d.cts +84 -6
- package/dist/ui/components/ui/input-group.d.ts +84 -6
- package/dist/ui/components/ui/input-group.js.map +1 -1
- package/dist/ui/components/ui/input-otp.cjs.map +1 -1
- package/dist/ui/components/ui/input-otp.d.cts +58 -4
- package/dist/ui/components/ui/input-otp.d.ts +58 -4
- package/dist/ui/components/ui/input-otp.js.map +1 -1
- package/dist/ui/components/ui/input.cjs.map +1 -1
- package/dist/ui/components/ui/input.d.cts +18 -10
- package/dist/ui/components/ui/input.d.ts +18 -10
- package/dist/ui/components/ui/input.js.map +1 -1
- package/dist/ui/components/ui/item.cjs.map +1 -1
- package/dist/ui/components/ui/item.d.cts +130 -10
- package/dist/ui/components/ui/item.d.ts +130 -10
- package/dist/ui/components/ui/item.js.map +1 -1
- package/dist/ui/components/ui/kbd.cjs.map +1 -1
- package/dist/ui/components/ui/kbd.d.cts +26 -2
- package/dist/ui/components/ui/kbd.d.ts +26 -2
- package/dist/ui/components/ui/kbd.js.map +1 -1
- package/dist/ui/components/ui/label.cjs.map +1 -1
- package/dist/ui/components/ui/label.d.cts +15 -0
- package/dist/ui/components/ui/label.d.ts +15 -0
- package/dist/ui/components/ui/label.js.map +1 -1
- package/dist/ui/components/ui/layout.cjs +1 -1
- package/dist/ui/components/ui/layout.cjs.map +1 -1
- package/dist/ui/components/ui/layout.d.cts +45 -11
- package/dist/ui/components/ui/layout.d.ts +45 -11
- package/dist/ui/components/ui/layout.js +22 -20
- package/dist/ui/components/ui/layout.js.map +1 -1
- package/dist/ui/components/ui/menubar.cjs.map +1 -1
- package/dist/ui/components/ui/menubar.d.cts +220 -16
- package/dist/ui/components/ui/menubar.d.ts +220 -16
- package/dist/ui/components/ui/menubar.js.map +1 -1
- package/dist/ui/components/ui/meter.cjs.map +1 -1
- package/dist/ui/components/ui/meter.d.cts +52 -4
- package/dist/ui/components/ui/meter.d.ts +52 -4
- package/dist/ui/components/ui/meter.js.map +1 -1
- package/dist/ui/components/ui/mobile-form-variants.cjs.map +1 -1
- package/dist/ui/components/ui/mobile-form-variants.d.cts +30 -0
- package/dist/ui/components/ui/mobile-form-variants.d.ts +30 -0
- package/dist/ui/components/ui/mobile-form-variants.js.map +1 -1
- package/dist/ui/components/ui/mobile-form.cjs.map +1 -1
- package/dist/ui/components/ui/mobile-form.d.cts +186 -9
- package/dist/ui/components/ui/mobile-form.d.ts +186 -9
- package/dist/ui/components/ui/mobile-form.js.map +1 -1
- package/dist/ui/components/ui/navigation-menu-components.cjs.map +1 -1
- package/dist/ui/components/ui/navigation-menu-components.d.cts +104 -8
- package/dist/ui/components/ui/navigation-menu-components.d.ts +104 -8
- package/dist/ui/components/ui/navigation-menu-components.js.map +1 -1
- package/dist/ui/components/ui/navigation-menu-variants.cjs.map +1 -1
- package/dist/ui/components/ui/navigation-menu-variants.d.cts +15 -0
- package/dist/ui/components/ui/navigation-menu-variants.d.ts +15 -0
- package/dist/ui/components/ui/navigation-menu-variants.js.map +1 -1
- package/dist/ui/components/ui/number-field.cjs.map +1 -1
- package/dist/ui/components/ui/number-field.d.cts +78 -6
- package/dist/ui/components/ui/number-field.d.ts +78 -6
- package/dist/ui/components/ui/number-field.js.map +1 -1
- package/dist/ui/components/ui/pagination.cjs.map +1 -1
- package/dist/ui/components/ui/pagination.d.cts +99 -7
- package/dist/ui/components/ui/pagination.d.ts +99 -7
- package/dist/ui/components/ui/pagination.js.map +1 -1
- package/dist/ui/components/ui/password-input.cjs.map +1 -1
- package/dist/ui/components/ui/password-input.d.cts +10 -7
- package/dist/ui/components/ui/password-input.d.ts +10 -7
- package/dist/ui/components/ui/password-input.js.map +1 -1
- package/dist/ui/components/ui/popover.cjs.map +1 -1
- package/dist/ui/components/ui/popover.d.cts +86 -2
- package/dist/ui/components/ui/popover.d.ts +86 -2
- package/dist/ui/components/ui/popover.js.map +1 -1
- package/dist/ui/components/ui/progress.cjs.map +1 -1
- package/dist/ui/components/ui/progress.d.cts +72 -2
- package/dist/ui/components/ui/progress.d.ts +72 -2
- package/dist/ui/components/ui/progress.js.map +1 -1
- package/dist/ui/components/ui/radio-card.cjs.map +1 -1
- package/dist/ui/components/ui/radio-card.d.cts +32 -4
- package/dist/ui/components/ui/radio-card.d.ts +32 -4
- package/dist/ui/components/ui/radio-card.js.map +1 -1
- package/dist/ui/components/ui/radio-group.cjs.map +1 -1
- package/dist/ui/components/ui/radio-group.d.cts +28 -2
- package/dist/ui/components/ui/radio-group.d.ts +28 -2
- package/dist/ui/components/ui/radio-group.js.map +1 -1
- package/dist/ui/components/ui/resizable.cjs.map +1 -1
- package/dist/ui/components/ui/resizable.d.cts +42 -3
- package/dist/ui/components/ui/resizable.d.ts +42 -3
- package/dist/ui/components/ui/resizable.js.map +1 -1
- package/dist/ui/components/ui/responsive-list.cjs.map +1 -1
- package/dist/ui/components/ui/responsive-list.d.cts +176 -13
- package/dist/ui/components/ui/responsive-list.d.ts +176 -13
- package/dist/ui/components/ui/responsive-list.js.map +1 -1
- package/dist/ui/components/ui/scroll-area.cjs.map +1 -1
- package/dist/ui/components/ui/scroll-area.d.cts +28 -1
- package/dist/ui/components/ui/scroll-area.d.ts +28 -1
- package/dist/ui/components/ui/scroll-area.js.map +1 -1
- package/dist/ui/components/ui/searchable-select-input.cjs.map +1 -1
- package/dist/ui/components/ui/searchable-select-input.d.cts +199 -49
- package/dist/ui/components/ui/searchable-select-input.d.ts +199 -49
- package/dist/ui/components/ui/searchable-select-input.js.map +1 -1
- package/dist/ui/components/ui/select.cjs.map +1 -1
- package/dist/ui/components/ui/select.d.cts +205 -40
- package/dist/ui/components/ui/select.d.ts +205 -40
- package/dist/ui/components/ui/select.js.map +1 -1
- package/dist/ui/components/ui/separator.cjs.map +1 -1
- package/dist/ui/components/ui/separator.d.cts +13 -2
- package/dist/ui/components/ui/separator.d.ts +13 -2
- package/dist/ui/components/ui/separator.js.map +1 -1
- package/dist/ui/components/ui/sheet.cjs.map +1 -1
- package/dist/ui/components/ui/sheet.d.cts +128 -3
- package/dist/ui/components/ui/sheet.d.ts +128 -3
- package/dist/ui/components/ui/sheet.js.map +1 -1
- package/dist/ui/components/ui/skeleton.cjs.map +1 -1
- package/dist/ui/components/ui/skeleton.d.cts +13 -1
- package/dist/ui/components/ui/skeleton.d.ts +13 -1
- package/dist/ui/components/ui/skeleton.js.map +1 -1
- package/dist/ui/components/ui/slider.cjs.map +1 -1
- package/dist/ui/components/ui/slider.d.cts +13 -7
- package/dist/ui/components/ui/slider.d.ts +13 -7
- package/dist/ui/components/ui/slider.js.map +1 -1
- package/dist/ui/components/ui/spinner.cjs.map +1 -1
- package/dist/ui/components/ui/spinner.d.cts +13 -1
- package/dist/ui/components/ui/spinner.d.ts +13 -1
- package/dist/ui/components/ui/spinner.js.map +1 -1
- package/dist/ui/components/ui/switch.cjs.map +1 -1
- package/dist/ui/components/ui/switch.d.cts +26 -0
- package/dist/ui/components/ui/switch.d.ts +26 -0
- package/dist/ui/components/ui/switch.js.map +1 -1
- package/dist/ui/components/ui/table.cjs.map +1 -1
- package/dist/ui/components/ui/table.d.cts +118 -2
- package/dist/ui/components/ui/table.d.ts +118 -2
- package/dist/ui/components/ui/table.js.map +1 -1
- package/dist/ui/components/ui/tabs-components.cjs.map +1 -1
- package/dist/ui/components/ui/tabs-components.d.cts +52 -5
- package/dist/ui/components/ui/tabs-components.d.ts +52 -5
- package/dist/ui/components/ui/tabs-components.js.map +1 -1
- package/dist/ui/components/ui/tabs-variants.cjs.map +1 -1
- package/dist/ui/components/ui/tabs-variants.d.cts +15 -0
- package/dist/ui/components/ui/tabs-variants.d.ts +15 -0
- package/dist/ui/components/ui/tabs-variants.js.map +1 -1
- package/dist/ui/components/ui/textarea.cjs.map +1 -1
- package/dist/ui/components/ui/textarea.d.cts +23 -0
- package/dist/ui/components/ui/textarea.d.ts +23 -0
- package/dist/ui/components/ui/textarea.js.map +1 -1
- package/dist/ui/components/ui/toast.cjs.map +1 -1
- package/dist/ui/components/ui/toast.d.cts +136 -0
- package/dist/ui/components/ui/toast.d.ts +136 -0
- package/dist/ui/components/ui/toast.js.map +1 -1
- package/dist/ui/components/ui/toaster.cjs.map +1 -1
- package/dist/ui/components/ui/toaster.d.cts +12 -3
- package/dist/ui/components/ui/toaster.d.ts +12 -3
- package/dist/ui/components/ui/toaster.js.map +1 -1
- package/dist/ui/components/ui/toggle-components.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-components.d.cts +15 -0
- package/dist/ui/components/ui/toggle-components.d.ts +15 -0
- package/dist/ui/components/ui/toggle-components.js.map +1 -1
- package/dist/ui/components/ui/toggle-group.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-group.d.cts +33 -0
- package/dist/ui/components/ui/toggle-group.d.ts +33 -0
- package/dist/ui/components/ui/toggle-group.js.map +1 -1
- package/dist/ui/components/ui/toggle-variants.cjs.map +1 -1
- package/dist/ui/components/ui/toggle-variants.d.cts +15 -0
- package/dist/ui/components/ui/toggle-variants.d.ts +15 -0
- package/dist/ui/components/ui/toggle-variants.js.map +1 -1
- package/dist/ui/components/ui/toolbar.cjs.map +1 -1
- package/dist/ui/components/ui/toolbar.d.cts +94 -7
- package/dist/ui/components/ui/toolbar.d.ts +94 -7
- package/dist/ui/components/ui/toolbar.js.map +1 -1
- package/dist/ui/components/ui/tooltip.cjs.map +1 -1
- package/dist/ui/components/ui/tooltip.d.cts +54 -3
- package/dist/ui/components/ui/tooltip.d.ts +54 -3
- package/dist/ui/components/ui/tooltip.js.map +1 -1
- package/dist/ui/lib/hooks/use-gps.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-gps.d.cts +29 -4
- package/dist/ui/lib/hooks/use-gps.d.ts +29 -4
- package/dist/ui/lib/hooks/use-gps.js.map +1 -1
- package/dist/ui/lib/hooks/use-is-client.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-is-client.d.cts +11 -2
- package/dist/ui/lib/hooks/use-is-client.d.ts +11 -2
- package/dist/ui/lib/hooks/use-is-client.js.map +1 -1
- package/dist/ui/lib/hooks/use-keyboard-shortcut.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-keyboard-shortcut.d.cts +48 -18
- package/dist/ui/lib/hooks/use-keyboard-shortcut.d.ts +48 -18
- package/dist/ui/lib/hooks/use-keyboard-shortcut.js.map +1 -1
- package/dist/ui/lib/hooks/use-mobile.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-mobile.d.cts +11 -3
- package/dist/ui/lib/hooks/use-mobile.d.ts +11 -3
- package/dist/ui/lib/hooks/use-mobile.js.map +1 -1
- package/dist/ui/lib/hooks/use-toast.cjs.map +1 -1
- package/dist/ui/lib/hooks/use-toast.d.cts +184 -15
- package/dist/ui/lib/hooks/use-toast.d.ts +184 -15
- package/dist/ui/lib/hooks/use-toast.js.map +1 -1
- package/dist/ui/lib/ime-utils.cjs.map +1 -1
- package/dist/ui/lib/ime-utils.d.cts +40 -13
- package/dist/ui/lib/ime-utils.d.ts +40 -13
- package/dist/ui/lib/ime-utils.js.map +1 -1
- package/dist/ui/lib/utils.cjs.map +1 -1
- package/dist/ui/lib/utils.d.cts +9 -6
- package/dist/ui/lib/utils.d.ts +9 -6
- package/dist/ui/lib/utils.js.map +1 -1
- package/docs/ai.md +34 -1
- package/docs/exports.md +5 -1
- package/docs/index.md +89 -16
- package/docs/migration.md +268 -0
- package/docs/request-form.md +4 -1
- package/docs/tools.md +4 -1
- package/docs/ui.md +4 -1
- package/llms-full.txt +499 -36
- package/llms.txt +4 -0
- package/package.json +35 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.cjs","names":["React","getInstanceCacheScope","getAdapterCacheScope","useQueryClient","useMemo","createAuthSession","useState","createSessionCache","useQuery","subscribeSessionCacheStorageEvent","useCallback","AuthContext","require_runtime","require_tools_components_auth_useAuth","require_tools_components_auth_auth_session","require_tools_components_auth_session_cache","react_jsx_runtime","react","_tanstack_react_query","_alneas_appkit_core_data","AuthProvider","providerId","scope","adapter","ScopedAuthProvider","queryClient","sessionId","session","epoch","isActionLoading","setIsActionLoading","actionError","setActionError","sessionCache","optimisticSession","mounted","placeholderData","hit","user","isQueryLoading","queryError","signal","isSessionVerified","isFetched","isPlaceholderData","isLoggedOutKnown","isLoading","error","unsubscribe","login","email","password","err","register","data","logout","resetPassword","updateEmail","updatePassword","reauthenticate","sendVerificationEmail","getToken","loginWithProvider","args"],"sources":["../../../../src/tools/components/auth/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { AuthAdapter } from './types';\nimport { AuthContext } from './useAuth';\nimport { getAdapterCacheScope, getInstanceCacheScope } from '../../lib/data-access/cache-scope';\nimport { createAuthSession } from './auth-session';\nimport {\n createSessionCache,\n subscribeSessionCacheStorageEvent,\n type SessionCacheOptions,\n} from './session-cache';\n\n/** 楽観セッションキャッシュの設定。`true` はデフォルト TTL で有効化、`false`/省略は無効 */\nexport type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;\n\ninterface AuthProviderProps {\n children: React.ReactNode;\n adapter: AuthAdapter;\n /**\n * 楽観セッションキャッシュ(stale-while-revalidate)を有効化します。\n *\n * 有効時は、前回のセッション検証結果を localStorage に保持し、リロード時に即座に\n * 最後の状態で描画します。裏で whoami 等を再検証し、クッキーが無効なら即座に\n * ログイン画面へフォールバックします。これにより「認証確認待ち」による画面ブロック\n * (特に初期ロード時のログイン画面遅延)を排除できます。\n *\n * 保存するのは表示用プロフィールのみで、トークン等の機密は含みません。未指定時は無効。\n *\n * @example\n * ```tsx\n * <AuthProvider adapter={adapter} optimisticSession />\n * // または TTL を指定\n * <AuthProvider adapter={adapter} optimisticSession={{ ttl: 1000 * 60 * 60 * 24 }} />\n * ```\n */\n optimisticSession?: OptimisticSessionOption;\n}\n\n/**\n * Authentication Provider Component\n *\n * Provides authentication context to child components with SSR support.\n *\n * Each provider/adapter has an isolated session key under `['session']`. On initial verification\n * and principal changes, application queries in the shared QueryClient are cancelled and removed,\n * and children remount to discard observer/component state. Same-user refreshes preserve them.\n * Use separate QueryClients for independent authentication domains. Data keys remain a cache\n * mechanism, not authorization; enforce access in the backend. Optimistic storage reuse across\n * reloads requires an explicit, non-secret `adapter.cacheScope`.\n *\n * **SSR Behavior:**\n * - During SSR and initial client render, auth state is `{ user: null, isLoading: true }`\n * - Auth listener is only activated after client-side mount\n * - This prevents hydration mismatches between server and client\n *\n * **Optimistic session:**\n * - `optimisticSession` が有効で、かつ直近のセッション状態が localStorage にあれば、\n * `isLoading` は即 `false` となり `user` は最後の値(または null)で描画されます。\n * その際 `isSessionVerified` は `false` となり、裏での再検証が完了するまで機微な\n * 画面をガードできます。\n *\n * @example\n * ```tsx\n * import { AuthProvider, BetterAuthAdapter } from '@alneas/appkit-react/tools/auth';\n *\n * const adapter = new BetterAuthAdapter(authClient);\n *\n * <AuthProvider adapter={adapter} optimisticSession>\n * <App />\n * </AuthProvider>\n * ```\n */\nexport function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps) {\n const providerId = React.useId();\n const scope = `${getInstanceCacheScope(adapter)}:${getAdapterCacheScope(adapter)}`;\n return (\n <ScopedAuthProvider\n key={scope}\n adapter={adapter}\n optimisticSession={optimisticSession}\n providerId={providerId}\n scope={scope}\n >\n {children}\n </ScopedAuthProvider>\n );\n}\n\nfunction ScopedAuthProvider({\n children,\n adapter,\n optimisticSession,\n providerId,\n scope,\n}: AuthProviderProps & { providerId: string; scope: string }) {\n const queryClient = useQueryClient();\n // A fresh mounted boundary must verify again even when returning to a previously used adapter.\n const sessionId = React.useId();\n const session = useMemo(\n () =>\n createAuthSession(queryClient, adapter, [\n 'session',\n 'react-tools.auth',\n providerId,\n scope,\n sessionId,\n ]),\n [queryClient, adapter, providerId, scope, sessionId],\n );\n const epoch = React.useSyncExternalStore(\n session.subscribe,\n session.getSnapshot,\n session.getServerSnapshot,\n );\n const [isActionLoading, setIsActionLoading] = useState(false);\n const [actionError, setActionError] = useState<Error | null>(null);\n\n const sessionCache = useMemo(() => {\n if (!optimisticSession) return null;\n const opts: SessionCacheOptions = optimisticSession === true ? {} : optimisticSession;\n return createSessionCache({\n ...opts,\n key: `dataarthub.auth.last-session:${providerId}:${getAdapterCacheScope(adapter)}`,\n });\n }, [optimisticSession, providerId, adapter]);\n\n // Mark component as mounted (client-side only)\n // useSyncExternalStore ensures we have a consistent value during hydration\n const mounted = React.useSyncExternalStore(\n React.useCallback(() => () => {}, []),\n () => true,\n () => false,\n );\n\n // 楽観表示用の placeholder を読み込む(mounted 以降、かつ有効期限内のみ)\n const placeholderData = React.useMemo(() => {\n if (!sessionCache || !mounted) return undefined;\n const hit = sessionCache.read();\n // eslint-disable-next-line react-hooks/purity\n if (!hit || hit.exp <= Date.now()) return undefined;\n return hit.user; // User | null(null は「最後に未ログイン」\n }, [sessionCache, mounted]);\n\n // Session query using TanStack Query\n const {\n data: user = null,\n isLoading: isQueryLoading,\n error: queryError,\n isPlaceholderData,\n isFetched,\n } = useQuery({\n queryKey: session.queryKey,\n queryFn: ({ signal }) => session.read(signal),\n enabled: mounted,\n placeholderData,\n staleTime: sessionCache ? 1000 * 60 * 5 : 0,\n });\n\n // 楽観表示中かどうか(placeholder データで描画中=裏で再検証中)\n const isSessionVerified = isFetched && !isPlaceholderData;\n // ログアウト確定など、明示的に未ログインが分かっている状態か\n const isLoggedOutKnown = isSessionVerified && user === null;\n\n const isLoading = !mounted || isQueryLoading || isActionLoading;\n const error = actionError || (queryError as Error | null);\n\n // 確定したセッション状態を localStorage に永続化(楽観キャッシュの更新)\n useEffect(() => {\n if (!sessionCache || !isFetched || isPlaceholderData) return;\n sessionCache.write(user);\n }, [sessionCache, isFetched, isPlaceholderData, user]);\n\n // 他タブでのログイン/ログアウトを検知して再検証\n useEffect(() => {\n if (!sessionCache || !mounted) return;\n return subscribeSessionCacheStorageEvent(sessionCache.key, () => {\n void queryClient.invalidateQueries({ queryKey: session.queryKey, exact: true });\n });\n }, [sessionCache, mounted, queryClient, session]);\n\n // Setup auth state listener only on client-side\n useEffect(() => {\n if (!mounted) return;\n\n session.activate();\n const unsubscribe = adapter.onAuthStateChanged(session.publish);\n return () => {\n unsubscribe();\n session.deactivate();\n };\n }, [adapter, mounted, session]);\n\n const login = useCallback(\n async (email: string, password: string) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.login(email, password));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const register = useCallback(\n async (email: string, password: string, data?: { name?: string }) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.register(email, password, data));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const logout = useCallback(async () => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n await session.run(() => adapter.logout(), true);\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n }, [adapter, session]);\n\n const resetPassword = useCallback(\n async (email: string) => {\n return adapter.resetPassword(email);\n },\n [adapter],\n );\n\n const updateEmail = useCallback(\n async (email: string) => {\n return adapter.updateEmail(email);\n },\n [adapter],\n );\n\n const updatePassword = useCallback(\n async (password: string) => {\n return adapter.updatePassword(password);\n },\n [adapter],\n );\n\n const reauthenticate = useMemo(() => {\n return adapter.reauthenticate\n ? async (password: string) => adapter.reauthenticate!(password)\n : undefined;\n }, [adapter]);\n\n const sendVerificationEmail = useMemo(() => {\n return adapter.sendVerificationEmail ? async () => adapter.sendVerificationEmail!() : undefined;\n }, [adapter]);\n\n const getToken = useMemo(() => {\n return adapter.getToken ? async () => adapter.getToken!() : undefined;\n }, [adapter]);\n\n const loginWithProvider = useCallback(\n async (...args: Parameters<NonNullable<AuthAdapter['loginWithProvider']>>) => {\n if (!adapter.loginWithProvider) {\n throw new Error('OAuth login is not supported by this adapter.');\n }\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.loginWithProvider!(...args));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isLoading,\n error,\n /** セッションが裏で再検証され、確定した状態か。楽観表示中は false */\n isSessionVerified,\n /** 再検証によって「未ログイン」が確定しているか */\n isLoggedOutKnown,\n /** 楽観キャッシュを利用中か */\n optimisticSession: !!sessionCache,\n login,\n register,\n logout,\n resetPassword,\n updateEmail,\n updatePassword,\n reauthenticate,\n sendVerificationEmail,\n getToken,\n loginWithProvider: adapter.loginWithProvider ? loginWithProvider : undefined,\n }}\n >\n <React.Fragment key={epoch}>{children}</React.Fragment>\n </AuthContext.Provider>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuthProvider.cjs","names":["React","getInstanceCacheScope","getAdapterCacheScope","useQueryClient","useMemo","createAuthSession","useState","createSessionCache","useQuery","subscribeSessionCacheStorageEvent","useCallback","AuthContext","require_runtime","require_tools_components_auth_useAuth","require_tools_components_auth_auth_session","require_tools_components_auth_session_cache","react_jsx_runtime","react","_tanstack_react_query","_alneas_appkit_core_data","AuthProvider","providerId","scope","adapter","ScopedAuthProvider","queryClient","sessionId","session","epoch","isActionLoading","setIsActionLoading","actionError","setActionError","sessionCache","optimisticSession","mounted","placeholderData","hit","user","isQueryLoading","queryError","signal","isSessionVerified","isFetched","isPlaceholderData","isLoggedOutKnown","isLoading","error","unsubscribe","login","email","password","err","register","data","logout","resetPassword","updateEmail","updatePassword","reauthenticate","sendVerificationEmail","getToken","loginWithProvider","args"],"sources":["../../../../src/tools/components/auth/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { AuthAdapter } from './types';\nimport { AuthContext } from './useAuth';\nimport { getAdapterCacheScope, getInstanceCacheScope } from '../../lib/data-access/cache-scope';\nimport { createAuthSession } from './auth-session';\nimport {\n createSessionCache,\n subscribeSessionCacheStorageEvent,\n type SessionCacheOptions,\n} from './session-cache';\n\n/**\n * Optimistic display-cache setting: true uses seven days; false/omission disables it.\n * @see AuthProvider for the canonical usage example.\n */\nexport type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;\n\n/**\n * Inputs to AuthProvider; see the component for provider setup.\n * @see AuthProvider for the canonical usage example.\n */\ninterface AuthProviderProps {\n /** Descendants that consume authentication context. */\n children: React.ReactNode;\n /** Stable host-owned authentication backend adapter. */\n adapter: AuthAdapter;\n /** Enable browser display snapshots with an optional TTL in milliseconds; defaults to disabled. */\n optimisticSession?: OptimisticSessionOption;\n}\n\n/**\n * Provides adapter-backed authentication state and actions to descendants.\n *\n * @param props - Children, stable host adapter and optional optimistic display caching.\n *\n * @returns Authentication context around children, remounted on principal transitions.\n *\n * @throws When rendered without an outer TanStack QueryClientProvider.\n *\n * @remarks Requires React and @tanstack/react-query; no CSS is required. Each mounted\n * provider scopes its session query. Initial verification and principal changes cancel\n * and remove application queries in the shared QueryClient and remount children;\n * same-user refreshes preserve them. Use separate QueryClients for independent auth domains.\n * SSR and hydration begin with user null and isLoading true. Subscriptions start after\n * mount and are disposed on cleanup. With optimisticSession, an unexpired localStorage\n * snapshot can appear while isSessionVerified remains false; gate sensitive UI on backend\n * verification. Storage contains the adapter's User display fields, so exclude secrets.\n * Cross-reload reuse requires an explicit non-secret adapter.cacheScope. Cache separation\n * is not authorization; the backend must enforce access. Login/register/logout/OAuth\n * failures reject and are exposed as context errors. Other adapter actions forward\n * their failures to the caller; session reads use TanStack Query error handling.\n *\n * @example\n * ```tsx\n * import type { ReactNode } from 'react';\n * import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n * import { AuthProvider, type AuthAdapter } from '@alneas/appkit-react/tools/auth';\n * export function AuthRoot({ adapter, queryClient, children }: {\n * adapter: AuthAdapter; queryClient: QueryClient; children: ReactNode;\n * }) {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <AuthProvider adapter={adapter} optimisticSession>{children}</AuthProvider>\n * </QueryClientProvider>\n * );\n * }\n * ```\n */\nexport function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps) {\n const providerId = React.useId();\n const scope = `${getInstanceCacheScope(adapter)}:${getAdapterCacheScope(adapter)}`;\n return (\n <ScopedAuthProvider\n key={scope}\n adapter={adapter}\n optimisticSession={optimisticSession}\n providerId={providerId}\n scope={scope}\n >\n {children}\n </ScopedAuthProvider>\n );\n}\n\nfunction ScopedAuthProvider({\n children,\n adapter,\n optimisticSession,\n providerId,\n scope,\n}: AuthProviderProps & { providerId: string; scope: string }) {\n const queryClient = useQueryClient();\n // A fresh mounted boundary must verify again even when returning to a previously used adapter.\n const sessionId = React.useId();\n const session = useMemo(\n () =>\n createAuthSession(queryClient, adapter, [\n 'session',\n 'react-tools.auth',\n providerId,\n scope,\n sessionId,\n ]),\n [queryClient, adapter, providerId, scope, sessionId],\n );\n const epoch = React.useSyncExternalStore(\n session.subscribe,\n session.getSnapshot,\n session.getServerSnapshot,\n );\n const [isActionLoading, setIsActionLoading] = useState(false);\n const [actionError, setActionError] = useState<Error | null>(null);\n\n const sessionCache = useMemo(() => {\n if (!optimisticSession) return null;\n const opts: SessionCacheOptions = optimisticSession === true ? {} : optimisticSession;\n return createSessionCache({\n ...opts,\n key: `dataarthub.auth.last-session:${providerId}:${getAdapterCacheScope(adapter)}`,\n });\n }, [optimisticSession, providerId, adapter]);\n\n // Mark component as mounted (client-side only)\n // useSyncExternalStore ensures we have a consistent value during hydration\n const mounted = React.useSyncExternalStore(\n React.useCallback(() => () => {}, []),\n () => true,\n () => false,\n );\n\n // 楽観表示用の placeholder を読み込む(mounted 以降、かつ有効期限内のみ)\n const placeholderData = React.useMemo(() => {\n if (!sessionCache || !mounted) return undefined;\n const hit = sessionCache.read();\n // eslint-disable-next-line react-hooks/purity\n if (!hit || hit.exp <= Date.now()) return undefined;\n return hit.user; // User | null(null は「最後に未ログイン」\n }, [sessionCache, mounted]);\n\n // Session query using TanStack Query\n const {\n data: user = null,\n isLoading: isQueryLoading,\n error: queryError,\n isPlaceholderData,\n isFetched,\n } = useQuery({\n queryKey: session.queryKey,\n queryFn: ({ signal }) => session.read(signal),\n enabled: mounted,\n placeholderData,\n staleTime: sessionCache ? 1000 * 60 * 5 : 0,\n });\n\n // 楽観表示中かどうか(placeholder データで描画中=裏で再検証中)\n const isSessionVerified = isFetched && !isPlaceholderData;\n // ログアウト確定など、明示的に未ログインが分かっている状態か\n const isLoggedOutKnown = isSessionVerified && user === null;\n\n const isLoading = !mounted || isQueryLoading || isActionLoading;\n const error = actionError || (queryError as Error | null);\n\n // 確定したセッション状態を localStorage に永続化(楽観キャッシュの更新)\n useEffect(() => {\n if (!sessionCache || !isFetched || isPlaceholderData) return;\n sessionCache.write(user);\n }, [sessionCache, isFetched, isPlaceholderData, user]);\n\n // 他タブでのログイン/ログアウトを検知して再検証\n useEffect(() => {\n if (!sessionCache || !mounted) return;\n return subscribeSessionCacheStorageEvent(sessionCache.key, () => {\n void queryClient.invalidateQueries({ queryKey: session.queryKey, exact: true });\n });\n }, [sessionCache, mounted, queryClient, session]);\n\n // Setup auth state listener only on client-side\n useEffect(() => {\n if (!mounted) return;\n\n session.activate();\n const unsubscribe = adapter.onAuthStateChanged(session.publish);\n return () => {\n unsubscribe();\n session.deactivate();\n };\n }, [adapter, mounted, session]);\n\n const login = useCallback(\n async (email: string, password: string) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.login(email, password));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const register = useCallback(\n async (email: string, password: string, data?: { name?: string }) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.register(email, password, data));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const logout = useCallback(async () => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n await session.run(() => adapter.logout(), true);\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n }, [adapter, session]);\n\n const resetPassword = useCallback(\n async (email: string) => {\n return adapter.resetPassword(email);\n },\n [adapter],\n );\n\n const updateEmail = useCallback(\n async (email: string) => {\n return adapter.updateEmail(email);\n },\n [adapter],\n );\n\n const updatePassword = useCallback(\n async (password: string) => {\n return adapter.updatePassword(password);\n },\n [adapter],\n );\n\n const reauthenticate = useMemo(() => {\n return adapter.reauthenticate\n ? async (password: string) => adapter.reauthenticate!(password)\n : undefined;\n }, [adapter]);\n\n const sendVerificationEmail = useMemo(() => {\n return adapter.sendVerificationEmail ? async () => adapter.sendVerificationEmail!() : undefined;\n }, [adapter]);\n\n const getToken = useMemo(() => {\n return adapter.getToken ? async () => adapter.getToken!() : undefined;\n }, [adapter]);\n\n const loginWithProvider = useCallback(\n async (...args: Parameters<NonNullable<AuthAdapter['loginWithProvider']>>) => {\n if (!adapter.loginWithProvider) {\n throw new Error('OAuth login is not supported by this adapter.');\n }\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.loginWithProvider!(...args));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isLoading,\n error,\n /** Whether backend verification completed; false during optimistic display. */\n isSessionVerified,\n /** Whether verification confirmed a logged-out state. */\n isLoggedOutKnown,\n /** Whether optimistic display caching is enabled. */\n optimisticSession: !!sessionCache,\n login,\n register,\n logout,\n resetPassword,\n updateEmail,\n updatePassword,\n reauthenticate,\n sendVerificationEmail,\n getToken,\n loginWithProvider: adapter.loginWithProvider ? loginWithProvider : undefined,\n }}\n >\n <React.Fragment key={epoch}>{children}</React.Fragment>\n </AuthContext.Provider>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,62 +1,59 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { AuthAdapter } from './types.cjs';
|
|
3
3
|
import { SessionCacheOptions } from './session-cache.cjs';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Optimistic display-cache setting: true uses seven days; false/omission disables it.
|
|
6
|
+
* @see AuthProvider for the canonical usage example.
|
|
7
|
+
*/
|
|
5
8
|
export type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;
|
|
9
|
+
/**
|
|
10
|
+
* Inputs to AuthProvider; see the component for provider setup.
|
|
11
|
+
* @see AuthProvider for the canonical usage example.
|
|
12
|
+
*/
|
|
6
13
|
interface AuthProviderProps {
|
|
14
|
+
/** Descendants that consume authentication context. */
|
|
7
15
|
children: React.ReactNode;
|
|
16
|
+
/** Stable host-owned authentication backend adapter. */
|
|
8
17
|
adapter: AuthAdapter;
|
|
9
|
-
/**
|
|
10
|
-
* 楽観セッションキャッシュ(stale-while-revalidate)を有効化します。
|
|
11
|
-
*
|
|
12
|
-
* 有効時は、前回のセッション検証結果を localStorage に保持し、リロード時に即座に
|
|
13
|
-
* 最後の状態で描画します。裏で whoami 等を再検証し、クッキーが無効なら即座に
|
|
14
|
-
* ログイン画面へフォールバックします。これにより「認証確認待ち」による画面ブロック
|
|
15
|
-
* (特に初期ロード時のログイン画面遅延)を排除できます。
|
|
16
|
-
*
|
|
17
|
-
* 保存するのは表示用プロフィールのみで、トークン等の機密は含みません。未指定時は無効。
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* <AuthProvider adapter={adapter} optimisticSession />
|
|
22
|
-
* // または TTL を指定
|
|
23
|
-
* <AuthProvider adapter={adapter} optimisticSession={{ ttl: 1000 * 60 * 60 * 24 }} />
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
18
|
+
/** Enable browser display snapshots with an optional TTL in milliseconds; defaults to disabled. */
|
|
26
19
|
optimisticSession?: OptimisticSessionOption;
|
|
27
20
|
}
|
|
28
21
|
/**
|
|
29
|
-
*
|
|
22
|
+
* Provides adapter-backed authentication state and actions to descendants.
|
|
30
23
|
*
|
|
31
|
-
*
|
|
24
|
+
* @param props - Children, stable host adapter and optional optimistic display caching.
|
|
32
25
|
*
|
|
33
|
-
*
|
|
34
|
-
* and principal changes, application queries in the shared QueryClient are cancelled and removed,
|
|
35
|
-
* and children remount to discard observer/component state. Same-user refreshes preserve them.
|
|
36
|
-
* Use separate QueryClients for independent authentication domains. Data keys remain a cache
|
|
37
|
-
* mechanism, not authorization; enforce access in the backend. Optimistic storage reuse across
|
|
38
|
-
* reloads requires an explicit, non-secret `adapter.cacheScope`.
|
|
26
|
+
* @returns Authentication context around children, remounted on principal transitions.
|
|
39
27
|
*
|
|
40
|
-
*
|
|
41
|
-
* - During SSR and initial client render, auth state is `{ user: null, isLoading: true }`
|
|
42
|
-
* - Auth listener is only activated after client-side mount
|
|
43
|
-
* - This prevents hydration mismatches between server and client
|
|
28
|
+
* @throws When rendered without an outer TanStack QueryClientProvider.
|
|
44
29
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
30
|
+
* @remarks Requires React and @tanstack/react-query; no CSS is required. Each mounted
|
|
31
|
+
* provider scopes its session query. Initial verification and principal changes cancel
|
|
32
|
+
* and remove application queries in the shared QueryClient and remount children;
|
|
33
|
+
* same-user refreshes preserve them. Use separate QueryClients for independent auth domains.
|
|
34
|
+
* SSR and hydration begin with user null and isLoading true. Subscriptions start after
|
|
35
|
+
* mount and are disposed on cleanup. With optimisticSession, an unexpired localStorage
|
|
36
|
+
* snapshot can appear while isSessionVerified remains false; gate sensitive UI on backend
|
|
37
|
+
* verification. Storage contains the adapter's User display fields, so exclude secrets.
|
|
38
|
+
* Cross-reload reuse requires an explicit non-secret adapter.cacheScope. Cache separation
|
|
39
|
+
* is not authorization; the backend must enforce access. Login/register/logout/OAuth
|
|
40
|
+
* failures reject and are exposed as context errors. Other adapter actions forward
|
|
41
|
+
* their failures to the caller; session reads use TanStack Query error handling.
|
|
50
42
|
*
|
|
51
43
|
* @example
|
|
52
44
|
* ```tsx
|
|
53
|
-
* import {
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
45
|
+
* import type { ReactNode } from 'react';
|
|
46
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
47
|
+
* import { AuthProvider, type AuthAdapter } from '@alneas/appkit-react/tools/auth';
|
|
48
|
+
* export function AuthRoot({ adapter, queryClient, children }: {
|
|
49
|
+
* adapter: AuthAdapter; queryClient: QueryClient; children: ReactNode;
|
|
50
|
+
* }) {
|
|
51
|
+
* return (
|
|
52
|
+
* <QueryClientProvider client={queryClient}>
|
|
53
|
+
* <AuthProvider adapter={adapter} optimisticSession>{children}</AuthProvider>
|
|
54
|
+
* </QueryClientProvider>
|
|
55
|
+
* );
|
|
56
|
+
* }
|
|
60
57
|
* ```
|
|
61
58
|
*/
|
|
62
59
|
export declare function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps): React.JSX.Element;
|
|
@@ -1,62 +1,59 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { AuthAdapter } from './types.js';
|
|
3
3
|
import { SessionCacheOptions } from './session-cache.js';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Optimistic display-cache setting: true uses seven days; false/omission disables it.
|
|
6
|
+
* @see AuthProvider for the canonical usage example.
|
|
7
|
+
*/
|
|
5
8
|
export type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;
|
|
9
|
+
/**
|
|
10
|
+
* Inputs to AuthProvider; see the component for provider setup.
|
|
11
|
+
* @see AuthProvider for the canonical usage example.
|
|
12
|
+
*/
|
|
6
13
|
interface AuthProviderProps {
|
|
14
|
+
/** Descendants that consume authentication context. */
|
|
7
15
|
children: React.ReactNode;
|
|
16
|
+
/** Stable host-owned authentication backend adapter. */
|
|
8
17
|
adapter: AuthAdapter;
|
|
9
|
-
/**
|
|
10
|
-
* 楽観セッションキャッシュ(stale-while-revalidate)を有効化します。
|
|
11
|
-
*
|
|
12
|
-
* 有効時は、前回のセッション検証結果を localStorage に保持し、リロード時に即座に
|
|
13
|
-
* 最後の状態で描画します。裏で whoami 等を再検証し、クッキーが無効なら即座に
|
|
14
|
-
* ログイン画面へフォールバックします。これにより「認証確認待ち」による画面ブロック
|
|
15
|
-
* (特に初期ロード時のログイン画面遅延)を排除できます。
|
|
16
|
-
*
|
|
17
|
-
* 保存するのは表示用プロフィールのみで、トークン等の機密は含みません。未指定時は無効。
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* <AuthProvider adapter={adapter} optimisticSession />
|
|
22
|
-
* // または TTL を指定
|
|
23
|
-
* <AuthProvider adapter={adapter} optimisticSession={{ ttl: 1000 * 60 * 60 * 24 }} />
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
18
|
+
/** Enable browser display snapshots with an optional TTL in milliseconds; defaults to disabled. */
|
|
26
19
|
optimisticSession?: OptimisticSessionOption;
|
|
27
20
|
}
|
|
28
21
|
/**
|
|
29
|
-
*
|
|
22
|
+
* Provides adapter-backed authentication state and actions to descendants.
|
|
30
23
|
*
|
|
31
|
-
*
|
|
24
|
+
* @param props - Children, stable host adapter and optional optimistic display caching.
|
|
32
25
|
*
|
|
33
|
-
*
|
|
34
|
-
* and principal changes, application queries in the shared QueryClient are cancelled and removed,
|
|
35
|
-
* and children remount to discard observer/component state. Same-user refreshes preserve them.
|
|
36
|
-
* Use separate QueryClients for independent authentication domains. Data keys remain a cache
|
|
37
|
-
* mechanism, not authorization; enforce access in the backend. Optimistic storage reuse across
|
|
38
|
-
* reloads requires an explicit, non-secret `adapter.cacheScope`.
|
|
26
|
+
* @returns Authentication context around children, remounted on principal transitions.
|
|
39
27
|
*
|
|
40
|
-
*
|
|
41
|
-
* - During SSR and initial client render, auth state is `{ user: null, isLoading: true }`
|
|
42
|
-
* - Auth listener is only activated after client-side mount
|
|
43
|
-
* - This prevents hydration mismatches between server and client
|
|
28
|
+
* @throws When rendered without an outer TanStack QueryClientProvider.
|
|
44
29
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
30
|
+
* @remarks Requires React and @tanstack/react-query; no CSS is required. Each mounted
|
|
31
|
+
* provider scopes its session query. Initial verification and principal changes cancel
|
|
32
|
+
* and remove application queries in the shared QueryClient and remount children;
|
|
33
|
+
* same-user refreshes preserve them. Use separate QueryClients for independent auth domains.
|
|
34
|
+
* SSR and hydration begin with user null and isLoading true. Subscriptions start after
|
|
35
|
+
* mount and are disposed on cleanup. With optimisticSession, an unexpired localStorage
|
|
36
|
+
* snapshot can appear while isSessionVerified remains false; gate sensitive UI on backend
|
|
37
|
+
* verification. Storage contains the adapter's User display fields, so exclude secrets.
|
|
38
|
+
* Cross-reload reuse requires an explicit non-secret adapter.cacheScope. Cache separation
|
|
39
|
+
* is not authorization; the backend must enforce access. Login/register/logout/OAuth
|
|
40
|
+
* failures reject and are exposed as context errors. Other adapter actions forward
|
|
41
|
+
* their failures to the caller; session reads use TanStack Query error handling.
|
|
50
42
|
*
|
|
51
43
|
* @example
|
|
52
44
|
* ```tsx
|
|
53
|
-
* import {
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
45
|
+
* import type { ReactNode } from 'react';
|
|
46
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
47
|
+
* import { AuthProvider, type AuthAdapter } from '@alneas/appkit-react/tools/auth';
|
|
48
|
+
* export function AuthRoot({ adapter, queryClient, children }: {
|
|
49
|
+
* adapter: AuthAdapter; queryClient: QueryClient; children: ReactNode;
|
|
50
|
+
* }) {
|
|
51
|
+
* return (
|
|
52
|
+
* <QueryClientProvider client={queryClient}>
|
|
53
|
+
* <AuthProvider adapter={adapter} optimisticSession>{children}</AuthProvider>
|
|
54
|
+
* </QueryClientProvider>
|
|
55
|
+
* );
|
|
56
|
+
* }
|
|
60
57
|
* ```
|
|
61
58
|
*/
|
|
62
59
|
export declare function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps): React.JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.js","names":["React","AuthProvider","providerId","scope","getInstanceCacheScope","adapter","getAdapterCacheScope","ScopedAuthProvider","queryClient","useQueryClient","sessionId","session","useMemo","createAuthSession","epoch","isActionLoading","setIsActionLoading","useState","actionError","setActionError","sessionCache","optimisticSession","createSessionCache","mounted","placeholderData","hit","user","isQueryLoading","queryError","useQuery","signal","isSessionVerified","isFetched","isPlaceholderData","isLoggedOutKnown","isLoading","error","useEffect","subscribeSessionCacheStorageEvent","unsubscribe","login","useCallback","email","password","err","register","data","logout","resetPassword","updateEmail","updatePassword","reauthenticate","sendVerificationEmail","getToken","loginWithProvider","args","AuthContext"],"sources":["../../../../src/tools/components/auth/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { AuthAdapter } from './types';\nimport { AuthContext } from './useAuth';\nimport { getAdapterCacheScope, getInstanceCacheScope } from '../../lib/data-access/cache-scope';\nimport { createAuthSession } from './auth-session';\nimport {\n createSessionCache,\n subscribeSessionCacheStorageEvent,\n type SessionCacheOptions,\n} from './session-cache';\n\n/** 楽観セッションキャッシュの設定。`true` はデフォルト TTL で有効化、`false`/省略は無効 */\nexport type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;\n\ninterface AuthProviderProps {\n children: React.ReactNode;\n adapter: AuthAdapter;\n /**\n * 楽観セッションキャッシュ(stale-while-revalidate)を有効化します。\n *\n * 有効時は、前回のセッション検証結果を localStorage に保持し、リロード時に即座に\n * 最後の状態で描画します。裏で whoami 等を再検証し、クッキーが無効なら即座に\n * ログイン画面へフォールバックします。これにより「認証確認待ち」による画面ブロック\n * (特に初期ロード時のログイン画面遅延)を排除できます。\n *\n * 保存するのは表示用プロフィールのみで、トークン等の機密は含みません。未指定時は無効。\n *\n * @example\n * ```tsx\n * <AuthProvider adapter={adapter} optimisticSession />\n * // または TTL を指定\n * <AuthProvider adapter={adapter} optimisticSession={{ ttl: 1000 * 60 * 60 * 24 }} />\n * ```\n */\n optimisticSession?: OptimisticSessionOption;\n}\n\n/**\n * Authentication Provider Component\n *\n * Provides authentication context to child components with SSR support.\n *\n * Each provider/adapter has an isolated session key under `['session']`. On initial verification\n * and principal changes, application queries in the shared QueryClient are cancelled and removed,\n * and children remount to discard observer/component state. Same-user refreshes preserve them.\n * Use separate QueryClients for independent authentication domains. Data keys remain a cache\n * mechanism, not authorization; enforce access in the backend. Optimistic storage reuse across\n * reloads requires an explicit, non-secret `adapter.cacheScope`.\n *\n * **SSR Behavior:**\n * - During SSR and initial client render, auth state is `{ user: null, isLoading: true }`\n * - Auth listener is only activated after client-side mount\n * - This prevents hydration mismatches between server and client\n *\n * **Optimistic session:**\n * - `optimisticSession` が有効で、かつ直近のセッション状態が localStorage にあれば、\n * `isLoading` は即 `false` となり `user` は最後の値(または null)で描画されます。\n * その際 `isSessionVerified` は `false` となり、裏での再検証が完了するまで機微な\n * 画面をガードできます。\n *\n * @example\n * ```tsx\n * import { AuthProvider, BetterAuthAdapter } from '@alneas/appkit-react/tools/auth';\n *\n * const adapter = new BetterAuthAdapter(authClient);\n *\n * <AuthProvider adapter={adapter} optimisticSession>\n * <App />\n * </AuthProvider>\n * ```\n */\nexport function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps) {\n const providerId = React.useId();\n const scope = `${getInstanceCacheScope(adapter)}:${getAdapterCacheScope(adapter)}`;\n return (\n <ScopedAuthProvider\n key={scope}\n adapter={adapter}\n optimisticSession={optimisticSession}\n providerId={providerId}\n scope={scope}\n >\n {children}\n </ScopedAuthProvider>\n );\n}\n\nfunction ScopedAuthProvider({\n children,\n adapter,\n optimisticSession,\n providerId,\n scope,\n}: AuthProviderProps & { providerId: string; scope: string }) {\n const queryClient = useQueryClient();\n // A fresh mounted boundary must verify again even when returning to a previously used adapter.\n const sessionId = React.useId();\n const session = useMemo(\n () =>\n createAuthSession(queryClient, adapter, [\n 'session',\n 'react-tools.auth',\n providerId,\n scope,\n sessionId,\n ]),\n [queryClient, adapter, providerId, scope, sessionId],\n );\n const epoch = React.useSyncExternalStore(\n session.subscribe,\n session.getSnapshot,\n session.getServerSnapshot,\n );\n const [isActionLoading, setIsActionLoading] = useState(false);\n const [actionError, setActionError] = useState<Error | null>(null);\n\n const sessionCache = useMemo(() => {\n if (!optimisticSession) return null;\n const opts: SessionCacheOptions = optimisticSession === true ? {} : optimisticSession;\n return createSessionCache({\n ...opts,\n key: `dataarthub.auth.last-session:${providerId}:${getAdapterCacheScope(adapter)}`,\n });\n }, [optimisticSession, providerId, adapter]);\n\n // Mark component as mounted (client-side only)\n // useSyncExternalStore ensures we have a consistent value during hydration\n const mounted = React.useSyncExternalStore(\n React.useCallback(() => () => {}, []),\n () => true,\n () => false,\n );\n\n // 楽観表示用の placeholder を読み込む(mounted 以降、かつ有効期限内のみ)\n const placeholderData = React.useMemo(() => {\n if (!sessionCache || !mounted) return undefined;\n const hit = sessionCache.read();\n // eslint-disable-next-line react-hooks/purity\n if (!hit || hit.exp <= Date.now()) return undefined;\n return hit.user; // User | null(null は「最後に未ログイン」\n }, [sessionCache, mounted]);\n\n // Session query using TanStack Query\n const {\n data: user = null,\n isLoading: isQueryLoading,\n error: queryError,\n isPlaceholderData,\n isFetched,\n } = useQuery({\n queryKey: session.queryKey,\n queryFn: ({ signal }) => session.read(signal),\n enabled: mounted,\n placeholderData,\n staleTime: sessionCache ? 1000 * 60 * 5 : 0,\n });\n\n // 楽観表示中かどうか(placeholder データで描画中=裏で再検証中)\n const isSessionVerified = isFetched && !isPlaceholderData;\n // ログアウト確定など、明示的に未ログインが分かっている状態か\n const isLoggedOutKnown = isSessionVerified && user === null;\n\n const isLoading = !mounted || isQueryLoading || isActionLoading;\n const error = actionError || (queryError as Error | null);\n\n // 確定したセッション状態を localStorage に永続化(楽観キャッシュの更新)\n useEffect(() => {\n if (!sessionCache || !isFetched || isPlaceholderData) return;\n sessionCache.write(user);\n }, [sessionCache, isFetched, isPlaceholderData, user]);\n\n // 他タブでのログイン/ログアウトを検知して再検証\n useEffect(() => {\n if (!sessionCache || !mounted) return;\n return subscribeSessionCacheStorageEvent(sessionCache.key, () => {\n void queryClient.invalidateQueries({ queryKey: session.queryKey, exact: true });\n });\n }, [sessionCache, mounted, queryClient, session]);\n\n // Setup auth state listener only on client-side\n useEffect(() => {\n if (!mounted) return;\n\n session.activate();\n const unsubscribe = adapter.onAuthStateChanged(session.publish);\n return () => {\n unsubscribe();\n session.deactivate();\n };\n }, [adapter, mounted, session]);\n\n const login = useCallback(\n async (email: string, password: string) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.login(email, password));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const register = useCallback(\n async (email: string, password: string, data?: { name?: string }) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.register(email, password, data));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const logout = useCallback(async () => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n await session.run(() => adapter.logout(), true);\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n }, [adapter, session]);\n\n const resetPassword = useCallback(\n async (email: string) => {\n return adapter.resetPassword(email);\n },\n [adapter],\n );\n\n const updateEmail = useCallback(\n async (email: string) => {\n return adapter.updateEmail(email);\n },\n [adapter],\n );\n\n const updatePassword = useCallback(\n async (password: string) => {\n return adapter.updatePassword(password);\n },\n [adapter],\n );\n\n const reauthenticate = useMemo(() => {\n return adapter.reauthenticate\n ? async (password: string) => adapter.reauthenticate!(password)\n : undefined;\n }, [adapter]);\n\n const sendVerificationEmail = useMemo(() => {\n return adapter.sendVerificationEmail ? async () => adapter.sendVerificationEmail!() : undefined;\n }, [adapter]);\n\n const getToken = useMemo(() => {\n return adapter.getToken ? async () => adapter.getToken!() : undefined;\n }, [adapter]);\n\n const loginWithProvider = useCallback(\n async (...args: Parameters<NonNullable<AuthAdapter['loginWithProvider']>>) => {\n if (!adapter.loginWithProvider) {\n throw new Error('OAuth login is not supported by this adapter.');\n }\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.loginWithProvider!(...args));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isLoading,\n error,\n /** セッションが裏で再検証され、確定した状態か。楽観表示中は false */\n isSessionVerified,\n /** 再検証によって「未ログイン」が確定しているか */\n isLoggedOutKnown,\n /** 楽観キャッシュを利用中か */\n optimisticSession: !!sessionCache,\n login,\n register,\n logout,\n resetPassword,\n updateEmail,\n updatePassword,\n reauthenticate,\n sendVerificationEmail,\n getToken,\n loginWithProvider: adapter.loginWithProvider ? loginWithProvider : undefined,\n }}\n >\n <React.Fragment key={epoch}>{children}</React.Fragment>\n </AuthContext.Provider>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuthProvider.js","names":["React","AuthProvider","providerId","scope","getInstanceCacheScope","adapter","getAdapterCacheScope","ScopedAuthProvider","queryClient","useQueryClient","sessionId","session","useMemo","createAuthSession","epoch","isActionLoading","setIsActionLoading","useState","actionError","setActionError","sessionCache","optimisticSession","createSessionCache","mounted","placeholderData","hit","user","isQueryLoading","queryError","useQuery","signal","isSessionVerified","isFetched","isPlaceholderData","isLoggedOutKnown","isLoading","error","useEffect","subscribeSessionCacheStorageEvent","unsubscribe","login","useCallback","email","password","err","register","data","logout","resetPassword","updateEmail","updatePassword","reauthenticate","sendVerificationEmail","getToken","loginWithProvider","args","AuthContext"],"sources":["../../../../src/tools/components/auth/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { AuthAdapter } from './types';\nimport { AuthContext } from './useAuth';\nimport { getAdapterCacheScope, getInstanceCacheScope } from '../../lib/data-access/cache-scope';\nimport { createAuthSession } from './auth-session';\nimport {\n createSessionCache,\n subscribeSessionCacheStorageEvent,\n type SessionCacheOptions,\n} from './session-cache';\n\n/**\n * Optimistic display-cache setting: true uses seven days; false/omission disables it.\n * @see AuthProvider for the canonical usage example.\n */\nexport type OptimisticSessionOption = boolean | Omit<SessionCacheOptions, 'key'>;\n\n/**\n * Inputs to AuthProvider; see the component for provider setup.\n * @see AuthProvider for the canonical usage example.\n */\ninterface AuthProviderProps {\n /** Descendants that consume authentication context. */\n children: React.ReactNode;\n /** Stable host-owned authentication backend adapter. */\n adapter: AuthAdapter;\n /** Enable browser display snapshots with an optional TTL in milliseconds; defaults to disabled. */\n optimisticSession?: OptimisticSessionOption;\n}\n\n/**\n * Provides adapter-backed authentication state and actions to descendants.\n *\n * @param props - Children, stable host adapter and optional optimistic display caching.\n *\n * @returns Authentication context around children, remounted on principal transitions.\n *\n * @throws When rendered without an outer TanStack QueryClientProvider.\n *\n * @remarks Requires React and @tanstack/react-query; no CSS is required. Each mounted\n * provider scopes its session query. Initial verification and principal changes cancel\n * and remove application queries in the shared QueryClient and remount children;\n * same-user refreshes preserve them. Use separate QueryClients for independent auth domains.\n * SSR and hydration begin with user null and isLoading true. Subscriptions start after\n * mount and are disposed on cleanup. With optimisticSession, an unexpired localStorage\n * snapshot can appear while isSessionVerified remains false; gate sensitive UI on backend\n * verification. Storage contains the adapter's User display fields, so exclude secrets.\n * Cross-reload reuse requires an explicit non-secret adapter.cacheScope. Cache separation\n * is not authorization; the backend must enforce access. Login/register/logout/OAuth\n * failures reject and are exposed as context errors. Other adapter actions forward\n * their failures to the caller; session reads use TanStack Query error handling.\n *\n * @example\n * ```tsx\n * import type { ReactNode } from 'react';\n * import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n * import { AuthProvider, type AuthAdapter } from '@alneas/appkit-react/tools/auth';\n * export function AuthRoot({ adapter, queryClient, children }: {\n * adapter: AuthAdapter; queryClient: QueryClient; children: ReactNode;\n * }) {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <AuthProvider adapter={adapter} optimisticSession>{children}</AuthProvider>\n * </QueryClientProvider>\n * );\n * }\n * ```\n */\nexport function AuthProvider({ children, adapter, optimisticSession }: AuthProviderProps) {\n const providerId = React.useId();\n const scope = `${getInstanceCacheScope(adapter)}:${getAdapterCacheScope(adapter)}`;\n return (\n <ScopedAuthProvider\n key={scope}\n adapter={adapter}\n optimisticSession={optimisticSession}\n providerId={providerId}\n scope={scope}\n >\n {children}\n </ScopedAuthProvider>\n );\n}\n\nfunction ScopedAuthProvider({\n children,\n adapter,\n optimisticSession,\n providerId,\n scope,\n}: AuthProviderProps & { providerId: string; scope: string }) {\n const queryClient = useQueryClient();\n // A fresh mounted boundary must verify again even when returning to a previously used adapter.\n const sessionId = React.useId();\n const session = useMemo(\n () =>\n createAuthSession(queryClient, adapter, [\n 'session',\n 'react-tools.auth',\n providerId,\n scope,\n sessionId,\n ]),\n [queryClient, adapter, providerId, scope, sessionId],\n );\n const epoch = React.useSyncExternalStore(\n session.subscribe,\n session.getSnapshot,\n session.getServerSnapshot,\n );\n const [isActionLoading, setIsActionLoading] = useState(false);\n const [actionError, setActionError] = useState<Error | null>(null);\n\n const sessionCache = useMemo(() => {\n if (!optimisticSession) return null;\n const opts: SessionCacheOptions = optimisticSession === true ? {} : optimisticSession;\n return createSessionCache({\n ...opts,\n key: `dataarthub.auth.last-session:${providerId}:${getAdapterCacheScope(adapter)}`,\n });\n }, [optimisticSession, providerId, adapter]);\n\n // Mark component as mounted (client-side only)\n // useSyncExternalStore ensures we have a consistent value during hydration\n const mounted = React.useSyncExternalStore(\n React.useCallback(() => () => {}, []),\n () => true,\n () => false,\n );\n\n // 楽観表示用の placeholder を読み込む(mounted 以降、かつ有効期限内のみ)\n const placeholderData = React.useMemo(() => {\n if (!sessionCache || !mounted) return undefined;\n const hit = sessionCache.read();\n // eslint-disable-next-line react-hooks/purity\n if (!hit || hit.exp <= Date.now()) return undefined;\n return hit.user; // User | null(null は「最後に未ログイン」\n }, [sessionCache, mounted]);\n\n // Session query using TanStack Query\n const {\n data: user = null,\n isLoading: isQueryLoading,\n error: queryError,\n isPlaceholderData,\n isFetched,\n } = useQuery({\n queryKey: session.queryKey,\n queryFn: ({ signal }) => session.read(signal),\n enabled: mounted,\n placeholderData,\n staleTime: sessionCache ? 1000 * 60 * 5 : 0,\n });\n\n // 楽観表示中かどうか(placeholder データで描画中=裏で再検証中)\n const isSessionVerified = isFetched && !isPlaceholderData;\n // ログアウト確定など、明示的に未ログインが分かっている状態か\n const isLoggedOutKnown = isSessionVerified && user === null;\n\n const isLoading = !mounted || isQueryLoading || isActionLoading;\n const error = actionError || (queryError as Error | null);\n\n // 確定したセッション状態を localStorage に永続化(楽観キャッシュの更新)\n useEffect(() => {\n if (!sessionCache || !isFetched || isPlaceholderData) return;\n sessionCache.write(user);\n }, [sessionCache, isFetched, isPlaceholderData, user]);\n\n // 他タブでのログイン/ログアウトを検知して再検証\n useEffect(() => {\n if (!sessionCache || !mounted) return;\n return subscribeSessionCacheStorageEvent(sessionCache.key, () => {\n void queryClient.invalidateQueries({ queryKey: session.queryKey, exact: true });\n });\n }, [sessionCache, mounted, queryClient, session]);\n\n // Setup auth state listener only on client-side\n useEffect(() => {\n if (!mounted) return;\n\n session.activate();\n const unsubscribe = adapter.onAuthStateChanged(session.publish);\n return () => {\n unsubscribe();\n session.deactivate();\n };\n }, [adapter, mounted, session]);\n\n const login = useCallback(\n async (email: string, password: string) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.login(email, password));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const register = useCallback(\n async (email: string, password: string, data?: { name?: string }) => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.register(email, password, data));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n const logout = useCallback(async () => {\n try {\n setIsActionLoading(true);\n setActionError(null);\n await session.run(() => adapter.logout(), true);\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n }, [adapter, session]);\n\n const resetPassword = useCallback(\n async (email: string) => {\n return adapter.resetPassword(email);\n },\n [adapter],\n );\n\n const updateEmail = useCallback(\n async (email: string) => {\n return adapter.updateEmail(email);\n },\n [adapter],\n );\n\n const updatePassword = useCallback(\n async (password: string) => {\n return adapter.updatePassword(password);\n },\n [adapter],\n );\n\n const reauthenticate = useMemo(() => {\n return adapter.reauthenticate\n ? async (password: string) => adapter.reauthenticate!(password)\n : undefined;\n }, [adapter]);\n\n const sendVerificationEmail = useMemo(() => {\n return adapter.sendVerificationEmail ? async () => adapter.sendVerificationEmail!() : undefined;\n }, [adapter]);\n\n const getToken = useMemo(() => {\n return adapter.getToken ? async () => adapter.getToken!() : undefined;\n }, [adapter]);\n\n const loginWithProvider = useCallback(\n async (...args: Parameters<NonNullable<AuthAdapter['loginWithProvider']>>) => {\n if (!adapter.loginWithProvider) {\n throw new Error('OAuth login is not supported by this adapter.');\n }\n try {\n setIsActionLoading(true);\n setActionError(null);\n const userResult = await session.run(() => adapter.loginWithProvider!(...args));\n return userResult;\n } catch (err) {\n setActionError(err as Error);\n throw err;\n } finally {\n setIsActionLoading(false);\n }\n },\n [adapter, session],\n );\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isLoading,\n error,\n /** Whether backend verification completed; false during optimistic display. */\n isSessionVerified,\n /** Whether verification confirmed a logged-out state. */\n isLoggedOutKnown,\n /** Whether optimistic display caching is enabled. */\n optimisticSession: !!sessionCache,\n login,\n register,\n logout,\n resetPassword,\n updateEmail,\n updatePassword,\n reauthenticate,\n sendVerificationEmail,\n getToken,\n loginWithProvider: adapter.loginWithProvider ? loginWithProvider : undefined,\n }}\n >\n <React.Fragment key={epoch}>{children}</React.Fragment>\n </AuthContext.Provider>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProtectedRoute.cjs","names":["useAuth","useUserProfile","_Fragment","useRoleCheck","require_runtime","require_tools_components_auth_useAuth","require_tools_components_auth_useUserProfile","require_tools_components_auth_useRoleCheck","react_jsx_runtime","react","ProtectedRoute","isAuthLoading","profile","isProfileLoading","profileContext","isLoading","isAuthenticated","user","isAuthorized","roles","userRole","roleField","role","condition","performRedirect","onRedirect","path","unauthorizedPath","loginPath","fallback","unauthorizedFallback","ShowFor","hasAnyRole"],"sources":["../../../../src/tools/components/auth/ProtectedRoute.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport { useAuth } from './useAuth';\nimport { useUserProfile } from './useUserProfile';\nimport { useRoleCheck } from './useRoleCheck';\nimport { BaseProfile } from './types';\n\nexport interface ProtectedRouteProps<T extends BaseProfile = BaseProfile> {\n children: React.ReactNode;\n
|
|
1
|
+
{"version":3,"file":"ProtectedRoute.cjs","names":["useAuth","useUserProfile","_Fragment","useRoleCheck","require_runtime","require_tools_components_auth_useAuth","require_tools_components_auth_useUserProfile","require_tools_components_auth_useRoleCheck","react_jsx_runtime","react","ProtectedRoute","isAuthLoading","profile","isProfileLoading","profileContext","isLoading","isAuthenticated","user","isAuthorized","roles","userRole","roleField","role","condition","performRedirect","onRedirect","path","unauthorizedPath","loginPath","fallback","unauthorizedFallback","ShowFor","hasAnyRole"],"sources":["../../../../src/tools/components/auth/ProtectedRoute.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport { useAuth } from './useAuth';\nimport { useUserProfile } from './useUserProfile';\nimport { useRoleCheck } from './useRoleCheck';\nimport { BaseProfile } from './types';\n\n/**\n * Route display restrictions and client redirects.\n *\n * @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.\n *\n * @see ProtectedRoute for provider setup and semantics.\n */\nexport interface ProtectedRouteProps<T extends BaseProfile = BaseProfile> {\n /**\n * Content rendered only after loading and successful display checks.\n */\n children: React.ReactNode;\n /**\n * Unauthenticated redirect destination; defaults to /login.\n */\n loginPath?: string;\n /**\n * Optional denied-access destination; omission renders unauthorizedFallback.\n */\n unauthorizedPath?: string;\n /**\n * Any one listed role must match; omission or an empty array skips role restriction.\n */\n roles?: string[];\n /**\n * Profile scalar/array role property; defaults to role.\n */\n roleField?: keyof T;\n /**\n * Additional synchronous predicate receiving the profile or null; must pass after role checks. Thrown errors propagate from render.\n */\n condition?: (profile: T | null) => boolean;\n /**\n * Loading content; defaults to null.\n */\n fallback?: React.ReactNode;\n /**\n * Denied-access content when unauthorizedPath is omitted; defaults to null.\n */\n unauthorizedFallback?: React.ReactNode;\n /**\n * Optional synchronous navigation callback receiving the destination; omission assigns window.location.href.\n */\n onRedirect?: (path: string) => void;\n}\n\n/**\n * Renders or redirects according to current auth, optional roles and an optional predicate.\n *\n * @typeParam T - Profile shape used by roleField and condition; defaults to BaseProfile.\n *\n * @param props - Children, access predicates, loading/denial content and navigation settings.\n *\n * @returns Loading fallback, permitted children, denied fallback or null while redirecting.\n *\n * @throws Error without AuthProvider; condition errors propagate during rendering.\n *\n * @remarks Requires AuthProvider inside QueryClientProvider. UserProfileProvider is optional\n * but needed for profile-based roles. Redirects run in effects; missing profiles fail a\n * nonempty role restriction. This uses display user state without isSessionVerified;\n * backend authorization is still required. No CSS is required.\n *\n * @example\n * ```tsx\n * import type { ReactNode } from 'react';\n * import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n * import { AuthProvider, ProtectedRoute, type AuthAdapter } from '@alneas/appkit-react/tools/auth';\n *\n * function Content() { return <ProtectedRoute><span>Account</span></ProtectedRoute>; }\n * export function Example({ adapter, queryClient }: { adapter: AuthAdapter; queryClient: QueryClient }) {\n * return <QueryClientProvider client={queryClient}><AuthProvider adapter={adapter}><Content /></AuthProvider></QueryClientProvider>;\n * }\n * ```\n */\nexport function ProtectedRoute<T extends BaseProfile = BaseProfile>({\n children,\n loginPath = '/login',\n unauthorizedPath,\n roles,\n roleField = 'role' as keyof T,\n condition,\n fallback = null,\n unauthorizedFallback = null,\n onRedirect,\n}: ProtectedRouteProps<T>) {\n const { user, isLoading: isAuthLoading } = useAuth();\n\n // UserProfileProvider はオプショナル\n let profile: T | null = null;\n let isProfileLoading = false;\n\n try {\n const profileContext = useUserProfile<T>();\n profile = profileContext.profile;\n isProfileLoading = profileContext.isLoading;\n } catch {\n // UserProfileProvider が存在しない場合は無視\n }\n\n const isLoading = isAuthLoading || isProfileLoading;\n\n // 認証チェック\n const isAuthenticated = !!user;\n\n // ロールチェック\n const hasRequiredRole = (): boolean => {\n if (!roles || roles.length === 0) return true;\n if (!profile) return false;\n\n const userRole = profile[roleField];\n if (Array.isArray(userRole)) {\n // ユーザーが複数ロールを持つ場合\n return roles.some((role) => userRole.includes(role));\n }\n return roles.includes(userRole as string);\n };\n\n // カスタム条件チェック\n const meetsCondition = (): boolean => {\n if (!condition) return true;\n return condition(profile);\n };\n\n // 認可チェック (ロール + 条件)\n const isAuthorized = hasRequiredRole() && meetsCondition();\n\n // リダイレクト処理 (useEffect内でのみwindow操作)\n useEffect(() => {\n if (isLoading) return;\n\n const performRedirect = (path: string) => {\n if (onRedirect) {\n onRedirect(path);\n } else {\n window.location.href = path;\n }\n };\n\n if (!isAuthenticated) {\n performRedirect(loginPath);\n return;\n }\n\n if (!isAuthorized && unauthorizedPath) {\n performRedirect(unauthorizedPath);\n }\n }, [isLoading, isAuthenticated, isAuthorized, loginPath, unauthorizedPath, onRedirect]);\n\n // ローディング中\n if (isLoading) {\n return <>{fallback}</>;\n }\n\n // 未認証\n if (!isAuthenticated) {\n return null; // リダイレクト処理中\n }\n\n // 認可エラー\n if (!isAuthorized) {\n if (unauthorizedPath) {\n return null; // リダイレクト処理中\n }\n return <>{unauthorizedFallback}</>;\n }\n\n // 認証・認可OK\n return <>{children}</>;\n}\n\n/**\n * Conditional display settings; see ShowFor for usage.\n *\n * @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.\n *\n * @see ShowFor for the canonical usage example.\n */\nexport interface ShowForProps<T extends BaseProfile = BaseProfile> {\n /**\n * Content to render when all supplied checks pass.\n */\n children: React.ReactNode;\n /**\n * Any one role must match; omission or empty array imposes no restriction.\n */\n roles?: string[];\n /**\n * Profile role property; defaults to role.\n */\n roleField?: keyof T;\n /**\n * Optional synchronous predicate receiving the current profile or null.\n */\n condition?: (profile: T | null) => boolean;\n /**\n * Content when a check fails; defaults to null.\n */\n fallback?: React.ReactNode;\n}\n\n/**\n * Conditionally displays children using profile roles and an optional predicate.\n *\n * @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.\n *\n * @param props - Role checks, profile predicate, children and optional fallback.\n *\n * @returns Children when checks pass; otherwise fallback, defaulting to null.\n *\n * @throws Predicate errors propagate from render.\n *\n * @remarks UserProfileProvider supplies profile data but is optional; without it profile\n * is null. With no restrictions children render even without a profile. Does not redirect,\n * wait for loading, verify authentication or enforce backend access. No CSS is required.\n *\n * @example\n * ```tsx\n * import { ShowFor } from '@alneas/appkit-react/tools/auth';\n * export function RoleLabel() { return <ShowFor roles={['admin']}><span>Admin controls</span></ShowFor>; }\n * ```\n */\nexport function ShowFor<T extends BaseProfile = BaseProfile>({\n children,\n roles,\n roleField = 'role' as keyof T,\n condition,\n fallback = null,\n}: ShowForProps<T>) {\n const { hasAnyRole, profile } = useRoleCheck<T>(roleField);\n\n const shouldShow = (): boolean => {\n if (roles && roles.length > 0) {\n if (!hasAnyRole(roles)) return false;\n }\n if (condition) {\n if (!condition(profile)) return false;\n }\n return true;\n };\n\n return shouldShow() ? <>{children}</> : <>{fallback}</>;\n}\n"],"mappings":"A,+SAgFA,SAAgBU,EAAoD,CAClE,WACA,YAAY,SACZ,mBACA,QACA,YAAY,OACZ,YACA,WAAW,KACX,uBAAuB,KACvB,cACyB,CACzB,GAAM,CAAE,OAAM,UAAWC,GAAkBX,EAAAA,QAAQ,EAG/CY,EAAoB,KACpBC,EAAmB,GAEvB,GAAI,CACF,IAAMC,EAAiBb,EAAAA,eAAkB,EACzC,EAAUa,EAAe,QACzB,EAAmBA,EAAe,SACpC,MAAQ,CAER,CAEA,IAAMC,EAAYJ,GAAiBE,EAG7BG,EAAkB,CAAC,CAACC,EAsBpBC,OAnBiC,CACrC,GAAI,CAACC,GAASA,EAAM,SAAW,EAAG,MAAO,GACzC,GAAI,CAACP,EAAS,MAAO,GAErB,IAAMQ,EAAWR,EAAQS,GAKzB,OAJI,MAAM,QAAQD,CAAQ,EAEjBD,EAAM,KAAM,GAASC,EAAS,SAASE,CAAI,CAAC,EAE9CH,EAAM,SAASC,CAAkB,CAC1C,EASqB,CAAgB,IALnC,CAAKG,GACEA,EAAUX,CAAO,GA+C1B,OAxCA,EAAAH,EAAA,UAAA,KAAgB,CACd,GAAIM,EAAW,OAEf,IAAMS,EAAmB,GAAiB,CACpCC,EACFA,EAAWC,CAAI,EAEf,OAAO,SAAS,KAAOA,CAE3B,EAEKV,EAKD,CAACE,GAAgBS,GACnBH,EAAgBG,CAAgB,EALhCH,EAAgBI,CAAS,CAO7B,EAAG,CAACb,EAAWC,EAAiBE,EAAcU,EAAWD,EAAkBF,CAAU,CAAC,EAGlFV,GACK,EAAAP,EAAA,IAAA,CAAAN,EAAAA,SAAA,CAAA,SAAG2B,CAAW,CAAA,EAIlBb,EAKAE,GAQE,EAAAV,EAAA,IAAA,CAAAN,EAAAA,SAAA,CAAG,UAAW,CAAA,EAPfyB,EACK,MAEF,EAAAnB,EAAA,IAAA,CAAAN,EAAAA,SAAA,CAAA,SAAG4B,CAAuB,CAAA,EAR1B,IAaX,CAqDA,SAAgBC,EAA6C,CAC3D,WACA,QACA,YAAY,OACZ,YACA,WAAW,MACO,CAClB,GAAM,CAAE,aAAY,WAAY5B,EAAAA,aAAgBkB,CAAS,EAYzD,OATMF,GAASA,EAAM,OAAS,GACtB,CAACa,EAAWb,CAAK,GAEnBI,GACE,CAACA,EAAUX,CAAO,GAKc,EAAAJ,EAAA,IAAA,CAAAN,EAAAA,SAAA,CAAA,SAAG2B,CAAW,CAAA,GAAhC,EAAArB,EAAA,IAAA,CAAAN,EAAAA,SAAA,CAAG,UAAW,CAAA,CACtC,C"}
|
|
@@ -1,112 +1,127 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { BaseProfile } from './types.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* Route display restrictions and client redirects.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.
|
|
7
|
+
*
|
|
8
|
+
* @see ProtectedRoute for provider setup and semantics.
|
|
9
|
+
*/
|
|
3
10
|
export interface ProtectedRouteProps<T extends BaseProfile = BaseProfile> {
|
|
11
|
+
/**
|
|
12
|
+
* Content rendered only after loading and successful display checks.
|
|
13
|
+
*/
|
|
4
14
|
children: React.ReactNode;
|
|
5
15
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @default '/login'
|
|
16
|
+
* Unauthenticated redirect destination; defaults to /login.
|
|
8
17
|
*/
|
|
9
18
|
loginPath?: string;
|
|
10
19
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @default undefined (リダイレクトしない)
|
|
20
|
+
* Optional denied-access destination; omission renders unauthorizedFallback.
|
|
13
21
|
*/
|
|
14
22
|
unauthorizedPath?: string;
|
|
15
23
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @example ['admin', 'manager']
|
|
24
|
+
* Any one listed role must match; omission or an empty array skips role restriction.
|
|
18
25
|
*/
|
|
19
26
|
roles?: string[];
|
|
20
27
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @default 'role'
|
|
28
|
+
* Profile scalar/array role property; defaults to role.
|
|
23
29
|
*/
|
|
24
30
|
roleField?: keyof T;
|
|
25
31
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @example (profile) => profile?.subscription === 'premium'
|
|
32
|
+
* Additional synchronous predicate receiving the profile or null; must pass after role checks. Thrown errors propagate from render.
|
|
28
33
|
*/
|
|
29
34
|
condition?: (profile: T | null) => boolean;
|
|
30
35
|
/**
|
|
31
|
-
*
|
|
36
|
+
* Loading content; defaults to null.
|
|
32
37
|
*/
|
|
33
38
|
fallback?: React.ReactNode;
|
|
34
39
|
/**
|
|
35
|
-
*
|
|
40
|
+
* Denied-access content when unauthorizedPath is omitted; defaults to null.
|
|
36
41
|
*/
|
|
37
42
|
unauthorizedFallback?: React.ReactNode;
|
|
38
43
|
/**
|
|
39
|
-
*
|
|
40
|
-
* @example (path) => navigate(path)
|
|
44
|
+
* Optional synchronous navigation callback receiving the destination; omission assigns window.location.href.
|
|
41
45
|
*/
|
|
42
46
|
onRedirect?: (path: string) => void;
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
|
-
*
|
|
49
|
+
* Renders or redirects according to current auth, optional roles and an optional predicate.
|
|
46
50
|
*
|
|
47
|
-
*
|
|
51
|
+
* @typeParam T - Profile shape used by roleField and condition; defaults to BaseProfile.
|
|
48
52
|
*
|
|
49
|
-
* @
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* </ProtectedRoute>
|
|
60
|
-
*
|
|
61
|
-
* // カスタム条件
|
|
62
|
-
* <ProtectedRoute
|
|
63
|
-
* condition={(profile) => profile?.plan === 'premium'}
|
|
64
|
-
* unauthorizedPath="/upgrade"
|
|
65
|
-
* >
|
|
66
|
-
* <PremiumPage />
|
|
67
|
-
* </ProtectedRoute>
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
export declare function ProtectedRoute<T extends BaseProfile = BaseProfile>({ children, loginPath, unauthorizedPath, roles, roleField, condition, fallback, unauthorizedFallback, onRedirect, }: ProtectedRouteProps<T>): React.JSX.Element | null;
|
|
71
|
-
/**
|
|
72
|
-
* ロールベースの表示制御フック
|
|
53
|
+
* @param props - Children, access predicates, loading/denial content and navigation settings.
|
|
54
|
+
*
|
|
55
|
+
* @returns Loading fallback, permitted children, denied fallback or null while redirecting.
|
|
56
|
+
*
|
|
57
|
+
* @throws Error without AuthProvider; condition errors propagate during rendering.
|
|
58
|
+
*
|
|
59
|
+
* @remarks Requires AuthProvider inside QueryClientProvider. UserProfileProvider is optional
|
|
60
|
+
* but needed for profile-based roles. Redirects run in effects; missing profiles fail a
|
|
61
|
+
* nonempty role restriction. This uses display user state without isSessionVerified;
|
|
62
|
+
* backend authorization is still required. No CSS is required.
|
|
73
63
|
*
|
|
74
64
|
* @example
|
|
75
65
|
* ```tsx
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* </div>
|
|
84
|
-
* );
|
|
66
|
+
* import type { ReactNode } from 'react';
|
|
67
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
68
|
+
* import { AuthProvider, ProtectedRoute, type AuthAdapter } from '@alneas/appkit-react/tools/auth';
|
|
69
|
+
*
|
|
70
|
+
* function Content() { return <ProtectedRoute><span>Account</span></ProtectedRoute>; }
|
|
71
|
+
* export function Example({ adapter, queryClient }: { adapter: AuthAdapter; queryClient: QueryClient }) {
|
|
72
|
+
* return <QueryClientProvider client={queryClient}><AuthProvider adapter={adapter}><Content /></AuthProvider></QueryClientProvider>;
|
|
85
73
|
* }
|
|
86
74
|
* ```
|
|
87
75
|
*/
|
|
76
|
+
export declare function ProtectedRoute<T extends BaseProfile = BaseProfile>({ children, loginPath, unauthorizedPath, roles, roleField, condition, fallback, unauthorizedFallback, onRedirect, }: ProtectedRouteProps<T>): React.JSX.Element | null;
|
|
88
77
|
/**
|
|
89
|
-
*
|
|
78
|
+
* Conditional display settings; see ShowFor for usage.
|
|
90
79
|
*
|
|
91
|
-
* @
|
|
92
|
-
* ```tsx
|
|
93
|
-
* <ShowFor roles={['admin']}>
|
|
94
|
-
* <AdminOnlyContent />
|
|
95
|
-
* </ShowFor>
|
|
80
|
+
* @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.
|
|
96
81
|
*
|
|
97
|
-
*
|
|
98
|
-
* <PremiumContent />
|
|
99
|
-
* </ShowFor>
|
|
100
|
-
* ```
|
|
82
|
+
* @see ShowFor for the canonical usage example.
|
|
101
83
|
*/
|
|
102
84
|
export interface ShowForProps<T extends BaseProfile = BaseProfile> {
|
|
85
|
+
/**
|
|
86
|
+
* Content to render when all supplied checks pass.
|
|
87
|
+
*/
|
|
103
88
|
children: React.ReactNode;
|
|
89
|
+
/**
|
|
90
|
+
* Any one role must match; omission or empty array imposes no restriction.
|
|
91
|
+
*/
|
|
104
92
|
roles?: string[];
|
|
93
|
+
/**
|
|
94
|
+
* Profile role property; defaults to role.
|
|
95
|
+
*/
|
|
105
96
|
roleField?: keyof T;
|
|
97
|
+
/**
|
|
98
|
+
* Optional synchronous predicate receiving the current profile or null.
|
|
99
|
+
*/
|
|
106
100
|
condition?: (profile: T | null) => boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Content when a check fails; defaults to null.
|
|
103
|
+
*/
|
|
107
104
|
fallback?: React.ReactNode;
|
|
108
105
|
}
|
|
109
106
|
/**
|
|
110
|
-
*
|
|
107
|
+
* Conditionally displays children using profile roles and an optional predicate.
|
|
108
|
+
*
|
|
109
|
+
* @typeParam T - Profile shape extending BaseProfile; defaults to BaseProfile.
|
|
110
|
+
*
|
|
111
|
+
* @param props - Role checks, profile predicate, children and optional fallback.
|
|
112
|
+
*
|
|
113
|
+
* @returns Children when checks pass; otherwise fallback, defaulting to null.
|
|
114
|
+
*
|
|
115
|
+
* @throws Predicate errors propagate from render.
|
|
116
|
+
*
|
|
117
|
+
* @remarks UserProfileProvider supplies profile data but is optional; without it profile
|
|
118
|
+
* is null. With no restrictions children render even without a profile. Does not redirect,
|
|
119
|
+
* wait for loading, verify authentication or enforce backend access. No CSS is required.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```tsx
|
|
123
|
+
* import { ShowFor } from '@alneas/appkit-react/tools/auth';
|
|
124
|
+
* export function RoleLabel() { return <ShowFor roles={['admin']}><span>Admin controls</span></ShowFor>; }
|
|
125
|
+
* ```
|
|
111
126
|
*/
|
|
112
127
|
export declare function ShowFor<T extends BaseProfile = BaseProfile>({ children, roles, roleField, condition, fallback, }: ShowForProps<T>): React.JSX.Element;
|