npm package: @lanauchea/cookies
Description: A tiny, modern, async/promise-based utility for managing HTTP cookies. Designed for edge/serverless environments with zero dependencies.
Author: La Nauchéa
Latest version: 0.1.0

# @lanauchea/cookies

A tiny, modern, async/promise-based utility for managing HTTP cookies. Designed for edge/serverless environments with zero dependencies.

[![Tests](https://img.shields.io/badge/tests-72%20passing-brightgreen)]()
[![License](https://img.shields.io/badge/license-MIT-blue)]()
[![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)]()

## Features

- 🚀 **Modern async/promise-based API**
- ⚡ **Sync alternatives** for high-performance edge computing
- 🌐 **Edge/Serverless ready** - Works in Cloudflare Workers, Vercel Edge, Deno Deploy
- 📦 **Zero dependencies**
- 🎯 **RFC 6265 compliant**
- 💪 **TypeScript support** with full type definitions
- ✅ **Battle-tested** with 72 comprehensive tests
- 🔒 **Production ready**

## Installation

```bash
npm install @lanauchea/cookies
```

## Quick Start

```javascript
import {
  parseCookie,
  parseCookieSync,
  stringifySetCookie,
  stringifySetCookieSync,
} from "@lanauchea/cookies";

// Parse Cookie header (async)
const cookies = await parseCookie("sessionId=abc123; theme=dark");
console.log(cookies); // { sessionId: 'abc123', theme: 'dark' }

// Parse Cookie header (sync - faster for edge)
const cookiesSync = parseCookieSync("sessionId=abc123; theme=dark");

// Create Set-Cookie header
const setCookie = stringifySetCookieSync("sessionId", "abc123", {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  maxAge: 3600,
});
// "sessionId=abc123; Max-Age=3600; HttpOnly; Secure; SameSite=Lax"
```

## API Reference

### Core Functions

#### `parseCookie(str, options?)` - Async

Parse a `Cookie` header string into an object.

```javascript
const cookies = await parseCookie("sessionId=abc; userId=123");
// { sessionId: 'abc', userId: '123' }

// With custom decoder
const cookies2 = await parseCookie("data=encrypted", {
  decode: async (val) => decrypt(val)
});
```

**Note:** When duplicate cookie names exist, the **first** value wins (per RFC 6265).

#### `parseCookieSync(str)` - Sync

Synchronous version for high-performance edge computing.

```javascript
const cookies = parseCookieSync("sessionId=abc; theme=dark");
```

#### `stringifySetCookie(name, value, options?)` - Async

Create a `Set-Cookie` header string.

```javascript
const cookie = await stringifySetCookie("sessionId", "abc123", {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  maxAge: 60 * 60 * 24 * 7, // 7 days
  path: "/",
  domain: ".example.com",
});
```

#### `stringifySetCookieSync(name, value, options?)` - Sync

Synchronous version for high-performance edge computing.

```javascript
const cookie = stringifySetCookieSync("sessionId", "abc123", {
  httpOnly: true,
  secure: true,
  sameSite: "lax",
  maxAge: 3600,
});
```

### Options

#### Cookie Options
- `maxAge` - Max age in seconds
- `expires` - Expiration date
- `domain` - Cookie domain
- `path` - Cookie path
- `httpOnly` - HttpOnly flag
- `secure` - Secure flag
- `partitioned` - Partitioned flag (CHIPS)
- `priority` - Priority (`"low"`, `"medium"`, `"high"`)
- `sameSite` - SameSite policy (`"strict"`, `"lax"`, `"none"`, or `true`)
- `encode` - Custom encoder function
- `decode` - Custom decoder function

## Usage Examples

### Cloudflare Workers

```javascript
export default {
  async fetch(request) {
    const cookies = parseCookieSync(request.headers.get("cookie") || "");
    
    if (!cookies.sessionId) {
      return new Response("Unauthorized", { status: 401 });
    }

    const newCookie = stringifySetCookieSync("visited", "true", {
      maxAge: 86400,
      secure: true,
      httpOnly: true,
    });

    return new Response("Hello", {
      headers: { "Set-Cookie": newCookie },
    });
  },
};
```

### Vercel Edge Functions

```javascript
export async function GET(request) {
  const cookies = parseCookieSync(request.headers.get("cookie") || "");
  return Response.json({ cookies });
}

export async function POST(request) {
  const body = await request.json();
  const cookie = stringifySetCookieSync("data", JSON.stringify(body), {
    httpOnly: true,
    secure: true,
    maxAge: 3600,
  });
  return new Response("Saved", { headers: { "Set-Cookie": cookie } });
}
```

### Custom Encryption

```javascript
async function encrypt(value) {
  // Your encryption logic
  return encrypted;
}

async function decrypt(value) {
  // Your decryption logic
  return decrypted;
}

// Set encrypted cookie
const cookie = await stringifySetCookie("userId", "12345", {
  encode: encrypt,
  httpOnly: true,
  secure: true,
});

// Read encrypted cookie
const cookies = await parseCookie(cookieHeader, {
  decode: decrypt,
});
```

### Multiple Cookies

```javascript
const cookies = await Promise.all([
  stringifySetCookie("session", "abc", { httpOnly: true, secure: true }),
  stringifySetCookie("theme", "dark", { maxAge: 31536000 }),
  stringifySetCookie("lang", "en", { path: "/" }),
]);

return new Response("OK", {
  headers: cookies.map(c => ["Set-Cookie", c]),
});
```

### Delete Cookie

```javascript
const deleteCookie = stringifySetCookieSync("sessionId", "", {
  maxAge: 0,
  path: "/",
});
```

## Performance Tips

1. **Use sync methods in edge middleware** - Avoid async overhead
2. **Parse once per request** - Cache parsed cookies
3. **Batch operations** - Use `Promise.all()` for multiple cookies
4. **Avoid unnecessary encoding** - Skip custom encoders when safe

## Security Best Practices

```javascript
// Secure cookie configuration
const secureCookie = await stringifySetCookie("session", sessionId, {
  httpOnly: true,      // No JS access
  secure: true,        // HTTPS only
  sameSite: "strict",  // CSRF protection
  maxAge: 3600,        // 1 hour
  path: "/",           // Explicit path
});
```

**Guidelines:**
- Always use `httpOnly` for session cookies
- Use `secure` in production
- Set `sameSite` to prevent CSRF
- Use short `maxAge` for sensitive data
- Set explicit `path` and `domain`

## TypeScript

Full TypeScript support included:

```typescript
import type {
  Cookies,
  CookieOptions,
  SetCookie,
  SetCookieOptions,
} from "@lanauchea/cookies";
```

## Testing

```bash
npm test              # Run tests
npm run test:watch    # Watch mode
```

## License

MIT © La Nauchéa

## Links

- [GitHub](https://github.com/lanauchea/cookies)
- [RFC 6265](https://tools.ietf.org/html/rfc6265)

---