Skip to content

Commit 62ca7bf

Browse files
committed
pretty format
1 parent 379e33a commit 62ca7bf

File tree

8 files changed

+77
-132
lines changed

8 files changed

+77
-132
lines changed

frontend/packages/core/src/billing/plans.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,19 @@ function getEntitlementsForPlan(plan: PlanType): Entitlement[] {
3535
}
3636

3737
// Single source of truth for all plan data
38-
export const PLANS: Record<PlanType, {
39-
name: string;
40-
description: string;
41-
price: number;
42-
billingPriceId: string;
43-
highlighted: boolean;
44-
badge: string | null;
45-
features: string[];
46-
entitlements: Entitlement[];
47-
}> = {
38+
export const PLANS: Record<
39+
PlanType,
40+
{
41+
name: string;
42+
description: string;
43+
price: number;
44+
billingPriceId: string;
45+
highlighted: boolean;
46+
badge: string | null;
47+
features: string[];
48+
entitlements: Entitlement[];
49+
}
50+
> = {
4851
free: {
4952
name: "Free",
5053
description: "Get started with basic features",
@@ -160,11 +163,9 @@ export function getEntitlements(plan: PlanType): Entitlement[] {
160163
export function requireEntitlement(
161164
plan: PlanType,
162165
entitlement: Entitlement,
163-
message?: string
166+
message?: string,
164167
): void {
165168
if (!hasEntitlement(plan, entitlement)) {
166-
throw new Error(
167-
message ?? `Plan "${plan}" does not have access to "${entitlement}"`
168-
);
169+
throw new Error(message ?? `Plan "${plan}" does not have access to "${entitlement}"`);
169170
}
170171
}

frontend/ui/src/app/api/billing/change-plan/route.ts

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { NextRequest, NextResponse } from "next/server";
22
import { getServerSession } from "next-auth";
33
import { authOptions } from "@/lib/auth";
4-
import {
5-
prisma,
6-
getStripeOrThrow,
7-
getPlanConfig,
8-
isUpgrade,
9-
type PlanType,
10-
} from "@traceroot/core";
4+
import { prisma, getStripeOrThrow, getPlanConfig, isUpgrade, type PlanType } from "@traceroot/core";
115

126
export async function POST(req: NextRequest) {
137
try {
@@ -27,10 +21,7 @@ export async function POST(req: NextRequest) {
2721
},
2822
});
2923
if (!workspace) {
30-
return NextResponse.json(
31-
{ error: "Workspace not found" },
32-
{ status: 404 },
33-
);
24+
return NextResponse.json({ error: "Workspace not found" }, { status: 404 });
3425
}
3526

3627
const stripe = getStripeOrThrow();
@@ -57,13 +48,12 @@ export async function POST(req: NextRequest) {
5748
}
5849

5950
// First, release any existing schedule
60-
const subscription = await stripe.subscriptions.retrieve(
61-
workspace.billingSubscriptionId
62-
);
51+
const subscription = await stripe.subscriptions.retrieve(workspace.billingSubscriptionId);
6352
if (subscription.schedule) {
64-
const scheduleId = typeof subscription.schedule === 'string'
65-
? subscription.schedule
66-
: subscription.schedule.id;
53+
const scheduleId =
54+
typeof subscription.schedule === "string"
55+
? subscription.schedule
56+
: subscription.schedule.id;
6757
await stripe.subscriptionSchedules.release(scheduleId);
6858
}
6959

@@ -74,22 +64,23 @@ export async function POST(req: NextRequest) {
7464

7565
return NextResponse.json({
7666
success: true,
77-
message: "Subscription will be canceled at period end"
67+
message: "Subscription will be canceled at period end",
7868
});
7969
}
8070

8171
// Case 2: No subscription yet = need to go through checkout
8272
if (!workspace.billingSubscriptionId) {
8373
return NextResponse.json(
84-
{ error: "No subscription. Use checkout endpoint instead.", redirect: "/api/billing/checkout" },
74+
{
75+
error: "No subscription. Use checkout endpoint instead.",
76+
redirect: "/api/billing/checkout",
77+
},
8578
{ status: 400 },
8679
);
8780
}
8881

8982
// Case 3: Has subscription, changing to another paid plan
90-
const subscription = await stripe.subscriptions.retrieve(
91-
workspace.billingSubscriptionId,
92-
);
83+
const subscription = await stripe.subscriptions.retrieve(workspace.billingSubscriptionId);
9384
const subscriptionItemId = subscription.items.data[0].id;
9485

9586
// If subscription is set to cancel, remove that first
@@ -103,9 +94,10 @@ export async function POST(req: NextRequest) {
10394
// UPGRADE: Immediate change with proration
10495
// First, release any existing schedule (e.g., pending downgrade)
10596
if (subscription.schedule) {
106-
const scheduleId = typeof subscription.schedule === 'string'
107-
? subscription.schedule
108-
: subscription.schedule.id;
97+
const scheduleId =
98+
typeof subscription.schedule === "string"
99+
? subscription.schedule
100+
: subscription.schedule.id;
109101
await stripe.subscriptionSchedules.release(scheduleId);
110102
}
111103

@@ -141,9 +133,10 @@ export async function POST(req: NextRequest) {
141133
// DOWNGRADE to lower paid plan: Schedule change at period end
142134
// First, release any existing schedule (release just detaches, cancel can affect subscription)
143135
if (subscription.schedule) {
144-
const scheduleId = typeof subscription.schedule === 'string'
145-
? subscription.schedule
146-
: subscription.schedule.id;
136+
const scheduleId =
137+
typeof subscription.schedule === "string"
138+
? subscription.schedule
139+
: subscription.schedule.id;
147140
await stripe.subscriptionSchedules.release(scheduleId);
148141
}
149142

@@ -155,9 +148,7 @@ export async function POST(req: NextRequest) {
155148
await stripe.subscriptionSchedules.update(schedule.id, {
156149
phases: [
157150
{
158-
items: [
159-
{ price: subscription.items.data[0].price.id, quantity: 1 },
160-
],
151+
items: [{ price: subscription.items.data[0].price.id, quantity: 1 }],
161152
start_date: schedule.phases[0].start_date,
162153
end_date: subscription.current_period_end,
163154
},
@@ -170,14 +161,11 @@ export async function POST(req: NextRequest) {
170161

171162
return NextResponse.json({
172163
success: true,
173-
message: "Downgrade scheduled for next billing period"
164+
message: "Downgrade scheduled for next billing period",
174165
});
175166
}
176167
} catch (error) {
177168
console.error("Change plan error:", error);
178-
return NextResponse.json(
179-
{ error: "Failed to change plan" },
180-
{ status: 500 },
181-
);
169+
return NextResponse.json({ error: "Failed to change plan" }, { status: 500 });
182170
}
183171
}

frontend/ui/src/app/api/billing/checkout/route.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { NextRequest, NextResponse } from "next/server";
22
import { getServerSession } from "next-auth";
33
import { authOptions } from "@/lib/auth";
4-
import {
5-
prisma,
6-
getStripeOrThrow,
7-
getPlanConfig,
8-
type PlanType,
9-
} from "@traceroot/core";
4+
import { prisma, getStripeOrThrow, getPlanConfig, type PlanType } from "@traceroot/core";
105

116
export async function POST(req: NextRequest) {
127
try {
@@ -36,10 +31,7 @@ export async function POST(req: NextRequest) {
3631
},
3732
});
3833
if (!workspace) {
39-
return NextResponse.json(
40-
{ error: "Workspace not found" },
41-
{ status: 404 },
42-
);
34+
return NextResponse.json({ error: "Workspace not found" }, { status: 404 });
4335
}
4436

4537
const stripe = getStripeOrThrow();
@@ -74,9 +66,6 @@ export async function POST(req: NextRequest) {
7466
return NextResponse.json({ url: checkoutSession.url });
7567
} catch (error) {
7668
console.error("Checkout error:", error);
77-
return NextResponse.json(
78-
{ error: "Failed to create checkout" },
79-
{ status: 500 },
80-
);
69+
return NextResponse.json({ error: "Failed to create checkout" }, { status: 500 });
8170
}
8271
}

frontend/ui/src/app/api/billing/portal/route.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@ export async function POST(req: NextRequest) {
1919
},
2020
});
2121
if (!workspace?.billingCustomerId) {
22-
return NextResponse.json(
23-
{ error: "No billing account" },
24-
{ status: 404 },
25-
);
22+
return NextResponse.json({ error: "No billing account" }, { status: 404 });
2623
}
2724

2825
const stripe = getStripeOrThrow();
@@ -35,9 +32,6 @@ export async function POST(req: NextRequest) {
3532
return NextResponse.json({ url: portalSession.url });
3633
} catch (error) {
3734
console.error("Portal error:", error);
38-
return NextResponse.json(
39-
{ error: "Failed to create portal" },
40-
{ status: 500 },
41-
);
35+
return NextResponse.json({ error: "Failed to create portal" }, { status: 500 });
4236
}
4337
}

frontend/ui/src/app/api/billing/subscription-info/route.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,15 @@ export async function GET(req: NextRequest) {
4747
const stripe = getStripeOrThrow();
4848

4949
// Fetch live subscription from Stripe
50-
const subscription = await stripe.subscriptions.retrieve(
51-
workspace.billingSubscriptionId,
52-
{ expand: ["schedule"] }
53-
);
50+
const subscription = await stripe.subscriptions.retrieve(workspace.billingSubscriptionId, {
51+
expand: ["schedule"],
52+
});
5453

5554
const nowSec = Math.floor(Date.now() / 1000);
5655

5756
// Check for cancellation
5857
let cancellation: SubscriptionInfo["cancellation"] = null;
59-
if (
60-
typeof subscription.cancel_at === "number" &&
61-
subscription.cancel_at > nowSec
62-
) {
58+
if (typeof subscription.cancel_at === "number" && subscription.cancel_at > nowSec) {
6359
cancellation = { cancelAt: new Date(subscription.cancel_at * 1000) };
6460
} else if (subscription.cancel_at_period_end === true) {
6561
cancellation = {
@@ -82,9 +78,7 @@ export async function GET(req: NextRequest) {
8278
"status" in schedule &&
8379
["active", "not_started"].includes(schedule.status)
8480
) {
85-
const fullSchedule = await stripe.subscriptionSchedules.retrieve(
86-
schedule.id
87-
);
81+
const fullSchedule = await stripe.subscriptionSchedules.retrieve(schedule.id);
8882
const phases = fullSchedule.phases ?? [];
8983
const nextPhase = phases.find((p) => (p.start_date ?? 0) > nowSec);
9084

@@ -107,9 +101,6 @@ export async function GET(req: NextRequest) {
107101
return NextResponse.json(info);
108102
} catch (error) {
109103
console.error("Subscription info error:", error);
110-
return NextResponse.json(
111-
{ error: "Failed to get subscription info" },
112-
{ status: 500 }
113-
);
104+
return NextResponse.json({ error: "Failed to get subscription info" }, { status: 500 });
114105
}
115106
}

frontend/ui/src/app/api/billing/webhook/route.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ export async function POST(req: NextRequest) {
5151
billingPriceId: priceId,
5252
billingStatus: subscription.status, // active, past_due, canceled, etc.
5353
billingPlan: plan,
54-
billingPeriodStart: new Date(
55-
subscription.billing_cycle_anchor * 1000,
56-
),
54+
billingPeriodStart: new Date(subscription.billing_cycle_anchor * 1000),
5755
},
5856
});
5957

@@ -84,9 +82,7 @@ export async function POST(req: NextRequest) {
8482
},
8583
});
8684

87-
console.log(
88-
`Subscription deleted for workspace ${workspaceId}, reverted to free plan`,
89-
);
85+
console.log(`Subscription deleted for workspace ${workspaceId}, reverted to free plan`);
9086
break;
9187
}
9288

0 commit comments

Comments
 (0)