Skip to content

chore: use scoped server pattern generation based subscription#1

Merged
BrooksFlannery merged 3 commits into
mainfrom
update-gen-based-sub
Dec 10, 2025
Merged

chore: use scoped server pattern generation based subscription#1
BrooksFlannery merged 3 commits into
mainfrom
update-gen-based-sub

Conversation

@BrooksFlannery

@BrooksFlannery BrooksFlannery commented Dec 10, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Documentation

    • Simplified installation and setup instructions by removing multi-step package-linking and streamlining dependency setup.
  • Chores

    • Updated a core integration package to v0.15.0.
    • Removed obsolete local publishing/linking helper scripts.
  • Bug Fixes / Improvements

    • API endpoints now require authentication and operate per signed-in user.
    • Usage/billing calls accept human-readable price identifiers and resolve internal IDs automatically.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 10, 2025

Copy link
Copy Markdown

Walkthrough

Refactors 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

Cohort / File(s) Summary
Documentation & packaging
generation-based-subscription/README.md, generation-based-subscription/package.json
Simplified README setup (removed yalc/monorepo linking and link/unlink steps), removed npm helper scripts (link:packages, unlink:packages), and bumped @flowglad/nextjs 0.12.3 → 0.15.0.
Flowglad factory
generation-based-subscription/src/lib/flowglad.ts
Replaced exported pre-configured flowgladServer with flowglad(customerExternalId) factory that returns a FlowgladServer bound to a customer; inlined getCustomerDetails using auth session headers.
API routes (auth integration & usage changes)
generation-based-subscription/src/app/api/flowglad/[...path]/route.ts, generation-based-subscription/src/app/api/usage-events/route.ts
Routes now obtain session via auth.api.getSession (using headers()), derive user.id as customerExternalId, instantiate Flowglad via flowglad(userId), and export GET/POST handlers from nextRouteHandler(...); usage-events now resolves and validates priceSlug instead of using priceId/usageMeterId.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Focus areas:
    • src/lib/flowglad.ts — factory wiring and getCustomerDetails using headers/session
    • src/app/api/*/route.ts — session retrieval, error handling, and new nextRouteHandler exports
    • src/app/api/usage-events/route.ts — priceSlug resolution and createUsageEvent parameters
    • package.json — dependency bump to @flowglad/nextjs@0.15.0

Possibly related PRs

  • chore: update-usage-limit-subscription #3 — Mirrors this change set by replacing a static flowgladServer with a per-customer flowglad(customerExternalId) factory and updating route handlers to use session-derived customer IDs.

Poem

🐰 I hopped through code with nimble toes,
Each user now gets their own little rose.
Sessions whisper IDs so true,
Flowglad wakes up fresh for you.
README light — I dance and pose. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: use scoped server pattern generation based subscription' accurately describes the main change: refactoring from a pre-configured FlowgladServer instance to a scoped/per-customer server pattern factory function, with authentication integrated throughout the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch update-gen-based-sub

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 IDs

The refactor to:

  • fetch the session via auth.api.getSession({ headers: await headers() }),
  • derive userId and 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 crypto aligns 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 ergonomics

The nextRouteHandler({ flowglad, getCustomerExternalId }) setup with auth.api.getSession({ headers: await headers() }) and returning userId is consistent with the new Flowglad factory and the usage-events route.

Two small nits you might consider:

  • Rename the unused req parameter to _req (or remove it if the type allows) to keep linters quiet.
  • Confirm that throwing a plain Error('User not found') is how nextRouteHandler expects 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 clarity

This flowglad(customerExternalId) factory cleanly switches you from a singleton to per-customer FlowgladServer instances and correctly wires getCustomerDetails through auth.api.getSession({ headers: await headers() }), enforcing authentication and exposing email/name.

Two small cleanups you might consider:

  • In getCustomerDetails, the customerExternalId parameter 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

📥 Commits

Reviewing files that changed from the base of the PR and between f30e840 and c249e6e.

⛔ Files ignored due to path filters (1)
  • generation-based-subscription/bun.lock is 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 alignment

The db:studio script is consistent with the Drizzle config and README, and the @flowglad/nextjs bump to 0.15.0 matches the new nextRouteHandler + flowglad factory usage in your API routes. Please just confirm builds/tests against this Flowglad version and its upgrade notes, as behavior may have changed between 0.12.x and 0.15.x.

generation-based-subscription/README.md (1)

46-86: Updated setup flow is consistent and clear

The new “Getting Started” steps (cd into generation-based-subscription, env vars, bun db:*, bun dev) line up with package.json scripts and the directory structure, and remove the previous monorepo/linking complexity. No issues from my side.

@BrooksFlannery BrooksFlannery changed the title chore: use updated scoped server pattern generation based subscription chore: use scoped server pattern generation based subscription Dec 10, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c249e6e and 35327b0.

📒 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 flowglad factory, auth for session management, and headers for Next.js 15 async request APIs.


53-61: LGTM! Authentication logic is correctly implemented.

The session-based authentication properly extracts the userId and returns a 401 error for unauthenticated requests. The use of await 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 priceSlug parameter in createUsageEvent() calls and the factory-based instantiation pattern. The refactoring from priceId to priceSlug aligns with the API specification.

Comment thread generation-based-subscription/src/app/api/usage-events/route.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 possible

Using auth.api.getSession({ headers: await headers() }) to derive userId and early‑returning 401 when missing is appropriate, and scoping flowgladServer via flowglad(userId) matches the per‑customer design. The only minor note is that if flowglad’s getCustomerDetails also 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

📥 Commits

Reviewing files that changed from the base of the PR and between 35327b0 and 18e14ff.

📒 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 pattern

Switching to the flowglad factory 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 around priceSlug is appropriate

Extracting priceSlug = usagePrice.slug and 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 calling createUsageEvent with incomplete identifiers. This is a good safety check.


115-118: Comment and payload now correctly use priceSlug

The inline comment now accurately states that the meter identifier is derived from priceSlug, and the createUsageEvent call passes priceSlug explicitly. This resolves the earlier “priceId”/priceSlug mismatch and keeps the usage‑event contract clear.

@joeysabs joeysabs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES!

@BrooksFlannery BrooksFlannery merged commit 0c21aaa into main Dec 10, 2025
2 checks passed
This was referenced Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants