longcelot-sheet-db
Version:
Google Sheets-backed staging database adapter for Node.js with schema-first design
82 lines • 3.22 kB
TypeScript
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