Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@moneydevkit/api-contract",
"version": "0.1.19",
"version": "0.1.20",
"description": "API Contract for moneydevkit",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
Expand Down
9 changes: 6 additions & 3 deletions src/contracts/checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,17 @@ export const paymentReceivedContract = oc
.output(z.object({ ok: z.boolean() }));

// List checkouts schemas
const CheckoutStatusSchema = z.enum([
export const CheckoutStatusSchema = z.enum([
"UNCONFIRMED",
"CONFIRMED",
"PENDING_PAYMENT",
"PAYMENT_RECEIVED",
"EXPIRED",
]);
export type CheckoutStatus = z.infer<typeof CheckoutStatusSchema>;

export const CheckoutTypeSchema = z.enum(["PRODUCTS", "AMOUNT", "TOP_UP"]);
export type CheckoutType = z.infer<typeof CheckoutTypeSchema>;

const ListCheckoutsInputSchema = PaginationInputSchema.extend({
status: CheckoutStatusSchema.optional(),
Expand All @@ -168,14 +172,13 @@ export const listCheckoutsContract = oc
.input(ListCheckoutsInputSchema)
.output(ListCheckoutsOutputSchema);

// MCP-specific embedded customer schema
const CheckoutCustomerSchema = CustomerSchema.nullable();

// MCP-specific summary schema for list (simpler than full CheckoutSchema)
const CheckoutListItemSchema = z.object({
id: z.string(),
status: CheckoutStatusSchema,
type: z.enum(["PRODUCTS", "AMOUNT", "TOP_UP"]),
type: CheckoutTypeSchema,
currency: CurrencySchema,
totalAmount: z.number().nullable(),
customerId: z.string().nullable(),
Expand Down
12 changes: 6 additions & 6 deletions src/contracts/customer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { oc } from "@orpc/contract";
import { z } from "zod";
import {
CustomerSchema,
McpCustomerSchema,
CustomerWithSubscriptionsSchema,
GetCustomerInputSchema as SdkGetCustomerInputSchema,
} from "../schemas/customer";
import {
Expand All @@ -13,7 +13,7 @@ import {
// MCP-specific schemas
const ListCustomersInputSchema = PaginationInputSchema;
const ListCustomersOutputSchema = PaginationOutputSchema.extend({
customers: z.array(McpCustomerSchema),
customers: z.array(CustomerSchema),
});

const McpGetCustomerInputSchema = z.object({ id: z.string() });
Expand All @@ -35,7 +35,7 @@ const DeleteCustomerInputSchema = z.object({ id: z.string() });
// SDK contract - uses flexible lookup (externalId/email/customerId)
export const getSdkCustomerContract = oc
.input(SdkGetCustomerInputSchema)
.output(CustomerSchema);
.output(CustomerWithSubscriptionsSchema);

// MCP contracts
export const listCustomersContract = oc
Expand All @@ -44,15 +44,15 @@ export const listCustomersContract = oc

export const getCustomerContract = oc
.input(McpGetCustomerInputSchema)
.output(McpCustomerSchema);
.output(CustomerSchema);

export const createCustomerContract = oc
.input(CreateCustomerInputSchema)
.output(McpCustomerSchema);
.output(CustomerSchema);

export const updateCustomerContract = oc
.input(UpdateCustomerInputSchema)
.output(McpCustomerSchema);
.output(CustomerSchema);

export const deleteCustomerContract = oc
.input(DeleteCustomerInputSchema)
Expand Down
29 changes: 17 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ import { products } from "./contracts/products";
import { subscription } from "./contracts/subscription";

export type {
CheckoutStatus,
CheckoutType,
ConfirmCheckout,
CreateCheckout,
PaymentReceived,
RegisterInvoice,
} from "./contracts/checkout";
export {
CheckoutStatusSchema,
CheckoutTypeSchema,
} from "./contracts/checkout";
export type {
BootstrapOnboarding,
BootstrapOnboardingResponse,
Expand Down Expand Up @@ -50,16 +56,11 @@ export {
SubscriptionWebhookEventSchema,
SubscriptionWebhookPayloadSchema,
} from "./schemas/subscription";
export type {
Customer,
CustomerSubscription,
McpCustomer,
} from "./schemas/customer";
export type { Customer, CustomerWithSubscriptions } from "./schemas/customer";
export {
CustomerSchema,
CustomerSubscriptionSchema,
CustomerWithSubscriptionsSchema,
GetCustomerInputSchema,
McpCustomerSchema,
} from "./schemas/customer";

// New MCP schemas
Expand All @@ -75,10 +76,12 @@ export {
PaginationOutputSchema,
} from "./schemas/pagination";
export type {
PriceAmountType,
ProductPriceInput,
RecurringIntervalInput,
} from "./schemas/product-price-input";
export {
PriceAmountTypeSchema,
ProductPriceInputSchema,
RecurringIntervalInputSchema,
} from "./schemas/product-price-input";
Expand All @@ -102,19 +105,21 @@ export const sdkContract = {
registerInvoice: checkout.registerInvoice,
paymentReceived: checkout.paymentReceived,
},
customer: {
get: customer.getSdk,
},
onboarding,
products: {
list: products.list,
},
subscription,
};

// MCP contract - only the methods the MCP router implements
export const mcpContract = {
customer,
customer: {
list: customer.list,
get: customer.get,
create: customer.create,
update: customer.update,
delete: customer.delete,
},
order,
checkout: {
list: checkout.listSummary,
Expand Down
57 changes: 19 additions & 38 deletions src/schemas/customer.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
import { z } from "zod";
import { CurrencySchema } from "./currency";
import {
RecurringIntervalSchema,
SubscriptionStatusSchema,
} from "./subscription";
import { SubscriptionSchema } from "./subscription";

/**
* Summary of a subscription for the customer response.
* Contains the essential fields needed for displaying subscription status.
* Customer schema for API responses.
* Represents a customer in the organization (admin view).
* Note: Uses modifiedAt to match Prisma schema naming.
*/
export const CustomerSubscriptionSchema = z.object({
export const CustomerSchema = z.object({
id: z.string(),
productId: z.string(),
status: SubscriptionStatusSchema,
currentPeriodStart: z.string().datetime(),
currentPeriodEnd: z.string().datetime(),
cancelAtPeriodEnd: z.boolean().optional(),
amount: z.number(),
currency: CurrencySchema,
recurringInterval: RecurringIntervalSchema,
name: z.string().nullable(),
email: z.string().nullable(),
emailVerified: z.boolean(),
externalId: z.string().nullable(),
userMetadata: z.record(z.string(), z.any()).nullable(),
organizationId: z.string(),
createdAt: z.date(),
modifiedAt: z.date().nullable(),
});

/**
* Customer data with their subscriptions.
* Customer data with their full subscriptions.
* Returned by the SDK customer.get endpoint.
*/
export const CustomerSchema = z.object({
export const CustomerWithSubscriptionsSchema = z.object({
id: z.string(),
email: z.string().nullable().optional(),
name: z.string().nullable().optional(),
externalId: z.string().nullable().optional(),
subscriptions: z.array(CustomerSubscriptionSchema),
subscriptions: z.array(SubscriptionSchema),
});

/**
Expand All @@ -56,24 +53,8 @@ export const GetCustomerInputSchema = z
},
);

/**
* Customer schema for MCP API responses.
* Represents a customer in the organization (admin view).
* Note: Uses modifiedAt to match Prisma schema naming.
*/
export const McpCustomerSchema = z.object({
id: z.string(),
name: z.string().nullable(),
email: z.string().nullable(),
emailVerified: z.boolean(),
externalId: z.string().nullable(),
userMetadata: z.record(z.string(), z.any()).nullable(),
organizationId: z.string(),
createdAt: z.date(),
modifiedAt: z.date().nullable(),
});

export type CustomerSubscription = z.infer<typeof CustomerSubscriptionSchema>;
export type Customer = z.infer<typeof CustomerSchema>;
export type McpCustomer = z.infer<typeof McpCustomerSchema>;
export type CustomerWithSubscriptions = z.infer<
typeof CustomerWithSubscriptionsSchema
>;
export type GetCustomerInput = z.infer<typeof GetCustomerInputSchema>;