diff --git a/sdks/node/src/__tests__/SubscriptionItems.spec.ts b/sdks/node/src/__tests__/SubscriptionItems.spec.ts new file mode 100644 index 0000000..9473bcf --- /dev/null +++ b/sdks/node/src/__tests__/SubscriptionItems.spec.ts @@ -0,0 +1,101 @@ +import { SubscriptionItems } from '../resources/SubscriptionItems'; +import { HttpClient } from '../HttpClient'; + +describe('SubscriptionItems Resource', () => { + let client: jest.Mocked; + let subscriptionItems: SubscriptionItems; + + beforeEach(() => { + client = { + Get: jest.fn(), + Post: jest.fn(), + Delete: jest.fn(), + } as unknown as jest.Mocked; + subscriptionItems = new SubscriptionItems(client); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('create', () => { + it('should send a POST request to /subscription_items with params', async () => { + const params = { + subscription: 'sub_123', + price: 'price_123', + quantity: 2, + }; + + await subscriptionItems.create(params); + + expect(client.Post).toHaveBeenCalledWith('/subscription_items', params); + }); + }); + + describe('update', () => { + it('should send a POST request to /subscription_items/:id with params', async () => { + const params = { + quantity: 3, + }; + + await subscriptionItems.update('si_123', params); + + expect(client.Post).toHaveBeenCalledWith( + '/subscription_items/si_123', + params + ); + }); + }); + + describe('retrieve', () => { + it('should send a GET request to /subscription_items/:id', async () => { + await subscriptionItems.retrieve('si_123'); + + expect(client.Get).toHaveBeenCalledWith('/subscription_items/si_123', {}); + }); + + it('should pass expand params if provided', async () => { + await subscriptionItems.retrieve('si_123', { expand: ['price'] }); + + expect(client.Get).toHaveBeenCalledWith('/subscription_items/si_123', { + expand: ['price'], + }); + }); + }); + + describe('list', () => { + it('should send a GET request to /subscription_items with query params', async () => { + await subscriptionItems.list({ + subscription: 'sub_123', + limit: 5, + starting_after: 'si_456', + }); + + expect(client.Get).toHaveBeenCalledWith('/subscription_items', { + subscription: 'sub_123', + limit: 5, + starting_after: 'si_456', + ending_before: undefined, + }); + }); + }); + + describe('del', () => { + it('should send a DELETE request to /subscription_items/:id', async () => { + await subscriptionItems.del('si_123'); + + expect(client.Delete).toHaveBeenCalledWith( + '/subscription_items/si_123', + {} + ); + }); + + it('should send optional proration params if provided', async () => { + await subscriptionItems.del('si_123', { clear_usage: true }); + + expect(client.Delete).toHaveBeenCalledWith('/subscription_items/si_123', { + clear_usage: true, + }); + }); + }); +}); diff --git a/sdks/node/src/generated/Inputs.ts b/sdks/node/src/generated/Inputs.ts index d418f83..1247205 100644 --- a/sdks/node/src/generated/Inputs.ts +++ b/sdks/node/src/generated/Inputs.ts @@ -1711,6 +1711,48 @@ export type CreateSubscriptionInput = { expand?: string[] | undefined; }; +export type CreateSubscriptionItemInput = { + subscription: string; + billing_thresholds?: '' | { usage_gte: number } | undefined; + discounts?: + | { + coupon?: string | undefined; + discount?: string | undefined; + promotion_code?: string | undefined; + }[] + | undefined; + metadata?: Record | undefined; + payment_behavior?: + | 'allow_incomplete' + | 'default_incomplete' + | 'error_if_incomplete' + | 'pending_if_incomplete' + | undefined; + price?: string | undefined; + price_data?: + | { + currency: string; + product: string; + recurring: { + interval: 'hour' | 'day' | 'week' | 'month' | 'year'; + interval_count?: number | undefined; + }; + tax_behavior?: 'inclusive' | 'exclusive' | 'unspecified' | undefined; + unit_amount?: number | undefined; + unit_amount_decimal?: string | undefined; + } + | undefined; + proration_behavior?: + | 'none' + | 'create_prorations' + | 'always_invoice' + | undefined; + proration_date?: number | undefined; + quantity?: number | undefined; + tax_rates?: string[] | undefined; + expand?: string[] | undefined; +}; + export type CreateTopUpInput = { amount: number; currency: string; @@ -1741,6 +1783,22 @@ export type CreateWebhookEndpointInput = { metadata?: Record | undefined; }; +export type DeleteSubscriptionItemInput = { + clear_usage?: boolean | undefined; + payment_behavior?: + | 'allow_incomplete' + | 'default_incomplete' + | 'error_if_incomplete' + | 'pending_if_incomplete' + | undefined; + proration_behavior?: + | 'none' + | 'create_prorations' + | 'always_invoice' + | undefined; + proration_date?: number | undefined; +}; + export type ExpireCheckoutSessionInput = Record; export type FinalizeInvoiceInput = { @@ -2100,6 +2158,14 @@ export type ListProductsInput = { expand?: string[] | undefined; }; +export type ListSubscriptionItemsInput = { + subscription: string; + ending_before?: string | undefined; + limit?: number | undefined; + starting_after?: string | undefined; + expand?: string[] | undefined; +}; + export type ListSubscriptionsInput = { automatic_tax?: { enabled: boolean } | undefined; collection_method?: 'charge_automatically' | 'send_invoice' | undefined; @@ -2250,6 +2316,8 @@ export type RetrieveProductInput = { expand?: string[] | undefined }; export type RetrieveSubscriptionInput = { expand?: string[] | undefined }; +export type RetrieveSubscriptionItemInput = { expand?: string[] | undefined }; + export type RunBillingForPlatformInput = { batch_size?: number | undefined }; export type UpdateAccountInput = { @@ -3418,6 +3486,49 @@ export type UpdateSubscriptionInput = { expand?: string[] | undefined; }; +export type UpdateSubscriptionItemInput = { + billing_thresholds?: '' | { usage_gte: number } | undefined; + discounts?: + | '' + | { + coupon?: string | undefined; + discount?: string | undefined; + promotion_code?: string | undefined; + }[] + | undefined; + metadata?: Record | undefined; + off_session?: boolean | undefined; + payment_behavior?: + | 'allow_incomplete' + | 'default_incomplete' + | 'error_if_incomplete' + | 'pending_if_incomplete' + | undefined; + price?: string | undefined; + price_data?: + | { + currency: string; + product: string; + recurring: { + interval: 'hour' | 'day' | 'week' | 'month' | 'year'; + interval_count?: number | undefined; + }; + tax_behavior?: 'inclusive' | 'exclusive' | 'unspecified' | undefined; + unit_amount?: number | undefined; + unit_amount_decimal?: string | undefined; + } + | undefined; + proration_behavior?: + | 'none' + | 'create_prorations' + | 'always_invoice' + | undefined; + proration_date?: number | undefined; + quantity?: number | undefined; + tax_rates?: '' | string[] | undefined; + expand?: string[] | undefined; +}; + export type UpdateTopUpInput = { description?: string | undefined; metadata?: Record | undefined; diff --git a/sdks/node/src/index.ts b/sdks/node/src/index.ts index 811b296..50c67ef 100644 --- a/sdks/node/src/index.ts +++ b/sdks/node/src/index.ts @@ -18,6 +18,7 @@ import { Payouts } from './resources/Payouts'; import { Prices } from './resources/Prices'; import { Products } from './resources/Products'; import { Subscriptions } from './resources/Subscriptions'; +import { SubscriptionItems } from './resources/SubscriptionItems'; import { TopUps } from './resources/TopUps'; import { Transfers } from './resources/Transfers'; import { WebhookEndpoints } from './resources/WebhookEndpoints'; @@ -109,6 +110,9 @@ export class Zoneless { /** Subscriptions API resource */ readonly subscriptions: Subscriptions; + /** SubscriptionItems API resource */ + readonly subscriptionItems: SubscriptionItems; + /** TopUps API resource */ readonly topups: TopUps; @@ -162,6 +166,7 @@ export class Zoneless { this.prices = new Prices(this.client); this.products = new Products(this.client); this.subscriptions = new Subscriptions(this.client); + this.subscriptionItems = new SubscriptionItems(this.client); this.topups = new TopUps(this.client); this.transfers = new Transfers(this.client); this.webhookEndpoints = new WebhookEndpoints(this.client); diff --git a/sdks/node/src/resources/SubscriptionItems.ts b/sdks/node/src/resources/SubscriptionItems.ts new file mode 100644 index 0000000..7572539 --- /dev/null +++ b/sdks/node/src/resources/SubscriptionItems.ts @@ -0,0 +1,80 @@ +import { BaseResource } from './Base'; +import { + SubscriptionItem, + SubscriptionItemDeleted, + ListResponse, +} from '@zoneless/shared-types'; +import type { + CreateSubscriptionItemInput, + ListSubscriptionItemsInput, + RetrieveSubscriptionItemInput, + UpdateSubscriptionItemInput, + DeleteSubscriptionItemInput, +} from '../generated/Inputs'; + +/** + * @see https://zoneless.com/docs/subscriptionitems + */ +export class SubscriptionItems extends BaseResource { + /** @see https://zoneless.com/docs/subscriptionitems/create */ + async create(params: CreateSubscriptionItemInput): Promise { + return this.client.Post('/subscription_items', params); + } + + /** @see https://zoneless.com/docs/subscriptionitems/update */ + async update( + id: string, + params: UpdateSubscriptionItemInput + ): Promise { + return this.client.Post( + `/subscription_items/${id}`, + params + ); + } + + /** @see https://zoneless.com/docs/subscriptionitems/retrieve */ + async retrieve( + id: string, + params: RetrieveSubscriptionItemInput = {} + ): Promise { + return this.client.Get( + `/subscription_items/${id}`, + params + ); + } + + /** @see https://zoneless.com/docs/subscriptionitems/list */ + async list( + params: ListSubscriptionItemsInput + ): Promise> { + return this.client.Get>( + '/subscription_items', + this.BuildQuery(params) + ); + } + + /** + * Deletes a subscription item. + * @see https://zoneless.com/docs/subscriptionitems/delete + */ + async del( + id: string, + params: DeleteSubscriptionItemInput = {} + ): Promise { + return this.client.Delete( + `/subscription_items/${id}`, + params + ); + } + + private BuildQuery( + params: ListSubscriptionItemsInput + ): Record { + return { + subscription: params.subscription, + limit: params.limit, + starting_after: params.starting_after, + ending_before: params.ending_before, + }; + } +} diff --git a/sdks/node/src/resources/index.ts b/sdks/node/src/resources/index.ts index 5e0bb26..bf9d6d7 100644 --- a/sdks/node/src/resources/index.ts +++ b/sdks/node/src/resources/index.ts @@ -24,6 +24,7 @@ export { Products } from './Products'; export { Checkout } from './Checkout'; export { CheckoutSessions } from './CheckoutSessions'; export { Subscriptions } from './Subscriptions'; +export { SubscriptionItems } from './SubscriptionItems'; export { TopUps } from './TopUps'; export { Transfers } from './Transfers'; export { WebhookEndpoints } from './WebhookEndpoints';