Storage implementations for AT Protocol OAuth applications. Provides a simple key-value storage interface with implementations for in-memory and SQLite backends.
1/**
2 * In-memory storage implementation for OAuth sessions.
3 * Perfect for testing and development.
4 */
5
6import type { OAuthStorage } from "./types.ts";
7
8interface StorageEntry {
9 value: unknown;
10 expiresAt?: number;
11}
12
13/**
14 * In-memory storage for OAuth sessions and tokens.
15 *
16 * Features:
17 * - Automatic TTL expiration
18 * - No external dependencies
19 * - Perfect for testing and single-process deployments
20 *
21 * Note: Data is lost when the process restarts.
22 * For production, use SQLiteStorage or another persistent implementation.
23 *
24 * @example
25 * ```typescript
26 * const storage = new MemoryStorage();
27 *
28 * // Store with TTL
29 * await storage.set("session:123", { did: "did:plc:abc" }, { ttl: 3600 });
30 *
31 * // Retrieve
32 * const session = await storage.get("session:123");
33 *
34 * // Delete
35 * await storage.delete("session:123");
36 * ```
37 */
38export class MemoryStorage implements OAuthStorage {
39 private data = new Map<string, StorageEntry>();
40
41 get<T = unknown>(key: string): Promise<T | null> {
42 const item = this.data.get(key);
43 if (!item) return Promise.resolve(null);
44
45 // Check expiration
46 if (item.expiresAt && item.expiresAt <= Date.now()) {
47 this.data.delete(key);
48 return Promise.resolve(null);
49 }
50
51 return Promise.resolve(item.value as T);
52 }
53
54 set<T = unknown>(
55 key: string,
56 value: T,
57 options?: { ttl?: number },
58 ): Promise<void> {
59 const expiresAt = options?.ttl
60 ? Date.now() + (options.ttl * 1000)
61 : undefined;
62
63 this.data.set(key, { value, expiresAt });
64 return Promise.resolve();
65 }
66
67 delete(key: string): Promise<void> {
68 this.data.delete(key);
69 return Promise.resolve();
70 }
71
72 /**
73 * Clear all entries from storage.
74 * Useful for testing.
75 */
76 clear(): void {
77 this.data.clear();
78 }
79
80 /**
81 * Get the number of entries in storage.
82 * Useful for testing.
83 */
84 get size(): number {
85 return this.data.size;
86 }
87}