UNPKG

longcelot-sheet-db

Version:

Google Sheets-backed staging database adapter for Node.js with schema-first design

82 lines 3.22 kB
import { SheetAdapter } from '../adapter/sheetAdapter'; import { OAuthConfig } from './oauth'; export type RegistrationPolicy = 'open' | 'login-only'; export interface AuthRouterOptions { /** The lsdb adapter instance (must have `users` schema registered) */ adapter: SheetAdapter; /** Secret used to sign JWTs */ jwtSecret: string; /** URL to redirect the browser to after successful auth (your frontend) */ frontendUrl: string; /** * Called with the verified Google profile after OAuth callback. * Return the user object to embed in the JWT, or null to reject. * * - `'open'` policy: if null is returned the user is created automatically. * - `'login-only'` policy: if null is returned a 401 is sent (no self-registration). */ onUser: (profile: GoogleProfile, adapter: SheetAdapter) => Promise<Record<string, unknown> | null>; /** * Controls whether unknown users can self-register. * - `'open'` (default) — any authenticated Google user can get in; call `adapter.createUserSheet()` in `onUser` for new users. * - `'login-only'` — user must already be returned by `onUser`; throws 401 if null. */ registrationPolicy?: RegistrationPolicy; /** OAuth config — if omitted, reads GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI from env */ oauthConfig?: OAuthConfig; /** Path prefix for the two routes (default: '') */ basePath?: string; } export interface GoogleProfile { sub: string; email: string; name: string; picture?: string; email_verified?: boolean; } /** Minimal type-safe shape for an Express-compatible request/response */ interface Req { query: Record<string, string | undefined>; } interface Res { redirect: (url: string) => void; status: (code: number) => { json: (body: unknown) => void; }; } export interface AuthRouter { /** Mount on an Express app: `app.use(router.handler)` */ handler: (req: Req, res: Res, next: () => void) => Promise<void>; /** The path that starts the OAuth flow (e.g. `/auth/google`) */ loginPath: string; /** The OAuth redirect path (e.g. `/auth/callback`) */ callbackPath: string; } /** * Creates an Express-compatible auth router that wires up two routes: * * GET {basePath}/auth/google — redirects to Google OAuth consent screen * GET {basePath}/auth/callback — exchanges code, verifies identity, issues JWT * * @example * ```typescript * import express from 'express' * import { createAuthRouter } from 'longcelot-sheet-db' * * const auth = createAuthRouter({ * adapter, * jwtSecret: process.env.JWT_SECRET!, * frontendUrl: process.env.FRONTEND_URL!, * registrationPolicy: 'login-only', // admin-only — no self-signup * async onUser(profile, adapter) { * const ctx = adapter.withContext({ userId: 'auth', actor: 'admin', actorSheetId: process.env.ADMIN_SHEET_ID! }) * return await ctx.table('users').findOne({ where: { email: profile.email } }) * }, * }) * * app.use(auth.handler) * ``` */ export declare function createAuthRouter(options: AuthRouterOptions): AuthRouter; export {}; //# sourceMappingURL=router.d.ts.map