Subscription
import { Subscription } from '@payments/driver/schemas/Subscription.schema'Location
- Subscription.schema.ts
Zod Schema
What the schema would look like when defined with z.object() in Zod V3:
const Subscription = 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'"),
customerId: z
.string()
.index()
.describe("Payment provider customer ID linked to this subscription.")
.sensitive() // = stripped in API responses, serverside only,
subscriptionId: z
.string()
.index()
.unique()
.describe("Payment provider subscription ID linked to this subscription.")
.sensitive() // = stripped in API responses, serverside only,
orderCheckoutId: z
.string()
.nullish()
.describe("Payment provider checkout session / order ID linked to this subscription.")
.sensitive() // = stripped in API responses, serverside only,
productId: z
.string()
.index()
.describe("Payment provider product ID linked to this subscription."),
sku: z
.string()
.index()
.describe("Shorthand alias for 'priceVariantId': Payment provider price / variant / sku ID linked to this subscription. Can be the same as productId for certain providers."),
priceVariantId: z
.string()
.index()
.describe("Payment provider price / variant / sku ID linked to this subscription. 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 subscription units purchased, e.g. number of seats"),
status: z
.enum(["active", "trialing", "past_due", "canceled", "expired", "inactive", "incomplete", "incomplete_expired"])
.describe("Subscription status, e.g. 'completed' or 'refunded'"),
startDate: z
.string()
.datetime()
.describe("ISO 8601 date string of when the subscription was started"),
currentPeriodStart: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of the start of the current billing period"),
currentPeriodEnd: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of the end of the current billing period"),
trialStartDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the trial period started, if applicable"),
trialEndDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the trial period ends, if applicable"),
purchaseDate: z
.string()
.datetime()
.describe("ISO 8601 date string of when the subscription was started"),
canceledDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the subscription was canceled, if applicable"),
refundedDate: z
.string()
.datetime()
.nullish()
.describe("ISO 8601 date string of when the subscription was refunded, if applicable"),
raw: z
.string()
.nullish()
.describe("JSON stringified raw subscription object as received from the payment provider")
.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 Subscription = z.input<typeof Subscription>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";
/** Payment provider customer ID linked to this subscription. */
customerId: string;
/** Payment provider subscription ID linked to this subscription. */
subscriptionId: string;
/** Payment provider checkout session / order ID linked to this subscription. */
orderCheckoutId?: (string | null) | undefined;
/** Payment provider product ID linked to this subscription. */
productId: string;
/** Shorthand alias for 'priceVariantId': Payment provider price / variant / sku ID linked to this subscription. Can be the same as productId for certain providers. */
sku: string;
/** Payment provider price / variant / sku ID linked to this subscription. 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 subscription units purchased, e.g. number of seats */
quantity?: number;
/** Subscription status, e.g. 'completed' or 'refunded' */
status: "active" | "trialing" | "past_due" | "canceled" | "expired" | "inactive" | "incomplete" | "incomplete_expired";
/** ISO 8601 date string of when the subscription was started */
startDate: string;
/** ISO 8601 date string of the start of the current billing period */
currentPeriodStart?: (string | null) | undefined;
/** ISO 8601 date string of the end of the current billing period */
currentPeriodEnd?: (string | null) | undefined;
/** ISO 8601 date string of when the trial period started, if applicable */
trialStartDate?: (string | null) | undefined;
/** ISO 8601 date string of when the trial period ends, if applicable */
trialEndDate?: (string | null) | undefined;
/** ISO 8601 date string of when the subscription was started */
purchaseDate: string;
/** ISO 8601 date string of when the subscription was canceled, if applicable */
canceledDate?: (string | null) | undefined;
/** ISO 8601 date string of when the subscription was refunded, if applicable */
refundedDate?: (string | null) | undefined;
/** JSON stringified raw subscription object as received from the payment provider */
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 subscription = Subscription.parse(data)
// Returns { success: boolean, data?: T, error?: ZodError }
const subscription = Subscription.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(Subscription, {
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 ‘Subscription’ schema is to type component props, provide default values and generate documentation for that component:
export const SubscriptionComponentProps = Subscription.extend({
// Add any additional props here
})
export type SubscriptionComponentProps = z.input<typeof SubscriptionComponentProps>
/* --- <SubscriptionComponent/> --------------- */
export const SubscriptionComponent = (rawProps: SubscriptionComponentProps) => {
// Extract the props and apply defaults + infer resulting type
const props = ComponentProps.applyDefaults(rawProps)
// ... rest of the component logic ...
}
/* --- Documentation --------------- */
export const documentationProps = SubscriptionComponentProps.documentationProps('SubscriptionComponent')
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.
