@remcostoeten/fync
Version:
Unified TypeScript library for 9 popular APIs with consistent functional architecture
284 lines (283 loc) • 12 kB
JavaScript
"use strict";
var _fync = require("@remcostoeten/fync");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /**
* Simple OAuth2 Usage Examples
*
* Quick examples showing how to use fync OAuth2 authentication
* without complex integrations.
*/
// ==============================================================================
// Basic GitHub OAuth Example
// ==============================================================================
async function githubOAuthExample() {
// Initialize GitHub OAuth
const githubAuth = (0, _fync.GitHubOAuth)({
clientId: 'your-github-client-id',
clientSecret: 'your-github-client-secret',
redirectUri: 'http://localhost:3000/auth/github/callback'
});
// Step 1: Generate authorization URL
const {
url,
codeVerifier
} = githubAuth.getAuthorizationUrl({
scope: ['user:email', 'repo'],
state: 'random-state-for-csrf-protection'
});
console.log('Visit this URL to authorize:', url);
// Step 2: After user authorizes, you'll receive a code in your callback
// Exchange the code for tokens
const code = 'authorization-code-from-callback';
const tokens = await githubAuth.exchangeCodeForToken(code);
console.log('Access Token:', tokens.access_token);
console.log('Token Type:', tokens.token_type);
console.log('Scope:', tokens.scope);
// Step 3: Use the token to get user info
const user = await githubAuth.withToken(tokens.access_token).getUser();
console.log('User:', user.login, user.email);
// Get user's email addresses
const emails = await githubAuth.withToken(tokens.access_token).getUserEmails();
console.log('Emails:', emails);
// Get primary email
const primaryEmail = await githubAuth.withToken(tokens.access_token).getPrimaryEmail();
console.log('Primary Email:', primaryEmail);
// Check token validity
const isValid = await githubAuth.withToken(tokens.access_token).validateToken();
console.log('Token is valid:', isValid);
// Get token scopes
const scopes = await githubAuth.withToken(tokens.access_token).getTokenScopes();
console.log('Token scopes:', scopes);
// Get complete profile
const profile = await githubAuth.withToken(tokens.access_token).getCompleteProfile();
console.log('Complete profile:', profile);
// Refresh token (if available)
if (tokens.refresh_token) {
const newTokens = await githubAuth.refreshToken(tokens.refresh_token);
console.log('New access token:', newTokens.access_token);
}
// Revoke token
await githubAuth.revokeToken(tokens.access_token);
console.log('Token revoked');
}
// ==============================================================================
// Basic Google OAuth Example
// ==============================================================================
async function googleOAuthExample() {
// Initialize Google OAuth
const googleAuth = (0, _fync.GoogleOAuth)({
clientId: 'your-google-client-id.apps.googleusercontent.com',
clientSecret: 'your-google-client-secret',
redirectUri: 'http://localhost:3000/auth/google/callback'
});
// Step 1: Generate authorization URL
const {
url,
codeVerifier
} = googleAuth.getAuthorizationUrl({
scope: ['openid', 'email', 'profile', 'https://www.googleapis.com/auth/calendar'],
state: 'random-state-for-csrf-protection',
accessType: 'offline',
// Required for refresh tokens
pkce: true // Use PKCE for better security
});
console.log('Visit this URL to authorize:', url);
console.log('Store this code verifier:', codeVerifier);
// Step 2: After user authorizes, you'll receive a code in your callback
// Exchange the code for tokens
const code = 'authorization-code-from-callback';
const tokens = await googleAuth.exchangeCodeForToken(code, codeVerifier);
console.log('Access Token:', tokens.access_token);
console.log('Refresh Token:', tokens.refresh_token);
console.log('Expires In:', tokens.expires_in);
console.log('Scope:', tokens.scope);
// Step 3: Use the token to get user info
const user = await googleAuth.withToken(tokens.access_token).getUser();
console.log('User:', user.name, user.email);
// Get token information
const tokenInfo = await googleAuth.withToken(tokens.access_token).getTokenInfo();
console.log('Token expires at:', new Date(tokenInfo.exp * 1000));
// Check token validity
const isValid = await googleAuth.withToken(tokens.access_token).validateToken();
console.log('Token is valid:', isValid);
// Get token scopes
const scopes = await googleAuth.withToken(tokens.access_token).getTokenScopes();
console.log('Token scopes:', scopes);
// Check if token has specific scope
const hasCalendarScope = await googleAuth.withToken(tokens.access_token).hasScope('https://www.googleapis.com/auth/calendar');
console.log('Has calendar scope:', hasCalendarScope);
// Get complete profile
const profile = await googleAuth.withToken(tokens.access_token).getCompleteProfile();
console.log('Complete profile:', profile);
// Check token expiration
const expirationTime = await googleAuth.withToken(tokens.access_token).getTokenExpirationTime();
console.log('Token expires in:', expirationTime, 'seconds');
const isExpired = await googleAuth.withToken(tokens.access_token).isTokenExpired(300); // 5 minutes buffer
console.log('Token is expired (with 5min buffer):', isExpired);
// Refresh token
if (tokens.refresh_token) {
const newTokens = await googleAuth.refreshToken(tokens.refresh_token);
console.log('New access token:', newTokens.access_token);
}
// Revoke token
await googleAuth.revokeToken(tokens.access_token);
console.log('Token revoked');
}
// ==============================================================================
// Using OAuth tokens with other fync APIs
// ==============================================================================
async function usingOAuthWithAPIs() {
// After getting tokens from OAuth flow...
const githubAccessToken = 'github-access-token';
const googleAccessToken = 'google-access-token';
// Use GitHub token with GitHub API
const {
GitHub
} = await Promise.resolve().then(() => _interopRequireWildcard(require('@remcostoeten/fync/github')));
const github = GitHub({
token: githubAccessToken
});
const user = await github.me.getAuthenticatedUser();
const repos = await github.me.getMyRepos();
console.log('GitHub user:', user.login);
console.log('Repositories count:', repos.length);
// Use Google token with Google Calendar API
const {
GoogleCalendar
} = await Promise.resolve().then(() => _interopRequireWildcard(require('@remcostoeten/fync/google-calendar')));
const calendar = GoogleCalendar({
token: googleAccessToken
});
const calendars = await calendar.getCalendars();
const events = await calendar.getUpcomingEvents('primary', 10);
console.log('Calendars count:', calendars.items?.length || 0);
console.log('Upcoming events count:', events.length);
}
// ==============================================================================
// Express.js Integration Example
// ==============================================================================
async function expressIntegrationExample() {
// This would be in your Express.js routes
const express = require('express');
const app = express();
// GitHub OAuth routes
app.get('/auth/github', (req, res) => {
const githubAuth = (0, _fync.GitHubOAuth)({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/auth/github/callback'
});
const {
url
} = githubAuth.getAuthorizationUrl({
scope: ['user:email'],
state: req.session?.id || 'random-state'
});
res.redirect(url);
});
app.get('/auth/github/callback', async (req, res) => {
const {
code,
state
} = req.query;
try {
const githubAuth = (0, _fync.GitHubOAuth)({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/auth/github/callback'
});
const tokens = await githubAuth.exchangeCodeForToken(code, state);
const user = await githubAuth.withToken(tokens.access_token).getUser();
// Store user and tokens in session/database
req.session.user = user;
req.session.tokens = tokens;
res.redirect('/dashboard');
} catch (error) {
res.redirect('/auth/error');
}
});
// Google OAuth routes
app.get('/auth/google', (req, res) => {
const googleAuth = (0, _fync.GoogleOAuth)({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/auth/google/callback'
});
const {
url,
codeVerifier
} = googleAuth.getAuthorizationUrl({
scope: ['openid', 'email', 'profile'],
state: req.session?.id || 'random-state',
accessType: 'offline',
pkce: true
});
// Store code verifier in session
req.session.codeVerifier = codeVerifier;
res.redirect(url);
});
app.get('/auth/google/callback', async (req, res) => {
const {
code
} = req.query;
const codeVerifier = req.session?.codeVerifier;
try {
const googleAuth = (0, _fync.GoogleOAuth)({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/auth/google/callback'
});
const tokens = await googleAuth.exchangeCodeForToken(code, codeVerifier);
const user = await googleAuth.withToken(tokens.access_token).getUser();
// Store user and tokens in session/database
req.session.user = user;
req.session.tokens = tokens;
res.redirect('/dashboard');
} catch (error) {
res.redirect('/auth/error');
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
}
// ==============================================================================
// Error Handling Examples
// ==============================================================================
async function errorHandlingExample() {
const githubAuth = (0, _fync.GitHubOAuth)({
clientId: 'invalid-client-id',
clientSecret: 'invalid-client-secret',
redirectUri: 'http://localhost:3000/callback'
});
try {
const tokens = await githubAuth.exchangeCodeForToken('invalid-code');
} catch (error) {
if (error instanceof Error) {
console.error('OAuth error:', error.message);
// Handle specific error cases
if (error.message.includes('invalid_client')) {
console.log('Invalid client credentials');
} else if (error.message.includes('invalid_grant')) {
console.log('Invalid authorization code');
} else if (error.message.includes('expired')) {
console.log('Authorization code has expired');
}
}
}
// Token validation with error handling
try {
const isValid = await githubAuth.withToken('invalid-token').validateToken();
console.log('Token is valid:', isValid); // Will be false
} catch (error) {
console.log('Token validation failed');
}
}
// Run examples
if (require.main === module) {
console.log('Running OAuth examples...');
// Uncomment the examples you want to run
// githubOAuthExample();
// googleOAuthExample();
// usingOAuthWithAPIs();
// errorHandlingExample();
}