fix: 5 bugs critiques de l'éditeur (Phase 1 audit)
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 5m39s
CI / Deploy production (on server) (push) Successful in 22s

1. replaceAll (Find & Replace) — une seule transaction ProseMirror
   au lieu d'un forEach cassé. Tous les matchs sont maintenant remplacés.

2. Link Preview unwrap — deleteNode() au lieu de clearer les attrs
   qui laissaient un nœud fantôme invisible dans le document.

3. Conversion Markdown → richtext — breaks: true dans marked.parse()
   Les simple newlines sont maintenant convertis en <br>.
   + préserve les blocs custom (toggle, callout, math, columns,
   outline, link-preview) en commentaires HTML lors de l'export MD.

4. emitNoteChange exercices — shape corrigée (type:'created' attend
   un objet Note, pas noteId/notebookId séparés).

5. Raccourcis clavier sans conflit :
   Cmd+Shift+C → Cmd+Alt+C (callout, avant: copier)
   Cmd+Shift+O → Cmd+Alt+O (outline, avant: historique/signets)
   Cmd+Shift+L → Cmd+Alt+L (colonnes, avant: lock screen macOS)
This commit is contained in:
Antigravity
2026-06-20 15:48:18 +00:00
parent 5b13a88b72
commit ee70e74bf5
51 changed files with 1483 additions and 252 deletions

View File

@@ -26,7 +26,7 @@ export async function POST(req: NextRequest) {
const userEmail = session.user.email;
try {
const priceId = resolvePriceId(tier, interval);
const priceId = await resolvePriceId(tier, interval);
const subscription = await prisma.subscription.findUnique({ where: { userId } });
let customerId = subscription?.stripeCustomerId ?? undefined;

View File

@@ -3,7 +3,7 @@ import { auth } from '@/auth';
import { getUserInfo, getEffectiveTier } from '@/lib/entitlements';
import { stripe } from '@/lib/stripe';
import type Stripe from 'stripe';
import { priceIdToTier, getDynamicPrices } from '@/lib/billing/stripe-prices';
import { priceIdToTier, getDynamicPrices, isBillingEnabled } from '@/lib/billing/stripe-prices';
export const dynamic = 'force-dynamic';
@@ -28,7 +28,7 @@ export async function GET(req: NextRequest) {
const sub = await stripe.subscriptions.retrieve(subId) as any;
const priceId = sub.items.data[0].price.id;
const tier = priceIdToTier(priceId) || (checkoutSession.metadata?.tier as any) || 'PRO';
const tier = (await priceIdToTier(priceId)) || (checkoutSession.metadata?.tier as any) || 'PRO';
const currentPeriodStartTimestamp =
sub.current_period_start ??
@@ -75,6 +75,7 @@ export async function GET(req: NextRequest) {
const effectiveTier = await getEffectiveTier(userId);
const subscription = await prisma.subscription.findUnique({ where: { userId } });
const prices = await getDynamicPrices();
const billingEnabled = await isBillingEnabled();
return NextResponse.json({
tier,
@@ -85,6 +86,7 @@ export async function GET(req: NextRequest) {
cancelAtPeriodEnd: subscription?.cancelAtPeriodEnd ?? false,
hasStripeSubscription: !!subscription?.stripeSubscriptionId,
prices,
billingEnabled,
});
} catch (error) {
console.error('[billing/status]', error);