@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,928 @@
|
|
|
1
|
+
import { OAuthSession, NodeSavedSession, NodeSavedState } from '@atproto/oauth-client-node';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* OAuth session with DPoP (Demonstrating Proof of Possession) support.
|
|
6
|
+
*
|
|
7
|
+
* This type represents an authenticated user session. It wraps the
|
|
8
|
+
* `@atproto/oauth-client-node` OAuthSession and contains:
|
|
9
|
+
* - Access token for API requests
|
|
10
|
+
* - Refresh token for obtaining new access tokens
|
|
11
|
+
* - DPoP key pair for proof-of-possession
|
|
12
|
+
* - User's DID and other identity information
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* Sessions are managed by the SDK and automatically refresh when tokens expire.
|
|
16
|
+
* Store the user's DID to restore sessions later with {@link ATProtoSDK.restoreSession}.
|
|
17
|
+
*
|
|
18
|
+
* Key properties from OAuthSession:
|
|
19
|
+
* - `did` or `sub`: The user's DID
|
|
20
|
+
* - `handle`: The user's handle (e.g., "user.bsky.social")
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const session = await sdk.callback(params);
|
|
25
|
+
*
|
|
26
|
+
* // Access user identity
|
|
27
|
+
* console.log(`Logged in as: ${session.did}`);
|
|
28
|
+
*
|
|
29
|
+
* // Use session for repository operations
|
|
30
|
+
* const repo = sdk.repository(session);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @see https://atproto.com/specs/oauth for OAuth specification
|
|
34
|
+
*/
|
|
35
|
+
type Session = OAuthSession;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Storage interface for persisting OAuth sessions.
|
|
39
|
+
*
|
|
40
|
+
* Implement this interface to provide persistent storage for user sessions.
|
|
41
|
+
* Sessions contain sensitive data including access tokens, refresh tokens,
|
|
42
|
+
* and DPoP key pairs.
|
|
43
|
+
*
|
|
44
|
+
* The SDK provides {@link InMemorySessionStore} for development/testing,
|
|
45
|
+
* but **production applications should implement persistent storage**
|
|
46
|
+
* (e.g., Redis, PostgreSQL, MongoDB).
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* - Sessions are keyed by the user's DID (Decentralized Identifier)
|
|
50
|
+
* - The `NodeSavedSession` type comes from `@atproto/oauth-client-node`
|
|
51
|
+
* - Sessions may be large (~2-4KB) due to embedded cryptographic keys
|
|
52
|
+
* - Consider encrypting sessions at rest for additional security
|
|
53
|
+
*
|
|
54
|
+
* @example Redis implementation
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { Redis } from "ioredis";
|
|
57
|
+
* import type { SessionStore } from "@hypercerts-org/sdk";
|
|
58
|
+
* import type { NodeSavedSession } from "@atproto/oauth-client-node";
|
|
59
|
+
*
|
|
60
|
+
* class RedisSessionStore implements SessionStore {
|
|
61
|
+
* constructor(private redis: Redis, private prefix = "session:") {}
|
|
62
|
+
*
|
|
63
|
+
* async get(did: string): Promise<NodeSavedSession | undefined> {
|
|
64
|
+
* const data = await this.redis.get(this.prefix + did);
|
|
65
|
+
* return data ? JSON.parse(data) : undefined;
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* async set(did: string, session: NodeSavedSession): Promise<void> {
|
|
69
|
+
* // Set with 30-day expiry (sessions can be refreshed)
|
|
70
|
+
* await this.redis.setex(
|
|
71
|
+
* this.prefix + did,
|
|
72
|
+
* 30 * 24 * 60 * 60,
|
|
73
|
+
* JSON.stringify(session)
|
|
74
|
+
* );
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* async del(did: string): Promise<void> {
|
|
78
|
+
* await this.redis.del(this.prefix + did);
|
|
79
|
+
* }
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @see {@link InMemorySessionStore} for the default in-memory implementation
|
|
84
|
+
*/
|
|
85
|
+
interface SessionStore {
|
|
86
|
+
/**
|
|
87
|
+
* Retrieves a session by DID.
|
|
88
|
+
*
|
|
89
|
+
* @param did - The user's Decentralized Identifier (e.g., "did:plc:abc123...")
|
|
90
|
+
* @returns The stored session, or `undefined` if not found
|
|
91
|
+
*/
|
|
92
|
+
get(did: string): Promise<NodeSavedSession | undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Stores or updates a session.
|
|
95
|
+
*
|
|
96
|
+
* This is called after successful authentication and whenever tokens are refreshed.
|
|
97
|
+
*
|
|
98
|
+
* @param did - The user's DID to use as the storage key
|
|
99
|
+
* @param session - The session data to store (contains tokens, DPoP keys, etc.)
|
|
100
|
+
*/
|
|
101
|
+
set(did: string, session: NodeSavedSession): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Deletes a session.
|
|
104
|
+
*
|
|
105
|
+
* Called when a user logs out or when a session is revoked.
|
|
106
|
+
*
|
|
107
|
+
* @param did - The user's DID
|
|
108
|
+
*/
|
|
109
|
+
del(did: string): Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Storage interface for OAuth state during the authorization flow.
|
|
113
|
+
*
|
|
114
|
+
* Implement this interface to provide temporary storage for OAuth state
|
|
115
|
+
* parameters. State is used for CSRF protection and PKCE (Proof Key for
|
|
116
|
+
* Code Exchange) during the authorization flow.
|
|
117
|
+
*
|
|
118
|
+
* @remarks
|
|
119
|
+
* - State is short-lived (typically 10-15 minutes)
|
|
120
|
+
* - Keys are random state strings generated by the OAuth client
|
|
121
|
+
* - The `NodeSavedState` type comes from `@atproto/oauth-client-node`
|
|
122
|
+
* - State should be automatically cleaned up after expiry
|
|
123
|
+
*
|
|
124
|
+
* @example Redis implementation with automatic expiry
|
|
125
|
+
* ```typescript
|
|
126
|
+
* import { Redis } from "ioredis";
|
|
127
|
+
* import type { StateStore } from "@hypercerts-org/sdk";
|
|
128
|
+
* import type { NodeSavedState } from "@atproto/oauth-client-node";
|
|
129
|
+
*
|
|
130
|
+
* class RedisStateStore implements StateStore {
|
|
131
|
+
* constructor(
|
|
132
|
+
* private redis: Redis,
|
|
133
|
+
* private prefix = "oauth-state:",
|
|
134
|
+
* private ttlSeconds = 900 // 15 minutes
|
|
135
|
+
* ) {}
|
|
136
|
+
*
|
|
137
|
+
* async get(key: string): Promise<NodeSavedState | undefined> {
|
|
138
|
+
* const data = await this.redis.get(this.prefix + key);
|
|
139
|
+
* return data ? JSON.parse(data) : undefined;
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* async set(key: string, state: NodeSavedState): Promise<void> {
|
|
143
|
+
* await this.redis.setex(
|
|
144
|
+
* this.prefix + key,
|
|
145
|
+
* this.ttlSeconds,
|
|
146
|
+
* JSON.stringify(state)
|
|
147
|
+
* );
|
|
148
|
+
* }
|
|
149
|
+
*
|
|
150
|
+
* async del(key: string): Promise<void> {
|
|
151
|
+
* await this.redis.del(this.prefix + key);
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @see {@link InMemoryStateStore} for the default in-memory implementation
|
|
157
|
+
*/
|
|
158
|
+
interface StateStore {
|
|
159
|
+
/**
|
|
160
|
+
* Retrieves OAuth state by key.
|
|
161
|
+
*
|
|
162
|
+
* @param key - The state key (random string from authorization URL)
|
|
163
|
+
* @returns The stored state, or `undefined` if not found or expired
|
|
164
|
+
*/
|
|
165
|
+
get(key: string): Promise<NodeSavedState | undefined>;
|
|
166
|
+
/**
|
|
167
|
+
* Stores OAuth state temporarily.
|
|
168
|
+
*
|
|
169
|
+
* Called when starting the authorization flow. The state should be
|
|
170
|
+
* stored with a short TTL (10-15 minutes recommended).
|
|
171
|
+
*
|
|
172
|
+
* @param key - The state key to use for storage
|
|
173
|
+
* @param state - The OAuth state data (includes PKCE verifier, etc.)
|
|
174
|
+
*/
|
|
175
|
+
set(key: string, state: NodeSavedState): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* Deletes OAuth state.
|
|
178
|
+
*
|
|
179
|
+
* Called after the state has been used (successful or failed callback).
|
|
180
|
+
*
|
|
181
|
+
* @param key - The state key to delete
|
|
182
|
+
*/
|
|
183
|
+
del(key: string): Promise<void>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Generic cache interface for profiles, metadata, and other data.
|
|
187
|
+
*
|
|
188
|
+
* Implement this interface to provide caching for frequently accessed data.
|
|
189
|
+
* Caching can significantly reduce API calls and improve performance.
|
|
190
|
+
*
|
|
191
|
+
* @remarks
|
|
192
|
+
* The SDK does not provide a default cache implementation - you must
|
|
193
|
+
* implement this interface if you want caching. Consider using:
|
|
194
|
+
* - In-memory cache (e.g., `lru-cache`) for single-instance applications
|
|
195
|
+
* - Redis for distributed applications
|
|
196
|
+
* - Database-backed cache for persistence
|
|
197
|
+
*
|
|
198
|
+
* @example LRU cache implementation
|
|
199
|
+
* ```typescript
|
|
200
|
+
* import { LRUCache } from "lru-cache";
|
|
201
|
+
* import type { CacheInterface } from "@hypercerts-org/sdk";
|
|
202
|
+
*
|
|
203
|
+
* class LRUCacheAdapter implements CacheInterface {
|
|
204
|
+
* private cache = new LRUCache<string, unknown>({
|
|
205
|
+
* max: 1000,
|
|
206
|
+
* ttl: 5 * 60 * 1000, // 5 minutes default
|
|
207
|
+
* });
|
|
208
|
+
*
|
|
209
|
+
* async get<T>(key: string): Promise<T | undefined> {
|
|
210
|
+
* return this.cache.get(key) as T | undefined;
|
|
211
|
+
* }
|
|
212
|
+
*
|
|
213
|
+
* async set<T>(key: string, value: T, ttlSeconds?: number): Promise<void> {
|
|
214
|
+
* this.cache.set(key, value, {
|
|
215
|
+
* ttl: ttlSeconds ? ttlSeconds * 1000 : undefined,
|
|
216
|
+
* });
|
|
217
|
+
* }
|
|
218
|
+
*
|
|
219
|
+
* async del(key: string): Promise<void> {
|
|
220
|
+
* this.cache.delete(key);
|
|
221
|
+
* }
|
|
222
|
+
*
|
|
223
|
+
* async clear(): Promise<void> {
|
|
224
|
+
* this.cache.clear();
|
|
225
|
+
* }
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
interface CacheInterface {
|
|
230
|
+
/**
|
|
231
|
+
* Gets a cached value by key.
|
|
232
|
+
*
|
|
233
|
+
* @typeParam T - The expected type of the cached value
|
|
234
|
+
* @param key - The cache key
|
|
235
|
+
* @returns The cached value, or `undefined` if not found or expired
|
|
236
|
+
*/
|
|
237
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
238
|
+
/**
|
|
239
|
+
* Sets a cached value with optional TTL (time-to-live).
|
|
240
|
+
*
|
|
241
|
+
* @typeParam T - The type of the value being cached
|
|
242
|
+
* @param key - The cache key
|
|
243
|
+
* @param value - The value to cache
|
|
244
|
+
* @param ttlSeconds - Optional time-to-live in seconds. If not provided,
|
|
245
|
+
* the cache implementation should use its default TTL.
|
|
246
|
+
*/
|
|
247
|
+
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
248
|
+
/**
|
|
249
|
+
* Deletes a cached value.
|
|
250
|
+
*
|
|
251
|
+
* @param key - The cache key to delete
|
|
252
|
+
*/
|
|
253
|
+
del(key: string): Promise<void>;
|
|
254
|
+
/**
|
|
255
|
+
* Clears all cached values.
|
|
256
|
+
*
|
|
257
|
+
* Use with caution in production as this affects all cached data.
|
|
258
|
+
*/
|
|
259
|
+
clear(): Promise<void>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Logger interface for debugging and observability.
|
|
263
|
+
*
|
|
264
|
+
* Implement this interface to receive log messages from the SDK.
|
|
265
|
+
* The interface is compatible with `console` and most popular
|
|
266
|
+
* logging libraries (Pino, Winston, Bunyan, etc.).
|
|
267
|
+
*
|
|
268
|
+
* @remarks
|
|
269
|
+
* Log levels follow standard conventions:
|
|
270
|
+
* - `debug`: Detailed information for debugging (tokens, request details)
|
|
271
|
+
* - `info`: General operational messages (initialization, successful auth)
|
|
272
|
+
* - `warn`: Potentially problematic situations (deprecated features, retries)
|
|
273
|
+
* - `error`: Errors that don't crash the application (failed requests, validation)
|
|
274
|
+
*
|
|
275
|
+
* @example Using console
|
|
276
|
+
* ```typescript
|
|
277
|
+
* const sdk = new ATProtoSDK({
|
|
278
|
+
* // ...
|
|
279
|
+
* logger: console,
|
|
280
|
+
* });
|
|
281
|
+
* ```
|
|
282
|
+
*
|
|
283
|
+
* @example Using Pino
|
|
284
|
+
* ```typescript
|
|
285
|
+
* import pino from "pino";
|
|
286
|
+
*
|
|
287
|
+
* const logger = pino({ level: "debug" });
|
|
288
|
+
* const sdk = new ATProtoSDK({
|
|
289
|
+
* // ...
|
|
290
|
+
* logger: logger,
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*
|
|
294
|
+
* @example Custom logger with context
|
|
295
|
+
* ```typescript
|
|
296
|
+
* const logger: LoggerInterface = {
|
|
297
|
+
* debug: (msg, ...args) => console.debug(`[SDK] ${msg}`, ...args),
|
|
298
|
+
* info: (msg, ...args) => console.info(`[SDK] ${msg}`, ...args),
|
|
299
|
+
* warn: (msg, ...args) => console.warn(`[SDK] ${msg}`, ...args),
|
|
300
|
+
* error: (msg, ...args) => console.error(`[SDK] ${msg}`, ...args),
|
|
301
|
+
* };
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
interface LoggerInterface {
|
|
305
|
+
/**
|
|
306
|
+
* Logs debug-level messages.
|
|
307
|
+
*
|
|
308
|
+
* Used for detailed diagnostic information. May include sensitive
|
|
309
|
+
* data like request URLs and headers (but not tokens).
|
|
310
|
+
*
|
|
311
|
+
* @param message - The log message
|
|
312
|
+
* @param args - Additional arguments (objects, error details, etc.)
|
|
313
|
+
*/
|
|
314
|
+
debug(message: string, ...args: unknown[]): void;
|
|
315
|
+
/**
|
|
316
|
+
* Logs info-level messages.
|
|
317
|
+
*
|
|
318
|
+
* Used for general operational information like successful
|
|
319
|
+
* initialization, authentication events, etc.
|
|
320
|
+
*
|
|
321
|
+
* @param message - The log message
|
|
322
|
+
* @param args - Additional arguments
|
|
323
|
+
*/
|
|
324
|
+
info(message: string, ...args: unknown[]): void;
|
|
325
|
+
/**
|
|
326
|
+
* Logs warning-level messages.
|
|
327
|
+
*
|
|
328
|
+
* Used for potentially problematic situations that don't prevent
|
|
329
|
+
* operation but may indicate issues.
|
|
330
|
+
*
|
|
331
|
+
* @param message - The log message
|
|
332
|
+
* @param args - Additional arguments
|
|
333
|
+
*/
|
|
334
|
+
warn(message: string, ...args: unknown[]): void;
|
|
335
|
+
/**
|
|
336
|
+
* Logs error-level messages.
|
|
337
|
+
*
|
|
338
|
+
* Used for error conditions that should be investigated.
|
|
339
|
+
* The SDK continues to operate after logging errors.
|
|
340
|
+
*
|
|
341
|
+
* @param message - The log message
|
|
342
|
+
* @param args - Additional arguments (typically includes the error object)
|
|
343
|
+
*/
|
|
344
|
+
error(message: string, ...args: unknown[]): void;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Zod schema for OAuth configuration validation.
|
|
349
|
+
*
|
|
350
|
+
* @remarks
|
|
351
|
+
* All URLs must be valid and use HTTPS in production. The `jwkPrivate` field
|
|
352
|
+
* should contain the private key in JWK (JSON Web Key) format as a string.
|
|
353
|
+
*/
|
|
354
|
+
declare const OAuthConfigSchema: z.ZodObject<{
|
|
355
|
+
/**
|
|
356
|
+
* URL to the OAuth client metadata JSON document.
|
|
357
|
+
* This document describes your application to the authorization server.
|
|
358
|
+
*
|
|
359
|
+
* @see https://atproto.com/specs/oauth#client-metadata
|
|
360
|
+
*/
|
|
361
|
+
clientId: z.ZodString;
|
|
362
|
+
/**
|
|
363
|
+
* URL where users are redirected after authentication.
|
|
364
|
+
* Must match one of the redirect URIs in your client metadata.
|
|
365
|
+
*/
|
|
366
|
+
redirectUri: z.ZodString;
|
|
367
|
+
/**
|
|
368
|
+
* OAuth scopes to request, space-separated.
|
|
369
|
+
* Common scopes: "atproto", "transition:generic"
|
|
370
|
+
*/
|
|
371
|
+
scope: z.ZodString;
|
|
372
|
+
/**
|
|
373
|
+
* URL to your public JWKS (JSON Web Key Set) endpoint.
|
|
374
|
+
* Used by the authorization server to verify your client's signatures.
|
|
375
|
+
*/
|
|
376
|
+
jwksUri: z.ZodString;
|
|
377
|
+
/**
|
|
378
|
+
* Private JWK (JSON Web Key) as a JSON string.
|
|
379
|
+
* Used for signing DPoP proofs and client assertions.
|
|
380
|
+
*
|
|
381
|
+
* @remarks
|
|
382
|
+
* This should be kept secret and never exposed to clients.
|
|
383
|
+
* Typically loaded from environment variables or a secrets manager.
|
|
384
|
+
*/
|
|
385
|
+
jwkPrivate: z.ZodString;
|
|
386
|
+
}, "strip", z.ZodTypeAny, {
|
|
387
|
+
clientId: string;
|
|
388
|
+
redirectUri: string;
|
|
389
|
+
scope: string;
|
|
390
|
+
jwksUri: string;
|
|
391
|
+
jwkPrivate: string;
|
|
392
|
+
}, {
|
|
393
|
+
clientId: string;
|
|
394
|
+
redirectUri: string;
|
|
395
|
+
scope: string;
|
|
396
|
+
jwksUri: string;
|
|
397
|
+
jwkPrivate: string;
|
|
398
|
+
}>;
|
|
399
|
+
/**
|
|
400
|
+
* Zod schema for server URL configuration.
|
|
401
|
+
*
|
|
402
|
+
* @remarks
|
|
403
|
+
* At least one server (PDS or SDS) should be configured for the SDK to be useful.
|
|
404
|
+
*/
|
|
405
|
+
declare const ServerConfigSchema: z.ZodObject<{
|
|
406
|
+
/**
|
|
407
|
+
* Personal Data Server URL - the user's own AT Protocol server.
|
|
408
|
+
* This is the primary server for user data operations.
|
|
409
|
+
*
|
|
410
|
+
* @example "https://bsky.social"
|
|
411
|
+
*/
|
|
412
|
+
pds: z.ZodOptional<z.ZodString>;
|
|
413
|
+
/**
|
|
414
|
+
* Shared Data Server URL - for collaborative data storage.
|
|
415
|
+
* Required for collaborator and organization operations.
|
|
416
|
+
*
|
|
417
|
+
* @example "https://sds.hypercerts.org"
|
|
418
|
+
*/
|
|
419
|
+
sds: z.ZodOptional<z.ZodString>;
|
|
420
|
+
}, "strip", z.ZodTypeAny, {
|
|
421
|
+
pds?: string | undefined;
|
|
422
|
+
sds?: string | undefined;
|
|
423
|
+
}, {
|
|
424
|
+
pds?: string | undefined;
|
|
425
|
+
sds?: string | undefined;
|
|
426
|
+
}>;
|
|
427
|
+
/**
|
|
428
|
+
* Zod schema for timeout configuration.
|
|
429
|
+
*
|
|
430
|
+
* @remarks
|
|
431
|
+
* All timeout values are in milliseconds.
|
|
432
|
+
*/
|
|
433
|
+
declare const TimeoutConfigSchema: z.ZodObject<{
|
|
434
|
+
/**
|
|
435
|
+
* Timeout for fetching PDS metadata during identity resolution.
|
|
436
|
+
* @default 5000 (5 seconds, set by OAuthClient)
|
|
437
|
+
*/
|
|
438
|
+
pdsMetadata: z.ZodOptional<z.ZodNumber>;
|
|
439
|
+
/**
|
|
440
|
+
* Timeout for general API requests to PDS/SDS.
|
|
441
|
+
* @default 30000 (30 seconds)
|
|
442
|
+
*/
|
|
443
|
+
apiRequests: z.ZodOptional<z.ZodNumber>;
|
|
444
|
+
}, "strip", z.ZodTypeAny, {
|
|
445
|
+
pdsMetadata?: number | undefined;
|
|
446
|
+
apiRequests?: number | undefined;
|
|
447
|
+
}, {
|
|
448
|
+
pdsMetadata?: number | undefined;
|
|
449
|
+
apiRequests?: number | undefined;
|
|
450
|
+
}>;
|
|
451
|
+
/**
|
|
452
|
+
* Configuration options for the ATProto SDK.
|
|
453
|
+
*
|
|
454
|
+
* This interface defines all configuration needed to initialize the SDK,
|
|
455
|
+
* including OAuth credentials, server endpoints, and optional customizations.
|
|
456
|
+
*
|
|
457
|
+
* @example Minimal configuration
|
|
458
|
+
* ```typescript
|
|
459
|
+
* const config: ATProtoSDKConfig = {
|
|
460
|
+
* oauth: {
|
|
461
|
+
* clientId: "https://my-app.com/client-metadata.json",
|
|
462
|
+
* redirectUri: "https://my-app.com/callback",
|
|
463
|
+
* scope: "atproto transition:generic",
|
|
464
|
+
* jwksUri: "https://my-app.com/.well-known/jwks.json",
|
|
465
|
+
* jwkPrivate: process.env.JWK_PRIVATE_KEY!,
|
|
466
|
+
* },
|
|
467
|
+
* servers: {
|
|
468
|
+
* pds: "https://bsky.social",
|
|
469
|
+
* },
|
|
470
|
+
* };
|
|
471
|
+
* ```
|
|
472
|
+
*
|
|
473
|
+
* @example Full configuration with custom storage
|
|
474
|
+
* ```typescript
|
|
475
|
+
* const config: ATProtoSDKConfig = {
|
|
476
|
+
* oauth: { ... },
|
|
477
|
+
* servers: {
|
|
478
|
+
* pds: "https://bsky.social",
|
|
479
|
+
* sds: "https://sds.hypercerts.org",
|
|
480
|
+
* },
|
|
481
|
+
* storage: {
|
|
482
|
+
* sessionStore: new RedisSessionStore(redisClient),
|
|
483
|
+
* stateStore: new RedisStateStore(redisClient),
|
|
484
|
+
* },
|
|
485
|
+
* timeouts: {
|
|
486
|
+
* pdsMetadata: 5000,
|
|
487
|
+
* apiRequests: 30000,
|
|
488
|
+
* },
|
|
489
|
+
* logger: console,
|
|
490
|
+
* };
|
|
491
|
+
* ```
|
|
492
|
+
*/
|
|
493
|
+
interface ATProtoSDKConfig {
|
|
494
|
+
/**
|
|
495
|
+
* OAuth 2.0 configuration for authentication.
|
|
496
|
+
*
|
|
497
|
+
* Required fields for the OAuth flow with DPoP (Demonstrating Proof of Possession).
|
|
498
|
+
* Your application must host the client metadata and JWKS endpoints.
|
|
499
|
+
*
|
|
500
|
+
* @see https://atproto.com/specs/oauth for AT Protocol OAuth specification
|
|
501
|
+
*/
|
|
502
|
+
oauth: z.infer<typeof OAuthConfigSchema>;
|
|
503
|
+
/**
|
|
504
|
+
* Server URLs for PDS and SDS connections.
|
|
505
|
+
*
|
|
506
|
+
* - **PDS**: Personal Data Server - user's own data storage
|
|
507
|
+
* - **SDS**: Shared Data Server - collaborative storage with access control
|
|
508
|
+
*/
|
|
509
|
+
servers?: z.infer<typeof ServerConfigSchema>;
|
|
510
|
+
/**
|
|
511
|
+
* Storage adapters for persisting OAuth sessions and state.
|
|
512
|
+
*
|
|
513
|
+
* If not provided, in-memory implementations are used automatically.
|
|
514
|
+
* **Warning**: In-memory storage is lost on process restart - use persistent
|
|
515
|
+
* storage (Redis, database, etc.) in production.
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```typescript
|
|
519
|
+
* storage: {
|
|
520
|
+
* sessionStore: new RedisSessionStore(redis),
|
|
521
|
+
* stateStore: new RedisStateStore(redis),
|
|
522
|
+
* }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
storage?: {
|
|
526
|
+
/**
|
|
527
|
+
* Persistent storage for OAuth sessions.
|
|
528
|
+
* Sessions contain access tokens, refresh tokens, and DPoP keys.
|
|
529
|
+
*/
|
|
530
|
+
sessionStore?: SessionStore;
|
|
531
|
+
/**
|
|
532
|
+
* Temporary storage for OAuth state during the authorization flow.
|
|
533
|
+
* State is short-lived and used for PKCE and CSRF protection.
|
|
534
|
+
*/
|
|
535
|
+
stateStore?: StateStore;
|
|
536
|
+
};
|
|
537
|
+
/**
|
|
538
|
+
* Custom fetch implementation for HTTP requests.
|
|
539
|
+
*
|
|
540
|
+
* Use this to add custom headers, logging, or to use a different HTTP client.
|
|
541
|
+
* Must be compatible with the standard Fetch API.
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* fetch: async (url, init) => {
|
|
546
|
+
* console.log(`Fetching: ${url}`);
|
|
547
|
+
* return globalThis.fetch(url, init);
|
|
548
|
+
* }
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
fetch?: typeof fetch;
|
|
552
|
+
/**
|
|
553
|
+
* Timeout configuration for network requests.
|
|
554
|
+
* Values are in milliseconds.
|
|
555
|
+
*/
|
|
556
|
+
timeouts?: z.infer<typeof TimeoutConfigSchema>;
|
|
557
|
+
/**
|
|
558
|
+
* Cache for profiles, metadata, and other frequently accessed data.
|
|
559
|
+
*
|
|
560
|
+
* Implementing caching can significantly reduce API calls and improve performance.
|
|
561
|
+
* The SDK does not provide a default cache - you must implement {@link CacheInterface}.
|
|
562
|
+
*/
|
|
563
|
+
cache?: CacheInterface;
|
|
564
|
+
/**
|
|
565
|
+
* Logger for debugging and observability.
|
|
566
|
+
*
|
|
567
|
+
* The logger receives debug, info, warn, and error messages from the SDK.
|
|
568
|
+
* Compatible with `console` or any logger implementing {@link LoggerInterface}.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```typescript
|
|
572
|
+
* logger: console
|
|
573
|
+
* // or
|
|
574
|
+
* logger: pino()
|
|
575
|
+
* // or
|
|
576
|
+
* logger: winston.createLogger({ ... })
|
|
577
|
+
* ```
|
|
578
|
+
*/
|
|
579
|
+
logger?: LoggerInterface;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Mock factories for testing.
|
|
584
|
+
*
|
|
585
|
+
* This module provides factory functions to create mock objects
|
|
586
|
+
* for testing SDK functionality without real AT Protocol connections.
|
|
587
|
+
*
|
|
588
|
+
* @packageDocumentation
|
|
589
|
+
*/
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Creates a mock OAuth session for testing.
|
|
593
|
+
*
|
|
594
|
+
* The mock session includes all required properties and a mock
|
|
595
|
+
* `fetchHandler` that returns empty successful responses by default.
|
|
596
|
+
*
|
|
597
|
+
* @param overrides - Partial session object to override default values
|
|
598
|
+
* @returns A mock Session object suitable for testing
|
|
599
|
+
*
|
|
600
|
+
* @remarks
|
|
601
|
+
* The mock session is cast to `Session` type for compatibility.
|
|
602
|
+
* In real usage, sessions come from the OAuth flow and contain
|
|
603
|
+
* actual tokens and a real fetch handler.
|
|
604
|
+
*
|
|
605
|
+
* **Default Values**:
|
|
606
|
+
* - `did`: `"did:plc:test123"`
|
|
607
|
+
* - `handle`: `"test.bsky.social"`
|
|
608
|
+
* - `fetchHandler`: Returns `Response` with `{}` body
|
|
609
|
+
*
|
|
610
|
+
* @example Basic mock session
|
|
611
|
+
* ```typescript
|
|
612
|
+
* import { createMockSession } from "@hypercerts-org/sdk/testing";
|
|
613
|
+
*
|
|
614
|
+
* const session = createMockSession();
|
|
615
|
+
* const repo = sdk.repository(session);
|
|
616
|
+
* ```
|
|
617
|
+
*
|
|
618
|
+
* @example With custom DID
|
|
619
|
+
* ```typescript
|
|
620
|
+
* const session = createMockSession({
|
|
621
|
+
* did: "did:plc:custom-test-user",
|
|
622
|
+
* handle: "custom.bsky.social",
|
|
623
|
+
* });
|
|
624
|
+
* ```
|
|
625
|
+
*
|
|
626
|
+
* @example With custom fetch handler
|
|
627
|
+
* ```typescript
|
|
628
|
+
* const session = createMockSession({
|
|
629
|
+
* fetchHandler: async (url, init) => {
|
|
630
|
+
* // Custom response logic
|
|
631
|
+
* return new Response(JSON.stringify({ success: true }));
|
|
632
|
+
* },
|
|
633
|
+
* });
|
|
634
|
+
* ```
|
|
635
|
+
*/
|
|
636
|
+
declare function createMockSession(overrides?: Partial<Session>): Session;
|
|
637
|
+
/**
|
|
638
|
+
* Creates a mock SDK configuration for testing.
|
|
639
|
+
*
|
|
640
|
+
* The configuration includes all required OAuth settings with
|
|
641
|
+
* placeholder values suitable for testing (not real credentials).
|
|
642
|
+
*
|
|
643
|
+
* @param overrides - Partial configuration to override default values
|
|
644
|
+
* @returns A complete ATProtoSDKConfig suitable for testing
|
|
645
|
+
*
|
|
646
|
+
* @remarks
|
|
647
|
+
* The default configuration uses example.com domains and a minimal
|
|
648
|
+
* JWK structure. This is sufficient for unit tests but won't work
|
|
649
|
+
* for integration tests that require real OAuth flows.
|
|
650
|
+
*
|
|
651
|
+
* **Default Values**:
|
|
652
|
+
* - `clientId`: `"https://test.example.com/client-metadata.json"`
|
|
653
|
+
* - `pds`: `"https://bsky.social"`
|
|
654
|
+
* - `sds`: `"https://sds.example.com"`
|
|
655
|
+
*
|
|
656
|
+
* @example Basic test config
|
|
657
|
+
* ```typescript
|
|
658
|
+
* import { createTestConfig } from "@hypercerts-org/sdk/testing";
|
|
659
|
+
*
|
|
660
|
+
* const config = createTestConfig();
|
|
661
|
+
* const sdk = new ATProtoSDK(config);
|
|
662
|
+
* ```
|
|
663
|
+
*
|
|
664
|
+
* @example With custom PDS
|
|
665
|
+
* ```typescript
|
|
666
|
+
* const config = createTestConfig({
|
|
667
|
+
* servers: {
|
|
668
|
+
* pds: "https://custom-pds.example.com",
|
|
669
|
+
* },
|
|
670
|
+
* });
|
|
671
|
+
* ```
|
|
672
|
+
*
|
|
673
|
+
* @example With logger for debugging tests
|
|
674
|
+
* ```typescript
|
|
675
|
+
* const config = createTestConfig({
|
|
676
|
+
* logger: console,
|
|
677
|
+
* });
|
|
678
|
+
* ```
|
|
679
|
+
*/
|
|
680
|
+
declare function createTestConfig(overrides?: Partial<ATProtoSDKConfig>): ATProtoSDKConfig;
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Mock storage implementations for testing.
|
|
684
|
+
*
|
|
685
|
+
* This module provides mock implementations of SessionStore and StateStore
|
|
686
|
+
* that track all operations for verification in tests.
|
|
687
|
+
*
|
|
688
|
+
* @packageDocumentation
|
|
689
|
+
*/
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Mock session store that tracks all operations.
|
|
693
|
+
*
|
|
694
|
+
* This implementation stores sessions in memory and records all
|
|
695
|
+
* method calls for verification in tests.
|
|
696
|
+
*
|
|
697
|
+
* @remarks
|
|
698
|
+
* Use this in tests to:
|
|
699
|
+
* - Verify that sessions are being stored correctly
|
|
700
|
+
* - Check what DIDs have been accessed
|
|
701
|
+
* - Assert on the number and order of operations
|
|
702
|
+
* - Pre-populate sessions for testing restore flows
|
|
703
|
+
*
|
|
704
|
+
* @example Basic usage
|
|
705
|
+
* ```typescript
|
|
706
|
+
* import { MockSessionStore } from "@hypercerts-org/sdk/testing";
|
|
707
|
+
*
|
|
708
|
+
* const sessionStore = new MockSessionStore();
|
|
709
|
+
* const sdk = new ATProtoSDK({
|
|
710
|
+
* ...config,
|
|
711
|
+
* storage: { sessionStore },
|
|
712
|
+
* });
|
|
713
|
+
*
|
|
714
|
+
* // After some operations...
|
|
715
|
+
* expect(sessionStore.setCalls).toHaveLength(1);
|
|
716
|
+
* expect(sessionStore.getCalls).toContain("did:plc:test123");
|
|
717
|
+
* ```
|
|
718
|
+
*
|
|
719
|
+
* @example Pre-populating for tests
|
|
720
|
+
* ```typescript
|
|
721
|
+
* const sessionStore = new MockSessionStore();
|
|
722
|
+
*
|
|
723
|
+
* // Pre-populate a session
|
|
724
|
+
* await sessionStore.set("did:plc:existing", mockSessionData);
|
|
725
|
+
*
|
|
726
|
+
* // Reset tracking (keeps the data)
|
|
727
|
+
* sessionStore.getCalls = [];
|
|
728
|
+
* sessionStore.setCalls = [];
|
|
729
|
+
*
|
|
730
|
+
* // Now test restore behavior
|
|
731
|
+
* const session = await sdk.restoreSession("did:plc:existing");
|
|
732
|
+
* expect(sessionStore.getCalls).toContain("did:plc:existing");
|
|
733
|
+
* ```
|
|
734
|
+
*
|
|
735
|
+
* @example Asserting on operations
|
|
736
|
+
* ```typescript
|
|
737
|
+
* const sessionStore = new MockSessionStore();
|
|
738
|
+
*
|
|
739
|
+
* // ... perform operations ...
|
|
740
|
+
*
|
|
741
|
+
* // Verify session was stored for correct DID
|
|
742
|
+
* expect(sessionStore.setCalls[0].did).toBe("did:plc:expected");
|
|
743
|
+
*
|
|
744
|
+
* // Verify session was deleted on logout
|
|
745
|
+
* expect(sessionStore.delCalls).toContain("did:plc:logged-out");
|
|
746
|
+
* ```
|
|
747
|
+
*/
|
|
748
|
+
declare class MockSessionStore implements SessionStore {
|
|
749
|
+
/**
|
|
750
|
+
* Internal storage for sessions.
|
|
751
|
+
* @internal
|
|
752
|
+
*/
|
|
753
|
+
private store;
|
|
754
|
+
/**
|
|
755
|
+
* Record of all `get()` calls made to this store.
|
|
756
|
+
*
|
|
757
|
+
* Each entry is the DID that was requested.
|
|
758
|
+
*/
|
|
759
|
+
getCalls: string[];
|
|
760
|
+
/**
|
|
761
|
+
* Record of all `set()` calls made to this store.
|
|
762
|
+
*
|
|
763
|
+
* Each entry contains the DID and session that was stored.
|
|
764
|
+
*/
|
|
765
|
+
setCalls: Array<{
|
|
766
|
+
did: string;
|
|
767
|
+
session: NodeSavedSession;
|
|
768
|
+
}>;
|
|
769
|
+
/**
|
|
770
|
+
* Record of all `del()` calls made to this store.
|
|
771
|
+
*
|
|
772
|
+
* Each entry is the DID that was deleted.
|
|
773
|
+
*/
|
|
774
|
+
delCalls: string[];
|
|
775
|
+
/**
|
|
776
|
+
* Retrieves a session by DID.
|
|
777
|
+
*
|
|
778
|
+
* Records the call in `getCalls`.
|
|
779
|
+
*
|
|
780
|
+
* @param did - The DID to look up
|
|
781
|
+
* @returns The stored session or undefined
|
|
782
|
+
*/
|
|
783
|
+
get(did: string): Promise<NodeSavedSession | undefined>;
|
|
784
|
+
/**
|
|
785
|
+
* Stores a session.
|
|
786
|
+
*
|
|
787
|
+
* Records the call in `setCalls`.
|
|
788
|
+
*
|
|
789
|
+
* @param did - The DID to store under
|
|
790
|
+
* @param session - The session data to store
|
|
791
|
+
*/
|
|
792
|
+
set(did: string, session: NodeSavedSession): Promise<void>;
|
|
793
|
+
/**
|
|
794
|
+
* Deletes a session.
|
|
795
|
+
*
|
|
796
|
+
* Records the call in `delCalls`.
|
|
797
|
+
*
|
|
798
|
+
* @param did - The DID to delete
|
|
799
|
+
*/
|
|
800
|
+
del(did: string): Promise<void>;
|
|
801
|
+
/**
|
|
802
|
+
* Resets the store to initial state.
|
|
803
|
+
*
|
|
804
|
+
* Clears all stored sessions and all recorded calls.
|
|
805
|
+
* Call this in `beforeEach` or `afterEach` to ensure test isolation.
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* beforeEach(() => {
|
|
810
|
+
* sessionStore.reset();
|
|
811
|
+
* });
|
|
812
|
+
* ```
|
|
813
|
+
*/
|
|
814
|
+
reset(): void;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Mock state store that tracks all operations.
|
|
818
|
+
*
|
|
819
|
+
* This implementation stores OAuth state in memory and records all
|
|
820
|
+
* method calls for verification in tests.
|
|
821
|
+
*
|
|
822
|
+
* @remarks
|
|
823
|
+
* Use this in tests to:
|
|
824
|
+
* - Verify OAuth state is being created during authorization
|
|
825
|
+
* - Check that state is retrieved during callback
|
|
826
|
+
* - Assert that state is cleaned up after use
|
|
827
|
+
* - Test error handling for missing/invalid state
|
|
828
|
+
*
|
|
829
|
+
* @example Basic usage
|
|
830
|
+
* ```typescript
|
|
831
|
+
* import { MockStateStore } from "@hypercerts-org/sdk/testing";
|
|
832
|
+
*
|
|
833
|
+
* const stateStore = new MockStateStore();
|
|
834
|
+
* const sdk = new ATProtoSDK({
|
|
835
|
+
* ...config,
|
|
836
|
+
* storage: { stateStore },
|
|
837
|
+
* });
|
|
838
|
+
*
|
|
839
|
+
* // After authorize()
|
|
840
|
+
* expect(stateStore.setCalls).toHaveLength(1);
|
|
841
|
+
*
|
|
842
|
+
* // After callback()
|
|
843
|
+
* expect(stateStore.getCalls).toHaveLength(1);
|
|
844
|
+
* expect(stateStore.delCalls).toHaveLength(1);
|
|
845
|
+
* ```
|
|
846
|
+
*
|
|
847
|
+
* @example Testing invalid state
|
|
848
|
+
* ```typescript
|
|
849
|
+
* const stateStore = new MockStateStore();
|
|
850
|
+
* // Don't pre-populate - state will be missing
|
|
851
|
+
*
|
|
852
|
+
* // This should fail because state doesn't exist
|
|
853
|
+
* await expect(sdk.callback(params)).rejects.toThrow();
|
|
854
|
+
*
|
|
855
|
+
* // Verify the lookup was attempted
|
|
856
|
+
* expect(stateStore.getCalls).toContain(stateKey);
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
declare class MockStateStore implements StateStore {
|
|
860
|
+
/**
|
|
861
|
+
* Internal storage for OAuth state.
|
|
862
|
+
* @internal
|
|
863
|
+
*/
|
|
864
|
+
private store;
|
|
865
|
+
/**
|
|
866
|
+
* Record of all `get()` calls made to this store.
|
|
867
|
+
*
|
|
868
|
+
* Each entry is the state key that was requested.
|
|
869
|
+
*/
|
|
870
|
+
getCalls: string[];
|
|
871
|
+
/**
|
|
872
|
+
* Record of all `set()` calls made to this store.
|
|
873
|
+
*
|
|
874
|
+
* Each entry contains the key and state that was stored.
|
|
875
|
+
*/
|
|
876
|
+
setCalls: Array<{
|
|
877
|
+
key: string;
|
|
878
|
+
state: NodeSavedState;
|
|
879
|
+
}>;
|
|
880
|
+
/**
|
|
881
|
+
* Record of all `del()` calls made to this store.
|
|
882
|
+
*
|
|
883
|
+
* Each entry is the state key that was deleted.
|
|
884
|
+
*/
|
|
885
|
+
delCalls: string[];
|
|
886
|
+
/**
|
|
887
|
+
* Retrieves OAuth state by key.
|
|
888
|
+
*
|
|
889
|
+
* Records the call in `getCalls`.
|
|
890
|
+
*
|
|
891
|
+
* @param key - The state key to look up
|
|
892
|
+
* @returns The stored state or undefined
|
|
893
|
+
*/
|
|
894
|
+
get(key: string): Promise<NodeSavedState | undefined>;
|
|
895
|
+
/**
|
|
896
|
+
* Stores OAuth state.
|
|
897
|
+
*
|
|
898
|
+
* Records the call in `setCalls`.
|
|
899
|
+
*
|
|
900
|
+
* @param key - The state key to store under
|
|
901
|
+
* @param state - The OAuth state data to store
|
|
902
|
+
*/
|
|
903
|
+
set(key: string, state: NodeSavedState): Promise<void>;
|
|
904
|
+
/**
|
|
905
|
+
* Deletes OAuth state.
|
|
906
|
+
*
|
|
907
|
+
* Records the call in `delCalls`.
|
|
908
|
+
*
|
|
909
|
+
* @param key - The state key to delete
|
|
910
|
+
*/
|
|
911
|
+
del(key: string): Promise<void>;
|
|
912
|
+
/**
|
|
913
|
+
* Resets the store to initial state.
|
|
914
|
+
*
|
|
915
|
+
* Clears all stored state and all recorded calls.
|
|
916
|
+
* Call this in `beforeEach` or `afterEach` to ensure test isolation.
|
|
917
|
+
*
|
|
918
|
+
* @example
|
|
919
|
+
* ```typescript
|
|
920
|
+
* beforeEach(() => {
|
|
921
|
+
* stateStore.reset();
|
|
922
|
+
* });
|
|
923
|
+
* ```
|
|
924
|
+
*/
|
|
925
|
+
reset(): void;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
export { MockSessionStore, MockStateStore, createMockSession, createTestConfig };
|