Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ MAPBOX_ACCESS_TOKEN=your_mapbox_api_key

# For client-side usage (if needed)
NEXT_PUBLIC_COMPOSIO_API_KEY=your_composio_api_key
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPbox_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com
Comment on lines 10 to 13
Copy link

Choose a reason for hiding this comment

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

The example value changed from ac_YOUR_MAPBOX_CONFIG_ID to ac_YOUR_MAPbox_CONFIG_ID (case changed in MAPBOX). That inconsistency looks accidental and can cause confusion when copying env examples.

Suggestion

Revert the casing change to keep the placeholder consistent.

NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID

Reply with "@CharlieHelps yes please" if you'd like me to add a commit fixing this.


# NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is already used by mapbox-map.tsx
Expand All @@ -25,3 +25,6 @@ NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL_HERE
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY_HERE
SUPABASE_SERVICE_ROLE_KEY=YOUR_SUPABASE_SERVICE_ROLE_KEY_HERE
DATABASE_URL=postgresql://postgres:[YOUR-POSTGRES-PASSWORD]@[YOUR-SUPABASE-DB-HOST]:[PORT]/postgres

# Polar Access Token
POLAR_ACCESS_TOKEN=your_polar_access_token
39 changes: 39 additions & 0 deletions app/api/meter/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Polar } from "@polar-sh/sdk";
import { getCurrentUserIdOnServer } from "@/lib/auth/get-current-user";
import { NextRequest, NextResponse } from "next/server";

const polar = new Polar({
accessToken: process.env["POLAR_ACCESS_TOKEN"] ?? "",
});
Comment on lines +5 to +7
Copy link

Choose a reason for hiding this comment

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

POLAR_ACCESS_TOKEN is defaulting to an empty string. In production this can lead to confusing runtime failures (and potentially repeated failing ingest attempts) rather than a clear configuration error. This route should fail fast when the token is missing, ideally before attempting to call Polar.

Suggestion

Prefer validating POLAR_ACCESS_TOKEN once and returning a deterministic error when absent.

const POLAR_ACCESS_TOKEN = process.env["POLAR_ACCESS_TOKEN"];
if (!POLAR_ACCESS_TOKEN) {
  throw new Error("POLAR_ACCESS_TOKEN is not configured");
}

const polar = new Polar({ accessToken: POLAR_ACCESS_TOKEN });

If you want this to be request-scoped instead of module-scoped, you can also validate inside GET and return 500 with a generic message. Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.


export const GET = async (req: NextRequest) => {
try {
const customerId = await getCurrentUserIdOnServer();

if (!customerId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

await polar.events.ingest({
events: [
{
name: "api_call",
externalCustomerId: customerId,
metadata: {
route: "/api/meter",
method: "GET",
},
},
],
});

return NextResponse.json({ hello: "world" });
Comment on lines +9 to +30
Copy link

Choose a reason for hiding this comment

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

This endpoint performs a billable metering action but is exposed as GET. GET is commonly preloaded/prefetched, cached, or retried by clients/CDNs, which can lead to accidental double-counting or inflated usage. Metering endpoints should generally be non-idempotent and use POST (or make idempotency explicit with an idempotency key).

Suggestion

Switch the route to export const POST and require an explicit request body (even if minimal). If you need idempotency, accept an idempotencyKey and include it in the Polar event metadata (or use a dedupe field if the SDK supports it).

export const POST = async (req: NextRequest) => {
  const { idempotencyKey } = await req.json().catch(() => ({}));
  // validate and ingest
};

Reply with "@CharlieHelps yes please" if you'd like me to add a commit converting this to POST and adjusting the event metadata accordingly.

Copy link

Choose a reason for hiding this comment

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

The handler returns { hello: "world" }, which looks like placeholder/debug output. For a metering endpoint, returning a stable, semantically meaningful response (e.g., { ok: true }) and/or the ingest result (if safe) helps clients understand what happened without leaking internals.

Suggestion

Return a minimal success payload and consider including a request identifier if available.

return NextResponse.json({ ok: true });

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

} catch (error) {
console.error("Error in GET /api/meter:", error);
let errorMessage = "Internal Server Error";
if (error instanceof Error) {
errorMessage = error.message;
}
return NextResponse.json({ error: errorMessage }, { status: 500 });
}
Comment on lines +31 to +38
Copy link

Choose a reason for hiding this comment

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

This code reports the raw error.message back to the client. That can leak sensitive operational details (e.g., upstream auth failures, request signatures, internal IDs) and makes error responses unstable. Prefer returning a generic message to clients while logging the detailed error server-side.

Suggestion

Always return a generic error message to the client and keep details only in logs.

} catch (error) {
  console.error("Error in GET /api/meter:", error);
  return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}

If you want to distinguish Polar auth/config errors, map them to stable error codes without exposing raw messages. Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this change.

};
Loading