chore: strengthen api schema

This commit is contained in:
Charlie Lamb
2026-05-04 13:24:07 +01:00
parent 15c9426fdc
commit f42895448a
4 changed files with 54 additions and 2 deletions

View File

@@ -0,0 +1,47 @@
import { describe, expect, test } from "bun:test";
import { AttachParamsV0Schema } from "@api/billing/attachV2/attachParamsV0";
import { AttachParamsV1Schema } from "@api/billing/attachV2/attachParamsV1";
const schemas = [
[
"V0",
AttachParamsV0Schema,
{ customer_id: "cus", product_id: "pro" },
],
[
"V1",
AttachParamsV1Schema,
{ customer_id: "cus", plan_id: "pro" },
],
] as const;
describe("attach params start_date", () => {
test.each(schemas)("%s accepts Unix-ms integers", (_, schema, params) => {
expect(
schema.safeParse({
...params,
start_date: 1_775_123_200_000,
}).success,
).toBe(true);
});
test.each(schemas)(
"%s rejects malformed numeric timestamps",
(_, schema, params) => {
for (const start_date of [
1_775_123_200_000.5,
Number.NaN,
Infinity,
-1,
Number.MAX_SAFE_INTEGER + 1,
]) {
expect(
schema.safeParse({
...params,
start_date,
}).success,
).toBe(false);
}
},
);
});

View File

@@ -4,6 +4,7 @@ import { ProductItemSchema } from "../../../models/productV2Models/productItemMo
import { BillingBehaviorSchema } from "../common/billingBehavior";
import { BillingCycleAnchorSchema } from "../common/billingCycleAnchor";
import { BillingParamsBaseV0Schema } from "../common/billingParamsBase/billingParamsBaseV0";
import { UnixMsTimestampSchema } from "../common/unixMsTimestamp";
import { AttachDiscountSchema } from "./attachDiscount";
export const ExtAttachParamsV0Schema = BillingParamsBaseV0Schema.extend({
@@ -21,7 +22,7 @@ export const ExtAttachParamsV0Schema = BillingParamsBaseV0Schema.extend({
billing_cycle_anchor: BillingCycleAnchorSchema.optional(),
plan_schedule: PlanTimingSchema.optional(),
start_date: z.number().optional(),
start_date: UnixMsTimestampSchema.optional(),
// Discounts to apply (Stripe coupon IDs or human-readable promo code strings)
discounts: z.array(AttachDiscountSchema).optional(),

View File

@@ -3,6 +3,7 @@ import { z } from "zod/v4";
import { PlanTimingSchema } from "../../../models/billingModels/context/attachBillingContext";
import { BillingCycleAnchorSchema } from "../common/billingCycleAnchor";
import { CustomLineItemSchema } from "../common/customLineItem";
import { UnixMsTimestampSchema } from "../common/unixMsTimestamp";
import { AttachDiscountSchema } from "./attachDiscount";
export const AttachParamsV1Schema = BillingParamsBaseV1Schema.extend({
@@ -26,7 +27,7 @@ export const AttachParamsV1Schema = BillingParamsBaseV1Schema.extend({
description:
"When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled.",
}),
start_date: z.number().optional().meta({
start_date: UnixMsTimestampSchema.optional().meta({
description:
"Unix timestamp in milliseconds for when the attached plan should start. Future dates create a scheduled subscription.",
}),

View File

@@ -0,0 +1,3 @@
import { z } from "zod/v4";
export const UnixMsTimestampSchema = z.number().int().safe().nonnegative();