-
-
Notifications
You must be signed in to change notification settings - Fork 7
Implement Polar Metering API #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8b2d6c8
4407470
827dd4a
efb4c8a
14ace31
4de04d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
SuggestionPrefer validating 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 |
||
|
|
||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This endpoint performs a billable metering action but is exposed as SuggestionSwitch the route to 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The handler returns SuggestionReturn 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code reports the raw SuggestionAlways 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. |
||
| }; | ||
There was a problem hiding this comment.
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_IDtoac_YOUR_MAPbox_CONFIG_ID(case changed inMAPBOX). That inconsistency looks accidental and can cause confusion when copying env examples.Suggestion
Revert the casing change to keep the placeholder consistent.
Reply with "@CharlieHelps yes please" if you'd like me to add a commit fixing this.