feat: task 1.5 directus auth client + zustand auth store
Six files under src/auth/:
- client.ts: createDirectus<Schema>().with(authentication('cookie', ...))
.with(rest(...)). Lazy singleton via initDirectusClient(url) +
getDirectus() + useDirectus() (React-side helper). DirectusUser type;
empty Schema (grows in Phase 2+).
- store.ts: Zustand store with discriminated AuthState
(unknown / anonymous / authenticating / authenticated). Actions:
initialize, login, logout, setUser. humanizeAuthError maps Directus
error codes (INVALID_CREDENTIALS / INVALID_OTP / USER_SUSPENDED) to
user-facing strings.
- guard.ts: useRequireAuth (redirect to /login on anonymous) and
useRequireRole (bounce to / on role mismatch). Uses TanStack Router's
useNavigate; effective once 1.7 wires the router.
- bootstrap.tsx: <AuthBootstrap> component runs initDirectusClient +
initialize() once after the runtime config is loaded.
- index.ts: barrel re-exports.
main.tsx wraps App in <RuntimeConfigProvider><AuthBootstrap>...
App.tsx shows the auth status as a smoke indicator before 1.6/1.7.
Deviations:
1. Split getDirectus into initDirectusClient(url) + getDirectus()
because the runtime config is a React context (per 1.4), not a
Zustand store. <AuthBootstrap> bridges from React land to the non-
React getter.
2. Added <AuthBootstrap> as a discrete component rather than putting
the bootstrap effect in App.tsx — App.tsx gets replaced by the
router in 1.7, but bootstrap needs to keep running.
This commit is contained in:
+9
-3
@@ -1,14 +1,20 @@
|
||||
import { Button } from '@/ui/primitives/button';
|
||||
import { useAuthStore } from '@/auth';
|
||||
|
||||
function App() {
|
||||
const status = useAuthStore((s) => s.status);
|
||||
const user = useAuthStore((s) => (s.status === 'authenticated' ? s.user : null));
|
||||
|
||||
return (
|
||||
<div className="min-h-screen grid place-items-center bg-muted">
|
||||
<div className="space-y-4 text-center">
|
||||
<h1 className="text-3xl font-semibold">TRM</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Phase 1 scaffold. Tailwind + shadcn primitives wired.
|
||||
Phase 1 scaffold. Routing + login UI land in 1.6 / 1.7.
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Auth status: <code className="font-mono">{status}</code>
|
||||
{user && <> · {user.first_name ?? user.email ?? user.id}</>}
|
||||
</p>
|
||||
<Button>Sample button</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user