Framework-agnostic OAuth integration for AT Protocol (Bluesky) applications.

1.0.0: Breaking change - standardize Logger interface

- Logger: Changed from (log, warn, error) to (debug, info, warn, error)
- Simplified OAuthClient logger adapter since interfaces now match
- Updated atproto-sessions dependency to 1.0.0

+64 -28
+46
CHANGELOG.md
··· 2 3 All notable changes to this project will be documented in this file. 4 5 ## [0.1.1] - 2025-11-28 6 7 ### Added
··· 2 3 All notable changes to this project will be documented in this file. 4 5 + ## [1.0.0] - 2025-11-28 6 + 7 + ### Breaking Changes 8 + 9 + - **Logger interface**: Changed from 3 methods (`log`, `warn`, `error`) to 4 10 + methods (`debug`, `info`, `warn`, `error`) for compatibility with 11 + oauth-client-deno. This allows unified logging across all AT Protocol OAuth 12 + libraries. 13 + 14 + ### Migration Guide 15 + 16 + **Logger interface:** 17 + 18 + ```typescript 19 + // Before 20 + const oauth = createATProtoOAuth({ 21 + // ... 22 + logger: { 23 + log: console.log, 24 + warn: console.warn, 25 + error: console.error, 26 + }, 27 + }); 28 + 29 + // After 30 + const oauth = createATProtoOAuth({ 31 + // ... 32 + logger: { 33 + debug: console.debug, 34 + info: console.info, 35 + warn: console.warn, 36 + error: console.error, 37 + }, 38 + }); 39 + 40 + // Or simply pass console (which has all 4 methods): 41 + const oauth = createATProtoOAuth({ 42 + // ... 43 + logger: console, 44 + }); 45 + ``` 46 + 47 + ### Changed 48 + 49 + - Updated `@tijs/atproto-sessions` dependency to 1.0.0 50 + 51 ## [0.1.1] - 2025-11-28 52 53 ### Added
+2 -2
deno.json
··· 1 { 2 "$schema": "https://jsr.io/schema/config-file.v1.json", 3 "name": "@tijs/atproto-oauth", 4 - "version": "0.1.1", 5 "license": "MIT", 6 "exports": "./mod.ts", 7 "publish": { ··· 11 "imports": { 12 "@std/assert": "jsr:@std/assert@1.0.16", 13 "@tijs/oauth-client-deno": "jsr:@tijs/oauth-client-deno@4.0.2", 14 - "@tijs/atproto-sessions": "jsr:@tijs/atproto-sessions@0.1.1", 15 "@tijs/atproto-storage": "jsr:@tijs/atproto-storage@0.1.1", 16 "@atproto/syntax": "npm:@atproto/syntax@0.3.0" 17 },
··· 1 { 2 "$schema": "https://jsr.io/schema/config-file.v1.json", 3 "name": "@tijs/atproto-oauth", 4 + "version": "1.0.0", 5 "license": "MIT", 6 "exports": "./mod.ts", 7 "publish": { ··· 11 "imports": { 12 "@std/assert": "jsr:@std/assert@1.0.16", 13 "@tijs/oauth-client-deno": "jsr:@tijs/oauth-client-deno@4.0.2", 14 + "@tijs/atproto-sessions": "jsr:@tijs/atproto-sessions@1.0.0", 15 "@tijs/atproto-storage": "jsr:@tijs/atproto-storage@0.1.1", 16 "@atproto/syntax": "npm:@atproto/syntax@0.3.0" 17 },
+2 -15
src/oauth.ts
··· 111 const mobileScheme = config.mobileScheme ?? DEFAULT_MOBILE_SCHEME; 112 const logger: Logger = config.logger ?? noopLogger; 113 114 - // Create OAuth client 115 const oauthClient = new OAuthClient({ 116 clientId: `${baseUrl}/oauth-client-metadata.json`, 117 redirectUri: `${baseUrl}/oauth/callback`, 118 storage: config.storage, 119 - logger: { 120 - debug: (msg: string, ...args: unknown[]) => { 121 - logger.log(`[DEBUG] ${msg}`, ...args); 122 - }, 123 - info: (msg: string, ...args: unknown[]) => { 124 - logger.log(`[INFO] ${msg}`, ...args); 125 - }, 126 - warn: (msg: string, ...args: unknown[]) => { 127 - logger.warn(msg, ...args); 128 - }, 129 - error: (msg: string, ...args: unknown[]) => { 130 - logger.error(msg, ...args); 131 - }, 132 - }, 133 }); 134 135 // Create session manager for cookie handling
··· 111 const mobileScheme = config.mobileScheme ?? DEFAULT_MOBILE_SCHEME; 112 const logger: Logger = config.logger ?? noopLogger; 113 114 + // Create OAuth client (Logger interfaces now match) 115 const oauthClient = new OAuthClient({ 116 clientId: `${baseUrl}/oauth-client-metadata.json`, 117 redirectUri: `${baseUrl}/oauth/callback`, 118 storage: config.storage, 119 + logger, 120 }); 121 122 // Create session manager for cookie handling
+8 -8
src/sessions.ts
··· 49 * Get OAuth session for a DID with automatic token refresh 50 */ 51 async getOAuthSession(did: string): Promise<SessionInterface | null> { 52 - this.logger.log(`Restoring OAuth session for DID: ${did}`); 53 54 try { 55 // The OAuth client's restore() method handles automatic token refresh 56 const session = await this.oauthClient.restore(did); 57 58 if (session) { 59 - this.logger.log(`OAuth session restored successfully for DID: ${did}`); 60 61 // Log token expiration information if available 62 if (session.timeUntilExpiry !== undefined) { ··· 67 const now = Date.now(); 68 const expiresAt = now + session.timeUntilExpiry; 69 70 - this.logger.log(`Token status for DID ${did}:`, { 71 expiresAt: new Date(expiresAt).toISOString(), 72 currentTime: new Date(now).toISOString(), 73 timeUntilExpiryMinutes, ··· 76 }); 77 } 78 } else { 79 - this.logger.log(`OAuth session not found for DID: ${did}`); 80 } 81 82 return session; ··· 94 * Save OAuth session to storage 95 */ 96 async saveOAuthSession(session: SessionInterface): Promise<void> { 97 - this.logger.log(`Saving OAuth session for DID: ${session.did}`); 98 99 await this.storage.set(`session:${session.did}`, session.toJSON(), { 100 ttl: this.sessionTtl, 101 }); 102 103 - this.logger.log(`OAuth session saved for DID: ${session.did}`); 104 } 105 106 /** 107 * Delete OAuth session from storage 108 */ 109 async deleteOAuthSession(did: string): Promise<void> { 110 - this.logger.log(`Deleting OAuth session for DID: ${did}`); 111 112 await this.storage.delete(`session:${did}`); 113 114 - this.logger.log(`OAuth session deleted for DID: ${did}`); 115 } 116 }
··· 49 * Get OAuth session for a DID with automatic token refresh 50 */ 51 async getOAuthSession(did: string): Promise<SessionInterface | null> { 52 + this.logger.debug(`Restoring OAuth session for DID: ${did}`); 53 54 try { 55 // The OAuth client's restore() method handles automatic token refresh 56 const session = await this.oauthClient.restore(did); 57 58 if (session) { 59 + this.logger.info(`OAuth session restored successfully for DID: ${did}`); 60 61 // Log token expiration information if available 62 if (session.timeUntilExpiry !== undefined) { ··· 67 const now = Date.now(); 68 const expiresAt = now + session.timeUntilExpiry; 69 70 + this.logger.debug(`Token status for DID ${did}:`, { 71 expiresAt: new Date(expiresAt).toISOString(), 72 currentTime: new Date(now).toISOString(), 73 timeUntilExpiryMinutes, ··· 76 }); 77 } 78 } else { 79 + this.logger.debug(`OAuth session not found for DID: ${did}`); 80 } 81 82 return session; ··· 94 * Save OAuth session to storage 95 */ 96 async saveOAuthSession(session: SessionInterface): Promise<void> { 97 + this.logger.debug(`Saving OAuth session for DID: ${session.did}`); 98 99 await this.storage.set(`session:${session.did}`, session.toJSON(), { 100 ttl: this.sessionTtl, 101 }); 102 103 + this.logger.info(`OAuth session saved for DID: ${session.did}`); 104 } 105 106 /** 107 * Delete OAuth session from storage 108 */ 109 async deleteOAuthSession(did: string): Promise<void> { 110 + this.logger.debug(`Deleting OAuth session for DID: ${did}`); 111 112 await this.storage.delete(`session:${did}`); 113 114 + this.logger.info(`OAuth session deleted for DID: ${did}`); 115 } 116 }
+6 -3
src/types.ts
··· 6 import type { OAuthStorage } from "@tijs/atproto-storage"; 7 8 /** 9 - * Logger interface for custom logging implementations 10 */ 11 export interface Logger { 12 - log(...args: unknown[]): void; 13 warn(...args: unknown[]): void; 14 error(...args: unknown[]): void; 15 } ··· 18 * No-op logger for production use 19 */ 20 export const noopLogger: Logger = { 21 - log: () => {}, 22 warn: () => {}, 23 error: () => {}, 24 };
··· 6 import type { OAuthStorage } from "@tijs/atproto-storage"; 7 8 /** 9 + * Logger interface for custom logging implementations. 10 + * Compatible with oauth-client-deno's Logger interface. 11 */ 12 export interface Logger { 13 + debug(...args: unknown[]): void; 14 + info(...args: unknown[]): void; 15 warn(...args: unknown[]): void; 16 error(...args: unknown[]): void; 17 } ··· 20 * No-op logger for production use 21 */ 22 export const noopLogger: Logger = { 23 + debug: () => {}, 24 + info: () => {}, 25 warn: () => {}, 26 error: () => {}, 27 };