Skip to content

Commit 8d6bb9a

Browse files
committed
feat: add customer schemas and contracts
Add customer endpoint support for subscription management: - CustomerSchema with subscriptions and hasActiveSubscription - CustomerSubscriptionSchema for subscription summaries - GetCustomerInputSchema with externalId/email/customerId lookup - customer.get ORPC contract
1 parent 4770609 commit 8d6bb9a

3 files changed

Lines changed: 84 additions & 1 deletion

File tree

src/contracts/customer.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { oc } from "@orpc/contract";
2+
import {
3+
CustomerSchema,
4+
GetCustomerInputSchema,
5+
} from "../schemas/customer";
6+
7+
export const getCustomerContract = oc
8+
.input(GetCustomerInputSchema)
9+
.output(CustomerSchema);
10+
11+
export const customer = {
12+
get: getCustomerContract,
13+
};

src/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { checkout } from "./contracts/checkout";
2+
import { customer } from "./contracts/customer";
23
import { onboarding } from "./contracts/onboarding";
34
import { products } from "./contracts/products";
45
import { subscription } from "./contracts/subscription";
@@ -23,6 +24,7 @@ export type {
2324
CreateRenewalCheckout,
2425
GetSubscriptionInput,
2526
} from "./contracts/subscription";
27+
export type { GetCustomerInput } from "./schemas/customer";
2628
export type { Checkout } from "./schemas/checkout";
2729
export { CheckoutSchema } from "./schemas/checkout";
2830
export type { Currency } from "./schemas/currency";
@@ -47,8 +49,17 @@ export {
4749
SubscriptionWebhookEventSchema,
4850
SubscriptionWebhookPayloadSchema,
4951
} from "./schemas/subscription";
52+
export type {
53+
Customer,
54+
CustomerSubscription,
55+
} from "./schemas/customer";
56+
export {
57+
CustomerSchema,
58+
CustomerSubscriptionSchema,
59+
GetCustomerInputSchema,
60+
} from "./schemas/customer";
5061

51-
export const contract = { checkout, onboarding, products, subscription };
62+
export const contract = { checkout, customer, onboarding, products, subscription };
5263

5364
export type { MetadataValidationError } from "./validation/metadata-validation";
5465
export {

src/schemas/customer.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { z } from "zod";
2+
import { CurrencySchema } from "./currency";
3+
import { RecurringIntervalSchema, SubscriptionStatusSchema } from "./subscription";
4+
5+
/**
6+
* Summary of a subscription for the customer response.
7+
* Contains the essential fields needed for displaying subscription status.
8+
*/
9+
export const CustomerSubscriptionSchema = z.object({
10+
id: z.string(),
11+
productId: z.string(),
12+
status: SubscriptionStatusSchema,
13+
currentPeriodStart: z.string(), // ISO date
14+
currentPeriodEnd: z.string(), // ISO date
15+
cancelAtPeriodEnd: z.boolean().optional(),
16+
amount: z.number(),
17+
currency: CurrencySchema,
18+
recurringInterval: RecurringIntervalSchema,
19+
});
20+
21+
/**
22+
* Customer data with their subscriptions.
23+
* Returned by the customer.get endpoint.
24+
*/
25+
export const CustomerSchema = z.object({
26+
id: z.string(),
27+
email: z.string().nullable().optional(),
28+
name: z.string().nullable().optional(),
29+
externalId: z.string().nullable().optional(),
30+
subscriptions: z.array(CustomerSubscriptionSchema),
31+
hasActiveSubscription: z.boolean(),
32+
});
33+
34+
/**
35+
* Input for getting a customer.
36+
* Requires exactly one of: externalId, email, or customerId.
37+
*/
38+
export const GetCustomerInputSchema = z
39+
.object({
40+
externalId: z.string().optional(),
41+
email: z.string().optional(),
42+
customerId: z.string().optional(),
43+
})
44+
.refine(
45+
(data) => {
46+
const fields = [data.externalId, data.email, data.customerId].filter(
47+
Boolean,
48+
);
49+
return fields.length === 1;
50+
},
51+
{
52+
message:
53+
"Exactly one of externalId, email, or customerId must be provided",
54+
},
55+
);
56+
57+
export type CustomerSubscription = z.infer<typeof CustomerSubscriptionSchema>;
58+
export type Customer = z.infer<typeof CustomerSchema>;
59+
export type GetCustomerInput = z.infer<typeof GetCustomerInputSchema>;

0 commit comments

Comments
 (0)