capture product metadata from webhooks

This commit is contained in:
Shawn Erquhart
2025-03-04 11:08:15 -05:00
parent 47eea6453d
commit 3afd571fb1
6 changed files with 68 additions and 21 deletions

View File

@@ -73,6 +73,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -105,6 +106,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -131,6 +134,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -162,6 +167,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -189,7 +195,7 @@ export declare const components: {
"query", "query",
"internal", "internal",
{ userId: string }, { userId: string },
{ id: string; userId: string } | null { id: string; metadata?: Record<string, any>; userId: string } | null
>; >;
getProduct: FunctionReference< getProduct: FunctionReference<
"query", "query",
@@ -220,6 +226,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -250,6 +257,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -265,7 +274,7 @@ export declare const components: {
insertCustomer: FunctionReference< insertCustomer: FunctionReference<
"mutation", "mutation",
"internal", "internal",
{ id: string; userId: string }, { id: string; metadata?: Record<string, any>; userId: string },
string string
>; >;
listCustomerSubscriptions: FunctionReference< listCustomerSubscriptions: FunctionReference<
@@ -280,6 +289,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -321,6 +332,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -352,6 +364,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -383,6 +397,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -435,6 +450,7 @@ export declare const components: {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -467,6 +483,8 @@ export declare const components: {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -484,7 +502,7 @@ export declare const components: {
upsertCustomer: FunctionReference< upsertCustomer: FunctionReference<
"mutation", "mutation",
"internal", "internal",
{ customerId: string; userId: string }, { id: string; metadata?: Record<string, any>; userId: string },
string string
>; >;
}; };

View File

@@ -67,7 +67,6 @@
} }
}, },
"peerDependencies": { "peerDependencies": {
"@polar-sh/sdk": "^0.26.1",
"convex": "^1.19.2", "convex": "^1.19.2",
"react": "^18", "react": "^18",
"react-dom": "^18" "react-dom": "^18"
@@ -88,7 +87,8 @@
"types": "./dist/commonjs/client/index.d.ts", "types": "./dist/commonjs/client/index.d.ts",
"module": "./dist/esm/client/index.js", "module": "./dist/esm/client/index.js",
"dependencies": { "dependencies": {
"@polar-sh/checkout": "^0.1.9", "@polar-sh/checkout": "^0.1.10",
"@polar-sh/sdk": "^0.28.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"convex-helpers": "^0.1.63", "convex-helpers": "^0.1.63",
"remeda": "^2.20.2", "remeda": "^2.20.2",

View File

@@ -59,6 +59,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -91,6 +92,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -117,6 +120,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -148,6 +153,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -175,7 +181,7 @@ export type Mounts = {
"query", "query",
"public", "public",
{ userId: string }, { userId: string },
{ id: string; userId: string } | null { id: string; metadata?: Record<string, any>; userId: string } | null
>; >;
getProduct: FunctionReference< getProduct: FunctionReference<
"query", "query",
@@ -206,6 +212,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -236,6 +243,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -251,7 +260,7 @@ export type Mounts = {
insertCustomer: FunctionReference< insertCustomer: FunctionReference<
"mutation", "mutation",
"public", "public",
{ id: string; userId: string }, { id: string; metadata?: Record<string, any>; userId: string },
string string
>; >;
listCustomerSubscriptions: FunctionReference< listCustomerSubscriptions: FunctionReference<
@@ -266,6 +275,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -307,6 +318,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -338,6 +350,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -369,6 +383,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -421,6 +436,7 @@ export type Mounts = {
storageVersion: string | null; storageVersion: string | null;
version: string | null; version: string | null;
}>; }>;
metadata?: Record<string, any>;
modifiedAt: string | null; modifiedAt: string | null;
name: string; name: string;
organizationId: string; organizationId: string;
@@ -453,6 +469,8 @@ export type Mounts = {
currency: string | null; currency: string | null;
currentPeriodEnd: string | null; currentPeriodEnd: string | null;
currentPeriodStart: string; currentPeriodStart: string;
customerCancellationComment?: string | null;
customerCancellationReason?: string | null;
customerId: string; customerId: string;
endedAt: string | null; endedAt: string | null;
id: string; id: string;
@@ -470,7 +488,7 @@ export type Mounts = {
upsertCustomer: FunctionReference< upsertCustomer: FunctionReference<
"mutation", "mutation",
"public", "public",
{ customerId: string; userId: string }, { id: string; metadata?: Record<string, any>; userId: string },
string string
>; >;
}; };

View File

@@ -19,24 +19,19 @@ export const getCustomerByUserId = query({
}); });
export const insertCustomer = mutation({ export const insertCustomer = mutation({
args: { args: schema.tables.customers.validator,
id: v.string(),
userId: v.string(),
},
returns: v.id("customers"), returns: v.id("customers"),
handler: async (ctx, args) => { handler: async (ctx, args) => {
return ctx.db.insert("customers", { return ctx.db.insert("customers", {
id: args.id, id: args.id,
userId: args.userId, userId: args.userId,
metadata: args.metadata,
}); });
}, },
}); });
export const upsertCustomer = mutation({ export const upsertCustomer = mutation({
args: { args: schema.tables.customers.validator,
userId: v.string(),
customerId: v.string(),
},
returns: v.string(), returns: v.string(),
handler: async (ctx, args) => { handler: async (ctx, args) => {
const customer = await ctx.db const customer = await ctx.db
@@ -45,8 +40,9 @@ export const upsertCustomer = mutation({
.unique(); .unique();
if (!customer) { if (!customer) {
const customerId = await ctx.db.insert("customers", { const customerId = await ctx.db.insert("customers", {
id: args.customerId, id: args.id,
userId: args.userId, userId: args.userId,
metadata: args.metadata,
}); });
const newCustomer = await ctx.db.get(customerId); const newCustomer = await ctx.db.get(customerId);
if (!newCustomer) { if (!newCustomer) {
@@ -203,7 +199,10 @@ export const createSubscription = mutation({
subscription: schema.tables.subscriptions.validator, subscription: schema.tables.subscriptions.validator,
}, },
handler: async (ctx, args) => { handler: async (ctx, args) => {
await ctx.db.insert("subscriptions", args.subscription); await ctx.db.insert("subscriptions", {
...args.subscription,
metadata: args.subscription.metadata,
});
}, },
}); });
@@ -219,7 +218,10 @@ export const updateSubscription = mutation({
if (!existingSubscription) { if (!existingSubscription) {
throw new Error(`Subscription not found: ${args.subscription.id}`); throw new Error(`Subscription not found: ${args.subscription.id}`);
} }
await ctx.db.patch(existingSubscription._id, args.subscription); await ctx.db.patch(existingSubscription._id, {
...args.subscription,
metadata: args.subscription.metadata,
});
}, },
}); });
@@ -228,7 +230,10 @@ export const createProduct = mutation({
product: schema.tables.products.validator, product: schema.tables.products.validator,
}, },
handler: async (ctx, args) => { handler: async (ctx, args) => {
await ctx.db.insert("products", args.product); await ctx.db.insert("products", {
...args.product,
metadata: args.product.metadata,
});
}, },
}); });
@@ -244,7 +249,10 @@ export const updateProduct = mutation({
if (!existingProduct) { if (!existingProduct) {
throw new Error(`Product not found: ${args.product.id}`); throw new Error(`Product not found: ${args.product.id}`);
} }
await ctx.db.patch(existingProduct._id, args.product); await ctx.db.patch(existingProduct._id, {
...args.product,
metadata: args.product.metadata,
});
}, },
}); });

View File

@@ -6,6 +6,7 @@ export default defineSchema(
customers: defineTable({ customers: defineTable({
id: v.string(), id: v.string(),
userId: v.string(), userId: v.string(),
metadata: v.optional(v.record(v.string(), v.any())),
}) })
.index("userId", ["userId"]) .index("userId", ["userId"])
.index("id", ["id"]), .index("id", ["id"]),
@@ -21,6 +22,7 @@ export default defineSchema(
isRecurring: v.boolean(), isRecurring: v.boolean(),
isArchived: v.boolean(), isArchived: v.boolean(),
organizationId: v.string(), organizationId: v.string(),
metadata: v.optional(v.record(v.string(), v.any())),
prices: v.array( prices: v.array(
v.object({ v.object({
id: v.string(), id: v.string(),

View File

@@ -110,6 +110,7 @@ export const convertToDatabaseProduct = (
createdAt: product.createdAt.toISOString(), createdAt: product.createdAt.toISOString(),
modifiedAt: product.modifiedAt?.toISOString() ?? null, modifiedAt: product.modifiedAt?.toISOString() ?? null,
recurringInterval: product.recurringInterval, recurringInterval: product.recurringInterval,
metadata: product.metadata,
prices: product.prices.map((price) => ({ prices: product.prices.map((price) => ({
id: price.id, id: price.id,
productId: price.productId, productId: price.productId,