Skip to content

Commit 0f848d3

Browse files
chore: update README and tests for pricing and environment variables
- Refactor README.md to improve formatting of environment variable table. - Update PricingPage tests to reflect currency change from USD to EUR. - Enhance code readability in setup-subscriptions-appwrite.ts and various service files by formatting multi-line statements.
1 parent b97ee33 commit 0f848d3

6 files changed

Lines changed: 62 additions & 31 deletions

File tree

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,13 @@ Open [http://localhost:3000](http://localhost:3000) to view the application.
7171

7272
### Required
7373

74-
| Variable | Description |
75-
| --------------------------------- | ---------------------------- |
76-
| `NEXT_PUBLIC_APPWRITE_ENDPOINT` | Appwrite API endpoint |
77-
| `NEXT_PUBLIC_APPWRITE_PROJECT_ID` | Appwrite project ID |
78-
| `APPWRITE_API_KEY` | Appwrite server-side API key |
79-
| `APPWRITE_DATABASE_ID` | Appwrite DB for app data |
80-
| `APPWRITE_COLLECTION_ID_AI_KEYS` | Appwrite collection for keys |
74+
| Variable | Description |
75+
| -------------------------------------- | ------------------------------------- |
76+
| `NEXT_PUBLIC_APPWRITE_ENDPOINT` | Appwrite API endpoint |
77+
| `NEXT_PUBLIC_APPWRITE_PROJECT_ID` | Appwrite project ID |
78+
| `APPWRITE_API_KEY` | Appwrite server-side API key |
79+
| `APPWRITE_DATABASE_ID` | Appwrite DB for app data |
80+
| `APPWRITE_COLLECTION_ID_AI_KEYS` | Appwrite collection for keys |
8181
| `APPWRITE_COLLECTION_ID_SUBSCRIPTIONS` | Appwrite collection for subscriptions |
8282

8383
Also required for trial features: `APPWRITE_COLLECTION_ID_TRIAL_SESSIONS`.
@@ -97,11 +97,11 @@ Also required for trial features: `APPWRITE_COLLECTION_ID_TRIAL_SESSIONS`.
9797
| `DEV_OVERRIDE_PRICING_TIER` | Temporary non-prod tier override (`FREE`,`ADS_FREE`,`LOCAL`,`BYOK`,`HOSTED_AI`) | unset |
9898
| `DEV_OVERRIDE_PRICING_TIER_USER_IDS` | Optional comma-separated user IDs for scoped override | unset |
9999
| `STRIPE_SECRET_KEY` | Stripe secret API key (`sk_*`) | unset |
100-
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret (`whsec_*`) | unset |
101-
| `STRIPE_PRICE_ADS_FREE` | Stripe recurring price id for Ads-free tier | unset |
102-
| `STRIPE_PRICE_LOCAL` | Stripe recurring price id for Local tier | unset |
103-
| `STRIPE_PRICE_BYOK` | Stripe recurring price id for BYOK tier | unset |
104-
| `STRIPE_PRICE_HOSTED_AI` | Stripe recurring price id for Hosted AI tier | unset |
100+
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret (`whsec_*`) | unset |
101+
| `STRIPE_PRICE_ADS_FREE` | Stripe recurring price id for Ads-free tier | unset |
102+
| `STRIPE_PRICE_LOCAL` | Stripe recurring price id for Local tier | unset |
103+
| `STRIPE_PRICE_BYOK` | Stripe recurring price id for BYOK tier | unset |
104+
| `STRIPE_PRICE_HOSTED_AI` | Stripe recurring price id for Hosted AI tier | unset |
105105

106106
See `.env.example` for the full list.
107107

components/__tests__/PricingPage.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ describe("PricingPage", () => {
142142

143143
it("should display monthly prices for paid tiers", () => {
144144
renderPricingPage();
145-
expect(screen.getByText("$4.99")).toBeInTheDocument();
146-
expect(screen.getByText("$9.99")).toBeInTheDocument();
147-
expect(screen.getByText("$14.99")).toBeInTheDocument();
148-
expect(screen.getByText("$19.99")).toBeInTheDocument();
145+
expect(screen.getByText("4.99")).toBeInTheDocument();
146+
expect(screen.getByText("9.99")).toBeInTheDocument();
147+
expect(screen.getByText("14.99")).toBeInTheDocument();
148+
expect(screen.getByText("19.99")).toBeInTheDocument();
149149
});
150150

151151
it("should display '/ mo' billing period for paid tiers", () => {

scripts/setup-subscriptions-appwrite.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ async function main() {
6969
};
7070

7171
await createAttribute("userId", () =>
72-
databases.createStringAttribute(databaseId, collectionId, "userId", 64, true)
72+
databases.createStringAttribute(
73+
databaseId,
74+
collectionId,
75+
"userId",
76+
64,
77+
true
78+
)
7379
);
7480
await createAttribute("tier", () =>
7581
databases.createStringAttribute(databaseId, collectionId, "tier", 32, true)

services/stripe-billing.service.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,19 @@ function getPeriodBounds(subscription: Stripe.Subscription): {
5858
const subAny = subscription as unknown as {
5959
current_period_start?: number;
6060
current_period_end?: number;
61-
items?: { data?: Array<{ current_period_start?: number; current_period_end?: number }> };
61+
items?: {
62+
data?: Array<{
63+
current_period_start?: number;
64+
current_period_end?: number;
65+
}>;
66+
};
6267
};
6368
return {
6469
start:
65-
subAny.current_period_start ?? subAny.items?.data?.[0]?.current_period_start,
66-
end: subAny.current_period_end ?? subAny.items?.data?.[0]?.current_period_end,
70+
subAny.current_period_start ??
71+
subAny.items?.data?.[0]?.current_period_start,
72+
end:
73+
subAny.current_period_end ?? subAny.items?.data?.[0]?.current_period_end,
6774
};
6875
}
6976

@@ -119,7 +126,9 @@ export class StripeBillingService {
119126
baseUrl: string;
120127
}): Promise<{ url: string }> {
121128
const stripe = requireStripeClient();
122-
const current = await subscriptionStoreService.getMostRecentForUser(args.userId);
129+
const current = await subscriptionStoreService.getMostRecentForUser(
130+
args.userId
131+
);
123132
const customerId = current?.stripeCustomerId?.trim();
124133
if (!customerId) {
125134
throw new Error("No Stripe customer found for this user.");
@@ -147,7 +156,8 @@ export class StripeBillingService {
147156
const userId = session.metadata?.appUserId;
148157
const subscriptionId =
149158
typeof session.subscription === "string" ? session.subscription : "";
150-
const customerId = typeof session.customer === "string" ? session.customer : "";
159+
const customerId =
160+
typeof session.customer === "string" ? session.customer : "";
151161
const priceId = session.metadata?.stripePriceId ?? "";
152162
if (!userId || !subscriptionId) return;
153163

@@ -163,7 +173,10 @@ export class StripeBillingService {
163173
subscriptionId,
164174
customerId,
165175
priceId:
166-
priceId || sub.items.data[0]?.price?.id || session.metadata?.stripePriceId || "",
176+
priceId ||
177+
sub.items.data[0]?.price?.id ||
178+
session.metadata?.stripePriceId ||
179+
"",
167180
status: sub.status,
168181
cancelAtPeriodEnd: sub.cancel_at_period_end,
169182
currentPeriodStart: bounds.start,

services/subscription-store.service.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,19 @@ export class SubscriptionStoreService {
6262
return { databases, databaseId, subscriptionsCollectionId };
6363
}
6464

65-
async getMostRecentForUser(userId: string): Promise<SubscriptionRecord | null> {
66-
const { databases, databaseId, subscriptionsCollectionId } = this.getClient();
65+
async getMostRecentForUser(
66+
userId: string
67+
): Promise<SubscriptionRecord | null> {
68+
const { databases, databaseId, subscriptionsCollectionId } =
69+
this.getClient();
6770
const result = (await databases.listDocuments(
6871
databaseId,
6972
subscriptionsCollectionId,
70-
[Query.equal("userId", userId), Query.orderDesc("$updatedAt"), Query.limit(1)]
73+
[
74+
Query.equal("userId", userId),
75+
Query.orderDesc("$updatedAt"),
76+
Query.limit(1),
77+
]
7178
)) as unknown as { documents: SubscriptionDocument[] };
7279

7380
const doc = result.documents[0];
@@ -78,7 +85,8 @@ export class SubscriptionStoreService {
7885
stripeSubscriptionId: string,
7986
payload: Omit<SubscriptionRecord, "id">
8087
): Promise<void> {
81-
const { databases, databaseId, subscriptionsCollectionId } = this.getClient();
88+
const { databases, databaseId, subscriptionsCollectionId } =
89+
this.getClient();
8290
const existing = (await databases.listDocuments(
8391
databaseId,
8492
subscriptionsCollectionId,
@@ -121,7 +129,8 @@ export class SubscriptionStoreService {
121129
async getByStripeSubscriptionId(
122130
stripeSubscriptionId: string
123131
): Promise<SubscriptionRecord | null> {
124-
const { databases, databaseId, subscriptionsCollectionId } = this.getClient();
132+
const { databases, databaseId, subscriptionsCollectionId } =
133+
this.getClient();
125134
const result = (await databases.listDocuments(
126135
databaseId,
127136
subscriptionsCollectionId,
@@ -137,7 +146,8 @@ export class SubscriptionStoreService {
137146
async getByStripeCustomerId(
138147
stripeCustomerId: string
139148
): Promise<SubscriptionRecord | null> {
140-
const { databases, databaseId, subscriptionsCollectionId } = this.getClient();
149+
const { databases, databaseId, subscriptionsCollectionId } =
150+
this.getClient();
141151
const result = (await databases.listDocuments(
142152
databaseId,
143153
subscriptionsCollectionId,

services/subscription.service.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ export class SubscriptionService {
182182
}
183183
}
184184

185-
const current = await subscriptionStoreService.getMostRecentForUser(userId);
185+
const current =
186+
await subscriptionStoreService.getMostRecentForUser(userId);
186187
if (!current) return "FREE";
187188

188189
const isActive =
@@ -346,7 +347,8 @@ export class SubscriptionService {
346347
try {
347348
logger.info("Cancelling subscription for user", { userId });
348349

349-
const current = await subscriptionStoreService.getMostRecentForUser(userId);
350+
const current =
351+
await subscriptionStoreService.getMostRecentForUser(userId);
350352
if (!current) {
351353
return { success: false, error: "No active subscription found" };
352354
}

0 commit comments

Comments
 (0)