@hypercerts-org/sdk-core 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +328 -0
- package/.turbo/turbo-test.log +118 -0
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/errors.cjs +260 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +233 -0
- package/dist/errors.mjs +253 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs +4531 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3430 -0
- package/dist/index.mjs +4448 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lexicons.cjs +420 -0
- package/dist/lexicons.cjs.map +1 -0
- package/dist/lexicons.d.ts +227 -0
- package/dist/lexicons.mjs +410 -0
- package/dist/lexicons.mjs.map +1 -0
- package/dist/storage.cjs +270 -0
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.d.ts +474 -0
- package/dist/storage.mjs +267 -0
- package/dist/storage.mjs.map +1 -0
- package/dist/testing.cjs +415 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.ts +928 -0
- package/dist/testing.mjs +410 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/types.cjs +220 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.ts +2118 -0
- package/dist/types.mjs +212 -0
- package/dist/types.mjs.map +1 -0
- package/eslint.config.mjs +22 -0
- package/package.json +90 -0
- package/rollup.config.js +75 -0
- package/src/auth/OAuthClient.ts +497 -0
- package/src/core/SDK.ts +410 -0
- package/src/core/config.ts +243 -0
- package/src/core/errors.ts +257 -0
- package/src/core/interfaces.ts +324 -0
- package/src/core/types.ts +281 -0
- package/src/errors.ts +57 -0
- package/src/index.ts +107 -0
- package/src/lexicons.ts +64 -0
- package/src/repository/BlobOperationsImpl.ts +199 -0
- package/src/repository/CollaboratorOperationsImpl.ts +288 -0
- package/src/repository/HypercertOperationsImpl.ts +1146 -0
- package/src/repository/LexiconRegistry.ts +332 -0
- package/src/repository/OrganizationOperationsImpl.ts +234 -0
- package/src/repository/ProfileOperationsImpl.ts +281 -0
- package/src/repository/RecordOperationsImpl.ts +340 -0
- package/src/repository/Repository.ts +482 -0
- package/src/repository/interfaces.ts +868 -0
- package/src/repository/types.ts +111 -0
- package/src/services/hypercerts/types.ts +87 -0
- package/src/storage/InMemorySessionStore.ts +127 -0
- package/src/storage/InMemoryStateStore.ts +146 -0
- package/src/storage.ts +63 -0
- package/src/testing/index.ts +67 -0
- package/src/testing/mocks.ts +142 -0
- package/src/testing/stores.ts +285 -0
- package/src/testing.ts +64 -0
- package/src/types.ts +86 -0
- package/tests/auth/OAuthClient.test.ts +164 -0
- package/tests/core/SDK.test.ts +176 -0
- package/tests/core/errors.test.ts +81 -0
- package/tests/repository/BlobOperationsImpl.test.ts +154 -0
- package/tests/repository/CollaboratorOperationsImpl.test.ts +323 -0
- package/tests/repository/HypercertOperationsImpl.test.ts +652 -0
- package/tests/repository/LexiconRegistry.test.ts +192 -0
- package/tests/repository/OrganizationOperationsImpl.test.ts +242 -0
- package/tests/repository/ProfileOperationsImpl.test.ts +254 -0
- package/tests/repository/RecordOperationsImpl.test.ts +375 -0
- package/tests/repository/Repository.test.ts +149 -0
- package/tests/utils/fixtures.ts +117 -0
- package/tests/utils/mocks.ts +109 -0
- package/tests/utils/repository-fixtures.ts +78 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +30 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { NodeSavedSession, NodeSavedState } from '@atproto/oauth-client-node';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Storage interface for persisting OAuth sessions.
|
|
5
|
+
*
|
|
6
|
+
* Implement this interface to provide persistent storage for user sessions.
|
|
7
|
+
* Sessions contain sensitive data including access tokens, refresh tokens,
|
|
8
|
+
* and DPoP key pairs.
|
|
9
|
+
*
|
|
10
|
+
* The SDK provides {@link InMemorySessionStore} for development/testing,
|
|
11
|
+
* but **production applications should implement persistent storage**
|
|
12
|
+
* (e.g., Redis, PostgreSQL, MongoDB).
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* - Sessions are keyed by the user's DID (Decentralized Identifier)
|
|
16
|
+
* - The `NodeSavedSession` type comes from `@atproto/oauth-client-node`
|
|
17
|
+
* - Sessions may be large (~2-4KB) due to embedded cryptographic keys
|
|
18
|
+
* - Consider encrypting sessions at rest for additional security
|
|
19
|
+
*
|
|
20
|
+
* @example Redis implementation
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { Redis } from "ioredis";
|
|
23
|
+
* import type { SessionStore } from "@hypercerts-org/sdk";
|
|
24
|
+
* import type { NodeSavedSession } from "@atproto/oauth-client-node";
|
|
25
|
+
*
|
|
26
|
+
* class RedisSessionStore implements SessionStore {
|
|
27
|
+
* constructor(private redis: Redis, private prefix = "session:") {}
|
|
28
|
+
*
|
|
29
|
+
* async get(did: string): Promise<NodeSavedSession | undefined> {
|
|
30
|
+
* const data = await this.redis.get(this.prefix + did);
|
|
31
|
+
* return data ? JSON.parse(data) : undefined;
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* async set(did: string, session: NodeSavedSession): Promise<void> {
|
|
35
|
+
* // Set with 30-day expiry (sessions can be refreshed)
|
|
36
|
+
* await this.redis.setex(
|
|
37
|
+
* this.prefix + did,
|
|
38
|
+
* 30 * 24 * 60 * 60,
|
|
39
|
+
* JSON.stringify(session)
|
|
40
|
+
* );
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* async del(did: string): Promise<void> {
|
|
44
|
+
* await this.redis.del(this.prefix + did);
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @see {@link InMemorySessionStore} for the default in-memory implementation
|
|
50
|
+
*/
|
|
51
|
+
interface SessionStore {
|
|
52
|
+
/**
|
|
53
|
+
* Retrieves a session by DID.
|
|
54
|
+
*
|
|
55
|
+
* @param did - The user's Decentralized Identifier (e.g., "did:plc:abc123...")
|
|
56
|
+
* @returns The stored session, or `undefined` if not found
|
|
57
|
+
*/
|
|
58
|
+
get(did: string): Promise<NodeSavedSession | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Stores or updates a session.
|
|
61
|
+
*
|
|
62
|
+
* This is called after successful authentication and whenever tokens are refreshed.
|
|
63
|
+
*
|
|
64
|
+
* @param did - The user's DID to use as the storage key
|
|
65
|
+
* @param session - The session data to store (contains tokens, DPoP keys, etc.)
|
|
66
|
+
*/
|
|
67
|
+
set(did: string, session: NodeSavedSession): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Deletes a session.
|
|
70
|
+
*
|
|
71
|
+
* Called when a user logs out or when a session is revoked.
|
|
72
|
+
*
|
|
73
|
+
* @param did - The user's DID
|
|
74
|
+
*/
|
|
75
|
+
del(did: string): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Storage interface for OAuth state during the authorization flow.
|
|
79
|
+
*
|
|
80
|
+
* Implement this interface to provide temporary storage for OAuth state
|
|
81
|
+
* parameters. State is used for CSRF protection and PKCE (Proof Key for
|
|
82
|
+
* Code Exchange) during the authorization flow.
|
|
83
|
+
*
|
|
84
|
+
* @remarks
|
|
85
|
+
* - State is short-lived (typically 10-15 minutes)
|
|
86
|
+
* - Keys are random state strings generated by the OAuth client
|
|
87
|
+
* - The `NodeSavedState` type comes from `@atproto/oauth-client-node`
|
|
88
|
+
* - State should be automatically cleaned up after expiry
|
|
89
|
+
*
|
|
90
|
+
* @example Redis implementation with automatic expiry
|
|
91
|
+
* ```typescript
|
|
92
|
+
* import { Redis } from "ioredis";
|
|
93
|
+
* import type { StateStore } from "@hypercerts-org/sdk";
|
|
94
|
+
* import type { NodeSavedState } from "@atproto/oauth-client-node";
|
|
95
|
+
*
|
|
96
|
+
* class RedisStateStore implements StateStore {
|
|
97
|
+
* constructor(
|
|
98
|
+
* private redis: Redis,
|
|
99
|
+
* private prefix = "oauth-state:",
|
|
100
|
+
* private ttlSeconds = 900 // 15 minutes
|
|
101
|
+
* ) {}
|
|
102
|
+
*
|
|
103
|
+
* async get(key: string): Promise<NodeSavedState | undefined> {
|
|
104
|
+
* const data = await this.redis.get(this.prefix + key);
|
|
105
|
+
* return data ? JSON.parse(data) : undefined;
|
|
106
|
+
* }
|
|
107
|
+
*
|
|
108
|
+
* async set(key: string, state: NodeSavedState): Promise<void> {
|
|
109
|
+
* await this.redis.setex(
|
|
110
|
+
* this.prefix + key,
|
|
111
|
+
* this.ttlSeconds,
|
|
112
|
+
* JSON.stringify(state)
|
|
113
|
+
* );
|
|
114
|
+
* }
|
|
115
|
+
*
|
|
116
|
+
* async del(key: string): Promise<void> {
|
|
117
|
+
* await this.redis.del(this.prefix + key);
|
|
118
|
+
* }
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @see {@link InMemoryStateStore} for the default in-memory implementation
|
|
123
|
+
*/
|
|
124
|
+
interface StateStore {
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves OAuth state by key.
|
|
127
|
+
*
|
|
128
|
+
* @param key - The state key (random string from authorization URL)
|
|
129
|
+
* @returns The stored state, or `undefined` if not found or expired
|
|
130
|
+
*/
|
|
131
|
+
get(key: string): Promise<NodeSavedState | undefined>;
|
|
132
|
+
/**
|
|
133
|
+
* Stores OAuth state temporarily.
|
|
134
|
+
*
|
|
135
|
+
* Called when starting the authorization flow. The state should be
|
|
136
|
+
* stored with a short TTL (10-15 minutes recommended).
|
|
137
|
+
*
|
|
138
|
+
* @param key - The state key to use for storage
|
|
139
|
+
* @param state - The OAuth state data (includes PKCE verifier, etc.)
|
|
140
|
+
*/
|
|
141
|
+
set(key: string, state: NodeSavedState): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Deletes OAuth state.
|
|
144
|
+
*
|
|
145
|
+
* Called after the state has been used (successful or failed callback).
|
|
146
|
+
*
|
|
147
|
+
* @param key - The state key to delete
|
|
148
|
+
*/
|
|
149
|
+
del(key: string): Promise<void>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Generic cache interface for profiles, metadata, and other data.
|
|
153
|
+
*
|
|
154
|
+
* Implement this interface to provide caching for frequently accessed data.
|
|
155
|
+
* Caching can significantly reduce API calls and improve performance.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* The SDK does not provide a default cache implementation - you must
|
|
159
|
+
* implement this interface if you want caching. Consider using:
|
|
160
|
+
* - In-memory cache (e.g., `lru-cache`) for single-instance applications
|
|
161
|
+
* - Redis for distributed applications
|
|
162
|
+
* - Database-backed cache for persistence
|
|
163
|
+
*
|
|
164
|
+
* @example LRU cache implementation
|
|
165
|
+
* ```typescript
|
|
166
|
+
* import { LRUCache } from "lru-cache";
|
|
167
|
+
* import type { CacheInterface } from "@hypercerts-org/sdk";
|
|
168
|
+
*
|
|
169
|
+
* class LRUCacheAdapter implements CacheInterface {
|
|
170
|
+
* private cache = new LRUCache<string, unknown>({
|
|
171
|
+
* max: 1000,
|
|
172
|
+
* ttl: 5 * 60 * 1000, // 5 minutes default
|
|
173
|
+
* });
|
|
174
|
+
*
|
|
175
|
+
* async get<T>(key: string): Promise<T | undefined> {
|
|
176
|
+
* return this.cache.get(key) as T | undefined;
|
|
177
|
+
* }
|
|
178
|
+
*
|
|
179
|
+
* async set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {
|
|
180
|
+
* this.cache.set(key, value, {
|
|
181
|
+
* ttl: ttlSeconds ? ttlSeconds * 1000 : undefined,
|
|
182
|
+
* });
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* async del(key: string): Promise<void> {
|
|
186
|
+
* this.cache.delete(key);
|
|
187
|
+
* }
|
|
188
|
+
*
|
|
189
|
+
* async clear(): Promise<void> {
|
|
190
|
+
* this.cache.clear();
|
|
191
|
+
* }
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
interface CacheInterface {
|
|
196
|
+
/**
|
|
197
|
+
* Gets a cached value by key.
|
|
198
|
+
*
|
|
199
|
+
* @typeParam T - The expected type of the cached value
|
|
200
|
+
* @param key - The cache key
|
|
201
|
+
* @returns The cached value, or `undefined` if not found or expired
|
|
202
|
+
*/
|
|
203
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
204
|
+
/**
|
|
205
|
+
* Sets a cached value with optional TTL (time-to-live).
|
|
206
|
+
*
|
|
207
|
+
* @typeParam T - The type of the value being cached
|
|
208
|
+
* @param key - The cache key
|
|
209
|
+
* @param value - The value to cache
|
|
210
|
+
* @param ttlSeconds - Optional time-to-live in seconds. If not provided,
|
|
211
|
+
* the cache implementation should use its default TTL.
|
|
212
|
+
*/
|
|
213
|
+
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
214
|
+
/**
|
|
215
|
+
* Deletes a cached value.
|
|
216
|
+
*
|
|
217
|
+
* @param key - The cache key to delete
|
|
218
|
+
*/
|
|
219
|
+
del(key: string): Promise<void>;
|
|
220
|
+
/**
|
|
221
|
+
* Clears all cached values.
|
|
222
|
+
*
|
|
223
|
+
* Use with caution in production as this affects all cached data.
|
|
224
|
+
*/
|
|
225
|
+
clear(): Promise<void>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* In-memory implementation of the SessionStore interface.
|
|
230
|
+
*
|
|
231
|
+
* This store keeps OAuth sessions in memory using a Map. It's intended
|
|
232
|
+
* for development, testing, and simple use cases where session persistence
|
|
233
|
+
* across restarts is not required.
|
|
234
|
+
*
|
|
235
|
+
* @remarks
|
|
236
|
+
* **Warning**: This implementation is **not suitable for production** because:
|
|
237
|
+
* - Sessions are lost when the process restarts
|
|
238
|
+
* - Sessions cannot be shared across multiple server instances
|
|
239
|
+
* - No automatic cleanup of expired sessions
|
|
240
|
+
*
|
|
241
|
+
* For production, implement {@link SessionStore} with a persistent backend:
|
|
242
|
+
* - **Redis**: Good for distributed systems, supports TTL
|
|
243
|
+
* - **PostgreSQL/MySQL**: Good for existing database infrastructure
|
|
244
|
+
* - **MongoDB**: Good for document-based storage
|
|
245
|
+
*
|
|
246
|
+
* @example Basic usage
|
|
247
|
+
* ```typescript
|
|
248
|
+
* import { InMemorySessionStore } from "@hypercerts-org/sdk/storage";
|
|
249
|
+
*
|
|
250
|
+
* const sessionStore = new InMemorySessionStore();
|
|
251
|
+
*
|
|
252
|
+
* const sdk = new ATProtoSDK({
|
|
253
|
+
* oauth: { ... },
|
|
254
|
+
* storage: {
|
|
255
|
+
* sessionStore, // Will warn in logs for production
|
|
256
|
+
* },
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
259
|
+
*
|
|
260
|
+
* @example Testing usage
|
|
261
|
+
* ```typescript
|
|
262
|
+
* const sessionStore = new InMemorySessionStore();
|
|
263
|
+
*
|
|
264
|
+
* // After tests, clean up
|
|
265
|
+
* sessionStore.clear();
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @see {@link SessionStore} for the interface definition
|
|
269
|
+
* @see {@link InMemoryStateStore} for the corresponding state store
|
|
270
|
+
*/
|
|
271
|
+
declare class InMemorySessionStore implements SessionStore {
|
|
272
|
+
/**
|
|
273
|
+
* Internal storage for sessions, keyed by DID.
|
|
274
|
+
* @internal
|
|
275
|
+
*/
|
|
276
|
+
private sessions;
|
|
277
|
+
/**
|
|
278
|
+
* Retrieves a session by DID.
|
|
279
|
+
*
|
|
280
|
+
* @param did - The user's Decentralized Identifier
|
|
281
|
+
* @returns Promise resolving to the session, or `undefined` if not found
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```typescript
|
|
285
|
+
* const session = await sessionStore.get("did:plc:abc123");
|
|
286
|
+
* if (session) {
|
|
287
|
+
* console.log("Session found");
|
|
288
|
+
* }
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
get(did: string): Promise<NodeSavedSession | undefined>;
|
|
292
|
+
/**
|
|
293
|
+
* Stores or updates a session.
|
|
294
|
+
*
|
|
295
|
+
* @param did - The user's DID to use as the key
|
|
296
|
+
* @param session - The session data to store
|
|
297
|
+
*
|
|
298
|
+
* @remarks
|
|
299
|
+
* If a session already exists for the DID, it is overwritten.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* await sessionStore.set("did:plc:abc123", sessionData);
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
set(did: string, session: NodeSavedSession): Promise<void>;
|
|
307
|
+
/**
|
|
308
|
+
* Deletes a session by DID.
|
|
309
|
+
*
|
|
310
|
+
* @param did - The DID of the session to delete
|
|
311
|
+
*
|
|
312
|
+
* @remarks
|
|
313
|
+
* If no session exists for the DID, this is a no-op.
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```typescript
|
|
317
|
+
* await sessionStore.del("did:plc:abc123");
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
del(did: string): Promise<void>;
|
|
321
|
+
/**
|
|
322
|
+
* Clears all stored sessions.
|
|
323
|
+
*
|
|
324
|
+
* This is primarily useful for testing to ensure a clean state
|
|
325
|
+
* between test runs.
|
|
326
|
+
*
|
|
327
|
+
* @remarks
|
|
328
|
+
* This method is synchronous (not async) for convenience in test cleanup.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* // In test teardown
|
|
333
|
+
* afterEach(() => {
|
|
334
|
+
* sessionStore.clear();
|
|
335
|
+
* });
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
clear(): void;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* In-memory implementation of the StateStore interface.
|
|
343
|
+
*
|
|
344
|
+
* This store keeps OAuth state parameters in memory using a Map. State is
|
|
345
|
+
* used during the OAuth authorization flow for CSRF protection and PKCE.
|
|
346
|
+
*
|
|
347
|
+
* @remarks
|
|
348
|
+
* **Warning**: This implementation is **not suitable for production** because:
|
|
349
|
+
* - State is lost when the process restarts (breaking in-progress OAuth flows)
|
|
350
|
+
* - State cannot be shared across multiple server instances
|
|
351
|
+
* - No automatic cleanup of expired state (memory leak potential)
|
|
352
|
+
*
|
|
353
|
+
* For production, implement {@link StateStore} with a persistent backend
|
|
354
|
+
* that supports TTL (time-to-live):
|
|
355
|
+
* - **Redis**: Ideal choice with built-in TTL support
|
|
356
|
+
* - **Database with cleanup job**: PostgreSQL/MySQL with periodic cleanup
|
|
357
|
+
*
|
|
358
|
+
* **State Lifecycle**:
|
|
359
|
+
* 1. Created when user starts OAuth flow (`authorize()`)
|
|
360
|
+
* 2. Retrieved and validated during callback
|
|
361
|
+
* 3. Deleted after successful or failed callback
|
|
362
|
+
* 4. Should expire after ~15 minutes if callback never happens
|
|
363
|
+
*
|
|
364
|
+
* @example Basic usage
|
|
365
|
+
* ```typescript
|
|
366
|
+
* import { InMemoryStateStore } from "@hypercerts-org/sdk/storage";
|
|
367
|
+
*
|
|
368
|
+
* const stateStore = new InMemoryStateStore();
|
|
369
|
+
*
|
|
370
|
+
* const sdk = new ATProtoSDK({
|
|
371
|
+
* oauth: { ... },
|
|
372
|
+
* storage: {
|
|
373
|
+
* stateStore, // Will warn in logs for production
|
|
374
|
+
* },
|
|
375
|
+
* });
|
|
376
|
+
* ```
|
|
377
|
+
*
|
|
378
|
+
* @example Testing usage
|
|
379
|
+
* ```typescript
|
|
380
|
+
* const stateStore = new InMemoryStateStore();
|
|
381
|
+
*
|
|
382
|
+
* // After tests, clean up
|
|
383
|
+
* stateStore.clear();
|
|
384
|
+
* ```
|
|
385
|
+
*
|
|
386
|
+
* @see {@link StateStore} for the interface definition
|
|
387
|
+
* @see {@link InMemorySessionStore} for the corresponding session store
|
|
388
|
+
*/
|
|
389
|
+
declare class InMemoryStateStore implements StateStore {
|
|
390
|
+
/**
|
|
391
|
+
* Internal storage for OAuth state, keyed by state string.
|
|
392
|
+
* @internal
|
|
393
|
+
*/
|
|
394
|
+
private states;
|
|
395
|
+
/**
|
|
396
|
+
* Retrieves OAuth state by key.
|
|
397
|
+
*
|
|
398
|
+
* @param key - The state key (random string from authorization URL)
|
|
399
|
+
* @returns Promise resolving to the state, or `undefined` if not found
|
|
400
|
+
*
|
|
401
|
+
* @remarks
|
|
402
|
+
* The key is a cryptographically random string generated during
|
|
403
|
+
* the authorization request. It's included in the callback URL
|
|
404
|
+
* and used to retrieve the associated PKCE verifier and other data.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* // During OAuth callback
|
|
409
|
+
* const state = await stateStore.get(params.get("state")!);
|
|
410
|
+
* if (!state) {
|
|
411
|
+
* throw new Error("Invalid or expired state");
|
|
412
|
+
* }
|
|
413
|
+
* ```
|
|
414
|
+
*/
|
|
415
|
+
get(key: string): Promise<NodeSavedState | undefined>;
|
|
416
|
+
/**
|
|
417
|
+
* Stores OAuth state temporarily.
|
|
418
|
+
*
|
|
419
|
+
* @param key - The state key to use for storage
|
|
420
|
+
* @param state - The OAuth state data (includes PKCE verifier, etc.)
|
|
421
|
+
*
|
|
422
|
+
* @remarks
|
|
423
|
+
* In production implementations, state should be stored with a TTL
|
|
424
|
+
* of approximately 10-15 minutes to prevent stale state accumulation.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```typescript
|
|
428
|
+
* // Called internally by OAuthClient during authorize()
|
|
429
|
+
* await stateStore.set(stateKey, {
|
|
430
|
+
* // PKCE code verifier, redirect URI, etc.
|
|
431
|
+
* });
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
set(key: string, state: NodeSavedState): Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Deletes OAuth state by key.
|
|
437
|
+
*
|
|
438
|
+
* @param key - The state key to delete
|
|
439
|
+
*
|
|
440
|
+
* @remarks
|
|
441
|
+
* Called after the OAuth callback is processed (whether successful or not)
|
|
442
|
+
* to clean up the temporary state.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* // After processing callback
|
|
447
|
+
* await stateStore.del(stateKey);
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
del(key: string): Promise<void>;
|
|
451
|
+
/**
|
|
452
|
+
* Clears all stored state.
|
|
453
|
+
*
|
|
454
|
+
* This is primarily useful for testing to ensure a clean state
|
|
455
|
+
* between test runs.
|
|
456
|
+
*
|
|
457
|
+
* @remarks
|
|
458
|
+
* This method is synchronous (not async) for convenience in test cleanup.
|
|
459
|
+
* In production, be careful using this as it will invalidate all
|
|
460
|
+
* in-progress OAuth flows.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```typescript
|
|
464
|
+
* // In test teardown
|
|
465
|
+
* afterEach(() => {
|
|
466
|
+
* stateStore.clear();
|
|
467
|
+
* });
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
clear(): void;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export { InMemorySessionStore, InMemoryStateStore };
|
|
474
|
+
export type { CacheInterface, SessionStore, StateStore };
|