diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..677225b --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Dependency directories +node_modules/ +dist +.DS_Store + +# Output of 'npm pack' +*.tgz + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# turbo +.turbo \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6a581e6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "editor.formatOnType": true, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 29e89bf..4549a0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +- [2024-10-02] [gitignore, biome, vscode](https://github.com/RubricLab/auth/commit/017182b92cbae09df53e41423db10c788ba94bf7) - [2024-10-02] [init](https://github.com/RubricLab/auth/commit/40145b017976d9a7393063a4640e6965af45eac4) # Changelog diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..e8d99dd --- /dev/null +++ b/biome.json @@ -0,0 +1,3 @@ +{ + "extends": ["@rubriclab/config/biome"] +} diff --git a/index.ts b/index.ts index 94dc280..f221e4c 100644 --- a/index.ts +++ b/index.ts @@ -1,4 +1,4 @@ export type { AuthProvider, - AuthProviderConfig, -} from "./lib/types"; + AuthProviderConfig +} from './lib/types' diff --git a/lib/route.ts b/lib/route.ts index 554bb40..bc79412 100644 --- a/lib/route.ts +++ b/lib/route.ts @@ -1,37 +1,31 @@ -import { type NextRequest, NextResponse } from "next/server"; -import type { - AuthProviders, - DB, - UserInfo, - AuthProvider, - AuthTokens, -} from "./types"; +import { type NextRequest, NextResponse } from 'next/server' +import type { AuthProviders, DB, UserInfo, AuthProvider, AuthTokens } from './types' async function connectAuthProvider({ userId, userInfo, provider, authTokens, - db, + db }: { - userId: string; - userInfo: UserInfo; - provider: AuthProvider; - authTokens: AuthTokens; - db: DB; + userId: string + userInfo: UserInfo + provider: AuthProvider + authTokens: AuthTokens + db: DB }) { await db.authProvider.upsert({ where: { userId_provider_accountId: { provider: provider.config.provider, userId, - accountId: userInfo.accountId, - }, + accountId: userInfo.accountId + } }, update: { accessToken: authTokens.accessToken, refreshToken: authTokens.refreshToken, - expiresAt: authTokens.expiresAt ? new Date(authTokens.expiresAt) : null, + expiresAt: authTokens.expiresAt ? new Date(authTokens.expiresAt) : null }, create: { provider: provider.config.provider, @@ -41,53 +35,50 @@ async function connectAuthProvider({ accessToken: authTokens.accessToken, refreshToken: authTokens.refreshToken, expiresAt: authTokens.expiresAt ? new Date(authTokens.expiresAt) : null, - userId, - }, - }); + userId + } + }) } export function createAuthCallbackHandler({ authProviders, db, - url, + url }: { - authProviders: AuthProviders; - db: DB; - url: string; + authProviders: AuthProviders + db: DB + url: string }) { return async ( request: NextRequest, - { params }: { params: { provider: keyof AuthProviders } }, + { params }: { params: { provider: keyof AuthProviders } } ): Promise => { - const provider = authProviders[params.provider]; + const provider = authProviders[params.provider] if (!provider) { - return NextResponse.redirect(`${url}?error=InvalidProvider`); + return NextResponse.redirect(`${url}?error=InvalidProvider`) } - const code = request.nextUrl.searchParams.get("code"); + const code = request.nextUrl.searchParams.get('code') if (!code) { - return NextResponse.redirect(`${url}?error=NoCodeProvided`); + return NextResponse.redirect(`${url}?error=NoCodeProvided`) } - const userId = request.nextUrl.searchParams.get("state"); + const userId = request.nextUrl.searchParams.get('state') if (!userId) { - return NextResponse.redirect(`${url}?error=NoUserIdProvided`); + return NextResponse.redirect(`${url}?error=NoUserIdProvided`) } try { - const authTokens = await provider.getTokensFromCode({ code }); + const authTokens = await provider.getTokensFromCode({ code }) const userInfo = await provider.getUserInfo({ - token: authTokens.accessToken, - }); + token: authTokens.accessToken + }) - await connectAuthProvider({ userId, provider, authTokens, userInfo, db }); + await connectAuthProvider({ userId, provider, authTokens, userInfo, db }) - return NextResponse.redirect(`${url}?success=true`); + return NextResponse.redirect(`${url}?success=true`) } catch (error) { - console.error( - `Error during ${provider.config.provider} auth callback:`, - error, - ); - return NextResponse.redirect(`${url}?error=AuthFailed`); + console.error(`Error during ${provider.config.provider} auth callback:`, error) + return NextResponse.redirect(`${url}?error=AuthFailed`) } - }; + } } diff --git a/lib/types.ts b/lib/types.ts index 7cf8fe6..24170ab 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,49 +1,49 @@ -import type { PrismaClient } from "@prisma/client"; +import type { PrismaClient } from '@prisma/client' export interface UserInfo { - accountId: string; - label: string; + accountId: string + label: string } export interface AuthProviderConfig { - provider: string; - scopes: string[]; - clientId: string; - clientSecret: string; + provider: string + scopes: string[] + clientId: string + clientSecret: string } export interface AuthTokens { - accessToken: string; - refreshToken: string | null; - expiresAt: number | null; + accessToken: string + refreshToken: string | null + expiresAt: number | null } export interface AuthProvider { - config: AuthProviderConfig; - getAuthUrl: ({ userId }: { userId: string }) => string; - getTokensFromCode({ code }: { code: string }): Promise; + config: AuthProviderConfig + getAuthUrl: ({ userId }: { userId: string }) => string + getTokensFromCode({ code }: { code: string }): Promise getAccessToken({ userId, - accountId, + accountId }: { - userId: string; - accountId: string; - }): Promise<{ accessToken: string }>; - getUserInfo({ token }: { token: string }): Promise; + userId: string + accountId: string + }): Promise<{ accessToken: string }> + getUserInfo({ token }: { token: string }): Promise } export type AuthProviders = { - [provider in string]?: AuthProvider; -}; + [provider in string]?: AuthProvider +} export interface User { - id: string; + id: string } export interface WebhookInfo { - id: string; - type: string; - enabled: boolean; + id: string + type: string + enabled: boolean } -export type DB = PrismaClient; +export type DB = PrismaClient diff --git a/lib/utils.ts b/lib/utils.ts index fd43f66..6baddeb 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,59 +1,59 @@ -import type { Prisma } from "@prisma/client"; +import type { Prisma } from '@prisma/client' -import type { AuthProviders } from "./types"; +import type { AuthProviders } from './types' export function createAuthActions({ authProviders, - db, + db }: { - authProviders: AuthProviders; + authProviders: AuthProviders db: { - authProvider: Prisma.AuthProviderDelegate; - }; + authProvider: Prisma.AuthProviderDelegate + } }) { return { async getAuthUrl({ userId, - provider, + provider }: { - userId: string; - provider: string; + userId: string + provider: string }) { - const authProvider = authProviders[provider]; + const authProvider = authProviders[provider] if (!authProvider) { - throw new Error(`Auth provider not found for ${provider}`); + throw new Error(`Auth provider not found for ${provider}`) } - return authProvider.getAuthUrl({ userId }); + return authProvider.getAuthUrl({ userId }) }, async getConnectedAccounts({ userId }: { userId: string }) { const connectedAccounts = await db.authProvider.findMany({ - where: { userId }, - }); + where: { userId } + }) - return connectedAccounts; + return connectedAccounts }, async disconnectAuthProvider({ userId, provider, - accountId, + accountId }: { - userId: string; - provider: string; - accountId: string; + userId: string + provider: string + accountId: string }) { await db.authProvider.delete({ where: { userId_provider_accountId: { userId, provider, - accountId, - }, - }, - }); - }, - }; + accountId + } + } + }) + } + } } diff --git a/package.json b/package.json index 859207a..a6386eb 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,11 @@ "lint:fix": "bun x biome lint . --write --unsafe" }, "name": "@rubriclab/auth", - "version": "0.0.1", + "version": "0.0.2", "main": "index.ts", "dependencies": { - "@rubriclab/package": "*" + "@rubriclab/package": "*", + "@rubriclab/config": "*" }, "simple-git-hooks": { "post-commit": "bun run rubriclab-postcommit"