mirror of
https://github.com/LukeHagar/polar.git
synced 2025-12-06 04:20:58 +00:00
use standalone functions to reduce bundle size
This commit is contained in:
1
example/convex/_generated/api.d.ts
vendored
1
example/convex/_generated/api.d.ts
vendored
@@ -17,6 +17,7 @@ import type {
|
||||
FilterApi,
|
||||
FunctionReference,
|
||||
} from "convex/server";
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's API.
|
||||
*
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Polar } from "@polar-sh/sdk";
|
||||
import { PolarCore } from "@polar-sh/sdk/core.js";
|
||||
import { productsCreate } from "@polar-sh/sdk/funcs/productsCreate.js";
|
||||
import { productsList } from "@polar-sh/sdk/funcs/productsList.js";
|
||||
import { internalAction, internalMutation } from "./_generated/server";
|
||||
import { internal } from "./_generated/api";
|
||||
|
||||
const accessToken = process.env.POLAR_ORGANIZATION_TOKEN;
|
||||
|
||||
const polar = new Polar({
|
||||
const polar = new PolarCore({
|
||||
accessToken,
|
||||
server: "sandbox",
|
||||
});
|
||||
@@ -36,7 +38,7 @@ const seed = internalAction({
|
||||
return items.length > 0;
|
||||
}
|
||||
}
|
||||
const result = await polar.products.list({
|
||||
const result = await productsList(polar, {
|
||||
isArchived: false,
|
||||
limit: 1,
|
||||
});
|
||||
@@ -52,7 +54,7 @@ const seed = internalAction({
|
||||
// Create example products. In a real app you would likely create your
|
||||
// products in the Polar dashboard and reference them by id in your application.
|
||||
await Promise.all([
|
||||
polar.products.create({
|
||||
productsCreate(polar, {
|
||||
name: PREMIUM_PLAN_NAME,
|
||||
description: "All the things for one low monthly price.",
|
||||
recurringInterval: "month",
|
||||
@@ -63,7 +65,7 @@ const seed = internalAction({
|
||||
},
|
||||
],
|
||||
}),
|
||||
polar.products.create({
|
||||
productsCreate(polar, {
|
||||
name: PREMIUM_PLAN_NAME,
|
||||
description: "All the things for one low annual price.",
|
||||
recurringInterval: "year",
|
||||
@@ -74,7 +76,7 @@ const seed = internalAction({
|
||||
},
|
||||
],
|
||||
}),
|
||||
polar.products.create({
|
||||
productsCreate(polar, {
|
||||
name: PREMIUM_PLUS_PLAN_NAME,
|
||||
description: "All the things for one low monthly price.",
|
||||
recurringInterval: "month",
|
||||
@@ -85,7 +87,7 @@ const seed = internalAction({
|
||||
},
|
||||
],
|
||||
}),
|
||||
polar.products.create({
|
||||
productsCreate(polar, {
|
||||
name: PREMIUM_PLUS_PLAN_NAME,
|
||||
description: "All the things for one low annual price.",
|
||||
recurringInterval: "year",
|
||||
|
||||
10
example/package-lock.json
generated
10
example/package-lock.json
generated
@@ -48,11 +48,9 @@
|
||||
},
|
||||
"..": {
|
||||
"name": "@convex-dev/polar",
|
||||
"version": "0.4.4",
|
||||
"version": "0.5.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@polar-sh/checkout": "0.1.10",
|
||||
"@polar-sh/sdk": "0.32.11",
|
||||
"buffer": "^6.0.3",
|
||||
"convex-helpers": "^0.1.63",
|
||||
"remeda": "^2.20.2",
|
||||
@@ -66,12 +64,14 @@
|
||||
"eslint": "^9.9.1",
|
||||
"globals": "^15.9.0",
|
||||
"prettier": "3.2.5",
|
||||
"typescript": "~5.0.3",
|
||||
"typescript": "^5.5.0",
|
||||
"typescript-eslint": "^8.4.0",
|
||||
"vitest": "^2.1.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"convex": "^1.19.2 || >=1.17.0 <1.25.0",
|
||||
"@polar-sh/checkout": ">=0.1.10",
|
||||
"@polar-sh/sdk": ">=0.32.11",
|
||||
"convex": "^1.25.4",
|
||||
"react": "^18 || ^19",
|
||||
"react-dom": "^18 || ^19"
|
||||
}
|
||||
|
||||
@@ -41,14 +41,16 @@ export default function TodoList() {
|
||||
|
||||
const getButtonText = (targetProductId: string) => {
|
||||
if (!user?.subscription) return "Upgrade";
|
||||
const currentAmount = user.subscription.amount ?? 0;
|
||||
const targetProduct = Object.values(products ?? {}).find(
|
||||
(p) => p?.id === targetProductId
|
||||
);
|
||||
const targetAmount = targetProduct?.prices[0].priceAmount ?? 0;
|
||||
if (targetAmount > currentAmount) return "Upgrade";
|
||||
if (targetAmount < currentAmount) return "Downgrade";
|
||||
return "Switch";
|
||||
const isPremium =
|
||||
user.subscription.productId === premiumMonthly?.id ||
|
||||
user.subscription.productId === premiumYearly?.id;
|
||||
const targetIsPremiumPlus =
|
||||
targetProductId === premiumPlusMonthly?.id ||
|
||||
targetProductId === premiumPlusYearly?.id;
|
||||
if (isPremium && targetIsPremiumPlus) {
|
||||
return "Upgrade";
|
||||
}
|
||||
return "Downgrade";
|
||||
};
|
||||
|
||||
const handlePlanChange = async (productId: string) => {
|
||||
|
||||
@@ -73,7 +73,9 @@
|
||||
}
|
||||
},
|
||||
"peerDependencies": {
|
||||
"convex": "^1.19.2 || >=1.17.0 <1.35.0",
|
||||
"@polar-sh/checkout": ">=0.1.10",
|
||||
"@polar-sh/sdk": ">=0.32.11",
|
||||
"convex": "^1.25.4",
|
||||
"react": "^18 || ^19",
|
||||
"react-dom": "^18 || ^19"
|
||||
},
|
||||
@@ -93,8 +95,6 @@
|
||||
"types": "./dist/commonjs/client/index.d.ts",
|
||||
"module": "./dist/esm/client/index.js",
|
||||
"dependencies": {
|
||||
"@polar-sh/checkout": "0.1.10",
|
||||
"@polar-sh/sdk": "0.32.11",
|
||||
"buffer": "^6.0.3",
|
||||
"convex-helpers": "^0.1.63",
|
||||
"remeda": "^2.20.2",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import "./polyfill";
|
||||
import { Polar as PolarSdk } from "@polar-sh/sdk";
|
||||
import { PolarCore } from "@polar-sh/sdk/core.js";
|
||||
import { customersCreate } from "@polar-sh/sdk/funcs/customersCreate.js";
|
||||
import { checkoutsCreate } from "@polar-sh/sdk/funcs/checkoutsCreate.js";
|
||||
import { customerSessionsCreate } from "@polar-sh/sdk/funcs/customerSessionsCreate.js";
|
||||
import { subscriptionsUpdate } from "@polar-sh/sdk/funcs/subscriptionsUpdate.js";
|
||||
|
||||
import type { Checkout } from "@polar-sh/sdk/models/components/checkout.js";
|
||||
import type { WebhookProductCreatedPayload } from "@polar-sh/sdk/models/components/webhookproductcreatedpayload.js";
|
||||
import type { WebhookProductUpdatedPayload } from "@polar-sh/sdk/models/components/webhookproductupdatedpayload.js";
|
||||
@@ -48,7 +53,7 @@ export class Polar<
|
||||
DataModel extends GenericDataModel = GenericDataModel,
|
||||
Products extends Record<string, string> = Record<string, string>,
|
||||
> {
|
||||
public sdk: PolarSdk;
|
||||
public polar: PolarCore;
|
||||
public products: Products;
|
||||
private organizationToken: string;
|
||||
private webhookSecret: string;
|
||||
@@ -77,7 +82,7 @@ export class Polar<
|
||||
(process.env["POLAR_SERVER"] as "sandbox" | "production") ??
|
||||
"sandbox";
|
||||
|
||||
this.sdk = new PolarSdk({
|
||||
this.polar = new PolarCore({
|
||||
accessToken: this.organizationToken,
|
||||
server: this.server,
|
||||
});
|
||||
@@ -116,20 +121,23 @@ export class Polar<
|
||||
const customerId =
|
||||
dbCustomer?.id ||
|
||||
(
|
||||
await this.sdk.customers.create({
|
||||
await customersCreate(this.polar, {
|
||||
email,
|
||||
metadata: {
|
||||
userId,
|
||||
},
|
||||
})
|
||||
).id;
|
||||
).value?.id;
|
||||
if (!customerId) {
|
||||
throw new Error("Customer not created");
|
||||
}
|
||||
if (!dbCustomer) {
|
||||
await ctx.runMutation(this.component.lib.insertCustomer, {
|
||||
id: customerId,
|
||||
userId,
|
||||
});
|
||||
}
|
||||
return this.sdk.checkouts.create({
|
||||
const checkout = await checkoutsCreate(this.polar, {
|
||||
allowDiscountCodes: true,
|
||||
customerId,
|
||||
embedOrigin: origin,
|
||||
@@ -138,6 +146,10 @@ export class Polar<
|
||||
? { products: productIds }
|
||||
: { products: productIds }),
|
||||
});
|
||||
if (!checkout.value) {
|
||||
throw new Error("Checkout not created");
|
||||
}
|
||||
return checkout.value;
|
||||
}
|
||||
async createCustomerPortalSession(
|
||||
ctx: GenericActionCtx<DataModel>,
|
||||
@@ -152,11 +164,14 @@ export class Polar<
|
||||
throw new Error("Customer not found");
|
||||
}
|
||||
|
||||
const session = await this.sdk.customerSessions.create({
|
||||
const session = await customerSessionsCreate(this.polar, {
|
||||
customerId: customer.id,
|
||||
});
|
||||
if (!session.value) {
|
||||
throw new Error("Customer session not created");
|
||||
}
|
||||
|
||||
return { url: session.customerPortalUrl };
|
||||
return { url: session.value.customerPortalUrl };
|
||||
}
|
||||
listProducts(
|
||||
ctx: RunQueryCtx,
|
||||
@@ -209,12 +224,16 @@ export class Polar<
|
||||
if (subscription.productId === productId) {
|
||||
throw new Error("Subscription already on this product");
|
||||
}
|
||||
await this.sdk.subscriptions.update({
|
||||
const updatedSubscription = await subscriptionsUpdate(this.polar, {
|
||||
id: subscription.id,
|
||||
subscriptionUpdate: {
|
||||
productId,
|
||||
},
|
||||
});
|
||||
if (!updatedSubscription.value) {
|
||||
throw new Error("Subscription not updated");
|
||||
}
|
||||
return updatedSubscription.value;
|
||||
}
|
||||
async cancelSubscription(
|
||||
ctx: RunActionCtx,
|
||||
@@ -228,13 +247,17 @@ export class Polar<
|
||||
if (subscription.status !== "active") {
|
||||
throw new Error("Subscription is not active");
|
||||
}
|
||||
await this.sdk.subscriptions.update({
|
||||
const updatedSubscription = await subscriptionsUpdate(this.polar, {
|
||||
id: subscription.id,
|
||||
subscriptionUpdate: {
|
||||
cancelAtPeriodEnd: revokeImmediately ? undefined : true,
|
||||
revoke: revokeImmediately ? true : undefined,
|
||||
},
|
||||
});
|
||||
if (!updatedSubscription.value) {
|
||||
throw new Error("Subscription not updated");
|
||||
}
|
||||
return updatedSubscription.value;
|
||||
}
|
||||
api() {
|
||||
return {
|
||||
|
||||
1
src/component/_generated/api.d.ts
vendored
1
src/component/_generated/api.d.ts
vendored
@@ -16,6 +16,7 @@ import type {
|
||||
FilterApi,
|
||||
FunctionReference,
|
||||
} from "convex/server";
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's API.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Polar as PolarSdk } from "@polar-sh/sdk";
|
||||
import { PolarCore } from "@polar-sh/sdk/core";
|
||||
import { productsList } from "@polar-sh/sdk/funcs/productsList.js";
|
||||
|
||||
import { v } from "convex/values";
|
||||
import { action, mutation, query } from "./_generated/server";
|
||||
import schema from "./schema";
|
||||
@@ -278,22 +280,25 @@ export const syncProducts = action({
|
||||
server: v.union(v.literal("sandbox"), v.literal("production")),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const sdk = new PolarSdk({
|
||||
const polar = new PolarCore({
|
||||
accessToken: args.polarAccessToken,
|
||||
server: args.server,
|
||||
});
|
||||
let page = 1;
|
||||
let maxPage;
|
||||
do {
|
||||
const products = await sdk.products.list({
|
||||
const products = await productsList(polar, {
|
||||
page,
|
||||
limit: 100,
|
||||
});
|
||||
if (!products.value) {
|
||||
throw new Error("Failed to get products");
|
||||
}
|
||||
page = page + 1;
|
||||
maxPage = products.result.pagination.maxPage;
|
||||
maxPage = products.value.result.pagination.maxPage;
|
||||
await ctx.runMutation(api.lib.updateProducts, {
|
||||
polarAccessToken: args.polarAccessToken,
|
||||
products: products.result.items.map(convertToDatabaseProduct),
|
||||
products: products.value.result.items.map(convertToDatabaseProduct),
|
||||
});
|
||||
} while (maxPage >= page);
|
||||
},
|
||||
|
||||
@@ -12,8 +12,8 @@ import type {
|
||||
import { GenericId } from "convex/values";
|
||||
import type { api } from "./_generated/api";
|
||||
import type { Doc } from "./_generated/dataModel";
|
||||
import { Subscription } from "@polar-sh/sdk/models/components/subscription.js";
|
||||
import { Product } from "@polar-sh/sdk/models/components/product.js";
|
||||
import type { Subscription } from "@polar-sh/sdk/models/components/subscription.js";
|
||||
import type { Product } from "@polar-sh/sdk/models/components/product.js";
|
||||
|
||||
export const omitSystemFields = <
|
||||
T extends { _id: string; _creationTime: number } | null | undefined,
|
||||
|
||||
Reference in New Issue
Block a user