@dainprotocol/oauth2-storage-drizzle
Drizzle ORM storage adapter for @dainprotocol/oauth2-token-manager.
Installation
npm install @dainprotocol/oauth2-storage-drizzle drizzle-orm
Usage
Database Setup
The adapter provides multiple ways to set up your database tables:
Option 1: Automatic Migrations (Recommended for Development)
Use the runMigrations
option to automatically create tables when initializing the adapter:
import { OAuth2Client } from '@dainprotocol/oauth2-token-manager';
import { DrizzleStorageAdapter } from '@dainprotocol/oauth2-storage-drizzle';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(connectionString);
const db = drizzle(client);
const storage = await DrizzleStorageAdapter.create(db, {
dialect: 'postgres',
runMigrations: true,
});
const oauth = new OAuth2Client({ storage });
Or use the constructor with manual migration:
import { migrate } from '@dainprotocol/oauth2-storage-drizzle';
await migrate(db, { dialect: 'postgres' });
const storage = new DrizzleStorageAdapter(db, { dialect: 'postgres' });
Custom Profile Fetchers
The Drizzle adapter supports registering custom profile fetchers to override default behavior or add support for new providers:
import { BaseProfileFetcher, UserProfile } from '@dainprotocol/oauth2-token-manager';
class CustomProviderFetcher extends BaseProfileFetcher {
constructor() {
super('https://api.provider.com/user/profile');
}
protected mapToUserProfile(rawData: any): UserProfile {
return {
email: rawData.contact.email,
name: rawData.display_name,
id: rawData.user_id,
avatar: rawData.avatar_url,
raw: rawData,
};
}
}
const storage = await DrizzleStorageAdapter.create(db, {
dialect: 'postgres',
profileFetchers: {
'custom-provider': new CustomProviderFetcher(),
github: new CustomGitHubFetcher(),
},
});
storage.registerProfileFetcher('another-provider', new AnotherFetcher());
const oauth = new OAuth2Client({
storage,
providers: {
'custom-provider': {
clientId: 'xxx',
clientSecret: 'xxx',
},
},
});
Option 2: Drizzle Kit (Recommended for Production)
For production environments, use Drizzle Kit for migration management:
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './node_modules/@dainprotocol/oauth2-storage-drizzle/dist/schema',
out: './drizzle',
dialect: 'postgresql',
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
});
Generate and run migrations:
npx drizzle-kit generate:pg
npx drizzle-kit migrate:pg
PostgreSQL
import { OAuth2Client } from '@dainprotocol/oauth2-token-manager';
import { DrizzleStorageAdapter } from '@dainprotocol/oauth2-storage-drizzle';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(connectionString);
const db = drizzle(client);
const storage = await DrizzleStorageAdapter.create(db, {
dialect: 'postgres',
runMigrations: process.env.NODE_ENV === 'development',
});
const oauth = new OAuth2Client({ storage });
MySQL
import { DrizzleStorageAdapter } from '@dainprotocol/oauth2-storage-drizzle';
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'oauth_tokens',
});
const db = drizzle(connection);
const storage = await DrizzleStorageAdapter.create(db, {
dialect: 'mysql',
runMigrations: process.env.NODE_ENV === 'development',
});
SQLite
import { DrizzleStorageAdapter } from '@dainprotocol/oauth2-storage-drizzle';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import Database from 'better-sqlite3';
const sqlite = new Database('oauth_tokens.db');
const db = drizzle(sqlite);
const storage = await DrizzleStorageAdapter.create(db, {
dialect: 'sqlite',
runMigrations: process.env.NODE_ENV === 'development',
});
API Methods
The DrizzleStorageAdapter implements all methods from the StorageAdapter interface:
Token Operations
saveToken(input)
- Save or update a token (unique by provider + email)
getToken(provider, email)
- Get a specific token
getTokenById(id)
- Get a token by its ID
getTokensByUserId(userId)
- Get all tokens for a user
getTokensByEmail(email)
- Get all tokens for an email
getTokensByProvider(provider)
- Get all tokens for a provider
getAccounts(userId, provider)
- Get all tokens for a specific user in a specific provider
getTokensForEmail(userId, provider, email)
- Get a single token for a specific user, provider, and email (returns null if not found)
getTokens(userId, provider)
- Get all tokens for a specific user in a specific provider (alias for getAccounts)
updateToken(id, update)
- Update a token
deleteToken(id)
- Delete a token by ID
deleteTokenByProviderEmail(provider, email)
- Delete a token by provider and email
deleteExpiredTokens()
- Clean up expired tokens
Authorization State Operations
saveAuthorizationState(state)
- Save an authorization state
getAuthorizationState(state)
- Get an authorization state
deleteAuthorizationState(state)
- Delete an authorization state
cleanupExpiredStates()
- Clean up expired states (older than 10 minutes)
Schema
The adapter automatically creates the following tables:
oauth2_tokens
id
- Unique identifier
provider
- OAuth provider name
userId
- User identifier
email
- User email
accessToken
- Encrypted access token
refreshToken
- Encrypted refresh token (optional)
expiresAt
- Token expiration timestamp
tokenType
- Token type (e.g., "Bearer")
scope
- OAuth scopes
metadata
- Additional metadata (JSON)
createdAt
- Creation timestamp
updatedAt
- Last update timestamp
Unique constraint: provider
+ email
oauth2_authorization_states
state
- Authorization state (primary key)
codeVerifier
- PKCE code verifier
config
- OAuth configuration (JSON)
metadata
- Additional metadata (JSON)
createdAt
- Creation timestamp
Features
- Multi-database support (PostgreSQL, MySQL, SQLite)
- Automatic schema creation
- Secure token encryption
- Built-in cleanup for expired tokens and states
- TypeScript support
License
MIT