diff --git a/api.md b/api.md index de5d1d6..707ba08 100644 --- a/api.md +++ b/api.md @@ -11,7 +11,7 @@ List methods return a `PagePromise`. Awaited, it gives the first `Page`: the res properties read on the page, with `items`, `hasNextPage()`, `getNextPage()` and `iterPages()`. Iterated with `for await`, it yields every item of every page. -[Add ons](#add-ons) · [Add ons entitlements](#add-ons-entitlements) · [Batch jobs](#batch-jobs) · [Checkout sessions](#checkout-sessions) · [Connect](#connect) · [Coupons](#coupons) · [Credit notes](#credit-notes) · [Custom properties](#custom-properties) · [Customers](#customers) · [Entitlements](#entitlements) · [Events](#events) · [Features](#features) · [Invoices](#invoices) · [Metrics](#metrics) · [Oauth](#oauth) · [Oauth apps](#oauth-apps) · [Plans](#plans) · [Plans versions](#plans-versions) · [Product families](#product-families) · [Products](#products) · [Products entitlements](#products-entitlements) · [Subscriptions](#subscriptions) · [Usage](#usage) +[Add ons](#add-ons) · [Add ons entitlements](#add-ons-entitlements) · [Batch jobs](#batch-jobs) · [Checkout sessions](#checkout-sessions) · [Connect](#connect) · [Coupons](#coupons) · [Credit notes](#credit-notes) · [Custom properties](#custom-properties) · [Customers](#customers) · [Entitlements](#entitlements) · [Events](#events) · [Features](#features) · [Invoices](#invoices) · [Metrics](#metrics) · [Oauth](#oauth) · [Oauth apps](#oauth-apps) · [Plans](#plans) · [Plans versions](#plans-versions) · [Product families](#product-families) · [Products](#products) · [Products entitlements](#products-entitlements) · [Subscriptions](#subscriptions) · [Usage](#usage) · [Webhook endpoints](#webhook-endpoints) · [Webhook endpoints endpoints](#webhook-endpoints-endpoints) ## Add ons @@ -284,3 +284,26 @@ Iterated with `for await`, it yields every item of every page. | `client.usage.retrieveCustomer(customerId: string, options: UsageRetrieveCustomerOptions): APIPromise` | `GET /api/v1/usage/customer/{customer_id}` | [`UsageResponse`](src/models/usageResponse.ts) | | `client.usage.retrieveSubscription(subscriptionId: string, options?: UsageRetrieveSubscriptionOptions): APIPromise` | `GET /api/v1/usage/subscription/{subscription_id}` | [`UsageResponse`](src/models/usageResponse.ts) | | `client.usage.retrieveSummary(options: UsageRetrieveSummaryOptions): APIPromise` | `GET /api/v1/usage/summary` | [`UsageResponse`](src/models/usageResponse.ts) | + +## Webhook endpoints + +[`client.webhookEndpoints`](src/api/webhookEndpoints.ts) + +| Method | Request | Returns | +| --- | --- | --- | +| `client.webhookEndpoints.resendWebhookDelivery(deliveryId: string): APIPromise` | `POST /api/v1/webhooks/deliveries/{delivery_id}/resend` | [`WebhookDelivery`](src/models/webhookDelivery.ts) | + +### Webhook endpoints endpoints + +[`client.webhookEndpoints.endpoints`](src/api/webhookEndpointsEndpoints.ts) + +| Method | Request | Returns | +| --- | --- | --- | +| `client.webhookEndpoints.endpoints.list(): APIPromise` | `GET /api/v1/webhooks/endpoints` | [`WebhookEndpointListResponse`](src/models/webhookEndpointListResponse.ts) | +| `client.webhookEndpoints.endpoints.create(createWebhookEndpointRequest: CreateWebhookEndpointRequest): APIPromise` | `POST /api/v1/webhooks/endpoints` | [`CreatedWebhookEndpoint`](src/models/createdWebhookEndpoint.ts) | +| `client.webhookEndpoints.endpoints.retrieve(endpointId: string): APIPromise` | `GET /api/v1/webhooks/endpoints/{endpoint_id}` | [`WebhookEndpoint`](src/models/webhookEndpoint.ts) | +| `client.webhookEndpoints.endpoints.delete(endpointId: string): APIPromise` | `DELETE /api/v1/webhooks/endpoints/{endpoint_id}` | nothing | +| `client.webhookEndpoints.endpoints.update(endpointId: string, updateWebhookEndpointRequest: UpdateWebhookEndpointRequest): APIPromise` | `PATCH /api/v1/webhooks/endpoints/{endpoint_id}` | [`WebhookEndpoint`](src/models/webhookEndpoint.ts) | +| `client.webhookEndpoints.endpoints.listDeliveries(endpointId: string, options?: WebhookEndpointsEndpointsListDeliveriesOptions): PagePromise` | `GET /api/v1/webhooks/endpoints/{endpoint_id}/deliveries` | [`WebhookDeliveryListResponse`](src/models/webhookDeliveryListResponse.ts) pages of [`WebhookDelivery`](src/models/webhookDelivery.ts) | +| `client.webhookEndpoints.endpoints.rotateSecret(endpointId: string): APIPromise` | `POST /api/v1/webhooks/endpoints/{endpoint_id}/rotate-secret` | [`WebhookEndpointSecret`](src/models/webhookEndpointSecret.ts) | +| `client.webhookEndpoints.endpoints.retrieveSecret(endpointId: string): APIPromise` | `GET /api/v1/webhooks/endpoints/{endpoint_id}/secret` | [`WebhookEndpointSecret`](src/models/webhookEndpointSecret.ts) | diff --git a/src/api/webhookEndpoints.ts b/src/api/webhookEndpoints.ts new file mode 100644 index 0000000..a142de5 --- /dev/null +++ b/src/api/webhookEndpoints.ts @@ -0,0 +1,44 @@ +// this file is @generated + +import { + type WebhookDelivery, + WebhookDeliverySerializer, +} from "../models/webhookDelivery.js"; +import { WebhookEndpointsEndpoints } from "./webhookEndpointsEndpoints.js"; +import type { APIPromise } from "../apiPromise.js"; +import { + MeteroidRequest, + type MeteroidRequestContext, + type RequestOptions, +} from "../request.js"; + +/** The webhook endpoints operations, reached through the client's `webhookEndpoints`. */ +export class WebhookEndpoints { + private _endpoints?: WebhookEndpointsEndpoints; + /** @internal */ + public constructor(private readonly requestCtx: MeteroidRequestContext) {} + + /** The endpoints operations. */ + public get endpoints(): WebhookEndpointsEndpoints { + this._endpoints ??= new WebhookEndpointsEndpoints(this.requestCtx); + return this._endpoints; + } + + /** + * Resend a webhook delivery + * + * Re-queues the same event for the same endpoint. Fails if the endpoint is disabled. + */ + public resendWebhookDelivery( + deliveryId: string, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "POST", + "/api/v1/webhooks/deliveries/{delivery_id}/resend" + ); + + request.setPathParam("delivery_id", deliveryId); + return request.send(this.requestCtx, WebhookDeliverySerializer.parse, requestOptions); + } +} diff --git a/src/api/webhookEndpointsEndpoints.ts b/src/api/webhookEndpointsEndpoints.ts new file mode 100644 index 0000000..80e0de1 --- /dev/null +++ b/src/api/webhookEndpointsEndpoints.ts @@ -0,0 +1,226 @@ +// this file is @generated + +import { + type CreateWebhookEndpointRequest, + CreateWebhookEndpointRequestSerializer, +} from "../models/createWebhookEndpointRequest.js"; +import { + type CreatedWebhookEndpoint, + CreatedWebhookEndpointSerializer, +} from "../models/createdWebhookEndpoint.js"; +import { + type UpdateWebhookEndpointRequest, + UpdateWebhookEndpointRequestSerializer, +} from "../models/updateWebhookEndpointRequest.js"; +import type { WebhookDelivery } from "../models/webhookDelivery.js"; +import { + type WebhookDeliveryListResponse, + WebhookDeliveryListResponseSerializer, +} from "../models/webhookDeliveryListResponse.js"; +import type { WebhookDeliveryStatus } from "../models/webhookDeliveryStatus.js"; +import { + type WebhookEndpoint, + WebhookEndpointSerializer, +} from "../models/webhookEndpoint.js"; +import { + type WebhookEndpointListResponse, + WebhookEndpointListResponseSerializer, +} from "../models/webhookEndpointListResponse.js"; +import { + type WebhookEndpointSecret, + WebhookEndpointSecretSerializer, +} from "../models/webhookEndpointSecret.js"; +import type { APIPromise } from "../apiPromise.js"; +import { PagePromise } from "../pagination.js"; +import { + MeteroidRequest, + type MeteroidRequestContext, + type RequestOptions, +} from "../request.js"; + +/** The query and header parameters of `listDeliveries`. */ +export interface WebhookEndpointsEndpointsListDeliveriesOptions { + /** Only return deliveries in this state. */ + status?: WebhookDeliveryStatus | undefined; + /** Page number (0-indexed) */ + page?: number | undefined; + /** Number of items per page */ + perPage?: number | undefined; +} + +/** The webhook endpoints endpoints operations, reached through the client's `webhookEndpoints.endpoints`. */ +export class WebhookEndpointsEndpoints { + /** @internal */ + public constructor(private readonly requestCtx: MeteroidRequestContext) {} + + /** List webhook endpoints */ + public list(requestOptions?: RequestOptions): APIPromise { + const request = new MeteroidRequest("GET", "/api/v1/webhooks/endpoints"); + + return request.send( + this.requestCtx, + WebhookEndpointListResponseSerializer.parse, + requestOptions + ); + } + + /** + * Create a webhook endpoint + * + * The signing secret is returned once, in this response only. + */ + public create( + createWebhookEndpointRequest: CreateWebhookEndpointRequest, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest("POST", "/api/v1/webhooks/endpoints"); + + request.setBody( + CreateWebhookEndpointRequestSerializer.serialize(createWebhookEndpointRequest) + ); + return request.send( + this.requestCtx, + CreatedWebhookEndpointSerializer.parse, + requestOptions + ); + } + + /** Get a webhook endpoint */ + public retrieve( + endpointId: string, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "GET", + "/api/v1/webhooks/endpoints/{endpoint_id}" + ); + + request.setPathParam("endpoint_id", endpointId); + return request.send(this.requestCtx, WebhookEndpointSerializer.parse, requestOptions); + } + + /** + * Delete a webhook endpoint + * + * The endpoint is archived and its pending deliveries are cancelled. + */ + public delete(endpointId: string, requestOptions?: RequestOptions): APIPromise { + const request = new MeteroidRequest( + "DELETE", + "/api/v1/webhooks/endpoints/{endpoint_id}" + ); + + request.setPathParam("endpoint_id", endpointId); + return request.sendNoResponseBody(this.requestCtx, requestOptions); + } + + /** + * Update a webhook endpoint + * + * Omitted fields are left untouched. Re-enabling a disabled endpoint resets its + * consecutive failure count. + */ + public update( + endpointId: string, + updateWebhookEndpointRequest: UpdateWebhookEndpointRequest, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "PATCH", + "/api/v1/webhooks/endpoints/{endpoint_id}" + ); + + request.setPathParam("endpoint_id", endpointId); + request.setBody( + UpdateWebhookEndpointRequestSerializer.serialize(updateWebhookEndpointRequest) + ); + return request.send(this.requestCtx, WebhookEndpointSerializer.parse, requestOptions); + } + + /** + * List deliveries for a webhook endpoint + * + * Await it for the first page: the response body, its properties read on the page, with + * `items`, `hasNextPage()`, `getNextPage()` and `iterPages()`. Or iterate it with `for await` + * over every item of every page, fetched on demand. + */ + public listDeliveries( + endpointId: string, + options?: WebhookEndpointsEndpointsListDeliveriesOptions, + requestOptions?: RequestOptions + ): PagePromise { + return new PagePromise( + { + style: "page", + items: (page) => page.data, + totalPages: (page) => page.paginationMeta?.totalPages, + firstPage: 0, + fetch: (page) => + this.#listDeliveries(endpointId, { ...options, page: page }, requestOptions), + }, + options?.page + ); + } + + #listDeliveries( + endpointId: string, + options?: WebhookEndpointsEndpointsListDeliveriesOptions, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "GET", + "/api/v1/webhooks/endpoints/{endpoint_id}/deliveries" + ); + + request.setPathParam("endpoint_id", endpointId); + request.setQueryParam("status", options?.status); + request.setQueryParam("page", options?.page); + request.setQueryParam("per_page", options?.perPage); + return request.send( + this.requestCtx, + WebhookDeliveryListResponseSerializer.parse, + requestOptions + ); + } + + /** + * Rotate a webhook endpoint secret + * + * The previous secret keeps signing alongside the new one for 24 hours, so consumers + * can roll over without dropping events. + */ + public rotateSecret( + endpointId: string, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "POST", + "/api/v1/webhooks/endpoints/{endpoint_id}/rotate-secret" + ); + + request.setPathParam("endpoint_id", endpointId); + return request.send( + this.requestCtx, + WebhookEndpointSecretSerializer.parse, + requestOptions + ); + } + + /** Reveal a webhook endpoint secret */ + public retrieveSecret( + endpointId: string, + requestOptions?: RequestOptions + ): APIPromise { + const request = new MeteroidRequest( + "GET", + "/api/v1/webhooks/endpoints/{endpoint_id}/secret" + ); + + request.setPathParam("endpoint_id", endpointId); + return request.send( + this.requestCtx, + WebhookEndpointSecretSerializer.parse, + requestOptions + ); + } +} diff --git a/src/index.ts b/src/index.ts index 4088a86..1517939 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ import { ProductFamilies } from "./api/productFamilies.js"; import { Products } from "./api/products.js"; import { Subscriptions } from "./api/subscriptions.js"; import { Usage } from "./api/usage.js"; +import { WebhookEndpoints } from "./api/webhookEndpoints.js"; import type { Security, SecurityScheme } from "./auth.js"; import type { Middleware } from "./middleware.js"; import { readEnv, type MeteroidRequestContext } from "./request.js"; @@ -115,6 +116,9 @@ export { Usage } from "./api/usage.js"; export type { UsageRetrieveCustomerOptions } from "./api/usage.js"; export type { UsageRetrieveSubscriptionOptions } from "./api/usage.js"; export type { UsageRetrieveSummaryOptions } from "./api/usage.js"; +export { WebhookEndpoints } from "./api/webhookEndpoints.js"; +export { WebhookEndpointsEndpoints } from "./api/webhookEndpointsEndpoints.js"; +export type { WebhookEndpointsEndpointsListDeliveriesOptions } from "./api/webhookEndpointsEndpoints.js"; export type MeteroidOptions = { /** @@ -212,6 +216,7 @@ export class Meteroid { private _products?: Products; private _subscriptions?: Subscriptions; private _usage?: Usage; + private _webhookEndpoints?: WebhookEndpoints; /** * Reads the API key from `METEROID_API_KEY` and the base URL from `METEROID_BASE_URL` @@ -357,4 +362,10 @@ export class Meteroid { this._usage ??= new Usage(this.requestCtx); return this._usage; } + + /** The webhook endpoints API. */ + public get webhookEndpoints(): WebhookEndpoints { + this._webhookEndpoints ??= new WebhookEndpoints(this.requestCtx); + return this._webhookEndpoints; + } } diff --git a/src/models/createWebhookEndpointRequest.ts b/src/models/createWebhookEndpointRequest.ts new file mode 100644 index 0000000..57a17bc --- /dev/null +++ b/src/models/createWebhookEndpointRequest.ts @@ -0,0 +1,92 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { + decodeInteger, + decodeList, + decodeObject, + decodePath, + decodeString, +} from "../decode.js"; +import { + type WebhookHeaderInput, + WebhookHeaderInputSerializer, +} from "./webhookHeaderInput.js"; + +export interface CreateWebhookEndpointRequest { + description?: string | null | undefined; + /** Event types to subscribe to. Omit or leave empty to receive every event type. */ + eventTypes?: string[] | undefined; + /** Custom headers sent with every delivery. */ + headers?: WebhookHeaderInput[] | undefined; + /** Deliveries started per second, at most (1 to 1000). */ + rateLimitPerSec?: number | null | undefined; + /** + * HTTPS destination. Private and loopback addresses are rejected unless the + * instance is configured to allow them. + */ + url: string; +} + +/** Converts `CreateWebhookEndpointRequest` values from (`parse`) and to (`serialize`) their JSON form. */ +export const CreateWebhookEndpointRequestSerializer = { + parse(json: any, path = "$"): CreateWebhookEndpointRequest { + decodeObject(json, path); + return { + ...extraProperties(json, [ + "description", + "event_types", + "headers", + "rate_limit_per_sec", + "url", + ]), + description: + json["description"] != null + ? decodeString(json["description"], path, "description") + : json["description"], + eventTypes: + json["event_types"] != null + ? decodeList( + json["event_types"], + path, + "event_types", + (item: any, p: string, i: number) => decodeString(item, p, i) + ) + : undefined, + headers: + json["headers"] != null + ? decodeList( + json["headers"], + path, + "headers", + (item: any, p: string, i: number) => + WebhookHeaderInputSerializer.parse(item, decodePath(p, i)) + ) + : undefined, + rateLimitPerSec: + json["rate_limit_per_sec"] != null + ? decodeInteger(json["rate_limit_per_sec"], path, "rate_limit_per_sec") + : json["rate_limit_per_sec"], + url: decodeString(json["url"], path, "url"), + }; + }, + + serialize(value: CreateWebhookEndpointRequest): any { + return { + ...extraProperties(value, [ + "description", + "eventTypes", + "headers", + "rateLimitPerSec", + "url", + ]), + description: value.description, + event_types: value.eventTypes, + headers: + value.headers != null + ? value.headers.map((item: any) => WebhookHeaderInputSerializer.serialize(item)) + : undefined, + rate_limit_per_sec: value.rateLimitPerSec, + url: value.url, + }; + }, +}; diff --git a/src/models/createdWebhookEndpoint.ts b/src/models/createdWebhookEndpoint.ts new file mode 100644 index 0000000..7d054d0 --- /dev/null +++ b/src/models/createdWebhookEndpoint.ts @@ -0,0 +1,101 @@ +// this file is @generated +import { extraProperties, pickProperties } from "../json.js"; +import { decodeObject, decodeString } from "../decode.js"; +import { type WebhookEndpoint, WebhookEndpointSerializer } from "./webhookEndpoint.js"; +/** + * The signing secret is returned in full here and never again outside the reveal + * and rotate endpoints. + */ +export interface CreatedWebhookEndpoint extends WebhookEndpoint { + secret: string; +} + +/** Converts `CreatedWebhookEndpoint` values from (`parse`) and to (`serialize`) their JSON form. */ +export const CreatedWebhookEndpointSerializer = { + parse(json: any, path = "$"): CreatedWebhookEndpoint { + decodeObject(json, path); + return { + ...extraProperties(json, [ + "secret", + "consecutive_failures", + "created_at", + "description", + "disabled", + "disabled_reason", + "event_types", + "headers", + "id", + "last_failure_at", + "last_success_at", + "max_in_flight", + "needs_setup", + "paused_until", + "rate_limit_per_sec", + "updated_at", + "url", + ]), + ...pickProperties(WebhookEndpointSerializer.parse(json, path), [ + "consecutiveFailures", + "createdAt", + "description", + "disabled", + "disabledReason", + "eventTypes", + "headers", + "id", + "lastFailureAt", + "lastSuccessAt", + "maxInFlight", + "needsSetup", + "pausedUntil", + "rateLimitPerSec", + "updatedAt", + "url", + ]), + secret: decodeString(json["secret"], path, "secret"), + }; + }, + + serialize(value: CreatedWebhookEndpoint): any { + return { + ...extraProperties(value, [ + "secret", + "consecutiveFailures", + "createdAt", + "description", + "disabled", + "disabledReason", + "eventTypes", + "headers", + "id", + "lastFailureAt", + "lastSuccessAt", + "maxInFlight", + "needsSetup", + "pausedUntil", + "rateLimitPerSec", + "updatedAt", + "url", + ]), + ...pickProperties(WebhookEndpointSerializer.serialize(value), [ + "consecutive_failures", + "created_at", + "description", + "disabled", + "disabled_reason", + "event_types", + "headers", + "id", + "last_failure_at", + "last_success_at", + "max_in_flight", + "needs_setup", + "paused_until", + "rate_limit_per_sec", + "updated_at", + "url", + ]), + secret: value.secret, + }; + }, +}; diff --git a/src/models/customerCreateRequest.ts b/src/models/customerCreateRequest.ts index 707a8e5..5c2a1f7 100644 --- a/src/models/customerCreateRequest.ts +++ b/src/models/customerCreateRequest.ts @@ -33,13 +33,13 @@ export interface CustomerCreateRequest { * tenant's `CUSTOMER` property definitions. Omit to leave unset. */ customProperties?: unknown | undefined; - customTaxes: CustomTaxRate[]; + customTaxes?: CustomTaxRate[] | undefined; /** `INDIVIDUAL` requires `first_name`, `last_name`, and a billing-address country. */ customerType?: CustomerType | undefined; /** Free-text legal exemption mention surfaced on exempt invoices. */ exemptionReason?: string | null | undefined; firstName?: string | null | undefined; - invoicingEmails: string[]; + invoicingEmails?: string[] | undefined; invoicingEntityId?: InvoicingEntityId | null | undefined; /** * Deprecated: use `preferred_locales`. Applied only when `preferred_locales` is absent. @@ -119,13 +119,16 @@ export const CustomerCreateRequestSerializer = { : json["connected_account_id"], currency: CurrencySerializer.parse(json["currency"], decodePath(path, "currency")), customProperties: json["custom_properties"], - customTaxes: decodeList( - json["custom_taxes"], - path, - "custom_taxes", - (item: any, p: string, i: number) => - CustomTaxRateSerializer.parse(item, decodePath(p, i)) - ), + customTaxes: + json["custom_taxes"] != null + ? decodeList( + json["custom_taxes"], + path, + "custom_taxes", + (item: any, p: string, i: number) => + CustomTaxRateSerializer.parse(item, decodePath(p, i)) + ) + : undefined, customerType: json["customer_type"] != null ? CustomerTypeSerializer.parse( @@ -141,12 +144,15 @@ export const CustomerCreateRequestSerializer = { json["first_name"] != null ? decodeString(json["first_name"], path, "first_name") : json["first_name"], - invoicingEmails: decodeList( - json["invoicing_emails"], - path, - "invoicing_emails", - (item: any, p: string, i: number) => decodeString(item, p, i) - ), + invoicingEmails: + json["invoicing_emails"] != null + ? decodeList( + json["invoicing_emails"], + path, + "invoicing_emails", + (item: any, p: string, i: number) => decodeString(item, p, i) + ) + : undefined, invoicingEntityId: json["invoicing_entity_id"] != null ? InvoicingEntityIdSerializer.parse( @@ -234,9 +240,10 @@ export const CustomerCreateRequestSerializer = { connected_account_id: value.connectedAccountId, currency: CurrencySerializer.serialize(value.currency), custom_properties: value.customProperties, - custom_taxes: value.customTaxes.map((item: any) => - CustomTaxRateSerializer.serialize(item) - ), + custom_taxes: + value.customTaxes != null + ? value.customTaxes.map((item: any) => CustomTaxRateSerializer.serialize(item)) + : undefined, customer_type: value.customerType != null ? CustomerTypeSerializer.serialize(value.customerType) diff --git a/src/models/event.ts b/src/models/event.ts index ee5a2ab..ded0951 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -1,6 +1,6 @@ // this file is @generated import { extraProperties } from "../json.js"; -import { decodeMap, decodeObject, decodeString } from "../decode.js"; +import { decodeDateTime, decodeMap, decodeObject, decodeString } from "../decode.js"; export interface Event { /** Billable metric code. Max 512 characters. */ @@ -15,7 +15,7 @@ export interface Event { * RFC 3339 timestamp. Defaults to ingestion time if omitted. * Must be between 24 hours ago and 1 hour from now. Set `allow_backfilling` to remove the past limit. */ - timestamp: string; + timestamp?: Date | null | undefined; } /** Converts `Event` values from (`parse`) and to (`serialize`) their JSON form. */ @@ -42,7 +42,10 @@ export const EventSerializer = { (entry: any, p: string, key: string) => decodeString(entry, p, key) ) : undefined, - timestamp: decodeString(json["timestamp"], path, "timestamp"), + timestamp: + json["timestamp"] != null + ? decodeDateTime(json["timestamp"], path, "timestamp") + : json["timestamp"], }; }, diff --git a/src/models/index.ts b/src/models/index.ts index ed14775..1072570 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -164,6 +164,10 @@ export type { CreateSubscriptionAddOn } from "./createSubscriptionAddOn.js"; export { CreateSubscriptionAddOnSerializer } from "./createSubscriptionAddOn.js"; export type { CreateSubscriptionComponents } from "./createSubscriptionComponents.js"; export { CreateSubscriptionComponentsSerializer } from "./createSubscriptionComponents.js"; +export type { CreateWebhookEndpointRequest } from "./createWebhookEndpointRequest.js"; +export { CreateWebhookEndpointRequestSerializer } from "./createWebhookEndpointRequest.js"; +export type { CreatedWebhookEndpoint } from "./createdWebhookEndpoint.js"; +export { CreatedWebhookEndpointSerializer } from "./createdWebhookEndpoint.js"; export type { CreditNote } from "./creditNote.js"; export { CreditNoteSerializer } from "./creditNote.js"; export type { CreditNoteCustomPropertiesRequest } from "./creditNoteCustomPropertiesRequest.js"; @@ -670,6 +674,8 @@ export type { UpdateMetricRequest } from "./updateMetricRequest.js"; export { UpdateMetricRequestSerializer } from "./updateMetricRequest.js"; export type { UpdateProductRequest } from "./updateProductRequest.js"; export { UpdateProductRequestSerializer } from "./updateProductRequest.js"; +export type { UpdateWebhookEndpointRequest } from "./updateWebhookEndpointRequest.js"; +export { UpdateWebhookEndpointRequestSerializer } from "./updateWebhookEndpointRequest.js"; export type { UsageFee } from "./usageFee.js"; export { UsageFeeSerializer } from "./usageFee.js"; export type { UsageFeeStructure } from "./usageFeeStructure.js"; @@ -687,3 +693,29 @@ export type { VolumePlanPricing } from "./volumePlanPricing.js"; export { VolumePlanPricingSerializer } from "./volumePlanPricing.js"; export type { VolumePricing } from "./volumePricing.js"; export { VolumePricingSerializer } from "./volumePricing.js"; +export type { WebhookDelivery } from "./webhookDelivery.js"; +export { WebhookDeliverySerializer } from "./webhookDelivery.js"; +export type { WebhookDeliveryId } from "./webhookDeliveryId.js"; +export { WebhookDeliveryIdSerializer } from "./webhookDeliveryId.js"; +export type { WebhookDeliveryListResponse } from "./webhookDeliveryListResponse.js"; +export { WebhookDeliveryListResponseSerializer } from "./webhookDeliveryListResponse.js"; +export { + WebhookDeliveryStatus, + WebhookDeliveryStatusSerializer, +} from "./webhookDeliveryStatus.js"; +export type { WebhookEndpoint } from "./webhookEndpoint.js"; +export { WebhookEndpointSerializer } from "./webhookEndpoint.js"; +export { + WebhookEndpointDisabledReason, + WebhookEndpointDisabledReasonSerializer, +} from "./webhookEndpointDisabledReason.js"; +export type { WebhookEndpointId } from "./webhookEndpointId.js"; +export { WebhookEndpointIdSerializer } from "./webhookEndpointId.js"; +export type { WebhookEndpointListResponse } from "./webhookEndpointListResponse.js"; +export { WebhookEndpointListResponseSerializer } from "./webhookEndpointListResponse.js"; +export type { WebhookEndpointSecret } from "./webhookEndpointSecret.js"; +export { WebhookEndpointSecretSerializer } from "./webhookEndpointSecret.js"; +export type { WebhookHeader } from "./webhookHeader.js"; +export { WebhookHeaderSerializer } from "./webhookHeader.js"; +export type { WebhookHeaderInput } from "./webhookHeaderInput.js"; +export { WebhookHeaderInputSerializer } from "./webhookHeaderInput.js"; diff --git a/src/models/plan.ts b/src/models/plan.ts index 9f08973..fdcfca3 100644 --- a/src/models/plan.ts +++ b/src/models/plan.ts @@ -13,6 +13,7 @@ import { type AvailableParameters, AvailableParametersSerializer, } from "./availableParameters.js"; +import { type Currency, CurrencySerializer } from "./currency.js"; import { type Entitlement, EntitlementSerializer } from "./entitlement.js"; import { type MinimumCommitment, @@ -30,7 +31,7 @@ export interface Plan { availableParameters: AvailableParameters; billingCycles?: number | null | undefined; createdAt: Date; - currency: string; + currency: Currency; description?: string | null | undefined; entitlements?: Entitlement[] | undefined; id: PlanId; @@ -91,7 +92,7 @@ export const PlanSerializer = { ? decodeInteger(json["billing_cycles"], path, "billing_cycles") : json["billing_cycles"], createdAt: decodeDateTime(json["created_at"], path, "created_at"), - currency: decodeString(json["currency"], path, "currency"), + currency: CurrencySerializer.parse(json["currency"], decodePath(path, "currency")), description: json["description"] != null ? decodeString(json["description"], path, "description") @@ -182,7 +183,7 @@ export const PlanSerializer = { ), billing_cycles: value.billingCycles, created_at: value.createdAt, - currency: value.currency, + currency: CurrencySerializer.serialize(value.currency), description: value.description, entitlements: value.entitlements != null diff --git a/src/models/planVersionSummary.ts b/src/models/planVersionSummary.ts index fd98e4c..5b91ca8 100644 --- a/src/models/planVersionSummary.ts +++ b/src/models/planVersionSummary.ts @@ -6,13 +6,13 @@ import { decodeInteger, decodeObject, decodePath, - decodeString, } from "../decode.js"; +import { type Currency, CurrencySerializer } from "./currency.js"; import { type PlanVersionId, PlanVersionIdSerializer } from "./planVersionId.js"; export interface PlanVersionSummary { createdAt: Date; - currency: string; + currency: Currency; id: PlanVersionId; isDraft: boolean; version: number; @@ -25,7 +25,7 @@ export const PlanVersionSummarySerializer = { return { ...extraProperties(json, ["created_at", "currency", "id", "is_draft", "version"]), createdAt: decodeDateTime(json["created_at"], path, "created_at"), - currency: decodeString(json["currency"], path, "currency"), + currency: CurrencySerializer.parse(json["currency"], decodePath(path, "currency")), id: PlanVersionIdSerializer.parse(json["id"], decodePath(path, "id")), isDraft: decodeBoolean(json["is_draft"], path, "is_draft"), version: decodeInteger(json["version"], path, "version"), @@ -36,7 +36,7 @@ export const PlanVersionSummarySerializer = { return { ...extraProperties(value, ["createdAt", "currency", "id", "isDraft", "version"]), created_at: value.createdAt, - currency: value.currency, + currency: CurrencySerializer.serialize(value.currency), id: PlanVersionIdSerializer.serialize(value.id), is_draft: value.isDraft, version: value.version, diff --git a/src/models/updateWebhookEndpointRequest.ts b/src/models/updateWebhookEndpointRequest.ts new file mode 100644 index 0000000..5723452 --- /dev/null +++ b/src/models/updateWebhookEndpointRequest.ts @@ -0,0 +1,99 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { + decodeBoolean, + decodeInteger, + decodeList, + decodeObject, + decodePath, + decodeString, +} from "../decode.js"; +import { + type WebhookHeaderInput, + WebhookHeaderInputSerializer, +} from "./webhookHeaderInput.js"; + +export interface UpdateWebhookEndpointRequest { + /** Omit to leave unchanged; send `null` or an empty string to clear. */ + description?: string | null | undefined; + /** Re-enabling an endpoint also resets its consecutive failure count. */ + disabled?: boolean | null | undefined; + /** Replaces the subscription list. An empty array subscribes to every event type. */ + eventTypes?: string[] | null | undefined; + /** Replaces the custom header list. An empty array removes every header. */ + headers?: WebhookHeaderInput[] | null | undefined; + /** Omit to leave unchanged; send `null` to remove the rate limit. */ + rateLimitPerSec?: number | null | undefined; + url?: string | null | undefined; +} + +/** Converts `UpdateWebhookEndpointRequest` values from (`parse`) and to (`serialize`) their JSON form. */ +export const UpdateWebhookEndpointRequestSerializer = { + parse(json: any, path = "$"): UpdateWebhookEndpointRequest { + decodeObject(json, path); + return { + ...extraProperties(json, [ + "description", + "disabled", + "event_types", + "headers", + "rate_limit_per_sec", + "url", + ]), + description: + json["description"] != null + ? decodeString(json["description"], path, "description") + : json["description"], + disabled: + json["disabled"] != null + ? decodeBoolean(json["disabled"], path, "disabled") + : json["disabled"], + eventTypes: + json["event_types"] != null + ? decodeList( + json["event_types"], + path, + "event_types", + (item: any, p: string, i: number) => decodeString(item, p, i) + ) + : json["event_types"], + headers: + json["headers"] != null + ? decodeList( + json["headers"], + path, + "headers", + (item: any, p: string, i: number) => + WebhookHeaderInputSerializer.parse(item, decodePath(p, i)) + ) + : json["headers"], + rateLimitPerSec: + json["rate_limit_per_sec"] != null + ? decodeInteger(json["rate_limit_per_sec"], path, "rate_limit_per_sec") + : json["rate_limit_per_sec"], + url: json["url"] != null ? decodeString(json["url"], path, "url") : json["url"], + }; + }, + + serialize(value: UpdateWebhookEndpointRequest): any { + return { + ...extraProperties(value, [ + "description", + "disabled", + "eventTypes", + "headers", + "rateLimitPerSec", + "url", + ]), + description: value.description, + disabled: value.disabled, + event_types: value.eventTypes, + headers: + value.headers != null + ? value.headers.map((item: any) => WebhookHeaderInputSerializer.serialize(item)) + : value.headers, + rate_limit_per_sec: value.rateLimitPerSec, + url: value.url, + }; + }, +}; diff --git a/src/models/webhookDelivery.ts b/src/models/webhookDelivery.ts new file mode 100644 index 0000000..5ca527f --- /dev/null +++ b/src/models/webhookDelivery.ts @@ -0,0 +1,126 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { + decodeBoolean, + decodeDateTime, + decodeInteger, + decodeObject, + decodePath, + decodeString, +} from "../decode.js"; +import { type EventId, EventIdSerializer } from "./eventId.js"; +import { + type WebhookDeliveryId, + WebhookDeliveryIdSerializer, +} from "./webhookDeliveryId.js"; +import { + type WebhookDeliveryStatus, + WebhookDeliveryStatusSerializer, +} from "./webhookDeliveryStatus.js"; +import { + type WebhookEndpointId, + WebhookEndpointIdSerializer, +} from "./webhookEndpointId.js"; +/** One event queued for one endpoint, with the state of its retry cycle. */ +export interface WebhookDelivery { + attemptCount: number; + completedAt?: Date | null | undefined; + createdAt: Date; + endpointId: WebhookEndpointId; + eventType: string; + id: WebhookDeliveryId; + lastError?: string | null | undefined; + lastResponseStatus?: number | null | undefined; + /** True when the delivery was created by a resend or a test event. */ + manual: boolean; + messageId: EventId; + nextAttemptAt?: Date | null | undefined; + status: WebhookDeliveryStatus; +} + +/** Converts `WebhookDelivery` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookDeliverySerializer = { + parse(json: any, path = "$"): WebhookDelivery { + decodeObject(json, path); + return { + ...extraProperties(json, [ + "attempt_count", + "completed_at", + "created_at", + "endpoint_id", + "event_type", + "id", + "last_error", + "last_response_status", + "manual", + "message_id", + "next_attempt_at", + "status", + ]), + attemptCount: decodeInteger(json["attempt_count"], path, "attempt_count"), + completedAt: + json["completed_at"] != null + ? decodeDateTime(json["completed_at"], path, "completed_at") + : json["completed_at"], + createdAt: decodeDateTime(json["created_at"], path, "created_at"), + endpointId: WebhookEndpointIdSerializer.parse( + json["endpoint_id"], + decodePath(path, "endpoint_id") + ), + eventType: decodeString(json["event_type"], path, "event_type"), + id: WebhookDeliveryIdSerializer.parse(json["id"], decodePath(path, "id")), + lastError: + json["last_error"] != null + ? decodeString(json["last_error"], path, "last_error") + : json["last_error"], + lastResponseStatus: + json["last_response_status"] != null + ? decodeInteger(json["last_response_status"], path, "last_response_status") + : json["last_response_status"], + manual: decodeBoolean(json["manual"], path, "manual"), + messageId: EventIdSerializer.parse( + json["message_id"], + decodePath(path, "message_id") + ), + nextAttemptAt: + json["next_attempt_at"] != null + ? decodeDateTime(json["next_attempt_at"], path, "next_attempt_at") + : json["next_attempt_at"], + status: WebhookDeliveryStatusSerializer.parse( + json["status"], + decodePath(path, "status") + ), + }; + }, + + serialize(value: WebhookDelivery): any { + return { + ...extraProperties(value, [ + "attemptCount", + "completedAt", + "createdAt", + "endpointId", + "eventType", + "id", + "lastError", + "lastResponseStatus", + "manual", + "messageId", + "nextAttemptAt", + "status", + ]), + attempt_count: value.attemptCount, + completed_at: value.completedAt, + created_at: value.createdAt, + endpoint_id: WebhookEndpointIdSerializer.serialize(value.endpointId), + event_type: value.eventType, + id: WebhookDeliveryIdSerializer.serialize(value.id), + last_error: value.lastError, + last_response_status: value.lastResponseStatus, + manual: value.manual, + message_id: EventIdSerializer.serialize(value.messageId), + next_attempt_at: value.nextAttemptAt, + status: WebhookDeliveryStatusSerializer.serialize(value.status), + }; + }, +}; diff --git a/src/models/webhookDeliveryId.ts b/src/models/webhookDeliveryId.ts new file mode 100644 index 0000000..a5e9c2c --- /dev/null +++ b/src/models/webhookDeliveryId.ts @@ -0,0 +1,15 @@ +// this file is @generated +import { decodeString } from "../decode.js"; + +export type WebhookDeliveryId = string; + +/** Converts `WebhookDeliveryId` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookDeliveryIdSerializer = { + parse(json: any, path = "$"): WebhookDeliveryId { + return decodeString(json, path); + }, + + serialize(value: WebhookDeliveryId): any { + return value; + }, +}; diff --git a/src/models/webhookDeliveryListResponse.ts b/src/models/webhookDeliveryListResponse.ts new file mode 100644 index 0000000..a0ebd44 --- /dev/null +++ b/src/models/webhookDeliveryListResponse.ts @@ -0,0 +1,38 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { decodeList, decodeObject, decodePath } from "../decode.js"; +import { + type PaginationResponse, + PaginationResponseSerializer, +} from "./paginationResponse.js"; +import { type WebhookDelivery, WebhookDeliverySerializer } from "./webhookDelivery.js"; + +export interface WebhookDeliveryListResponse { + data: WebhookDelivery[]; + paginationMeta: PaginationResponse; +} + +/** Converts `WebhookDeliveryListResponse` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookDeliveryListResponseSerializer = { + parse(json: any, path = "$"): WebhookDeliveryListResponse { + decodeObject(json, path); + return { + ...extraProperties(json, ["data", "pagination_meta"]), + data: decodeList(json["data"], path, "data", (item: any, p: string, i: number) => + WebhookDeliverySerializer.parse(item, decodePath(p, i)) + ), + paginationMeta: PaginationResponseSerializer.parse( + json["pagination_meta"], + decodePath(path, "pagination_meta") + ), + }; + }, + + serialize(value: WebhookDeliveryListResponse): any { + return { + ...extraProperties(value, ["data", "paginationMeta"]), + data: value.data.map((item: any) => WebhookDeliverySerializer.serialize(item)), + pagination_meta: PaginationResponseSerializer.serialize(value.paginationMeta), + }; + }, +}; diff --git a/src/models/webhookDeliveryStatus.ts b/src/models/webhookDeliveryStatus.ts new file mode 100644 index 0000000..91f515a --- /dev/null +++ b/src/models/webhookDeliveryStatus.ts @@ -0,0 +1,24 @@ +// this file is @generated +import { decodeString } from "../decode.js"; + +export const WebhookDeliveryStatus = { + Pending: "PENDING", + InFlight: "IN_FLIGHT", + Succeeded: "SUCCEEDED", + Failed: "FAILED", + Cancelled: "CANCELLED", +} as const; +export type WebhookDeliveryStatus = + | (typeof WebhookDeliveryStatus)[keyof typeof WebhookDeliveryStatus] + | (string & {}); + +/** Converts `WebhookDeliveryStatus` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookDeliveryStatusSerializer = { + parse(json: any, path = "$"): WebhookDeliveryStatus { + return decodeString(json, path); + }, + + serialize(value: WebhookDeliveryStatus): any { + return value; + }, +}; diff --git a/src/models/webhookEndpoint.ts b/src/models/webhookEndpoint.ts new file mode 100644 index 0000000..123f4ea --- /dev/null +++ b/src/models/webhookEndpoint.ts @@ -0,0 +1,179 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { + decodeBoolean, + decodeDateTime, + decodeInteger, + decodeList, + decodeObject, + decodePath, + decodeString, +} from "../decode.js"; +import { + type WebhookEndpointDisabledReason, + WebhookEndpointDisabledReasonSerializer, +} from "./webhookEndpointDisabledReason.js"; +import { + type WebhookEndpointId, + WebhookEndpointIdSerializer, +} from "./webhookEndpointId.js"; +import { type WebhookHeader, WebhookHeaderSerializer } from "./webhookHeader.js"; +/** A destination Meteroid POSTs signed event payloads to. */ +export interface WebhookEndpoint { + /** Failures since the last success, reset to 0 on any 2xx. */ + consecutiveFailures: number; + createdAt: Date; + description?: string | null | undefined; + disabled: boolean; + disabledReason?: WebhookEndpointDisabledReason | null | undefined; + /** Subscribed event types. Empty means every event type. */ + eventTypes: string[]; + /** Custom headers sent with every delivery. */ + headers: WebhookHeader[]; + id: WebhookEndpointId; + lastFailureAt?: Date | null | undefined; + lastSuccessAt?: Date | null | undefined; + /** + * How many deliveries this endpoint may have in flight at once. Read-only; it is + * set from the tenant's environment when the endpoint is created. + */ + maxInFlight: number; + /** + * A sensitive header still waits for its value; the endpoint cannot be enabled + * until it is set. + */ + needsSetup: boolean; + /** + * The endpoint was unreachable several times in a row: nothing is sent before + * this time, then it is retried one delivery at a time until it answers again. + */ + pausedUntil?: Date | null | undefined; + /** Deliveries started per second, at most. */ + rateLimitPerSec?: number | null | undefined; + updatedAt?: Date | null | undefined; + url: string; +} + +/** Converts `WebhookEndpoint` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookEndpointSerializer = { + parse(json: any, path = "$"): WebhookEndpoint { + decodeObject(json, path); + return { + ...extraProperties(json, [ + "consecutive_failures", + "created_at", + "description", + "disabled", + "disabled_reason", + "event_types", + "headers", + "id", + "last_failure_at", + "last_success_at", + "max_in_flight", + "needs_setup", + "paused_until", + "rate_limit_per_sec", + "updated_at", + "url", + ]), + consecutiveFailures: decodeInteger( + json["consecutive_failures"], + path, + "consecutive_failures" + ), + createdAt: decodeDateTime(json["created_at"], path, "created_at"), + description: + json["description"] != null + ? decodeString(json["description"], path, "description") + : json["description"], + disabled: decodeBoolean(json["disabled"], path, "disabled"), + disabledReason: + json["disabled_reason"] != null + ? WebhookEndpointDisabledReasonSerializer.parse( + json["disabled_reason"], + decodePath(path, "disabled_reason") + ) + : json["disabled_reason"], + eventTypes: decodeList( + json["event_types"], + path, + "event_types", + (item: any, p: string, i: number) => decodeString(item, p, i) + ), + headers: decodeList( + json["headers"], + path, + "headers", + (item: any, p: string, i: number) => + WebhookHeaderSerializer.parse(item, decodePath(p, i)) + ), + id: WebhookEndpointIdSerializer.parse(json["id"], decodePath(path, "id")), + lastFailureAt: + json["last_failure_at"] != null + ? decodeDateTime(json["last_failure_at"], path, "last_failure_at") + : json["last_failure_at"], + lastSuccessAt: + json["last_success_at"] != null + ? decodeDateTime(json["last_success_at"], path, "last_success_at") + : json["last_success_at"], + maxInFlight: decodeInteger(json["max_in_flight"], path, "max_in_flight"), + needsSetup: decodeBoolean(json["needs_setup"], path, "needs_setup"), + pausedUntil: + json["paused_until"] != null + ? decodeDateTime(json["paused_until"], path, "paused_until") + : json["paused_until"], + rateLimitPerSec: + json["rate_limit_per_sec"] != null + ? decodeInteger(json["rate_limit_per_sec"], path, "rate_limit_per_sec") + : json["rate_limit_per_sec"], + updatedAt: + json["updated_at"] != null + ? decodeDateTime(json["updated_at"], path, "updated_at") + : json["updated_at"], + url: decodeString(json["url"], path, "url"), + }; + }, + + serialize(value: WebhookEndpoint): any { + return { + ...extraProperties(value, [ + "consecutiveFailures", + "createdAt", + "description", + "disabled", + "disabledReason", + "eventTypes", + "headers", + "id", + "lastFailureAt", + "lastSuccessAt", + "maxInFlight", + "needsSetup", + "pausedUntil", + "rateLimitPerSec", + "updatedAt", + "url", + ]), + consecutive_failures: value.consecutiveFailures, + created_at: value.createdAt, + description: value.description, + disabled: value.disabled, + disabled_reason: + value.disabledReason != null + ? WebhookEndpointDisabledReasonSerializer.serialize(value.disabledReason) + : value.disabledReason, + event_types: value.eventTypes, + headers: value.headers.map((item: any) => WebhookHeaderSerializer.serialize(item)), + id: WebhookEndpointIdSerializer.serialize(value.id), + last_failure_at: value.lastFailureAt, + last_success_at: value.lastSuccessAt, + max_in_flight: value.maxInFlight, + needs_setup: value.needsSetup, + paused_until: value.pausedUntil, + rate_limit_per_sec: value.rateLimitPerSec, + updated_at: value.updatedAt, + url: value.url, + }; + }, +}; diff --git a/src/models/webhookEndpointDisabledReason.ts b/src/models/webhookEndpointDisabledReason.ts new file mode 100644 index 0000000..d8d6b8a --- /dev/null +++ b/src/models/webhookEndpointDisabledReason.ts @@ -0,0 +1,22 @@ +// this file is @generated +import { decodeString } from "../decode.js"; + +export const WebhookEndpointDisabledReason = { + Manual: "MANUAL", + AutoFailures: "AUTO_FAILURES", + Gone: "GONE", +} as const; +export type WebhookEndpointDisabledReason = + | (typeof WebhookEndpointDisabledReason)[keyof typeof WebhookEndpointDisabledReason] + | (string & {}); + +/** Converts `WebhookEndpointDisabledReason` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookEndpointDisabledReasonSerializer = { + parse(json: any, path = "$"): WebhookEndpointDisabledReason { + return decodeString(json, path); + }, + + serialize(value: WebhookEndpointDisabledReason): any { + return value; + }, +}; diff --git a/src/models/webhookEndpointId.ts b/src/models/webhookEndpointId.ts new file mode 100644 index 0000000..42cdb3e --- /dev/null +++ b/src/models/webhookEndpointId.ts @@ -0,0 +1,15 @@ +// this file is @generated +import { decodeString } from "../decode.js"; + +export type WebhookEndpointId = string; + +/** Converts `WebhookEndpointId` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookEndpointIdSerializer = { + parse(json: any, path = "$"): WebhookEndpointId { + return decodeString(json, path); + }, + + serialize(value: WebhookEndpointId): any { + return value; + }, +}; diff --git a/src/models/webhookEndpointListResponse.ts b/src/models/webhookEndpointListResponse.ts new file mode 100644 index 0000000..c91c369 --- /dev/null +++ b/src/models/webhookEndpointListResponse.ts @@ -0,0 +1,28 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { decodeList, decodeObject, decodePath } from "../decode.js"; +import { type WebhookEndpoint, WebhookEndpointSerializer } from "./webhookEndpoint.js"; + +export interface WebhookEndpointListResponse { + data: WebhookEndpoint[]; +} + +/** Converts `WebhookEndpointListResponse` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookEndpointListResponseSerializer = { + parse(json: any, path = "$"): WebhookEndpointListResponse { + decodeObject(json, path); + return { + ...extraProperties(json, ["data"]), + data: decodeList(json["data"], path, "data", (item: any, p: string, i: number) => + WebhookEndpointSerializer.parse(item, decodePath(p, i)) + ), + }; + }, + + serialize(value: WebhookEndpointListResponse): any { + return { + ...extraProperties(value, ["data"]), + data: value.data.map((item: any) => WebhookEndpointSerializer.serialize(item)), + }; + }, +}; diff --git a/src/models/webhookEndpointSecret.ts b/src/models/webhookEndpointSecret.ts new file mode 100644 index 0000000..9c09dc6 --- /dev/null +++ b/src/models/webhookEndpointSecret.ts @@ -0,0 +1,25 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { decodeObject, decodeString } from "../decode.js"; + +export interface WebhookEndpointSecret { + secret: string; +} + +/** Converts `WebhookEndpointSecret` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookEndpointSecretSerializer = { + parse(json: any, path = "$"): WebhookEndpointSecret { + decodeObject(json, path); + return { + ...extraProperties(json, ["secret"]), + secret: decodeString(json["secret"], path, "secret"), + }; + }, + + serialize(value: WebhookEndpointSecret): any { + return { + ...extraProperties(value, ["secret"]), + secret: value.secret, + }; + }, +}; diff --git a/src/models/webhookHeader.ts b/src/models/webhookHeader.ts new file mode 100644 index 0000000..d93fedb --- /dev/null +++ b/src/models/webhookHeader.ts @@ -0,0 +1,40 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { decodeBoolean, decodeObject, decodeString } from "../decode.js"; +/** + * A custom header sent with every delivery. A sensitive header never returns its + * value; `set` says whether it has one. + */ +export interface WebhookHeader { + name: string; + sensitive: boolean; + set: boolean; + value?: string | null | undefined; +} + +/** Converts `WebhookHeader` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookHeaderSerializer = { + parse(json: any, path = "$"): WebhookHeader { + decodeObject(json, path); + return { + ...extraProperties(json, ["name", "sensitive", "set", "value"]), + name: decodeString(json["name"], path, "name"), + sensitive: decodeBoolean(json["sensitive"], path, "sensitive"), + set: decodeBoolean(json["set"], path, "set"), + value: + json["value"] != null + ? decodeString(json["value"], path, "value") + : json["value"], + }; + }, + + serialize(value: WebhookHeader): any { + return { + ...extraProperties(value, ["name", "sensitive", "set", "value"]), + name: value.name, + sensitive: value.sensitive, + set: value.set, + value: value.value, + }; + }, +}; diff --git a/src/models/webhookHeaderInput.ts b/src/models/webhookHeaderInput.ts new file mode 100644 index 0000000..4b9a3bc --- /dev/null +++ b/src/models/webhookHeaderInput.ts @@ -0,0 +1,40 @@ +// this file is @generated +import { extraProperties } from "../json.js"; +import { decodeBoolean, decodeObject, decodeString } from "../decode.js"; +/** + * A custom header to send with every delivery. A sensitive header is write-only: + * it is never returned, and on update sending it without a value keeps its value. + */ +export interface WebhookHeaderInput { + name: string; + sensitive?: boolean | undefined; + value?: string | null | undefined; +} + +/** Converts `WebhookHeaderInput` values from (`parse`) and to (`serialize`) their JSON form. */ +export const WebhookHeaderInputSerializer = { + parse(json: any, path = "$"): WebhookHeaderInput { + decodeObject(json, path); + return { + ...extraProperties(json, ["name", "sensitive", "value"]), + name: decodeString(json["name"], path, "name"), + sensitive: + json["sensitive"] != null + ? decodeBoolean(json["sensitive"], path, "sensitive") + : undefined, + value: + json["value"] != null + ? decodeString(json["value"], path, "value") + : json["value"], + }; + }, + + serialize(value: WebhookHeaderInput): any { + return { + ...extraProperties(value, ["name", "sensitive", "value"]), + name: value.name, + sensitive: value.sensitive, + value: value.value, + }; + }, +}; diff --git a/tests/api/customers.test.ts b/tests/api/customers.test.ts index ef57d6c..bfd8e36 100644 --- a/tests/api/customers.test.ts +++ b/tests/api/customers.test.ts @@ -27,11 +27,7 @@ test("customers.create", async () => { body: '{"currency":"ERN","custom_properties":{"key":"value","count":3,"ratio":0.5,"flags":[true,false],"nested":{"ok":true}},"custom_taxes":[{"name":"sample","rate":"sample","tax_code":"sample"}],"id":"customer_id_1","invoicing_emails":["sample"],"invoicing_entity_id":"invoicing_entity_id_83","name":"sample","preferred_locales":["sample"]}', }); await client.customers.create( - CustomerCreateRequestSerializer.parse( - parseJson( - '{"currency":"ERN","custom_taxes":[{"name":"sample","rate":"sample","tax_code":"sample"}],"invoicing_emails":["sample"]}' - ) - ) + CustomerCreateRequestSerializer.parse(parseJson('{"currency":"ERN"}')) ); assert.deepEqual(requests, ["POST /api/v1/customers"]); }); diff --git a/tests/api/events.test.ts b/tests/api/events.test.ts index 7f79045..deb8db7 100644 --- a/tests/api/events.test.ts +++ b/tests/api/events.test.ts @@ -13,7 +13,7 @@ test("events.ingest", async () => { await client.events.ingest( IngestEventsRequestSerializer.parse( parseJson( - '{"events":[{"code":"sample","customer_id":"sample","event_id":"sample","timestamp":"sample"}]}' + '{"events":[{"code":"sample","customer_id":"sample","event_id":"sample"}]}' ) ) ); diff --git a/tests/api/plans.test.ts b/tests/api/plans.test.ts index ff1cf2d..d1fe03e 100644 --- a/tests/api/plans.test.ts +++ b/tests/api/plans.test.ts @@ -41,7 +41,7 @@ test("plans.list", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"data":[{"available_parameters":{},"created_at":"2024-03-15T10:30:45.123+02:00","currency":"sample","id":"plan_id_78","name":"sample","net_terms":-2147483648,"plan_type":"FREE","price_components":[{"id":"price_component_id_82","name":"sample"}],"product_family":{"id":"product_family_id_59","name":"sample"},"status":"INACTIVE","tax_inclusive":true,"version":-2147483648,"version_id":"plan_version_id_92"}],"pagination_meta":{"page":-123456789,"per_page":-123456789,"total_items":-9007199254740993,"total_pages":123456789}}', + body: '{"data":[{"available_parameters":{},"created_at":"2024-03-15T10:30:45.123+02:00","currency":"WST","id":"plan_id_78","name":"sample","net_terms":-2147483648,"plan_type":"FREE","price_components":[{"id":"price_component_id_82","name":"sample"}],"product_family":{"id":"product_family_id_59","name":"sample"},"status":"INACTIVE","tax_inclusive":true,"version":-2147483648,"version_id":"plan_version_id_92"}],"pagination_meta":{"page":-123456789,"per_page":-123456789,"total_items":-9007199254740993,"total_pages":123456789}}', }); await client.plans.list(); assert.deepEqual(requests, ["GET /api/v1/plans"]); @@ -51,7 +51,7 @@ test("plans.create", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', + body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"COP","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', }); await client.plans.create( CreatePlanRequestSerializer.parse( @@ -67,7 +67,7 @@ test("plans.retrieve", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', + body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"COP","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', }); await client.plans.retrieve("plan_id"); assert.deepEqual(requests, ["GET /api/v1/plans/plan_id"]); @@ -77,7 +77,7 @@ test("plans.replace", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', + body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"COP","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', }); await client.plans.replace( "plan_id", @@ -94,7 +94,7 @@ test("plans.update", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', + body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"COP","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', }); await client.plans.update("plan_id", PatchPlanRequestSerializer.parse(parseJson("{}"))); assert.deepEqual(requests, ["PATCH /api/v1/plans/plan_id"]); @@ -114,7 +114,7 @@ test("plans.publish", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', + body: '{"available_parameters":{},"created_at":"2023-12-31T23:59:59.999-05:30","currency":"COP","id":"plan_id_13","name":"sample","net_terms":2147483647,"plan_type":"FREE","price_components":[{"id":"price_component_id_38","name":"sample"}],"product_family":{"id":"product_family_id_66","name":"sample"},"status":"ARCHIVED","tax_inclusive":false,"version":123456789,"version_id":"plan_version_id_84"}', }); await client.plans.publish("plan_id"); assert.deepEqual(requests, ["POST /api/v1/plans/plan_id/publish"]); diff --git a/tests/api/plansVersions.test.ts b/tests/api/plansVersions.test.ts index 10c6666..a2f1609 100644 --- a/tests/api/plansVersions.test.ts +++ b/tests/api/plansVersions.test.ts @@ -33,7 +33,7 @@ test("plans.versions.list", async () => { const { client, requests } = mock({ status: 200, contentType: "application/json", - body: '{"data":[{"created_at":"2023-12-31T23:59:59.999-05:30","currency":"sample","id":"plan_version_id_2","is_draft":true,"version":-2147483648}],"pagination_meta":{"page":-123456789,"per_page":-123456789,"total_items":-9007199254740993,"total_pages":123456789}}', + body: '{"data":[{"created_at":"2023-12-31T23:59:59.999-05:30","currency":"CVE","id":"plan_version_id_2","is_draft":true,"version":-2147483648}],"pagination_meta":{"page":-123456789,"per_page":-123456789,"total_items":-9007199254740993,"total_pages":123456789}}', }); await client.plans.versions.list("plan_id"); assert.deepEqual(requests, ["GET /api/v1/plans/plan_id/versions"]); diff --git a/tests/api/webhookEndpoints.test.ts b/tests/api/webhookEndpoints.test.ts new file mode 100644 index 0000000..2ef6713 --- /dev/null +++ b/tests/api/webhookEndpoints.test.ts @@ -0,0 +1,14 @@ +// this file is @generated +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { mock } from "./mock.js"; + +test("webhook_endpoints.resend_webhook_delivery", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"attempt_count":-2147483648,"created_at":"2023-12-31T23:59:59.999-05:30","endpoint_id":"webhook_endpoint_id_44","event_type":"sample","id":"webhook_delivery_id_90","manual":false,"message_id":"event_id_90","status":"IN_FLIGHT"}', + }); + await client.webhookEndpoints.resendWebhookDelivery("delivery_id"); + assert.deepEqual(requests, ["POST /api/v1/webhooks/deliveries/delivery_id/resend"]); +}); diff --git a/tests/api/webhookEndpointsEndpoints.test.ts b/tests/api/webhookEndpointsEndpoints.test.ts new file mode 100644 index 0000000..3543611 --- /dev/null +++ b/tests/api/webhookEndpointsEndpoints.test.ts @@ -0,0 +1,96 @@ +// this file is @generated +import assert from "node:assert/strict"; +import { test } from "node:test"; +import { + parseJson, + CreateWebhookEndpointRequestSerializer, + UpdateWebhookEndpointRequestSerializer, +} from "../../src/index.js"; +import { mock } from "./mock.js"; + +test("webhook_endpoints.endpoints.list", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"data":[{"consecutive_failures":-123456789,"created_at":"2023-12-31T23:59:59.999-05:30","disabled":true,"event_types":["sample"],"headers":[{"name":"sample","sensitive":false,"set":true}],"id":"webhook_endpoint_id_25","max_in_flight":-2147483648,"needs_setup":false,"url":"sample"}]}', + }); + await client.webhookEndpoints.endpoints.list(); + assert.deepEqual(requests, ["GET /api/v1/webhooks/endpoints"]); +}); + +test("webhook_endpoints.endpoints.create", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"consecutive_failures":-123456789,"created_at":"2023-12-31T23:59:59.999-05:30","disabled":true,"event_types":["sample"],"headers":[{"name":"sample","sensitive":false,"set":true}],"id":"webhook_endpoint_id_25","max_in_flight":-2147483648,"needs_setup":false,"url":"sample","secret":"sample"}', + }); + await client.webhookEndpoints.endpoints.create( + CreateWebhookEndpointRequestSerializer.parse(parseJson('{"url":"sample"}')) + ); + assert.deepEqual(requests, ["POST /api/v1/webhooks/endpoints"]); +}); + +test("webhook_endpoints.endpoints.retrieve", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"consecutive_failures":-2147483648,"created_at":"2024-03-15T10:30:45.123+02:00","disabled":true,"event_types":["sample"],"headers":[{"name":"sample","sensitive":true,"set":true}],"id":"webhook_endpoint_id_40","max_in_flight":-123456789,"needs_setup":true,"url":"sample"}', + }); + await client.webhookEndpoints.endpoints.retrieve("endpoint_id"); + assert.deepEqual(requests, ["GET /api/v1/webhooks/endpoints/endpoint_id"]); +}); + +test("webhook_endpoints.endpoints.delete", async () => { + const { client, requests } = mock({ + status: 204, + contentType: null, + body: "", + }); + await client.webhookEndpoints.endpoints.delete("endpoint_id"); + assert.deepEqual(requests, ["DELETE /api/v1/webhooks/endpoints/endpoint_id"]); +}); + +test("webhook_endpoints.endpoints.update", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"consecutive_failures":-2147483648,"created_at":"2024-03-15T10:30:45.123+02:00","disabled":true,"event_types":["sample"],"headers":[{"name":"sample","sensitive":true,"set":true}],"id":"webhook_endpoint_id_40","max_in_flight":-123456789,"needs_setup":true,"url":"sample"}', + }); + await client.webhookEndpoints.endpoints.update( + "endpoint_id", + UpdateWebhookEndpointRequestSerializer.parse(parseJson("{}")) + ); + assert.deepEqual(requests, ["PATCH /api/v1/webhooks/endpoints/endpoint_id"]); +}); + +test("webhook_endpoints.endpoints.list_deliveries", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"data":[{"attempt_count":-123456789,"created_at":"2024-03-15T10:30:45.123+02:00","endpoint_id":"webhook_endpoint_id_90","event_type":"sample","id":"webhook_delivery_id_0","manual":false,"message_id":"event_id_67","status":"SUCCEEDED"}],"pagination_meta":{"page":-123456789,"per_page":-123456789,"total_items":-9007199254740993,"total_pages":123456789}}', + }); + await client.webhookEndpoints.endpoints.listDeliveries("endpoint_id"); + assert.deepEqual(requests, ["GET /api/v1/webhooks/endpoints/endpoint_id/deliveries"]); +}); + +test("webhook_endpoints.endpoints.rotate_secret", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"secret":"sample"}', + }); + await client.webhookEndpoints.endpoints.rotateSecret("endpoint_id"); + assert.deepEqual(requests, [ + "POST /api/v1/webhooks/endpoints/endpoint_id/rotate-secret", + ]); +}); + +test("webhook_endpoints.endpoints.retrieve_secret", async () => { + const { client, requests } = mock({ + status: 200, + contentType: "application/json", + body: '{"secret":"sample"}', + }); + await client.webhookEndpoints.endpoints.retrieveSecret("endpoint_id"); + assert.deepEqual(requests, ["GET /api/v1/webhooks/endpoints/endpoint_id/secret"]); +});