npm package: @keyra/core
Description: Core authentication client and utilities for Keyra - Clerk alternative
Author: Keyra
Latest version: 1.1.1

# @keyra/core

Core authentication client and utilities for Keyra - a modern authentication platform for developers.

## Installation

```bash
npm install @keyra/core
```

## Overview

`@keyra/core` is the foundational package for Keyra authentication. It provides:

- **KeyraClient**: Main client for interacting with Keyra authentication services
- **Type Definitions**: Complete TypeScript types for all Keyra resources
- **Utility Functions**: JWT parsing, cookie management, validation helpers, and more

This package is typically used as a dependency for `@keyra/react` and `@keyra/nextjs`, but can be used directly in Node.js environments or for custom integrations.

---

## KeyraClient

The main client for interacting with Keyra authentication services.

### Constructor

```typescript
import { KeyraClient } from '@keyra/core'

const keyra = new KeyraClient({
  publishableKey: 'pk_test_...',  // For client-side
  // or
  secretKey: 'sk_test_...',        // For server-side
  apiUrl: 'https://api.keyra.app', // Optional
  apiVersion: 'v1',                // Optional
})
```

**Options:**
- `publishableKey`: Your Keyra publishable key (for client-side use)
- `secretKey`: Your Keyra secret key (for server-side use)
- `apiUrl`: Custom API URL (optional, defaults to production API)
- `apiVersion`: API version (optional, defaults to 'v1')

---

## Authentication Methods

### Sign In

```typescript
const result = await keyra.createSignIn({
  identifier: 'user@example.com',
  password: 'password123',
})

if (result.status === 'complete') {
  console.log('Signed in!', result.createdSessionId)
}
```

### Sign Up

```typescript
const result = await keyra.createSignUp({
  emailAddress: 'user@example.com',
  password: 'password123',
  firstName: 'John',
  lastName: 'Doe',
})

if (result.status === 'complete') {
  console.log('Signed up!', result.createdSessionId)
}
```

### Sign Out

```typescript
await keyra.signOut()
```

---

## User Management

### Get User

```typescript
const user = await keyra.getUser('user_123')

console.log(user.email)
console.log(user.firstName)
console.log(user.lastName)
```

### Update User

```typescript
const updatedUser = await keyra.updateUser('user_123', {
  firstName: 'Jane',
  lastName: 'Smith',
  publicMetadata: {
    role: 'admin',
  },
})
```

### Delete User

```typescript
await keyra.deleteUser('user_123')
```

---

## Session Management

### Get All Sessions

```typescript
const sessions = await keyra.getSessions()

sessions.forEach(session => {
  console.log(session.id, session.userId)
})
```

### Get Session

```typescript
const session = await keyra.getSession('sess_123')

console.log(session.userId)
console.log(session.expireAt)
```

### Set Active Session

```typescript
await keyra.setActiveSession('sess_123')
```

### End Session

```typescript
await keyra.endSession('sess_123')
```

---

## Organization Management

### Get Organization

```typescript
const org = await keyra.getOrganization('org_123')

console.log(org.name)
console.log(org.slug)
```

### Create Organization

```typescript
const org = await keyra.createOrganization({
  name: 'Acme Inc',
  slug: 'acme',
})
```

### Update Organization

```typescript
const updatedOrg = await keyra.updateOrganization('org_123', {
  name: 'Acme Corporation',
})
```

### Delete Organization

```typescript
await keyra.deleteOrganization('org_123')
```

---

## Utility Functions

### JWT Utilities

#### Parse JWT

```typescript
import { parseJWT } from '@keyra/core'

const token = 'eyJhbGc...'
const payload = parseJWT(token)

console.log(payload.userId)
console.log(payload.exp)
```

#### Check Token Expiration

```typescript
import { isTokenExpired } from '@keyra/core'

const token = 'eyJhbGc...'
const expired = isTokenExpired(token)

if (expired) {
  console.log('Token has expired')
}
```

### Cookie Utilities

#### Get Cookie

```typescript
import { getCookie } from '@keyra/core'

const sessionCookie = getCookie('__keyra_session')
```

#### Set Cookie

```typescript
import { setCookie } from '@keyra/core'

setCookie('__keyra_session', token, 7) // 7 days
```

#### Delete Cookie

```typescript
import { deleteCookie } from '@keyra/core'

deleteCookie('__keyra_session')
```

### Storage Utilities

#### Local Storage

```typescript
import { 
  getFromStorage, 
  setInStorage, 
  removeFromStorage 
} from '@keyra/core'

// Set
setInStorage('user_preferences', { theme: 'dark' })

// Get
const prefs = getFromStorage('user_preferences')

// Remove
removeFromStorage('user_preferences')
```

### Validation Utilities

#### Email Validation

```typescript
import { isValidEmail } from '@keyra/core'

const valid = isValidEmail('user@example.com') // true
const invalid = isValidEmail('not-an-email') // false
```

#### Phone Validation

```typescript
import { isValidPhone } from '@keyra/core'

const valid = isValidPhone('+1-555-123-4567') // true
```

#### Password Strength

```typescript
import { isStrongPassword } from '@keyra/core'

const strong = isStrongPassword('MyP@ssw0rd123') // true
const weak = isStrongPassword('password') // false
```

### Auth State Utilities

#### Build Request State

```typescript
import { buildRequestState } from '@keyra/core'

const authState = {
  userId: 'user_123',
  sessionId: 'sess_456',
}

const requestState = buildRequestState(authState)

console.log(requestState.isSignedIn) // true
console.log(requestState.userId) // 'user_123'
```

#### Sanitize Auth State

```typescript
import { sanitizeAuthState } from '@keyra/core'

const authState = {
  userId: 'user_123',
  sessionId: 'sess_456',
  // ... other properties
}

const sanitized = sanitizeAuthState(authState)
// Removes sensitive information
```

### URL Utilities

#### Build URL

```typescript
import { buildUrl } from '@keyra/core'

const url = buildUrl('/api/users', {
  page: 1,
  limit: 10,
})
// Returns: '/api/users?page=1&limit=10'
```

#### Get Query Parameter

```typescript
import { getQueryParam } from '@keyra/core'

// Current URL: https://example.com?redirect=/dashboard
const redirect = getQueryParam('redirect')
// Returns: '/dashboard'
```

#### Remove Query Parameter

```typescript
import { removeQueryParam } from '@keyra/core'

// Current URL: https://example.com?redirect=/dashboard&foo=bar
const newUrl = removeQueryParam('redirect')
// Returns: 'https://example.com?foo=bar'
```

### Browser Utilities

```typescript
import { isBrowser, isNode, getUserAgent } from '@keyra/core'

if (isBrowser()) {
  console.log('Running in browser')
}

if (isNode()) {
  console.log('Running in Node.js')
}

const userAgent = getUserAgent()
console.log('User Agent:', userAgent)
```

### Async Utilities

#### Debounce

```typescript
import { debounce } from '@keyra/core'

const searchAPI = debounce((query: string) => {
  fetch(`/api/search?q=${query}`)
}, 300)

// Will only call API 300ms after last invocation
searchAPI('hello')
searchAPI('hello world') // Only this one will execute
```

#### Throttle

```typescript
import { throttle } from '@keyra/core'

const handleScroll = throttle(() => {
  console.log('Scrolled')
}, 100)

// Will only execute once per 100ms
window.addEventListener('scroll', handleScroll)
```

### Error Utilities

#### Check Keyra Error

```typescript
import { isKeyraError, getErrorMessage } from '@keyra/core'

try {
  await keyra.signIn({ ... })
} catch (error) {
  if (isKeyraError(error)) {
    console.log('Keyra error:', getErrorMessage(error))
    console.log('Error code:', error.code)
  }
}
```

### Crypto Utilities

#### SHA-256 Hash

```typescript
import { sha256 } from '@keyra/core'

const hash = await sha256('my-string')
console.log(hash) // Hex string
```

#### Generate Random String

```typescript
import { generateRandomString } from '@keyra/core'

const randomId = generateRandomString(16)
console.log(randomId) // Random 16-character string
```

---

## TypeScript Types

All types are fully exported and documented:

### Core Types

```typescript
import type {
  User,
  Session,
  Organization,
  SignInResource,
  SignUpResource,
  ClientResource,
} from '@keyra/core'
```

### Auth State Types

```typescript
import type {
  AuthState,
  RequestState,
} from '@keyra/core'
```

### Parameter Types

```typescript
import type {
  SignInParams,
  SignUpParams,
  CreateOrganizationParams,
  UpdateUserParams,
  UpdateOrganizationParams,
} from '@keyra/core'
```

### Error Types

```typescript
import type {
  KeyraError,
  AuthErrorCode,
} from '@keyra/core'
```

### Configuration Types

```typescript
import type {
  KeyraConfig,
  KeyraOptions,
} from '@keyra/core'
```

---

## Example: Custom Backend Integration

```typescript
import { KeyraClient, isValidEmail, parseJWT } from '@keyra/core'
import express from 'express'

const app = express()
const keyra = new KeyraClient({
  secretKey: process.env.KEYRA_SECRET_KEY!,
})

// Sign in endpoint
app.post('/auth/sign-in', async (req, res) => {
  const { email, password } = req.body
  
  // Validate email
  if (!isValidEmail(email)) {
    return res.status(400).json({ error: 'Invalid email' })
  }
  
  try {
    const result = await keyra.createSignIn({
      identifier: email,
      password,
    })
    
    if (result.status === 'complete') {
      res.json({ sessionId: result.createdSessionId })
    }
  } catch (error) {
    res.status(401).json({ error: 'Invalid credentials' })
  }
})

// Protected endpoint
app.get('/api/profile', async (req, res) => {
  const token = req.headers.authorization?.replace('Bearer ', '')
  
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' })
  }
  
  try {
    const payload = parseJWT(token)
    const user = await keyra.getUser(payload.userId)
    
    res.json(user)
  } catch (error) {
    res.status(401).json({ error: 'Invalid token' })
  }
})

app.listen(3000)
```

---

## Example: Custom React Integration

```typescript
import { KeyraClient, buildRequestState } from '@keyra/core'
import { createContext, useContext, useEffect, useState } from 'react'

const AuthContext = createContext(null)

export function AuthProvider({ children }) {
  const [authState, setAuthState] = useState(null)
  const keyra = new KeyraClient({
    publishableKey: import.meta.env.VITE_KEYRA_PUBLISHABLE_KEY,
  })
  
  useEffect(() => {
    // Load auth state from session
    const loadAuth = async () => {
      const sessions = await keyra.getSessions()
      if (sessions.length > 0) {
        const state = buildRequestState({
          userId: sessions[0].userId,
          sessionId: sessions[0].id,
        })
        setAuthState(state)
      }
    }
    
    loadAuth()
  }, [])
  
  return (
    <AuthContext.Provider value={{ authState, keyra }}>
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  return useContext(AuthContext)
}
```

---

## Error Codes

Keyra uses specific error codes for different authentication errors:

- `invalid_credentials`: Email or password is incorrect
- `user_not_found`: User doesn't exist
- `user_already_exists`: User with this email already exists
- `session_expired`: Session has expired
- `invalid_token`: JWT token is invalid
- `insufficient_permissions`: User doesn't have required permissions
- `organization_not_found`: Organization doesn't exist
- `rate_limit_exceeded`: Too many requests

```typescript
try {
  await keyra.signIn({ ... })
} catch (error) {
  if (error.code === 'invalid_credentials') {
    console.log('Wrong email or password')
  } else if (error.code === 'rate_limit_exceeded') {
    console.log('Too many attempts. Please try again later.')
  }
}
```

---

## Browser vs Server

### Client-Side (Browser)

Use `publishableKey` for client-side authentication:

```typescript
const keyra = new KeyraClient({
  publishableKey: 'pk_test_...',
})
```

This is safe to use in browsers and mobile apps.

### Server-Side (Node.js)

Use `secretKey` for server-side operations:

```typescript
const keyra = new KeyraClient({
  secretKey: 'sk_test_...',
})
```

⚠️ **Never expose your secret key in client-side code!**

---

## Environment Variables

Recommended environment variable names:

**Client-side:**
```bash
# For Vite
VITE_KEYRA_PUBLISHABLE_KEY=pk_test_...

# For Create React App
REACT_APP_KEYRA_PUBLISHABLE_KEY=pk_test_...

# For Next.js
NEXT_PUBLIC_KEYRA_PUBLISHABLE_KEY=pk_test_...
```

**Server-side:**
```bash
KEYRA_SECRET_KEY=sk_test_...
KEYRA_API_URL=https://api.keyra.app (optional)
```

---

## Testing

For testing, Keyra provides test keys:

```bash
KEYRA_PUBLISHABLE_KEY=pk_test_...
KEYRA_SECRET_KEY=sk_test_...
```

Test keys work with all Keyra features but don't send real emails or charge real payments.

---

## License

Proprietary - Commercial software. See your Keyra subscription for usage terms.

---

## Links

- [Documentation](https://keyra.app/docs)
- [GitHub](https://github.com/yourusername/keyra)
- [Examples](https://github.com/yourusername/keyra/tree/main/packages/examples)
- [@keyra/react](https://www.npmjs.com/package/@keyra/react)
- [@keyra/nextjs](https://www.npmjs.com/package/@keyra/nextjs)