chore: generate

This commit is contained in:
GitHub Action
2026-01-22 22:04:55 +00:00
parent 5f3ab9395f
commit c128579cfc
5 changed files with 122 additions and 181 deletions

View File

@@ -421,7 +421,10 @@ export async function POST(input: APIEvent) {
}) })
} }
if (body.type === "invoice.payment_succeeded") { if (body.type === "invoice.payment_succeeded") {
if (body.data.object.billing_reason === "subscription_cycle" || body.data.object.billing_reason === "subscription_create") { if (
body.data.object.billing_reason === "subscription_cycle" ||
body.data.object.billing_reason === "subscription_create"
) {
const invoiceID = body.data.object.id as string const invoiceID = body.data.object.id as string
const amountInCents = body.data.object.amount_paid const amountInCents = body.data.object.amount_paid
const customerID = body.data.object.customer as string const customerID = body.data.object.customer as string

View File

@@ -43,9 +43,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"account_id_pk": { "account_id_pk": {
"name": "account_id_pk", "name": "account_id_pk",
"columns": [ "columns": ["id"]
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -109,17 +107,12 @@
"indexes": { "indexes": {
"provider": { "provider": {
"name": "provider", "name": "provider",
"columns": [ "columns": ["provider", "subject"],
"provider",
"subject"
],
"isUnique": true "isUnique": true
}, },
"account_id": { "account_id": {
"name": "account_id", "name": "account_id",
"columns": [ "columns": ["account_id"],
"account_id"
],
"isUnique": false "isUnique": false
} }
}, },
@@ -127,9 +120,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"auth_id_pk": { "auth_id_pk": {
"name": "auth_id_pk", "name": "auth_id_pk",
"columns": [ "columns": ["id"]
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -193,9 +184,7 @@
"indexes": { "indexes": {
"time_created": { "time_created": {
"name": "time_created", "name": "time_created",
"columns": [ "columns": ["time_created"],
"time_created"
],
"isUnique": false "isUnique": false
} }
}, },
@@ -203,9 +192,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"benchmark_id_pk": { "benchmark_id_pk": {
"name": "benchmark_id_pk", "name": "benchmark_id_pk",
"columns": [ "columns": ["id"]
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -388,16 +375,12 @@
"indexes": { "indexes": {
"global_customer_id": { "global_customer_id": {
"name": "global_customer_id", "name": "global_customer_id",
"columns": [ "columns": ["customer_id"],
"customer_id"
],
"isUnique": true "isUnique": true
}, },
"global_subscription_id": { "global_subscription_id": {
"name": "global_subscription_id", "name": "global_subscription_id",
"columns": [ "columns": ["subscription_id"],
"subscription_id"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -405,10 +388,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"billing_workspace_id_id_pk": { "billing_workspace_id_id_pk": {
"name": "billing_workspace_id_id_pk", "name": "billing_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -502,10 +482,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"payment_workspace_id_id_pk": { "payment_workspace_id_id_pk": {
"name": "payment_workspace_id_id_pk", "name": "payment_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -590,10 +567,7 @@
"indexes": { "indexes": {
"workspace_user_id": { "workspace_user_id": {
"name": "workspace_user_id", "name": "workspace_user_id",
"columns": [ "columns": ["workspace_id", "user_id"],
"workspace_id",
"user_id"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -601,10 +575,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"subscription_workspace_id_id_pk": { "subscription_workspace_id_id_pk": {
"name": "subscription_workspace_id_id_pk", "name": "subscription_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -731,10 +702,7 @@
"indexes": { "indexes": {
"usage_time_created": { "usage_time_created": {
"name": "usage_time_created", "name": "usage_time_created",
"columns": [ "columns": ["workspace_id", "time_created"],
"workspace_id",
"time_created"
],
"isUnique": false "isUnique": false
} }
}, },
@@ -742,10 +710,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"usage_workspace_id_id_pk": { "usage_workspace_id_id_pk": {
"name": "usage_workspace_id_id_pk", "name": "usage_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -781,10 +746,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"ip_rate_limit_ip_interval_pk": { "ip_rate_limit_ip_interval_pk": {
"name": "ip_rate_limit_ip_interval_pk", "name": "ip_rate_limit_ip_interval_pk",
"columns": [ "columns": ["ip", "interval"]
"ip",
"interval"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -836,9 +798,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"ip_ip_pk": { "ip_ip_pk": {
"name": "ip_ip_pk", "name": "ip_ip_pk",
"columns": [ "columns": ["ip"]
"ip"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -916,9 +876,7 @@
"indexes": { "indexes": {
"global_key": { "global_key": {
"name": "global_key", "name": "global_key",
"columns": [ "columns": ["key"],
"key"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -926,10 +884,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"key_workspace_id_id_pk": { "key_workspace_id_id_pk": {
"name": "key_workspace_id_id_pk", "name": "key_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -986,10 +941,7 @@
"indexes": { "indexes": {
"model_workspace_model": { "model_workspace_model": {
"name": "model_workspace_model", "name": "model_workspace_model",
"columns": [ "columns": ["workspace_id", "model"],
"workspace_id",
"model"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -997,10 +949,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"model_workspace_id_id_pk": { "model_workspace_id_id_pk": {
"name": "model_workspace_id_id_pk", "name": "model_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1064,10 +1013,7 @@
"indexes": { "indexes": {
"workspace_provider": { "workspace_provider": {
"name": "workspace_provider", "name": "workspace_provider",
"columns": [ "columns": ["workspace_id", "provider"],
"workspace_id",
"provider"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -1075,10 +1021,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"provider_workspace_id_id_pk": { "provider_workspace_id_id_pk": {
"name": "provider_workspace_id_id_pk", "name": "provider_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1191,32 +1134,22 @@
"indexes": { "indexes": {
"user_account_id": { "user_account_id": {
"name": "user_account_id", "name": "user_account_id",
"columns": [ "columns": ["workspace_id", "account_id"],
"workspace_id",
"account_id"
],
"isUnique": true "isUnique": true
}, },
"user_email": { "user_email": {
"name": "user_email", "name": "user_email",
"columns": [ "columns": ["workspace_id", "email"],
"workspace_id",
"email"
],
"isUnique": true "isUnique": true
}, },
"global_account_id": { "global_account_id": {
"name": "global_account_id", "name": "global_account_id",
"columns": [ "columns": ["account_id"],
"account_id"
],
"isUnique": false "isUnique": false
}, },
"global_email": { "global_email": {
"name": "global_email", "name": "global_email",
"columns": [ "columns": ["email"],
"email"
],
"isUnique": false "isUnique": false
} }
}, },
@@ -1224,10 +1157,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"user_workspace_id_id_pk": { "user_workspace_id_id_pk": {
"name": "user_workspace_id_id_pk", "name": "user_workspace_id_id_pk",
"columns": [ "columns": ["workspace_id", "id"]
"workspace_id",
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1284,9 +1214,7 @@
"indexes": { "indexes": {
"slug": { "slug": {
"name": "slug", "name": "slug",
"columns": [ "columns": ["slug"],
"slug"
],
"isUnique": true "isUnique": true
} }
}, },
@@ -1294,9 +1222,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"workspace_id": { "workspace_id": {
"name": "workspace_id", "name": "workspace_id",
"columns": [ "columns": ["id"]
"id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1313,4 +1239,4 @@
"tables": {}, "tables": {},
"indexes": {} "indexes": {}
} }
} }

View File

@@ -395,4 +395,4 @@
"breakpoints": true "breakpoints": true
} }
] ]
} }

View File

@@ -290,65 +290,68 @@ export namespace Billing {
}, },
) )
export const subscribe = fn(z.object({ export const subscribe = fn(
seats: z.number(), z.object({
coupon: z.string().optional(), seats: z.number(),
}), async ({ seats, coupon }) => { coupon: z.string().optional(),
const user = Actor.assert("user") }),
const billing = await Database.use((tx) => async ({ seats, coupon }) => {
tx const user = Actor.assert("user")
.select({ const billing = await Database.use((tx) =>
customerID: BillingTable.customerID, tx
paymentMethodID: BillingTable.paymentMethodID, .select({
subscriptionID: BillingTable.subscriptionID, customerID: BillingTable.customerID,
subscriptionPlan: BillingTable.subscriptionPlan, paymentMethodID: BillingTable.paymentMethodID,
timeSubscriptionSelected: BillingTable.timeSubscriptionSelected, subscriptionID: BillingTable.subscriptionID,
}) subscriptionPlan: BillingTable.subscriptionPlan,
.from(BillingTable) timeSubscriptionSelected: BillingTable.timeSubscriptionSelected,
.where(eq(BillingTable.workspaceID, Actor.workspace())) })
.then((rows) => rows[0]), .from(BillingTable)
) .where(eq(BillingTable.workspaceID, Actor.workspace()))
.then((rows) => rows[0]),
)
if (!billing) throw new Error("Billing record not found") if (!billing) throw new Error("Billing record not found")
if (!billing.timeSubscriptionSelected) throw new Error("Not selected for subscription") if (!billing.timeSubscriptionSelected) throw new Error("Not selected for subscription")
if (billing.subscriptionID) throw new Error("Already subscribed") if (billing.subscriptionID) throw new Error("Already subscribed")
if (!billing.customerID) throw new Error("No customer ID") if (!billing.customerID) throw new Error("No customer ID")
if (!billing.paymentMethodID) throw new Error("No payment method") if (!billing.paymentMethodID) throw new Error("No payment method")
if (!billing.subscriptionPlan) throw new Error("No subscription plan") if (!billing.subscriptionPlan) throw new Error("No subscription plan")
const subscription = await Billing.stripe().subscriptions.create({ const subscription = await Billing.stripe().subscriptions.create({
customer: billing.customerID, customer: billing.customerID,
default_payment_method: billing.paymentMethodID, default_payment_method: billing.paymentMethodID,
items: [{ price: BlackData.planToPriceID({ plan: billing.subscriptionPlan }) }], items: [{ price: BlackData.planToPriceID({ plan: billing.subscriptionPlan }) }],
metadata: { metadata: {
workspaceID: Actor.workspace(), workspaceID: Actor.workspace(),
}, },
})
await Database.transaction(async (tx) => {
await tx
.update(BillingTable)
.set({
subscriptionID: subscription.id,
subscription: {
status: "subscribed",
coupon,
seats,
plan: billing.subscriptionPlan!,
},
subscriptionPlan: null,
timeSubscriptionBooked: null,
timeSubscriptionSelected: null,
})
.where(eq(BillingTable.workspaceID, Actor.workspace()))
await tx.insert(SubscriptionTable).values({
workspaceID: Actor.workspace(),
id: Identifier.create("subscription"),
userID: user.properties.userID,
}) })
})
return subscription.id await Database.transaction(async (tx) => {
}) await tx
.update(BillingTable)
.set({
subscriptionID: subscription.id,
subscription: {
status: "subscribed",
coupon,
seats,
plan: billing.subscriptionPlan!,
},
subscriptionPlan: null,
timeSubscriptionBooked: null,
timeSubscriptionSelected: null,
})
.where(eq(BillingTable.workspaceID, Actor.workspace()))
await tx.insert(SubscriptionTable).values({
workspaceID: Actor.workspace(),
id: Identifier.create("subscription"),
userID: user.properties.userID,
})
})
return subscription.id
},
)
} }

View File

@@ -28,28 +28,37 @@ export namespace BlackData {
return input return input
}) })
export const getLimits = fn(z.object({ export const getLimits = fn(
z.object({
plan: z.enum(SubscriptionPlan), plan: z.enum(SubscriptionPlan),
}), ({ plan }) => { }),
const json = JSON.parse(Resource.ZEN_BLACK_LIMITS.value) ({ plan }) => {
return Schema.parse(json)[plan] const json = JSON.parse(Resource.ZEN_BLACK_LIMITS.value)
}) return Schema.parse(json)[plan]
},
)
export const planToPriceID = fn(z.object({ export const planToPriceID = fn(
z.object({
plan: z.enum(SubscriptionPlan), plan: z.enum(SubscriptionPlan),
}), ({ plan }) => { }),
if (plan === "200") return Resource.ZEN_BLACK_PRICE.plan200 ({ plan }) => {
if (plan === "100") return Resource.ZEN_BLACK_PRICE.plan100 if (plan === "200") return Resource.ZEN_BLACK_PRICE.plan200
return Resource.ZEN_BLACK_PRICE.plan20 if (plan === "100") return Resource.ZEN_BLACK_PRICE.plan100
}) return Resource.ZEN_BLACK_PRICE.plan20
},
)
export const priceIDToPlan = fn(z.object({ export const priceIDToPlan = fn(
priceID: z.string(), z.object({
}), ({ priceID }) => { priceID: z.string(),
if (priceID === Resource.ZEN_BLACK_PRICE.plan200) return "200" }),
if (priceID === Resource.ZEN_BLACK_PRICE.plan100) return "100" ({ priceID }) => {
return "20" if (priceID === Resource.ZEN_BLACK_PRICE.plan200) return "200"
}) if (priceID === Resource.ZEN_BLACK_PRICE.plan100) return "100"
return "20"
},
)
} }
export namespace Black { export namespace Black {