diff --git a/src/utils/auth-helpers.ts b/src/utils/auth-helpers.ts new file mode 100644 index 0000000..93d65f0 --- /dev/null +++ b/src/utils/auth-helpers.ts @@ -0,0 +1,22 @@ +import type { TangledApiClient } from '../lib/api-client.js'; + +/** + * Validate that the client is authenticated and has an active session + * @throws Error if not authenticated or no session found + * @returns The current session with did and handle + */ +export async function requireAuth(client: TangledApiClient): Promise<{ + did: string; + handle: string; +}> { + if (!(await client.isAuthenticated())) { + throw new Error('Must be authenticated. Run "tangled auth login" first.'); + } + + const session = client.getSession(); + if (!session) { + throw new Error('No active session found'); + } + + return session; +} diff --git a/tests/utils/auth-helpers.test.ts b/tests/utils/auth-helpers.test.ts new file mode 100644 index 0000000..ef3627b --- /dev/null +++ b/tests/utils/auth-helpers.test.ts @@ -0,0 +1,38 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { requireAuth } from '../../src/utils/auth-helpers.js'; +import type { TangledApiClient } from '../../src/lib/api-client.js'; + +// Mock API client factory +const createMockClient = (authenticated: boolean, session: { did: string; handle: string } | null): TangledApiClient => { + return { + isAuthenticated: vi.fn(async () => authenticated), + getSession: vi.fn(() => session), + } as unknown as TangledApiClient; +}; + +describe('requireAuth', () => { + it('should return session when authenticated', async () => { + const mockSession = { did: 'did:plc:test123', handle: 'test.bsky.social' }; + const mockClient = createMockClient(true, mockSession); + + const result = await requireAuth(mockClient); + + expect(result).toEqual(mockSession); + }); + + it('should throw error when not authenticated', async () => { + const mockClient = createMockClient(false, null); + + await expect(requireAuth(mockClient)).rejects.toThrow( + 'Must be authenticated. Run "tangled auth login" first.', + ); + }); + + it('should throw error when authenticated but no session', async () => { + const mockClient = createMockClient(true, null); + + await expect(requireAuth(mockClient)).rejects.toThrow( + 'No active session found', + ); + }); +});