Purchase
import { Purchase } from '@payments/driver/schemas/Purchase.schema'Location
- Purchase.schema.ts
Zod Schema
What the schema would look like when defined with z.object() in Zod V3:
const Purchase = z.object({
userId: z
.string()
.index()
.describe("Auth provider user ID the plan is associated with"),
provider: z
.enum(["stripe", "revenuecat", "polar", "lemonsqueezy", "paddle", "clerk", "custom"])
.describe("Payment provider / driver name, e.g. 'stripe' or 'revenuecat'"),
purchaseId: z
.string()
.index()
.unique()
.describe("Unique internal purchase ID for the item + checkout combo. Often a combination of priceVariantId and orderCheckoutId."),
customerId: z
.string()
.index()
.describe("Payment provider customer ID linked to this purchase / checkout.")
.sensitive() // = stripped in API responses, serverside only,
orderCheckoutId: z
.string()
.describe("Payment provider checkout session / payment intent / order ID linked to this purchase.")
.sensitive() // = stripped in API responses, serverside only,
productId: z
.string()
.index()
.describe("Payment provider product ID linked to this purchase / checkout."),
sku: z
.string()
.index()
.describe("Shorthand alias for 'priceVariantId': Payment provider price / variant / sku ID linked to this purchase / checkout. Can be the same as productId for certain providers."),
priceVariantId: z
.string()
.index()
.describe("Payment provider price / variant / sku ID linked to this purchase / checkout. Can be the same as productId for certain providers."),
productName: z
.string()
.nullish()
.describe("Optional human readable name for the product, if available from the payment provider."),
priceVariantName: z
.string()
.nullish()
.describe("Optional human readable name for the price variant / sku, if available from the payment provider."),
unitPriceAmount: z
.number()
.nullable()
.describe("Unit price amount in the smallest currency unit (e.g. cents for USD)"),
unitPriceCurrency: z
.string()
.describe("Currency code in ISO 4217 format, e.g. USD or EUR"),
quantity: z
.number()
.default(1)
.describe("Quantity of units purchased"),
status: z
.enum(["pending", "completed", "canceled", "refunded", "expired", "failed"])
.describe("Purchase status, e.g. 'completed' or 'refunded'"),
purchaseDate: z
.string()
.datetime()
.describe("ISO 8601 date string of when the purchase was made / completed"),
canceledDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the purchase was canceled, if applicable"),
refundedDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the purchase was refunded, if applicable"),
raw: z
.string()
.nullish()
.describe("JSON stringified raw related checkouts / payment intent / orders / invoice / charge objects as received from the payment provider and were used to populate this purchase record.")
.sensitive() // = stripped in API responses, serverside only,
})(💡 Could be handy to copy-paste this schema info into an AI chat assistant)
Type Definition
You can extract the TypeScript type from the schema using z.input(), z.output() or z.infer() methods. e.g.:
type Purchase = z.input<typeof Purchase>What the resulting TypeScript type would look like:
{
/** Auth provider user ID the plan is associated with */
userId: string;
/** Payment provider / driver name, e.g. 'stripe' or 'revenuecat' */
provider: "stripe" | "revenuecat" | "polar" | "lemonsqueezy" | "paddle" | "clerk" | "custom";
/** Unique internal purchase ID for the item + checkout combo. Often a combination of priceVariantId and orderCheckoutId. */
purchaseId: string;
/** Payment provider customer ID linked to this purchase / checkout. */
customerId: string;
/** Payment provider checkout session / payment intent / order ID linked to this purchase. */
orderCheckoutId: string;
/** Payment provider product ID linked to this purchase / checkout. */
productId: string;
/** Shorthand alias for 'priceVariantId': Payment provider price / variant / sku ID linked to this purchase / checkout. Can be the same as productId for certain providers. */
sku: string;
/** Payment provider price / variant / sku ID linked to this purchase / checkout. Can be the same as productId for certain providers. */
priceVariantId: string;
/** Optional human readable name for the product, if available from the payment provider. */
productName?: (string | null) | undefined;
/** Optional human readable name for the price variant / sku, if available from the payment provider. */
priceVariantName?: (string | null) | undefined;
/** Unit price amount in the smallest currency unit (e.g. cents for USD) */
unitPriceAmount: number | null;
/** Currency code in ISO 4217 format, e.g. USD or EUR */
unitPriceCurrency: string;
/** Quantity of units purchased */
quantity?: number;
/** Purchase status, e.g. 'completed' or 'refunded' */
status: "pending" | "completed" | "canceled" | "refunded" | "expired" | "failed";
/** ISO 8601 date string of when the purchase was made / completed */
purchaseDate: string;
/** ISO 8601 date string of when the purchase was canceled, if applicable */
canceledDate?: (string | null) | undefined;
/** ISO 8601 date string of when the purchase was refunded, if applicable */
refundedDate?: (string | null) | undefined;
/** JSON stringified raw related checkouts / payment intent / orders / invoice / charge objects as received from the payment provider and were used to populate this purchase record. */
raw?: (string | null) | undefined;
}(💡 Could be handy to copy-paste this type info into an AI chat assistant)
Usage - Validation
To validate data against this schema, you have a few options:
// Throws if invalid
const purchase = Purchase.parse(data)
// Returns { success: boolean, data?: T, error?: ZodError }
const purchase = Purchase.safeParse(data)
This might be useful for parsing API input data or validating form data before submission.
You can also directly integrate this schema with form state managers like our own:
Usage - Form State
import { useFormState } from '@green-stack/forms/useFormState'
const formState = useFormState(Purchase, {
initialValues: { /* ... */ }, // Provide initial values?
validateOnMount: true, // Validate on component mount?
})
Learn more about using schemas for form state in our Form Management Docs.
Usage - Component Props / Docs
Another potential use case for the ‘Purchase’ schema is to type component props, provide default values and generate documentation for that component:
export const PurchaseComponentProps = Purchase.extend({
// Add any additional props here
})
export type PurchaseComponentProps = z.input<typeof PurchaseComponentProps>
/* --- <PurchaseComponent/> --------------- */
export const PurchaseComponent = (rawProps: PurchaseComponentProps) => {
// Extract the props and apply defaults + infer resulting type
const props = ComponentProps.applyDefaults(rawProps)
// ... rest of the component logic ...
}
/* --- Documentation --------------- */
export const documentationProps = PurchaseComponentProps.documentationProps('PurchaseComponent')
Other
Disclaimer - Automatic Docgen
These dynamic schema docs were auto-generated with npm run regenerate-docs. This happens automatically for schema files in any \schemas\ folder. You can opt-out of this by adding // export const optOut = true somewhere in the file.
