chore: use scoped server pattern generation based subscription#1
Conversation
WalkthroughRefactors Flowglad from a single shared instance to a per-customer factory, adds session-based auth in API routes to derive customerExternalId, replaces route handler wiring to use nextRouteHandler with getCustomerExternalId, updates usage event logic to use priceSlug, and simplifies README and package.json scripts/dependencies. Changes
Sequence DiagramsequenceDiagram
participant Client as Client (Browser)
participant NextRoute as Next.js Route Handler
participant Auth as Auth System
participant FlowgladFactory as flowglad(customerExternalId)
participant Flowglad as Flowglad Server
participant Business as Billing/Usage Logic
Client->>NextRoute: HTTP API request (cookies/headers)
NextRoute->>Auth: auth.api.getSession(headers)
Auth-->>NextRoute: session (user)
alt authenticated
NextRoute->>FlowgladFactory: flowglad(user.id)
FlowgladFactory->>Flowglad: create/configure instance (getCustomerDetails)
NextRoute->>Business: perform billing/usage operation (priceSlug)
Business->>Flowglad: query/update billing state
Flowglad-->>Business: response
Business-->>NextRoute: result
NextRoute-->>Client: 200 OK (result)
else unauthenticated
NextRoute-->>Client: 401 Unauthorized
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
generation-based-subscription/src/app/api/usage-events/route.ts (1)
1-7: Auth-scoped Flowglad usage event creation looks solid; consider stronger transaction IDsThe refactor to:
- fetch the session via
auth.api.getSession({ headers: await headers() }),- derive
userIdand short‑circuit with a 401 when missing, and- construct a per-user
flowgladServer = flowglad(userId);fits well with the new Flowglad factory and keeps usage events properly tied to an authenticated customer.
The only thing I’d tweak is the fallback transaction ID:
Date.now()+Math.random()is fine for low volume but not ideal for long-term idempotency. You could prefer a UUID-based ID instead, e.g.:+import { randomUUID } from 'crypto'; @@ - const finalTransactionId = - transactionId || - `usage_${Date.now()}_${Math.random().toString(36).substring(7)}`; + const finalTransactionId = + transactionId || `usage_${randomUUID()}`;If you adopt this, just confirm that importing from
cryptoaligns with your chosen runtime (Node vs Edge).Also applies to: 48-52, 53-65, 114-122
generation-based-subscription/src/app/api/flowglad/[...path]/route.ts (1)
1-18: Per-customer Flowglad router wiring looks good; minor ergonomicsThe
nextRouteHandler({ flowglad, getCustomerExternalId })setup withauth.api.getSession({ headers: await headers() })and returninguserIdis consistent with the new Flowglad factory and the usage-events route.Two small nits you might consider:
- Rename the unused
reqparameter to_req(or remove it if the type allows) to keep linters quiet.- Confirm that throwing a plain
Error('User not found')is hownextRouteHandlerexpects you to signal “unauthenticated/unknown customer” so it returns the right HTTP status, vs needing a specific error type or 401 response.generation-based-subscription/src/lib/flowglad.ts (1)
5-23: Flowglad factory integration is correct; mark unused arg for clarityThis
flowglad(customerExternalId)factory cleanly switches you from a singleton to per-customerFlowgladServerinstances and correctly wiresgetCustomerDetailsthroughauth.api.getSession({ headers: await headers() }), enforcing authentication and exposing email/name.Two small cleanups you might consider:
- In
getCustomerDetails, thecustomerExternalIdparameter isn’t used. Renaming it to_customerExternalId(or omitting the name if the type allows) will better signal that it’s intentionally unused and avoid lint noise.- You now resolve the session both in the routes (to get
userId) and again here. That’s fine for now, but if this endpoint gets very hot you could later look at threading the session/user details into this factory instead of re-fetching.Functionally this looks good as-is.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
generation-based-subscription/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
generation-based-subscription/README.md(3 hunks)generation-based-subscription/package.json(1 hunks)generation-based-subscription/src/app/api/flowglad/[...path]/route.ts(1 hunks)generation-based-subscription/src/app/api/usage-events/route.ts(2 hunks)generation-based-subscription/src/lib/flowglad.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
generation-based-subscription/src/app/api/usage-events/route.ts (1)
generation-based-subscription/src/lib/flowglad.ts (1)
flowglad(5-23)
🔇 Additional comments (2)
generation-based-subscription/package.json (1)
20-23: Flowglad version bump and DB tooling alignmentThe
db:studioscript is consistent with the Drizzle config and README, and the@flowglad/nextjsbump to0.15.0matches the newnextRouteHandler+flowgladfactory usage in your API routes. Please just confirm builds/tests against this Flowglad version and its upgrade notes, as behavior may have changed between0.12.xand0.15.x.generation-based-subscription/README.md (1)
46-86: Updated setup flow is consistent and clearThe new “Getting Started” steps (cd into
generation-based-subscription, env vars,bun db:*,bun dev) line up withpackage.jsonscripts and the directory structure, and remove the previous monorepo/linking complexity. No issues from my side.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
generation-based-subscription/src/app/api/usage-events/route.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
generation-based-subscription/src/app/api/usage-events/route.ts (1)
generation-based-subscription/src/lib/flowglad.ts (1)
flowglad(5-23)
🔇 Additional comments (3)
generation-based-subscription/src/app/api/usage-events/route.ts (3)
1-4: LGTM! Imports align with the new scoped pattern.The updated imports correctly bring in the
flowgladfactory,authfor session management, andheadersfor Next.js 15 async request APIs.
53-61: LGTM! Authentication logic is correctly implemented.The session-based authentication properly extracts the
userIdand returns a 401 error for unauthenticated requests. The use ofawait headers()is correct for Next.js 15's async request APIs.
64-64: API compatibility with Flowglad 0.15.0 is supported.The codebase uses @flowglad/nextjs@0.15.0 which supports both the
priceSlugparameter increateUsageEvent()calls and the factory-based instantiation pattern. The refactoring frompriceIdtopriceSlugaligns with the API specification.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
generation-based-subscription/src/app/api/usage-events/route.ts (1)
53-64: Session‑based user resolution and per‑user Flowglad instance look solid; minor optimization possibleUsing
auth.api.getSession({ headers: await headers() })to deriveuserIdand early‑returning 401 when missing is appropriate, and scopingflowgladServerviaflowglad(userId)matches the per‑customer design. The only minor note is that ifflowglad’sgetCustomerDetailsalso fetches the session, this may result in two session lookups per request; if this route becomes hot, consider threading the session or user details into the factory to avoid duplicate work.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
generation-based-subscription/src/app/api/usage-events/route.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
generation-based-subscription/src/app/api/usage-events/route.ts (1)
generation-based-subscription/src/lib/flowglad.ts (1)
flowglad(5-23)
🔇 Additional comments (3)
generation-based-subscription/src/app/api/usage-events/route.ts (3)
1-4: Imports now match the scoped Flowglad server patternSwitching to the
flowgladfactory plus adding the auth and headers imports keeps this route aligned with the new per-customer server approach while keeping concerns local to this handler. No issues here.
102-111: Defensive guard aroundpriceSlugis appropriateExtracting
priceSlug = usagePrice.slugand returning a 500 when it’s missing correctly treats this as a server‑side configuration error (pricing model misconfigured) rather than a client error, and prevents callingcreateUsageEventwith incomplete identifiers. This is a good safety check.
115-118: Comment and payload now correctly usepriceSlugThe inline comment now accurately states that the meter identifier is derived from
priceSlug, and thecreateUsageEventcall passespriceSlugexplicitly. This resolves the earlier “priceId”/priceSlugmismatch and keeps the usage‑event contract clear.
Summary by CodeRabbit
Documentation
Chores
Bug Fixes / Improvements
✏️ Tip: You can customize this high-level summary in your review settings.