Documentation

Helpers utilitaires

Index des libs internes (`lib/intl.ts`, `lib/auth-guards.ts`, `lib/sanitize.ts`, etc.) pour ne pas réinventer la roue.

Liste des helpers réutilisables — quand tu construis une nouvelle feature, vérifie qu'il n'y en a pas déjà un qui fait le job avant de coder.

lib/auth-guards.ts

import { requireApiAuth } from "@/lib/auth-guards";

const guard = await requireApiAuth({ admin: true });
if (guard instanceof NextResponse) return guard;
const session = guard;
  • Sans options → user authentifié + 2FA validée
  • { admin: true } → restreint aux ADMIN
  • { allowPending2fa: true } → pour les routes 2FA elles-mêmes

lib/intl.ts

FonctionRôle
intlLocaleFor(locale)"fr" → "fr-FR", "en" → "en-US", etc. (pour Intl APIs)
localeLabel(code)"fr" → "Français", etc. (pour UI)
stripHtml(html)retire toutes les balises (pour notifications, twitter cards…)
stripAndShorten(html, max)strip + tronque à N caractères
READABLE_ALPHABET"ABCDEFGHJKLMNPQRSTUVWXYZ23456789" (sans 0/O/1/I)

lib/sanitize.ts

Voir Sanitization HTML.

lib/rate-limit.ts + lib/cron-auth.ts

Voir Rate limiting & cron auth.

lib/feature-flags.ts

Voir Feature flags.

lib/two-factor-verify.ts

import { verifyTwoFactorAttempt } from "@/lib/two-factor-verify";

const result = await verifyTwoFactorAttempt(userId, email, code);
// "ok" | "locked" | "invalid"

Anti-bruteforce + replay + backup codes atomiques. Voir 2FA.

lib/webhook-idempotence.ts

import { claimWebhookEvent } from "@/lib/webhook-idempotence";

if ((await claimWebhookEvent(event.id, event.type)) === "duplicate") {
  return ack();
}

Voir Idempotence des webhooks.

lib/email-log.ts

import { logEmail } from "@/lib/email-log";

await logEmail({
  to, subject, templateKey: "welcome", providerId: result.data?.id,
});

Voir Email logs.

lib/profile-completeness.ts

Pure function. Voir Profile completeness.

lib/totp.ts

import { generateTotpSecret, totpUri, totpQrCode, verifyTotp } from "@/lib/totp";

Voir 2FA.

lib/site-config.ts

import { getCachedSiteConfig, pickLocalized } from "@/lib/site-config";

const cfg = await getCachedSiteConfig();   // appName, appUrl, supportEmail…
const text = pickLocalized(plan.name, "fr");

lib/audit.ts

import { logAudit } from "@/lib/audit";

await logAudit({
  userId: session.user.id,
  action: "user.something",
  entity: "User",
  entityId: targetId,
  metadata: { /* ... */ },
  req,    // optionnel — capture IP + UA
});

Voir Audit log.

components/ui/data-list.tsx

Voir DataList. Toutes les listes admin l'utilisent (users, billing, sessions, email logs, activity).

components/ui/responsive-tabs.tsx

Tabs qui se transforment en <select> sur mobile (sm/md/lg breakpoints). Utilisé partout où on a des tabs (settings, fiche user, etc.).

components/ui/responsive-dialog.tsx

Modal qui adapte son rendu selon le viewport :

  • Desktop (≥768px) → <Dialog> Radix centré, click-outside, X
  • Mobile (<768px) → <Drawer> vaul drag-to-close natif

API unique :

<ResponsiveDialog
  open={open}
  onOpenChange={setOpen}
  title="Email"
  subheader={<MetadataChips />}
  desktopMaxWidth="max-w-3xl"
  mobileHeight="h-[90vh]"
>
  {body}
</ResponsiveDialog>

À utiliser à chaque fois que tu ouvres un panneau de détail / preview / édition substantielle. Pour les confirms tout courts un <Dialog> simple suffit — pas besoin du drawer mobile.

lib/use-is-desktop.ts

const isDesktop = useIsDesktop();   // true ≥ 768px, listens to resize

Force mobile via ?mobile=1 dans l'URL pour tester depuis Chrome desktop. Utilisé par <ResponsiveDialog>, <NotificationBell>, etc.

On this page