diff --git a/README.md b/README.md index 6334786..f1cce33 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This library provides convenient access to the Metronome REST API from server-side TypeScript or JavaScript. -The API documentation can be found [here](https://docs.metronome.com). +The REST API documentation can be found [on docs.metronome.com](https://docs.metronome.com). The full API of this library can be found in [api.md](api.md). ## Installation @@ -16,7 +16,7 @@ yarn add @metronome-industries/metronome ## Usage -The full API of this library can be found in [api.md](https://www.github.com/Metronome-Industries/metronome-node/blob/main/api.md). +The full API of this library can be found in [api.md](api.md). ```js @@ -211,8 +211,8 @@ import { fetch } from 'undici'; // as one example import Metronome from '@metronome-industries/metronome'; const client = new Metronome({ - fetch: (url: RequestInfo, init?: RequestInfo): Response => { - console.log('About to make request', url, init); + fetch: async (url: RequestInfo, init?: RequestInfo): Promise => { + console.log('About to make a request', url, init); const response = await fetch(url, init); console.log('Got response', response); return response; diff --git a/api.md b/api.md index 00364ef..d7e02c4 100644 --- a/api.md +++ b/api.md @@ -35,11 +35,12 @@ Types: - CustomerAlert - CustomerAlertRetrieveResponse +- CustomerAlertListResponse Methods: - client.customerAlerts.retrieve({ ...params }) -> CustomerAlertRetrieveResponse -- client.customerAlerts.list({ ...params }) -> CustomerAlertsPage +- client.customerAlerts.list({ ...params }) -> CustomerAlertListResponse # Plans @@ -53,10 +54,10 @@ Types: Methods: -- client.plans.list({ ...params }) -> PlanListResponsesPage +- client.plans.list({ ...params }) -> PlanListResponse - client.plans.getDetails(planId) -> PlanGetDetailsResponse -- client.plans.listCharges(planId, { ...params }) -> PlanListChargesResponsesPage -- client.plans.listCustomers(planId, { ...params }) -> PlanListCustomersResponsesPage +- client.plans.listCharges(planId, { ...params }) -> PlanListChargesResponse +- client.plans.listCustomers(planId, { ...params }) -> PlanListCustomersResponse # Credits @@ -72,8 +73,8 @@ Methods: - client.credits.createGrant({ ...params }) -> CreditCreateGrantResponse - client.credits.editGrant({ ...params }) -> CreditEditGrantResponse -- client.credits.listEntries({ ...params }) -> CreditListEntriesResponsesPage -- client.credits.listGrants({ ...params }) -> CreditListGrantsResponsesPage +- client.credits.listEntries({ ...params }) -> CreditListEntriesResponse +- client.credits.listGrants({ ...params }) -> CreditListGrantsResponse - client.credits.voidGrant({ ...params }) -> CreditVoidGrantResponse # CreditTypes @@ -84,7 +85,7 @@ Types: Methods: -- client.creditTypes.list({ ...params }) -> CreditTypeListResponsesPage +- client.creditTypes.list({ ...params }) -> CreditTypeListResponse # Customers @@ -94,6 +95,7 @@ Types: - CustomerDetail - CustomerCreateResponse - CustomerRetrieveResponse +- CustomerListResponse - CustomerArchiveResponse - CustomerListBillableMetricsResponse - CustomerListCostsResponse @@ -103,10 +105,10 @@ Methods: - client.customers.create({ ...params }) -> CustomerCreateResponse - client.customers.retrieve(customerId) -> CustomerRetrieveResponse -- client.customers.list({ ...params }) -> CustomerDetailsPage +- client.customers.list({ ...params }) -> CustomerListResponse - client.customers.archive({ ...params }) -> CustomerArchiveResponse -- client.customers.listBillableMetrics(customerId, { ...params }) -> CustomerListBillableMetricsResponsesPage -- client.customers.listCosts(customerId, { ...params }) -> CustomerListCostsResponsesPage +- client.customers.listBillableMetrics(customerId, { ...params }) -> CustomerListBillableMetricsResponse +- client.customers.listCosts(customerId, { ...params }) -> CustomerListCostsResponse - client.customers.setIngestAliases(customerId, { ...params }) -> void - client.customers.setName(customerId, { ...params }) -> CustomerSetNameResponse - client.customers.updateConfig(customerId, { ...params }) -> void @@ -122,10 +124,10 @@ Types: Methods: -- client.customers.plans.list(customerId, { ...params }) -> PlanListResponsesPage +- client.customers.plans.list(customerId, { ...params }) -> PlanListResponse - client.customers.plans.add(customerId, { ...params }) -> PlanAddResponse - client.customers.plans.end(customerId, customerPlanId, { ...params }) -> PlanEndResponse -- client.customers.plans.listPriceAdjustments(customerId, customerPlanId, { ...params }) -> PlanListPriceAdjustmentsResponsesPage +- client.customers.plans.listPriceAdjustments(customerId, customerPlanId, { ...params }) -> PlanListPriceAdjustmentsResponse ## Invoices @@ -133,11 +135,12 @@ Types: - Invoice - InvoiceRetrieveResponse +- InvoiceListResponse Methods: - client.customers.invoices.retrieve(customerId, invoiceId) -> InvoiceRetrieveResponse -- client.customers.invoices.list(customerId, { ...params }) -> InvoicesPage +- client.customers.invoices.list(customerId, { ...params }) -> InvoiceListResponse ## BillingConfig @@ -177,8 +180,8 @@ Types: Methods: -- client.usage.list({ ...params }) -> UsageListResponsesPage -- client.usage.listWithGroups({ ...params }) -> UsageListWithGroupsResponsesPage +- client.usage.list({ ...params }) -> UsageListResponse +- client.usage.listWithGroups({ ...params }) -> UsageListWithGroupsResponse # AuditLogs @@ -188,7 +191,7 @@ Types: Methods: -- client.auditLogs.list({ ...params }) -> AuditLogListResponsesPage +- client.auditLogs.list({ ...params }) -> AuditLogListResponse # CustomFields @@ -200,6 +203,6 @@ Methods: - client.customFields.addKey({ ...params }) -> void - client.customFields.deleteValues({ ...params }) -> void -- client.customFields.listKeys({ ...params }) -> CustomFieldListKeysResponsesPage +- client.customFields.listKeys({ ...params }) -> CustomFieldListKeysResponse - client.customFields.removeKey({ ...params }) -> void - client.customFields.setValues({ ...params }) -> void diff --git a/release-please-config.json b/release-please-config.json index 217f18a..624ed99 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -5,6 +5,8 @@ "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", "include-v-in-tag": true, "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": false, "pull-request-header": "Automated Release PR", diff --git a/scripts/fix-index-exports.cjs b/scripts/fix-index-exports.cjs index 0909af7..b61b2ea 100644 --- a/scripts/fix-index-exports.cjs +++ b/scripts/fix-index-exports.cjs @@ -1,7 +1,11 @@ const fs = require('fs'); const path = require('path'); -const indexJs = path.resolve(__dirname, '..', 'dist', 'index.js'); +const indexJs = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH'], 'index.js') + : path.resolve(__dirname, '..', 'dist', 'index.js'); + let before = fs.readFileSync(indexJs, 'utf8'); let after = before.replace( /^\s*exports\.default\s*=\s*(\w+)/m, diff --git a/scripts/make-dist-package-json.cjs b/scripts/make-dist-package-json.cjs index def768e..d4a0a69 100644 --- a/scripts/make-dist-package-json.cjs +++ b/scripts/make-dist-package-json.cjs @@ -1,4 +1,4 @@ -const pkgJson = require('../package.json'); +const pkgJson = require(process.env['PKG_JSON_PATH'] || '../package.json'); function processExportMap(m) { for (const key in m) { diff --git a/scripts/postprocess-files.cjs b/scripts/postprocess-files.cjs index 7915e0c..c8b6b53 100644 --- a/scripts/postprocess-files.cjs +++ b/scripts/postprocess-files.cjs @@ -2,7 +2,12 @@ const fs = require('fs'); const path = require('path'); const { parse } = require('@typescript-eslint/parser'); -const distDir = path.resolve(__dirname, '..', 'dist'); +const pkgImportPath = process.env['PKG_IMPORT_PATH'] ?? '@metronome-industries/metronome/' + +const distDir = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH']) + : path.resolve(__dirname, '..', 'dist'); const distSrcDir = path.join(distDir, 'src'); /** @@ -105,11 +110,11 @@ async function postprocess() { let transformed = mapModulePaths(code, (importPath) => { if (file.startsWith(distSrcDir)) { - if (importPath.startsWith('@metronome-industries/metronome/')) { + if (importPath.startsWith(pkgImportPath)) { // convert self-references in dist/src to relative paths let relativePath = path.relative( path.dirname(file), - path.join(distSrcDir, importPath.substring('@metronome-industries/metronome/'.length)), + path.join(distSrcDir, importPath.substring(pkgImportPath.length)), ); if (!relativePath.startsWith('.')) relativePath = `./${relativePath}`; return relativePath; diff --git a/src/core.ts b/src/core.ts index 230c8fc..3c38fbf 100644 --- a/src/core.ts +++ b/src/core.ts @@ -333,6 +333,11 @@ export abstract class APIClient { return reqHeaders; } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + */ + protected async prepareOptions(options: FinalRequestOptions): Promise {} + /** * Used as a callback for mutating the given `RequestInit` object. * @@ -378,6 +383,8 @@ export abstract class APIClient { retriesRemaining = options.maxRetries ?? this.maxRetries; } + await this.prepareOptions(options); + const { req, url, timeout } = this.buildRequest(options); await this.prepareRequest(req, { url, options }); @@ -408,14 +415,17 @@ export abstract class APIClient { if (!response.ok) { if (retriesRemaining && this.shouldRetry(response)) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders); return this.retryRequest(options, retriesRemaining, responseHeaders); } const errText = await response.text().catch((e) => castToError(e).message); const errJSON = safeJSON(errText); const errMessage = errJSON ? undefined : errText; + const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)`; - debug('response', response.status, url, responseHeaders, errMessage); + debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders, errMessage); const err = this.makeStatusError(response.status, errJSON, errMessage, responseHeaders); throw err; @@ -443,8 +453,8 @@ export abstract class APIClient { query = { ...defaultQuery, ...query } as Req; } - if (query) { - url.search = this.stringifyQuery(query); + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query as Record); } return url.toString(); @@ -520,11 +530,21 @@ export abstract class APIClient { retriesRemaining: number, responseHeaders?: Headers | undefined, ): Promise { - // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After let timeoutMillis: number | undefined; + + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders?.['retry-after-ms']; + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After const retryAfterHeader = responseHeaders?.['retry-after']; - if (retryAfterHeader) { - const timeoutSeconds = parseInt(retryAfterHeader); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); if (!Number.isNaN(timeoutSeconds)) { timeoutMillis = timeoutSeconds * 1000; } else { @@ -534,12 +554,7 @@ export abstract class APIClient { // If the API asks us to wait a certain amount of time (and it's a reasonable amount), // just do what it says, but otherwise calculate a default - if ( - !timeoutMillis || - !Number.isInteger(timeoutMillis) || - timeoutMillis <= 0 || - timeoutMillis > 60 * 1000 - ) { + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { const maxRetries = options.maxRetries ?? this.maxRetries; timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); } @@ -708,7 +723,7 @@ export type RequestOptions | Readable> = method?: HTTPMethod; path?: string; query?: Req | undefined; - body?: Req | undefined; + body?: Req | null | undefined; headers?: Headers | undefined; maxRetries?: number; @@ -1122,3 +1137,7 @@ export const toBase64 = (str: string | null | undefined): string => { throw new MetronomeError('Cannot generate b64 string; Expected `Buffer` or `btoa` to be defined'); }; + +export function isObj(obj: unknown): obj is Record { + return obj != null && typeof obj === 'object' && !Array.isArray(obj); +} diff --git a/src/index.ts b/src/index.ts index eef583a..6c46f65 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec by Stainless. import * as Core from './core'; -import * as Pagination from './pagination'; import * as Errors from './error'; import { type Agent } from './_shims/index'; import * as Uploads from './uploads'; @@ -13,12 +12,12 @@ export interface ClientOptions { /** * Defaults to process.env['METRONOME_BEARER_TOKEN']. */ - bearerToken?: string; + bearerToken?: string | undefined; /** * Defaults to process.env['METRONOME_WEBHOOK_SECRET']. */ - webhookSecret?: string | null; + webhookSecret?: string | null | undefined; /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" @@ -87,8 +86,8 @@ export class Metronome extends Core.APIClient { /** * API Client for interfacing with the Metronome API. * - * @param {string} [opts.bearerToken=process.env['METRONOME_BEARER_TOKEN'] ?? undefined] - * @param {string | null} [opts.webhookSecret=process.env['METRONOME_WEBHOOK_SECRET'] ?? null] + * @param {string | undefined} [opts.bearerToken=process.env['METRONOME_BEARER_TOKEN'] ?? undefined] + * @param {string | null | undefined} [opts.webhookSecret=process.env['METRONOME_WEBHOOK_SECRET'] ?? null] * @param {string} [opts.baseURL=process.env['METRONOME_BASE_URL'] ?? https://api.metronome.com/v1] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections. @@ -149,7 +148,7 @@ export class Metronome extends Core.APIClient { * to learn more about usage events. */ ingest(body: TopLevelAPI.IngestParams, options?: Core.RequestOptions): Core.APIPromise { - return this.post('/ingest', { body, ...options, headers: { Accept: '', ...options?.headers } }); + return this.post('/ingest', { body, ...options, headers: { Accept: '*/*', ...options?.headers } }); } protected override defaultQuery(): Core.DefaultQuery | undefined { @@ -214,10 +213,6 @@ export namespace Metronome { export import RequestOptions = Core.RequestOptions; - export import Page = Pagination.Page; - export import PageParams = Pagination.PageParams; - export import PageResponse = Pagination.PageResponse; - export import IngestParams = API.IngestParams; export import Alerts = API.Alerts; @@ -229,7 +224,7 @@ export namespace Metronome { export import CustomerAlerts = API.CustomerAlerts; export import CustomerAlert = API.CustomerAlert; export import CustomerAlertRetrieveResponse = API.CustomerAlertRetrieveResponse; - export import CustomerAlertsPage = API.CustomerAlertsPage; + export import CustomerAlertListResponse = API.CustomerAlertListResponse; export import CustomerAlertRetrieveParams = API.CustomerAlertRetrieveParams; export import CustomerAlertListParams = API.CustomerAlertListParams; @@ -239,9 +234,6 @@ export namespace Metronome { export import PlanGetDetailsResponse = API.PlanGetDetailsResponse; export import PlanListChargesResponse = API.PlanListChargesResponse; export import PlanListCustomersResponse = API.PlanListCustomersResponse; - export import PlanListResponsesPage = API.PlanListResponsesPage; - export import PlanListChargesResponsesPage = API.PlanListChargesResponsesPage; - export import PlanListCustomersResponsesPage = API.PlanListCustomersResponsesPage; export import PlanListParams = API.PlanListParams; export import PlanListChargesParams = API.PlanListChargesParams; export import PlanListCustomersParams = API.PlanListCustomersParams; @@ -252,8 +244,6 @@ export namespace Metronome { export import CreditListEntriesResponse = API.CreditListEntriesResponse; export import CreditListGrantsResponse = API.CreditListGrantsResponse; export import CreditVoidGrantResponse = API.CreditVoidGrantResponse; - export import CreditListEntriesResponsesPage = API.CreditListEntriesResponsesPage; - export import CreditListGrantsResponsesPage = API.CreditListGrantsResponsesPage; export import CreditCreateGrantParams = API.CreditCreateGrantParams; export import CreditEditGrantParams = API.CreditEditGrantParams; export import CreditListEntriesParams = API.CreditListEntriesParams; @@ -262,7 +252,6 @@ export namespace Metronome { export import CreditTypes = API.CreditTypes; export import CreditTypeListResponse = API.CreditTypeListResponse; - export import CreditTypeListResponsesPage = API.CreditTypeListResponsesPage; export import CreditTypeListParams = API.CreditTypeListParams; export import Customers = API.Customers; @@ -270,13 +259,11 @@ export namespace Metronome { export import CustomerDetail = API.CustomerDetail; export import CustomerCreateResponse = API.CustomerCreateResponse; export import CustomerRetrieveResponse = API.CustomerRetrieveResponse; + export import CustomerListResponse = API.CustomerListResponse; export import CustomerArchiveResponse = API.CustomerArchiveResponse; export import CustomerListBillableMetricsResponse = API.CustomerListBillableMetricsResponse; export import CustomerListCostsResponse = API.CustomerListCostsResponse; export import CustomerSetNameResponse = API.CustomerSetNameResponse; - export import CustomerDetailsPage = API.CustomerDetailsPage; - export import CustomerListBillableMetricsResponsesPage = API.CustomerListBillableMetricsResponsesPage; - export import CustomerListCostsResponsesPage = API.CustomerListCostsResponsesPage; export import CustomerCreateParams = API.CustomerCreateParams; export import CustomerListParams = API.CustomerListParams; export import CustomerArchiveParams = API.CustomerArchiveParams; @@ -295,19 +282,15 @@ export namespace Metronome { export import Usage = API.Usage; export import UsageListResponse = API.UsageListResponse; export import UsageListWithGroupsResponse = API.UsageListWithGroupsResponse; - export import UsageListResponsesPage = API.UsageListResponsesPage; - export import UsageListWithGroupsResponsesPage = API.UsageListWithGroupsResponsesPage; export import UsageListParams = API.UsageListParams; export import UsageListWithGroupsParams = API.UsageListWithGroupsParams; export import AuditLogs = API.AuditLogs; export import AuditLogListResponse = API.AuditLogListResponse; - export import AuditLogListResponsesPage = API.AuditLogListResponsesPage; export import AuditLogListParams = API.AuditLogListParams; export import CustomFields = API.CustomFields; export import CustomFieldListKeysResponse = API.CustomFieldListKeysResponse; - export import CustomFieldListKeysResponsesPage = API.CustomFieldListKeysResponsesPage; export import CustomFieldAddKeyParams = API.CustomFieldAddKeyParams; export import CustomFieldDeleteValuesParams = API.CustomFieldDeleteValuesParams; export import CustomFieldListKeysParams = API.CustomFieldListKeysParams; diff --git a/src/pagination.ts b/src/pagination.ts deleted file mode 100644 index 487a808..0000000 --- a/src/pagination.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -import { AbstractPage, Response, APIClient, FinalRequestOptions, PageInfo } from './core'; - -export interface PageResponse { - data: Array; - - next_page: string | null; -} - -export interface PageParams { - /** - * Cursor that indicates where the next page of results should start. - */ - next_page?: string; -} - -export class Page extends AbstractPage implements PageResponse { - data: Array; - - next_page: string | null; - - constructor(client: APIClient, response: Response, body: PageResponse, options: FinalRequestOptions) { - super(client, response, body, options); - - this.data = body.data; - this.next_page = body.next_page; - } - - getPaginatedItems(): Item[] { - return this.data; - } - - // @deprecated Please use `nextPageInfo()` instead - nextPageParams(): Partial | null { - const info = this.nextPageInfo(); - if (!info) return null; - if ('params' in info) return info.params; - const params = Object.fromEntries(info.url.searchParams); - if (!Object.keys(params).length) return null; - return params; - } - - nextPageInfo(): PageInfo | null { - if (!this.next_page) return null; - - return { params: { next_page: this.next_page } }; - } -} diff --git a/src/resources/alerts.ts b/src/resources/alerts.ts index 8ff8592..ded6dcb 100644 --- a/src/resources/alerts.ts +++ b/src/resources/alerts.ts @@ -3,7 +3,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import * as AlertsAPI from '@metronome-industries/metronome/resources/alerts'; -import * as Shared from '@metronome-industries/metronome/resources/shared'; export class Alerts extends APIResource { /** @@ -22,11 +21,23 @@ export class Alerts extends APIResource { } export interface AlertCreateResponse { - data: Shared.ID; + data: AlertCreateResponse.Data; +} + +export namespace AlertCreateResponse { + export interface Data { + id: string; + } } export interface AlertArchiveResponse { - data: Shared.ID; + data: AlertArchiveResponse.Data; +} + +export namespace AlertArchiveResponse { + export interface Data { + id: string; + } } export interface AlertCreateParams { diff --git a/src/resources/audit-logs.ts b/src/resources/audit-logs.ts index ff60cef..facd8e5 100644 --- a/src/resources/audit-logs.ts +++ b/src/resources/audit-logs.ts @@ -4,7 +4,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as AuditLogsAPI from '@metronome-industries/metronome/resources/audit-logs'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class AuditLogs extends APIResource { /** @@ -13,56 +12,64 @@ export class AuditLogs extends APIResource { * subsequent requests using the same next_page value will be in the returned data * array, ensuring a continuous and uninterrupted reading of audit logs. */ - list( - query?: AuditLogListParams, - options?: Core.RequestOptions, - ): Core.PagePromise; - list(options?: Core.RequestOptions): Core.PagePromise; + list(query?: AuditLogListParams, options?: Core.RequestOptions): Core.APIPromise; + list(options?: Core.RequestOptions): Core.APIPromise; list( query: AuditLogListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list({}, query); } - return this._client.getAPIList('/auditLogs', AuditLogListResponsesPage, { query, ...options }); + return this._client.get('/auditLogs', { query, ...options }); } } -export class AuditLogListResponsesPage extends Page {} - export interface AuditLogListResponse { - id: string; + data: Array; - timestamp: string; + next_page: string | null; +} - action?: string; +export namespace AuditLogListResponse { + export interface Data { + id: string; - actor?: AuditLogListResponse.Actor; + timestamp: string; - resource_id?: string; + action?: string; - resource_type?: string; + actor?: Data.Actor; - status?: 'success' | 'failure' | 'pending'; -} + resource_id?: string; -export namespace AuditLogListResponse { - export interface Actor { - id: string; + resource_type?: string; + + status?: 'success' | 'failure' | 'pending'; + } + + export namespace Data { + export interface Actor { + id: string; - name: string; + name: string; - email?: string; + email?: string; + } } } -export interface AuditLogListParams extends PageParams { +export interface AuditLogListParams { /** * Max number of results that should be returned */ limit?: number; + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * RFC 3339 timestamp of the earliest audit log to return. Cannot be used with * 'next_page'. @@ -72,6 +79,5 @@ export interface AuditLogListParams extends PageParams { export namespace AuditLogs { export import AuditLogListResponse = AuditLogsAPI.AuditLogListResponse; - export import AuditLogListResponsesPage = AuditLogsAPI.AuditLogListResponsesPage; export import AuditLogListParams = AuditLogsAPI.AuditLogListParams; } diff --git a/src/resources/credit-types.ts b/src/resources/credit-types.ts index 264907e..344a3e0 100644 --- a/src/resources/credit-types.ts +++ b/src/resources/credit-types.ts @@ -4,47 +4,53 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as CreditTypesAPI from '@metronome-industries/metronome/resources/credit-types'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class CreditTypes extends APIResource { /** * List all pricing units (known in the API by the legacy term "credit types"). */ - list( - query?: CreditTypeListParams, - options?: Core.RequestOptions, - ): Core.PagePromise; - list(options?: Core.RequestOptions): Core.PagePromise; + list(query?: CreditTypeListParams, options?: Core.RequestOptions): Core.APIPromise; + list(options?: Core.RequestOptions): Core.APIPromise; list( query: CreditTypeListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list({}, query); } - return this._client.getAPIList('/credit-types/list', CreditTypeListResponsesPage, { query, ...options }); + return this._client.get('/credit-types/list', { query, ...options }); } } -export class CreditTypeListResponsesPage extends Page {} - export interface CreditTypeListResponse { - id?: string; + data: Array; + + next_page: string | null; +} - is_currency?: boolean; +export namespace CreditTypeListResponse { + export interface Data { + id?: string; - name?: string; + is_currency?: boolean; + + name?: string; + } } -export interface CreditTypeListParams extends PageParams { +export interface CreditTypeListParams { /** * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } export namespace CreditTypes { export import CreditTypeListResponse = CreditTypesAPI.CreditTypeListResponse; - export import CreditTypeListResponsesPage = CreditTypesAPI.CreditTypeListResponsesPage; export import CreditTypeListParams = CreditTypesAPI.CreditTypeListParams; } diff --git a/src/resources/credits.ts b/src/resources/credits.ts index ad4aa26..9b65d76 100644 --- a/src/resources/credits.ts +++ b/src/resources/credits.ts @@ -4,8 +4,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as CreditsAPI from '@metronome-industries/metronome/resources/credits'; -import * as Shared from '@metronome-industries/metronome/resources/shared'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Credits extends APIResource { /** @@ -36,24 +34,17 @@ export class Credits extends APIResource { listEntries( params?: CreditListEntriesParams, options?: Core.RequestOptions, - ): Core.PagePromise; - listEntries( - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + listEntries(options?: Core.RequestOptions): Core.APIPromise; listEntries( params: CreditListEntriesParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(params)) { return this.listEntries({}, params); } const { next_page, ...body } = params; - return this._client.getAPIList('/credits/listEntries', CreditListEntriesResponsesPage, { - query: { next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/credits/listEntries', { query: { next_page }, body, ...options }); } /** @@ -62,24 +53,17 @@ export class Credits extends APIResource { listGrants( params?: CreditListGrantsParams, options?: Core.RequestOptions, - ): Core.PagePromise; - listGrants( - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + listGrants(options?: Core.RequestOptions): Core.APIPromise; listGrants( params: CreditListGrantsParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(params)) { return this.listGrants({}, params); } const { next_page, ...body } = params; - return this._client.getAPIList('/credits/listGrants', CreditListGrantsResponsesPage, { - query: { next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/credits/listGrants', { query: { next_page }, body, ...options }); } /** @@ -93,72 +77,264 @@ export class Credits extends APIResource { } } -export class CreditListEntriesResponsesPage extends Page {} - -export class CreditListGrantsResponsesPage extends Page {} - export interface CreditCreateGrantResponse { - data: Shared.ID; + data: CreditCreateGrantResponse.Data; +} + +export namespace CreditCreateGrantResponse { + export interface Data { + id: string; + } } export interface CreditEditGrantResponse { - data: Shared.ID; + data: CreditEditGrantResponse.Data; +} + +export namespace CreditEditGrantResponse { + export interface Data { + id: string; + } } export interface CreditListEntriesResponse { - customer_id: string; + data: Array; - ledgers: Array; + next_page: string | null; } export namespace CreditListEntriesResponse { - export interface Ledger { - credit_type: Ledger.CreditType; + export interface Data { + customer_id: string; + ledgers: Array; + } + + export namespace Data { + export interface Ledger { + credit_type: Ledger.CreditType; + + /** + * the effective balances at the end of the specified time window + */ + ending_balance: Ledger.EndingBalance; + + entries: Array; + + pending_entries: Array; + + starting_balance: Ledger.StartingBalance; + } + + export namespace Ledger { + export interface CreditType { + id: string; + + name: string; + } + + /** + * the effective balances at the end of the specified time window + */ + export interface EndingBalance { + /** + * the ending_before request parameter (if supplied) or the current billing + * period's end date + */ + effective_at: string; + + /** + * the ending balance, including the balance of all grants that have not expired + * before the effective_at date and deductions that happened before the + * effective_at date + */ + excluding_pending: number; + + /** + * the excluding_pending balance plus any pending invoice deductions and + * expirations that will happen by the effective_at date + */ + including_pending: number; + } + + export interface Entry { + /** + * an amount representing the change to the customer's credit balance + */ + amount: number; + + created_by: string; + + /** + * the credit grant this entry is related to + */ + credit_grant_id: string; + + effective_at: string; + + reason: string; + + /** + * the running balance for this credit type at the time of the ledger entry, + * including all preceding charges + */ + running_balance: number; + + /** + * if this entry is a deduction, the Metronome ID of the invoice where the credit + * deduction was consumed; if this entry is a grant, the Metronome ID of the + * invoice where the grant's paid_amount was charged + */ + invoice_id?: string | null; + } + + export interface PendingEntry { + /** + * an amount representing the change to the customer's credit balance + */ + amount: number; + + created_by: string; + + /** + * the credit grant this entry is related to + */ + credit_grant_id: string; + + effective_at: string; + + reason: string; + + /** + * the running balance for this credit type at the time of the ledger entry, + * including all preceding charges + */ + running_balance: number; + + /** + * if this entry is a deduction, the Metronome ID of the invoice where the credit + * deduction was consumed; if this entry is a grant, the Metronome ID of the + * invoice where the grant's paid_amount was charged + */ + invoice_id?: string | null; + } + + export interface StartingBalance { + /** + * the starting_on request parameter (if supplied) or the first credit grant's + * effective_at date + */ + effective_at: string; + + /** + * the starting balance, including all posted grants, deductions, and expirations + * that happened at or before the effective_at timestamp + */ + excluding_pending: number; + + /** + * the excluding_pending balance plus any pending activity that has not been posted + * at the time of the query + */ + including_pending: number; + } + } + } +} + +export interface CreditListGrantsResponse { + data: Array; + + next_page: string | null; +} + +export namespace CreditListGrantsResponse { + export interface Data { /** - * the effective balances at the end of the specified time window + * the Metronome ID of the credit grant */ - ending_balance: Ledger.EndingBalance; + id: string; - entries: Array; + /** + * The effective balance of the grant as of the end of the customer's current + * billing period. Expiration deductions will be included only if the grant expires + * before the end of the current billing period. + */ + balance: Data.Balance; - pending_entries: Array; + custom_fields: Record; - starting_balance: Ledger.StartingBalance; - } + /** + * the Metronome ID of the customer + */ + customer_id: string; - export namespace Ledger { - export interface CreditType { - id: string; + deductions: Array; - name: string; - } + effective_at: string; + + expires_at: string; + + /** + * the amount of credits initially granted + */ + grant_amount: Data.GrantAmount; + + name: string; + + /** + * the amount paid for this credit grant + */ + paid_amount: Data.PaidAmount; + + pending_deductions: Array; + + priority: number; + + credit_grant_type?: string | null; + + /** + * the Metronome ID of the invoice with the purchase charge for this credit grant, + * if applicable + */ + invoice_id?: string | null; + + /** + * The products which these credits will be applied to. (If unspecified, the + * credits will be applied to charges for all products.) + */ + products?: Array; + + reason?: string | null; + } + export namespace Data { /** - * the effective balances at the end of the specified time window + * The effective balance of the grant as of the end of the customer's current + * billing period. Expiration deductions will be included only if the grant expires + * before the end of the current billing period. */ - export interface EndingBalance { + export interface Balance { /** - * the ending_before request parameter (if supplied) or the current billing - * period's end date + * The end_date of the customer's current billing period. */ effective_at: string; /** - * the ending balance, including the balance of all grants that have not expired - * before the effective_at date and deductions that happened before the - * effective_at date + * The grant's current balance including all posted deductions. If the grant has + * expired, this amount will be 0. */ excluding_pending: number; /** - * the excluding_pending balance plus any pending invoice deductions and - * expirations that will happen by the effective_at date + * The grant's current balance including all posted and pending deductions. If the + * grant expires before the end of the customer's current billing period, this + * amount will be 0. */ including_pending: number; } - export interface Entry { + export interface Deduction { /** * an amount representing the change to the customer's credit balance */ @@ -189,7 +365,53 @@ export namespace CreditListEntriesResponse { invoice_id?: string | null; } - export interface PendingEntry { + /** + * the amount of credits initially granted + */ + export interface GrantAmount { + amount: number; + + /** + * the credit type for the amount granted + */ + credit_type: GrantAmount.CreditType; + } + + export namespace GrantAmount { + /** + * the credit type for the amount granted + */ + export interface CreditType { + id: string; + + name: string; + } + } + + /** + * the amount paid for this credit grant + */ + export interface PaidAmount { + amount: number; + + /** + * the credit type for the amount paid + */ + credit_type: PaidAmount.CreditType; + } + + export namespace PaidAmount { + /** + * the credit type for the amount paid + */ + export interface CreditType { + id: string; + + name: string; + } + } + + export interface PendingDeduction { /** * an amount representing the change to the customer's credit balance */ @@ -220,232 +442,24 @@ export namespace CreditListEntriesResponse { invoice_id?: string | null; } - export interface StartingBalance { - /** - * the starting_on request parameter (if supplied) or the first credit grant's - * effective_at date - */ - effective_at: string; - - /** - * the starting balance, including all posted grants, deductions, and expirations - * that happened at or before the effective_at timestamp - */ - excluding_pending: number; - - /** - * the excluding_pending balance plus any pending activity that has not been posted - * at the time of the query - */ - including_pending: number; - } - } -} - -export interface CreditListGrantsResponse { - /** - * the Metronome ID of the credit grant - */ - id: string; - - /** - * The effective balance of the grant as of the end of the customer's current - * billing period. Expiration deductions will be included only if the grant expires - * before the end of the current billing period. - */ - balance: CreditListGrantsResponse.Balance; - - custom_fields: Record; - - /** - * the Metronome ID of the customer - */ - customer_id: string; - - deductions: Array; - - effective_at: string; - - expires_at: string; - - /** - * the amount of credits initially granted - */ - grant_amount: CreditListGrantsResponse.GrantAmount; - - name: string; - - /** - * the amount paid for this credit grant - */ - paid_amount: CreditListGrantsResponse.PaidAmount; - - pending_deductions: Array; - - priority: number; - - credit_grant_type?: string | null; - - /** - * the Metronome ID of the invoice with the purchase charge for this credit grant, - * if applicable - */ - invoice_id?: string | null; - - /** - * The products which these credits will be applied to. (If unspecified, the - * credits will be applied to charges for all products.) - */ - products?: Array; - - reason?: string | null; -} - -export namespace CreditListGrantsResponse { - /** - * The effective balance of the grant as of the end of the customer's current - * billing period. Expiration deductions will be included only if the grant expires - * before the end of the current billing period. - */ - export interface Balance { - /** - * The end_date of the customer's current billing period. - */ - effective_at: string; - - /** - * The grant's current balance including all posted deductions. If the grant has - * expired, this amount will be 0. - */ - excluding_pending: number; - - /** - * The grant's current balance including all posted and pending deductions. If the - * grant expires before the end of the customer's current billing period, this - * amount will be 0. - */ - including_pending: number; - } - - export interface Deduction { - /** - * an amount representing the change to the customer's credit balance - */ - amount: number; - - created_by: string; - - /** - * the credit grant this entry is related to - */ - credit_grant_id: string; - - effective_at: string; - - reason: string; - - /** - * the running balance for this credit type at the time of the ledger entry, - * including all preceding charges - */ - running_balance: number; - - /** - * if this entry is a deduction, the Metronome ID of the invoice where the credit - * deduction was consumed; if this entry is a grant, the Metronome ID of the - * invoice where the grant's paid_amount was charged - */ - invoice_id?: string | null; - } - - /** - * the amount of credits initially granted - */ - export interface GrantAmount { - amount: number; - - /** - * the credit type for the amount granted - */ - credit_type: GrantAmount.CreditType; - } - - export namespace GrantAmount { - /** - * the credit type for the amount granted - */ - export interface CreditType { - id: string; - - name: string; - } - } - - /** - * the amount paid for this credit grant - */ - export interface PaidAmount { - amount: number; - - /** - * the credit type for the amount paid - */ - credit_type: PaidAmount.CreditType; - } - - export namespace PaidAmount { - /** - * the credit type for the amount paid - */ - export interface CreditType { + export interface Product { id: string; name: string; } } +} - export interface PendingDeduction { - /** - * an amount representing the change to the customer's credit balance - */ - amount: number; - - created_by: string; - - /** - * the credit grant this entry is related to - */ - credit_grant_id: string; - - effective_at: string; - - reason: string; - - /** - * the running balance for this credit type at the time of the ledger entry, - * including all preceding charges - */ - running_balance: number; - - /** - * if this entry is a deduction, the Metronome ID of the invoice where the credit - * deduction was consumed; if this entry is a grant, the Metronome ID of the - * invoice where the grant's paid_amount was charged - */ - invoice_id?: string | null; - } +export interface CreditVoidGrantResponse { + data: CreditVoidGrantResponse.Data; +} - export interface Product { +export namespace CreditVoidGrantResponse { + export interface Data { id: string; - - name: string; } } -export interface CreditVoidGrantResponse { - data: Shared.ID; -} - export interface CreditCreateGrantParams { /** * the Metronome ID of the customer @@ -536,7 +550,12 @@ export interface CreditEditGrantParams { name?: string; } -export interface CreditListEntriesParams extends PageParams { +export interface CreditListEntriesParams { + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: A list of Metronome credit type IDs to fetch ledger entries for. If * absent, ledger entries for all credit types will be returned. @@ -564,7 +583,12 @@ export interface CreditListEntriesParams extends PageParams { starting_on?: string; } -export interface CreditListGrantsParams extends PageParams { +export interface CreditListGrantsParams { + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: An array of credit grant IDs. If this is specified, neither * credit_type_ids nor customer_ids may be specified. @@ -605,8 +629,6 @@ export namespace Credits { export import CreditListEntriesResponse = CreditsAPI.CreditListEntriesResponse; export import CreditListGrantsResponse = CreditsAPI.CreditListGrantsResponse; export import CreditVoidGrantResponse = CreditsAPI.CreditVoidGrantResponse; - export import CreditListEntriesResponsesPage = CreditsAPI.CreditListEntriesResponsesPage; - export import CreditListGrantsResponsesPage = CreditsAPI.CreditListGrantsResponsesPage; export import CreditCreateGrantParams = CreditsAPI.CreditCreateGrantParams; export import CreditEditGrantParams = CreditsAPI.CreditEditGrantParams; export import CreditListEntriesParams = CreditsAPI.CreditListEntriesParams; diff --git a/src/resources/custom-fields.ts b/src/resources/custom-fields.ts index 5908844..eeba78f 100644 --- a/src/resources/custom-fields.ts +++ b/src/resources/custom-fields.ts @@ -4,7 +4,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as CustomFieldsAPI from '@metronome-industries/metronome/resources/custom-fields'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class CustomFields extends APIResource { /** @@ -15,7 +14,7 @@ export class CustomFields extends APIResource { return this._client.post('/customFields/addKey', { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } @@ -26,7 +25,7 @@ export class CustomFields extends APIResource { return this._client.post('/customFields/deleteValues', { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } @@ -36,24 +35,17 @@ export class CustomFields extends APIResource { listKeys( params?: CustomFieldListKeysParams, options?: Core.RequestOptions, - ): Core.PagePromise; - listKeys( - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + listKeys(options?: Core.RequestOptions): Core.APIPromise; listKeys( params: CustomFieldListKeysParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(params)) { return this.listKeys({}, params); } const { next_page, ...body } = params; - return this._client.getAPIList('/customFields/listKeys', CustomFieldListKeysResponsesPage, { - query: { next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/customFields/listKeys', { query: { next_page }, body, ...options }); } /** @@ -63,7 +55,7 @@ export class CustomFields extends APIResource { return this._client.post('/customFields/removeKey', { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } @@ -80,48 +72,98 @@ export class CustomFields extends APIResource { return this._client.post('/customFields/setValues', { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } } -export class CustomFieldListKeysResponsesPage extends Page {} - export interface CustomFieldListKeysResponse { - enforce_uniqueness: boolean; + data: Array; - entity: 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric'; + next_page: string | null; +} - key: string; +export namespace CustomFieldListKeysResponse { + export interface Data { + enforce_uniqueness: boolean; + + entity: + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit'; + + key: string; + } } export interface CustomFieldAddKeyParams { enforce_uniqueness: boolean; - entity: 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric'; + entity: + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit'; key: string; } export interface CustomFieldDeleteValuesParams { - entity: 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric'; + entity: + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit'; entity_id: string; keys: Array; } -export interface CustomFieldListKeysParams extends PageParams { +export interface CustomFieldListKeysParams { + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: Optional list of entity types to return keys for */ entities?: Array< - 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric' + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit' >; } export interface CustomFieldRemoveKeyParams { - entity: 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric'; + entity: + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit'; key: string; } @@ -129,14 +171,21 @@ export interface CustomFieldRemoveKeyParams { export interface CustomFieldSetValuesParams { custom_fields: Record; - entity: 'charge' | 'credit_grant' | 'customer' | 'customer_plan' | 'plan' | 'product' | 'billable_metric'; + entity: + | 'charge' + | 'credit_grant' + | 'customer' + | 'customer_plan' + | 'plan' + | 'product' + | 'billable_metric' + | 'commit'; entity_id: string; } export namespace CustomFields { export import CustomFieldListKeysResponse = CustomFieldsAPI.CustomFieldListKeysResponse; - export import CustomFieldListKeysResponsesPage = CustomFieldsAPI.CustomFieldListKeysResponsesPage; export import CustomFieldAddKeyParams = CustomFieldsAPI.CustomFieldAddKeyParams; export import CustomFieldDeleteValuesParams = CustomFieldsAPI.CustomFieldDeleteValuesParams; export import CustomFieldListKeysParams = CustomFieldsAPI.CustomFieldListKeysParams; diff --git a/src/resources/customer-alerts.ts b/src/resources/customer-alerts.ts index 9e4e7fc..90bf02c 100644 --- a/src/resources/customer-alerts.ts +++ b/src/resources/customer-alerts.ts @@ -3,7 +3,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import * as CustomerAlertsAPI from '@metronome-industries/metronome/resources/customer-alerts'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class CustomerAlerts extends APIResource { /** @@ -23,19 +22,12 @@ export class CustomerAlerts extends APIResource { list( params: CustomerAlertListParams, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { const { next_page, ...body } = params; - return this._client.getAPIList('/customer-alerts/list', CustomerAlertsPage, { - query: { next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/customer-alerts/list', { query: { next_page }, body, ...options }); } } -export class CustomerAlertsPage extends Page {} - export interface CustomerAlert { alert: CustomerAlert.Alert; @@ -97,7 +89,137 @@ export namespace CustomerAlert { } export interface CustomerAlertRetrieveResponse { - data: CustomerAlert; + data: CustomerAlertRetrieveResponse.Data; +} + +export namespace CustomerAlertRetrieveResponse { + export interface Data { + alert: Data.Alert; + + /** + * The status of the customer alert. If the alert is archived, null will be + * returned. + */ + customer_status: 'ok' | 'in_alarm' | 'evaluating' | null; + } + + export namespace Data { + export interface Alert { + /** + * the Metronome ID of the alert + */ + id: string; + + credit_type: Alert.CreditType | null; + + /** + * Name of the alert + */ + name: string; + + /** + * Status of the alert + */ + status: 'enabled' | 'archived' | 'disabled'; + + /** + * Threshold value of the alert policy + */ + threshold: number; + + /** + * Type of the alert + */ + type: + | 'low_credit_balance_reached' + | 'spend_threshold_reached' + | 'monthly_invoice_total_spend_threshold_reached' + | 'low_remaining_days_in_plan_reached' + | 'low_remaining_credit_percentage_reached' + | 'usage_threshold_reached'; + + /** + * Timestamp for when the alert was last updated + */ + updated_at: string; + } + + export namespace Alert { + export interface CreditType { + id: string; + + name: string; + } + } + } +} + +export interface CustomerAlertListResponse { + data: Array; + + next_page: string | null; +} + +export namespace CustomerAlertListResponse { + export interface Data { + alert: Data.Alert; + + /** + * The status of the customer alert. If the alert is archived, null will be + * returned. + */ + customer_status: 'ok' | 'in_alarm' | 'evaluating' | null; + } + + export namespace Data { + export interface Alert { + /** + * the Metronome ID of the alert + */ + id: string; + + credit_type: Alert.CreditType | null; + + /** + * Name of the alert + */ + name: string; + + /** + * Status of the alert + */ + status: 'enabled' | 'archived' | 'disabled'; + + /** + * Threshold value of the alert policy + */ + threshold: number; + + /** + * Type of the alert + */ + type: + | 'low_credit_balance_reached' + | 'spend_threshold_reached' + | 'monthly_invoice_total_spend_threshold_reached' + | 'low_remaining_days_in_plan_reached' + | 'low_remaining_credit_percentage_reached' + | 'usage_threshold_reached'; + + /** + * Timestamp for when the alert was last updated + */ + updated_at: string; + } + + export namespace Alert { + export interface CreditType { + id: string; + + name: string; + } + } + } } export interface CustomerAlertRetrieveParams { @@ -112,12 +234,17 @@ export interface CustomerAlertRetrieveParams { customer_id: string; } -export interface CustomerAlertListParams extends PageParams { +export interface CustomerAlertListParams { /** * Body param: The Metronome ID of the customer */ customer_id: string; + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: Optionally filter by alert status. If absent, only enabled alerts * will be returned. @@ -138,7 +265,7 @@ export interface CustomerAlertListParams extends PageParams { export namespace CustomerAlerts { export import CustomerAlert = CustomerAlertsAPI.CustomerAlert; export import CustomerAlertRetrieveResponse = CustomerAlertsAPI.CustomerAlertRetrieveResponse; - export import CustomerAlertsPage = CustomerAlertsAPI.CustomerAlertsPage; + export import CustomerAlertListResponse = CustomerAlertsAPI.CustomerAlertListResponse; export import CustomerAlertRetrieveParams = CustomerAlertsAPI.CustomerAlertRetrieveParams; export import CustomerAlertListParams = CustomerAlertsAPI.CustomerAlertListParams; } diff --git a/src/resources/customers/billing-config.ts b/src/resources/customers/billing-config.ts index 7816bd4..7c0b6a9 100644 --- a/src/resources/customers/billing-config.ts +++ b/src/resources/customers/billing-config.ts @@ -23,7 +23,7 @@ export class BillingConfig extends APIResource { return this._client.post(`/customers/${customerId}/billing-config/${billingProviderType}`, { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } @@ -61,7 +61,7 @@ export class BillingConfig extends APIResource { ): Core.APIPromise { return this._client.delete(`/customers/${customerId}/billing-config/${billingProviderType}`, { ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } } diff --git a/src/resources/customers/customers.ts b/src/resources/customers/customers.ts index 7db5aaa..0e93769 100644 --- a/src/resources/customers/customers.ts +++ b/src/resources/customers/customers.ts @@ -4,11 +4,9 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as CustomersAPI from '@metronome-industries/metronome/resources/customers/customers'; -import * as Shared from '@metronome-industries/metronome/resources/shared'; import * as BillingConfigAPI from '@metronome-industries/metronome/resources/customers/billing-config'; import * as InvoicesAPI from '@metronome-industries/metronome/resources/customers/invoices'; import * as PlansAPI from '@metronome-industries/metronome/resources/customers/plans'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Customers extends APIResource { plans: PlansAPI.Plans = new PlansAPI.Plans(this._client); @@ -32,19 +30,16 @@ export class Customers extends APIResource { /** * List all customers. */ - list( - query?: CustomerListParams, - options?: Core.RequestOptions, - ): Core.PagePromise; - list(options?: Core.RequestOptions): Core.PagePromise; + list(query?: CustomerListParams, options?: Core.RequestOptions): Core.APIPromise; + list(options?: Core.RequestOptions): Core.APIPromise; list( query: CustomerListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list({}, query); } - return this._client.getAPIList('/customers', CustomerDetailsPage, { query, ...options }); + return this._client.get('/customers', { query, ...options }); } /** @@ -64,24 +59,20 @@ export class Customers extends APIResource { customerId: string, query?: CustomerListBillableMetricsParams, options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; listBillableMetrics( customerId: string, options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; listBillableMetrics( customerId: string, query: CustomerListBillableMetricsParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.listBillableMetrics(customerId, {}, query); } - return this._client.getAPIList( - `/customers/${customerId}/billable-metrics`, - CustomerListBillableMetricsResponsesPage, - { query, ...options }, - ); + return this._client.get(`/customers/${customerId}/billable-metrics`, { query, ...options }); } /** @@ -93,11 +84,8 @@ export class Customers extends APIResource { customerId: string, query: CustomerListCostsParams, options?: Core.RequestOptions, - ): Core.PagePromise { - return this._client.getAPIList(`/customers/${customerId}/costs`, CustomerListCostsResponsesPage, { - query, - ...options, - }); + ): Core.APIPromise { + return this._client.get(`/customers/${customerId}/costs`, { query, ...options }); } /** @@ -113,7 +101,7 @@ export class Customers extends APIResource { return this._client.post(`/customers/${customerId}/setIngestAliases`, { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } @@ -148,17 +136,11 @@ export class Customers extends APIResource { return this._client.post(`/customers/${customerId}/updateConfig`, { body, ...options, - headers: { Accept: '', ...options?.headers }, + headers: { Accept: '*/*', ...options?.headers }, }); } } -export class CustomerDetailsPage extends Page {} - -export class CustomerListBillableMetricsResponsesPage extends Page {} - -export class CustomerListCostsResponsesPage extends Page {} - export interface Customer { /** * the Metronome ID of the customer @@ -188,6 +170,8 @@ export interface CustomerDetail { */ id: string; + current_billable_status: CustomerDetail.CurrentBillableStatus; + custom_fields: Record; customer_config: CustomerDetail.CustomerConfig; @@ -208,6 +192,12 @@ export interface CustomerDetail { } export namespace CustomerDetail { + export interface CurrentBillableStatus { + value: 'billable' | 'unbillable'; + + effective_at?: string | null; + } + export interface CustomerConfig { /** * The Salesforce account ID for the customer @@ -217,57 +207,223 @@ export namespace CustomerDetail { } export interface CustomerCreateResponse { - data: Customer; + data: CustomerCreateResponse.Data; +} + +export namespace CustomerCreateResponse { + export interface Data { + /** + * the Metronome ID of the customer + */ + id: string; + + /** + * (deprecated, use ingest_aliases instead) the first ID (Metronome or ingest + * alias) that can be used in usage events + */ + external_id: string; + + /** + * aliases for this customer that can be used instead of the Metronome customer ID + * in usage events + */ + ingest_aliases: Array; + + name: string; + + custom_fields?: Record; + } } export interface CustomerRetrieveResponse { - data: CustomerDetail; + data: CustomerRetrieveResponse.Data; +} + +export namespace CustomerRetrieveResponse { + export interface Data { + /** + * the Metronome ID of the customer + */ + id: string; + + current_billable_status: Data.CurrentBillableStatus; + + custom_fields: Record; + + customer_config: Data.CustomerConfig; + + /** + * (deprecated, use ingest_aliases instead) the first ID (Metronome or ingest + * alias) that can be used in usage events + */ + external_id: string; + + /** + * aliases for this customer that can be used instead of the Metronome customer ID + * in usage events + */ + ingest_aliases: Array; + + name: string; + } + + export namespace Data { + export interface CurrentBillableStatus { + value: 'billable' | 'unbillable'; + + effective_at?: string | null; + } + + export interface CustomerConfig { + /** + * The Salesforce account ID for the customer + */ + salesforce_account_id: string | null; + } + } +} + +export interface CustomerListResponse { + data: Array; + + next_page: string | null; +} + +export namespace CustomerListResponse { + export interface Data { + /** + * the Metronome ID of the customer + */ + id: string; + + current_billable_status: Data.CurrentBillableStatus; + + custom_fields: Record; + + customer_config: Data.CustomerConfig; + + /** + * (deprecated, use ingest_aliases instead) the first ID (Metronome or ingest + * alias) that can be used in usage events + */ + external_id: string; + + /** + * aliases for this customer that can be used instead of the Metronome customer ID + * in usage events + */ + ingest_aliases: Array; + + name: string; + } + + export namespace Data { + export interface CurrentBillableStatus { + value: 'billable' | 'unbillable'; + + effective_at?: string | null; + } + + export interface CustomerConfig { + /** + * The Salesforce account ID for the customer + */ + salesforce_account_id: string | null; + } + } } export interface CustomerArchiveResponse { - data: Shared.ID; + data: CustomerArchiveResponse.Data; +} + +export namespace CustomerArchiveResponse { + export interface Data { + id: string; + } } export interface CustomerListBillableMetricsResponse { - id: string; + data: Array; - name: string; + next_page: string | null; +} - group_by?: Array; +export namespace CustomerListBillableMetricsResponse { + export interface Data { + id: string; + + name: string; + + group_by?: Array; + } } export interface CustomerListCostsResponse { - credit_types: Record; + data: Array; - end_timestamp: string; - - start_timestamp: string; + next_page: string | null; } export namespace CustomerListCostsResponse { - export interface CreditTypes { - cost?: number; + export interface Data { + credit_types: Record; - line_item_breakdown?: Array; + end_timestamp: string; - name?: string; + start_timestamp: string; } - export namespace CreditTypes { - export interface LineItemBreakdown { - cost: number; + export namespace Data { + export interface CreditTypes { + cost?: number; + + line_item_breakdown?: Array; + + name?: string; + } + + export namespace CreditTypes { + export interface LineItemBreakdown { + cost: number; - name: string; + name: string; - group_key?: string; + group_key?: string; - group_value?: string | null; + group_value?: string | null; + } } } } export interface CustomerSetNameResponse { - data: Customer; + data: CustomerSetNameResponse.Data; +} + +export namespace CustomerSetNameResponse { + export interface Data { + /** + * the Metronome ID of the customer + */ + id: string; + + /** + * (deprecated, use ingest_aliases instead) the first ID (Metronome or ingest + * alias) that can be used in usage events + */ + external_id: string; + + /** + * aliases for this customer that can be used instead of the Metronome customer ID + * in usage events + */ + ingest_aliases: Array; + + name: string; + + custom_fields?: Record; + } } export interface CustomerCreateParams { @@ -334,7 +490,7 @@ export namespace CustomerCreateParams { } } -export interface CustomerListParams extends PageParams { +export interface CustomerListParams { /** * Filter the customer list by customer_id. Up to 100 ids can be provided. */ @@ -350,6 +506,11 @@ export interface CustomerListParams extends PageParams { */ limit?: number; + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Filter the customer list by only archived customers. */ @@ -366,12 +527,17 @@ export interface CustomerArchiveParams { id: string; } -export interface CustomerListBillableMetricsParams extends PageParams { +export interface CustomerListBillableMetricsParams { /** * Max number of results that should be returned */ limit?: number; + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * If true, the list of metrics will be filtered to just ones that are on the * customer's current plan @@ -379,7 +545,7 @@ export interface CustomerListBillableMetricsParams extends PageParams { on_current_plan?: boolean; } -export interface CustomerListCostsParams extends PageParams { +export interface CustomerListCostsParams { /** * RFC 3339 timestamp (exclusive) */ @@ -394,6 +560,11 @@ export interface CustomerListCostsParams extends PageParams { * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } export interface CustomerSetIngestAliasesParams { @@ -408,6 +579,12 @@ export interface CustomerSetNameParams { } export interface CustomerUpdateConfigParams { + /** + * Leave in draft or set to auto-advance on invoices sent to Stripe. Falls back to + * the client-level config if unset, which defaults to true if unset. + */ + leave_stripe_invoices_in_draft?: boolean | null; + /** * The Salesforce account ID for the customer */ @@ -419,13 +596,11 @@ export namespace Customers { export import CustomerDetail = CustomersAPI.CustomerDetail; export import CustomerCreateResponse = CustomersAPI.CustomerCreateResponse; export import CustomerRetrieveResponse = CustomersAPI.CustomerRetrieveResponse; + export import CustomerListResponse = CustomersAPI.CustomerListResponse; export import CustomerArchiveResponse = CustomersAPI.CustomerArchiveResponse; export import CustomerListBillableMetricsResponse = CustomersAPI.CustomerListBillableMetricsResponse; export import CustomerListCostsResponse = CustomersAPI.CustomerListCostsResponse; export import CustomerSetNameResponse = CustomersAPI.CustomerSetNameResponse; - export import CustomerDetailsPage = CustomersAPI.CustomerDetailsPage; - export import CustomerListBillableMetricsResponsesPage = CustomersAPI.CustomerListBillableMetricsResponsesPage; - export import CustomerListCostsResponsesPage = CustomersAPI.CustomerListCostsResponsesPage; export import CustomerCreateParams = CustomersAPI.CustomerCreateParams; export import CustomerListParams = CustomersAPI.CustomerListParams; export import CustomerArchiveParams = CustomersAPI.CustomerArchiveParams; @@ -439,8 +614,6 @@ export namespace Customers { export import PlanAddResponse = PlansAPI.PlanAddResponse; export import PlanEndResponse = PlansAPI.PlanEndResponse; export import PlanListPriceAdjustmentsResponse = PlansAPI.PlanListPriceAdjustmentsResponse; - export import PlanListResponsesPage = PlansAPI.PlanListResponsesPage; - export import PlanListPriceAdjustmentsResponsesPage = PlansAPI.PlanListPriceAdjustmentsResponsesPage; export import PlanListParams = PlansAPI.PlanListParams; export import PlanAddParams = PlansAPI.PlanAddParams; export import PlanEndParams = PlansAPI.PlanEndParams; @@ -448,7 +621,7 @@ export namespace Customers { export import Invoices = InvoicesAPI.Invoices; export import Invoice = InvoicesAPI.Invoice; export import InvoiceRetrieveResponse = InvoicesAPI.InvoiceRetrieveResponse; - export import InvoicesPage = InvoicesAPI.InvoicesPage; + export import InvoiceListResponse = InvoicesAPI.InvoiceListResponse; export import InvoiceListParams = InvoicesAPI.InvoiceListParams; export import BillingConfig = BillingConfigAPI.BillingConfig; export import BillingConfigRetrieveResponse = BillingConfigAPI.BillingConfigRetrieveResponse; diff --git a/src/resources/customers/index.ts b/src/resources/customers/index.ts index 5419b67..c200252 100644 --- a/src/resources/customers/index.ts +++ b/src/resources/customers/index.ts @@ -6,6 +6,7 @@ export { CustomerDetail, CustomerCreateResponse, CustomerRetrieveResponse, + CustomerListResponse, CustomerArchiveResponse, CustomerListBillableMetricsResponse, CustomerListCostsResponse, @@ -18,12 +19,15 @@ export { CustomerSetIngestAliasesParams, CustomerSetNameParams, CustomerUpdateConfigParams, - CustomerDetailsPage, - CustomerListBillableMetricsResponsesPage, - CustomerListCostsResponsesPage, Customers, } from './customers'; -export { Invoice, InvoiceRetrieveResponse, InvoiceListParams, InvoicesPage, Invoices } from './invoices'; +export { + Invoice, + InvoiceRetrieveResponse, + InvoiceListResponse, + InvoiceListParams, + Invoices, +} from './invoices'; export { PlanListResponse, PlanAddResponse, @@ -33,7 +37,5 @@ export { PlanAddParams, PlanEndParams, PlanListPriceAdjustmentsParams, - PlanListResponsesPage, - PlanListPriceAdjustmentsResponsesPage, Plans, } from './plans'; diff --git a/src/resources/customers/invoices.ts b/src/resources/customers/invoices.ts index b0f92fc..f0b9d5e 100644 --- a/src/resources/customers/invoices.ts +++ b/src/resources/customers/invoices.ts @@ -4,7 +4,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as InvoicesAPI from '@metronome-industries/metronome/resources/customers/invoices'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Invoices extends APIResource { /** @@ -26,25 +25,25 @@ export class Invoices extends APIResource { customerId: string, query?: InvoiceListParams, options?: Core.RequestOptions, - ): Core.PagePromise; - list(customerId: string, options?: Core.RequestOptions): Core.PagePromise; + ): Core.APIPromise; + list(customerId: string, options?: Core.RequestOptions): Core.APIPromise; list( customerId: string, query: InvoiceListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list(customerId, {}, query); } - return this._client.getAPIList(`/customers/${customerId}/invoices`, InvoicesPage, { query, ...options }); + return this._client.get(`/customers/${customerId}/invoices`, { query, ...options }); } } -export class InvoicesPage extends Page {} - export interface Invoice { id: string; + billable_status: 'billable' | 'unbillable'; + credit_type: Invoice.CreditType; customer_id: string; @@ -129,11 +128,28 @@ export namespace Invoice { */ commit_id?: string; + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_item_id?: string; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_sales_order_id?: string; + /** * only present for beta contract invoices */ commit_segment_id?: string; + /** + * only present for beta contract invoices + */ + commit_type?: string; + custom_fields?: Record; /** @@ -304,6 +320,8 @@ export namespace Invoice { name: string; total: number; + + credit_grant_id?: string; } export namespace InvoiceAdjustment { @@ -347,10 +365,670 @@ export namespace Invoice { } export interface InvoiceRetrieveResponse { - data: Invoice; + data: InvoiceRetrieveResponse.Data; } -export interface InvoiceListParams extends PageParams { +export namespace InvoiceRetrieveResponse { + export interface Data { + id: string; + + billable_status: 'billable' | 'unbillable'; + + credit_type: Data.CreditType; + + customer_id: string; + + line_items: Array; + + status: string; + + total: number; + + type: string; + + amendment_id?: string; + + contract_id?: string; + + correction_record?: Data.CorrectionRecord; + + custom_fields?: Record; + + /** + * End of the usage period this invoice covers (UTC) + */ + end_timestamp?: string; + + external_invoice?: Data.ExternalInvoice | null; + + invoice_adjustments?: Array; + + /** + * When the invoice was issued (UTC) + */ + issued_at?: string; + + net_payment_terms_days?: number; + + /** + * This field's availability is dependent on your client's configuration. + */ + netsuite_sales_order_id?: string; + + plan_custom_fields?: Record; + + plan_id?: string; + + plan_name?: string; + + /** + * only present for beta contract invoices with reseller royalties + */ + reseller_royalty?: Data.ResellerRoyalty; + + /** + * This field's availability is dependent on your client's configuration. + */ + salesforce_opportunity_id?: string; + + /** + * Beginning of the usage period this invoice covers (UTC) + */ + start_timestamp?: string; + + subtotal?: number; + } + + export namespace Data { + export interface CreditType { + id: string; + + name: string; + } + + export interface LineItem { + credit_type: LineItem.CreditType; + + name: string; + + total: number; + + /** + * only present for beta contract invoices + */ + commit_id?: string; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_item_id?: string; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_sales_order_id?: string; + + /** + * only present for beta contract invoices + */ + commit_segment_id?: string; + + /** + * only present for beta contract invoices + */ + commit_type?: string; + + custom_fields?: Record; + + /** + * only present for beta contract invoices + */ + ending_before?: string; + + group_key?: string; + + group_value?: string; + + /** + * only present for beta contract invoices + */ + is_prorated?: boolean; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + netsuite_item_id?: string; + + /** + * only present for beta contract invoices + */ + postpaid_commit?: LineItem.PostpaidCommit; + + product_id?: string; + + quantity?: number; + + reseller_type?: 'AWS' | 'GCP'; + + /** + * only present for beta contract invoices + */ + starting_at?: string; + + sub_line_items?: Array; + + /** + * only present for beta contract invoices + */ + unit_price?: number; + } + + export namespace LineItem { + export interface CreditType { + id: string; + + name: string; + } + + /** + * only present for beta contract invoices + */ + export interface PostpaidCommit { + id: string; + } + + export interface SubLineItem { + custom_fields: Record; + + name: string; + + quantity: number; + + subtotal: number; + + charge_id?: string; + + credit_grant_id?: string; + + /** + * the unit price for this charge, present only if the charge is not tiered and the + * quantity is nonzero + */ + price?: number; + + tiers?: Array; + } + + export namespace SubLineItem { + export interface Tier { + price: number; + + quantity: number; + + /** + * at what metric amount this tier begins + */ + starting_at: number; + + subtotal: number; + } + } + } + + export interface CorrectionRecord { + corrected_invoice_id: string; + + memo: string; + + reason: string; + + corrected_external_invoice?: CorrectionRecord.CorrectedExternalInvoice; + } + + export namespace CorrectionRecord { + export interface CorrectedExternalInvoice { + billing_provider_type: + | 'aws_marketplace' + | 'stripe' + | 'netsuite' + | 'custom' + | 'azure_marketplace' + | 'quickbooks_online'; + + external_status?: + | 'DRAFT' + | 'FINALIZED' + | 'PAID' + | 'UNCOLLECTIBLE' + | 'VOID' + | 'DELETED' + | 'PAYMENT_FAILED' + | 'INVALID_REQUEST_ERROR' + | 'SKIPPED' + | 'SENT' + | 'QUEUED'; + + invoice_id?: string; + + issued_at_timestamp?: string; + } + } + + export interface ExternalInvoice { + billing_provider_type: + | 'aws_marketplace' + | 'stripe' + | 'netsuite' + | 'custom' + | 'azure_marketplace' + | 'quickbooks_online'; + + external_status?: + | 'DRAFT' + | 'FINALIZED' + | 'PAID' + | 'UNCOLLECTIBLE' + | 'VOID' + | 'DELETED' + | 'PAYMENT_FAILED' + | 'INVALID_REQUEST_ERROR' + | 'SKIPPED' + | 'SENT' + | 'QUEUED'; + + invoice_id?: string; + + issued_at_timestamp?: string; + } + + export interface InvoiceAdjustment { + credit_type: InvoiceAdjustment.CreditType; + + name: string; + + total: number; + + credit_grant_id?: string; + } + + export namespace InvoiceAdjustment { + export interface CreditType { + id: string; + + name: string; + } + } + + /** + * only present for beta contract invoices with reseller royalties + */ + export interface ResellerRoyalty { + fraction: string; + + netsuite_reseller_id: string; + + reseller_type: 'AWS' | 'GCP'; + + aws_options?: ResellerRoyalty.AwsOptions; + + gcp_options?: ResellerRoyalty.GcpOptions; + } + + export namespace ResellerRoyalty { + export interface AwsOptions { + aws_account_number?: string; + + aws_offer_id?: string; + + aws_payer_reference_id?: string; + } + + export interface GcpOptions { + gcp_account_id?: string; + + gcp_offer_id?: string; + } + } + } +} + +export interface InvoiceListResponse { + data: Array; + + next_page: string | null; +} + +export namespace InvoiceListResponse { + export interface Data { + id: string; + + billable_status: 'billable' | 'unbillable'; + + credit_type: Data.CreditType; + + customer_id: string; + + line_items: Array; + + status: string; + + total: number; + + type: string; + + amendment_id?: string; + + contract_id?: string; + + correction_record?: Data.CorrectionRecord; + + custom_fields?: Record; + + /** + * End of the usage period this invoice covers (UTC) + */ + end_timestamp?: string; + + external_invoice?: Data.ExternalInvoice | null; + + invoice_adjustments?: Array; + + /** + * When the invoice was issued (UTC) + */ + issued_at?: string; + + net_payment_terms_days?: number; + + /** + * This field's availability is dependent on your client's configuration. + */ + netsuite_sales_order_id?: string; + + plan_custom_fields?: Record; + + plan_id?: string; + + plan_name?: string; + + /** + * only present for beta contract invoices with reseller royalties + */ + reseller_royalty?: Data.ResellerRoyalty; + + /** + * This field's availability is dependent on your client's configuration. + */ + salesforce_opportunity_id?: string; + + /** + * Beginning of the usage period this invoice covers (UTC) + */ + start_timestamp?: string; + + subtotal?: number; + } + + export namespace Data { + export interface CreditType { + id: string; + + name: string; + } + + export interface LineItem { + credit_type: LineItem.CreditType; + + name: string; + + total: number; + + /** + * only present for beta contract invoices + */ + commit_id?: string; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_item_id?: string; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + commit_netsuite_sales_order_id?: string; + + /** + * only present for beta contract invoices + */ + commit_segment_id?: string; + + /** + * only present for beta contract invoices + */ + commit_type?: string; + + custom_fields?: Record; + + /** + * only present for beta contract invoices + */ + ending_before?: string; + + group_key?: string; + + group_value?: string; + + /** + * only present for beta contract invoices + */ + is_prorated?: boolean; + + /** + * only present for beta contract invoices. This field's availability is dependent + * on your client's configuration. + */ + netsuite_item_id?: string; + + /** + * only present for beta contract invoices + */ + postpaid_commit?: LineItem.PostpaidCommit; + + product_id?: string; + + quantity?: number; + + reseller_type?: 'AWS' | 'GCP'; + + /** + * only present for beta contract invoices + */ + starting_at?: string; + + sub_line_items?: Array; + + /** + * only present for beta contract invoices + */ + unit_price?: number; + } + + export namespace LineItem { + export interface CreditType { + id: string; + + name: string; + } + + /** + * only present for beta contract invoices + */ + export interface PostpaidCommit { + id: string; + } + + export interface SubLineItem { + custom_fields: Record; + + name: string; + + quantity: number; + + subtotal: number; + + charge_id?: string; + + credit_grant_id?: string; + + /** + * the unit price for this charge, present only if the charge is not tiered and the + * quantity is nonzero + */ + price?: number; + + tiers?: Array; + } + + export namespace SubLineItem { + export interface Tier { + price: number; + + quantity: number; + + /** + * at what metric amount this tier begins + */ + starting_at: number; + + subtotal: number; + } + } + } + + export interface CorrectionRecord { + corrected_invoice_id: string; + + memo: string; + + reason: string; + + corrected_external_invoice?: CorrectionRecord.CorrectedExternalInvoice; + } + + export namespace CorrectionRecord { + export interface CorrectedExternalInvoice { + billing_provider_type: + | 'aws_marketplace' + | 'stripe' + | 'netsuite' + | 'custom' + | 'azure_marketplace' + | 'quickbooks_online'; + + external_status?: + | 'DRAFT' + | 'FINALIZED' + | 'PAID' + | 'UNCOLLECTIBLE' + | 'VOID' + | 'DELETED' + | 'PAYMENT_FAILED' + | 'INVALID_REQUEST_ERROR' + | 'SKIPPED' + | 'SENT' + | 'QUEUED'; + + invoice_id?: string; + + issued_at_timestamp?: string; + } + } + + export interface ExternalInvoice { + billing_provider_type: + | 'aws_marketplace' + | 'stripe' + | 'netsuite' + | 'custom' + | 'azure_marketplace' + | 'quickbooks_online'; + + external_status?: + | 'DRAFT' + | 'FINALIZED' + | 'PAID' + | 'UNCOLLECTIBLE' + | 'VOID' + | 'DELETED' + | 'PAYMENT_FAILED' + | 'INVALID_REQUEST_ERROR' + | 'SKIPPED' + | 'SENT' + | 'QUEUED'; + + invoice_id?: string; + + issued_at_timestamp?: string; + } + + export interface InvoiceAdjustment { + credit_type: InvoiceAdjustment.CreditType; + + name: string; + + total: number; + + credit_grant_id?: string; + } + + export namespace InvoiceAdjustment { + export interface CreditType { + id: string; + + name: string; + } + } + + /** + * only present for beta contract invoices with reseller royalties + */ + export interface ResellerRoyalty { + fraction: string; + + netsuite_reseller_id: string; + + reseller_type: 'AWS' | 'GCP'; + + aws_options?: ResellerRoyalty.AwsOptions; + + gcp_options?: ResellerRoyalty.GcpOptions; + } + + export namespace ResellerRoyalty { + export interface AwsOptions { + aws_account_number?: string; + + aws_offer_id?: string; + + aws_payer_reference_id?: string; + } + + export interface GcpOptions { + gcp_account_id?: string; + + gcp_offer_id?: string; + } + } + } +} + +export interface InvoiceListParams { /** * Only return invoices for the specified credit type */ @@ -367,6 +1045,11 @@ export interface InvoiceListParams extends PageParams { */ limit?: number; + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Invoice sort order by issued_at, e.g. date_asc or date_desc. Defaults to * date_asc. @@ -388,6 +1071,6 @@ export interface InvoiceListParams extends PageParams { export namespace Invoices { export import Invoice = InvoicesAPI.Invoice; export import InvoiceRetrieveResponse = InvoicesAPI.InvoiceRetrieveResponse; - export import InvoicesPage = InvoicesAPI.InvoicesPage; + export import InvoiceListResponse = InvoicesAPI.InvoiceListResponse; export import InvoiceListParams = InvoicesAPI.InvoiceListParams; } diff --git a/src/resources/customers/plans.ts b/src/resources/customers/plans.ts index beb9a4a..c322482 100644 --- a/src/resources/customers/plans.ts +++ b/src/resources/customers/plans.ts @@ -4,8 +4,6 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as PlansAPI from '@metronome-industries/metronome/resources/customers/plans'; -import * as Shared from '@metronome-industries/metronome/resources/shared'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Plans extends APIResource { /** @@ -15,23 +13,17 @@ export class Plans extends APIResource { customerId: string, query?: PlanListParams, options?: Core.RequestOptions, - ): Core.PagePromise; - list( - customerId: string, - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + list(customerId: string, options?: Core.RequestOptions): Core.APIPromise; list( customerId: string, query: PlanListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list(customerId, {}, query); } - return this._client.getAPIList(`/customers/${customerId}/plans`, PlanListResponsesPage, { - query, - ...options, - }); + return this._client.get(`/customers/${customerId}/plans`, { query, ...options }); } /** @@ -83,124 +75,146 @@ export class Plans extends APIResource { customerPlanId: string, query?: PlanListPriceAdjustmentsParams, options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; listPriceAdjustments( customerId: string, customerPlanId: string, options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; listPriceAdjustments( customerId: string, customerPlanId: string, query: PlanListPriceAdjustmentsParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.listPriceAdjustments(customerId, customerPlanId, {}, query); } - return this._client.getAPIList( - `/customers/${customerId}/plans/${customerPlanId}/priceAdjustments`, - PlanListPriceAdjustmentsResponsesPage, - { query, ...options }, - ); + return this._client.get(`/customers/${customerId}/plans/${customerPlanId}/priceAdjustments`, { + query, + ...options, + }); } } -export class PlanListResponsesPage extends Page {} - -export class PlanListPriceAdjustmentsResponsesPage extends Page {} - export interface PlanListResponse { - /** - * the ID of the customer plan - */ - id: string; + data: Array; - custom_fields: Record; + next_page: string | null; +} - plan_description: string; +export namespace PlanListResponse { + export interface Data { + /** + * the ID of the customer plan + */ + id: string; - /** - * the ID of the plan - */ - plan_id: string; + custom_fields: Record; - plan_name: string; + plan_description: string; - starting_on: string; + /** + * the ID of the plan + */ + plan_id: string; - ending_before?: string; + plan_name: string; - net_payment_terms_days?: number; + starting_on: string; - trial_info?: PlanListResponse.TrialInfo; -} + ending_before?: string; -export namespace PlanListResponse { - export interface TrialInfo { - ending_before: string; + net_payment_terms_days?: number; - spending_caps: Array; + trial_info?: Data.TrialInfo; } - export namespace TrialInfo { - export interface SpendingCap { - amount: number; + export namespace Data { + export interface TrialInfo { + ending_before: string; - amount_remaining: number; - - credit_type: SpendingCap.CreditType; + spending_caps: Array; } - export namespace SpendingCap { - export interface CreditType { - id: string; + export namespace TrialInfo { + export interface SpendingCap { + amount: number; + + amount_remaining: number; - name: string; + credit_type: SpendingCap.CreditType; + } + + export namespace SpendingCap { + export interface CreditType { + id: string; + + name: string; + } } } } } export interface PlanAddResponse { - data: Shared.ID; + data: PlanAddResponse.Data; +} + +export namespace PlanAddResponse { + export interface Data { + id: string; + } } export interface PlanEndResponse {} export interface PlanListPriceAdjustmentsResponse { - charge_id: string; + data: Array; - charge_type: 'usage' | 'fixed' | 'composite' | 'minimum' | 'seat'; + next_page: string | null; +} - prices: Array; +export namespace PlanListPriceAdjustmentsResponse { + export interface Data { + charge_id: string; - start_period: number; + charge_type: 'usage' | 'fixed' | 'composite' | 'minimum' | 'seat'; - quantity?: number; -} + prices: Array; -export namespace PlanListPriceAdjustmentsResponse { - export interface Price { - /** - * Determines how the value will be applied. - */ - adjustment_type: 'fixed' | 'quantity' | 'percentage' | 'override'; + start_period: number; - /** - * Used in pricing tiers. Indicates at what metric value the price applies. - */ - tier?: number; + quantity?: number; + } - value?: number; + export namespace Data { + export interface Price { + /** + * Determines how the value will be applied. + */ + adjustment_type: 'fixed' | 'quantity' | 'percentage' | 'override'; + + /** + * Used in pricing tiers. Indicates at what metric value the price applies. + */ + tier?: number; + + value?: number; + } } } -export interface PlanListParams extends PageParams { +export interface PlanListParams { /** * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } export interface PlanAddParams { @@ -285,11 +299,16 @@ export interface PlanEndParams { void_stripe_invoices?: boolean; } -export interface PlanListPriceAdjustmentsParams extends PageParams { +export interface PlanListPriceAdjustmentsParams { /** * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } export namespace Plans { @@ -297,8 +316,6 @@ export namespace Plans { export import PlanAddResponse = PlansAPI.PlanAddResponse; export import PlanEndResponse = PlansAPI.PlanEndResponse; export import PlanListPriceAdjustmentsResponse = PlansAPI.PlanListPriceAdjustmentsResponse; - export import PlanListResponsesPage = PlansAPI.PlanListResponsesPage; - export import PlanListPriceAdjustmentsResponsesPage = PlansAPI.PlanListPriceAdjustmentsResponsesPage; export import PlanListParams = PlansAPI.PlanListParams; export import PlanAddParams = PlansAPI.PlanAddParams; export import PlanEndParams = PlansAPI.PlanEndParams; diff --git a/src/resources/index.ts b/src/resources/index.ts index 79ba64c..6976fdc 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -8,7 +8,7 @@ export { AlertArchiveParams, Alerts, } from './alerts'; -export { AuditLogListResponse, AuditLogListParams, AuditLogListResponsesPage, AuditLogs } from './audit-logs'; +export { AuditLogListResponse, AuditLogListParams, AuditLogs } from './audit-logs'; export { CreditCreateGrantResponse, CreditEditGrantResponse, @@ -20,16 +20,9 @@ export { CreditListEntriesParams, CreditListGrantsParams, CreditVoidGrantParams, - CreditListEntriesResponsesPage, - CreditListGrantsResponsesPage, Credits, } from './credits'; -export { - CreditTypeListResponse, - CreditTypeListParams, - CreditTypeListResponsesPage, - CreditTypes, -} from './credit-types'; +export { CreditTypeListResponse, CreditTypeListParams, CreditTypes } from './credit-types'; export { CustomFieldListKeysResponse, CustomFieldAddKeyParams, @@ -37,7 +30,6 @@ export { CustomFieldListKeysParams, CustomFieldRemoveKeyParams, CustomFieldSetValuesParams, - CustomFieldListKeysResponsesPage, CustomFields, } from './custom-fields'; export { @@ -45,6 +37,7 @@ export { CustomerDetail, CustomerCreateResponse, CustomerRetrieveResponse, + CustomerListResponse, CustomerArchiveResponse, CustomerListBillableMetricsResponse, CustomerListCostsResponse, @@ -57,17 +50,14 @@ export { CustomerSetIngestAliasesParams, CustomerSetNameParams, CustomerUpdateConfigParams, - CustomerDetailsPage, - CustomerListBillableMetricsResponsesPage, - CustomerListCostsResponsesPage, Customers, } from './customers/customers'; export { CustomerAlert, CustomerAlertRetrieveResponse, + CustomerAlertListResponse, CustomerAlertRetrieveParams, CustomerAlertListParams, - CustomerAlertsPage, CustomerAlerts, } from './customer-alerts'; export { DashboardGetEmbeddableURLResponse, DashboardGetEmbeddableURLParams, Dashboards } from './dashboards'; @@ -81,9 +71,6 @@ export { PlanListParams, PlanListChargesParams, PlanListCustomersParams, - PlanListResponsesPage, - PlanListChargesResponsesPage, - PlanListCustomersResponsesPage, Plans, } from './plans'; export { @@ -91,8 +78,6 @@ export { UsageListWithGroupsResponse, UsageListParams, UsageListWithGroupsParams, - UsageListResponsesPage, - UsageListWithGroupsResponsesPage, Usage, } from './usage'; export { Webhooks } from './webhooks'; diff --git a/src/resources/plans.ts b/src/resources/plans.ts index 8f451dd..4a84e4f 100644 --- a/src/resources/plans.ts +++ b/src/resources/plans.ts @@ -4,26 +4,21 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import { isRequestOptions } from '@metronome-industries/metronome/core'; import * as PlansAPI from '@metronome-industries/metronome/resources/plans'; -import * as CustomersAPI from '@metronome-industries/metronome/resources/customers/customers'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Plans extends APIResource { /** * List all available plans. */ - list( - query?: PlanListParams, - options?: Core.RequestOptions, - ): Core.PagePromise; - list(options?: Core.RequestOptions): Core.PagePromise; + list(query?: PlanListParams, options?: Core.RequestOptions): Core.APIPromise; + list(options?: Core.RequestOptions): Core.APIPromise; list( query: PlanListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.list({}, query); } - return this._client.getAPIList('/plans', PlanListResponsesPage, { query, ...options }); + return this._client.get('/plans', { query, ...options }); } /** @@ -40,23 +35,17 @@ export class Plans extends APIResource { planId: string, query?: PlanListChargesParams, options?: Core.RequestOptions, - ): Core.PagePromise; - listCharges( - planId: string, - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + listCharges(planId: string, options?: Core.RequestOptions): Core.APIPromise; listCharges( planId: string, query: PlanListChargesParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.listCharges(planId, {}, query); } - return this._client.getAPIList(`/planDetails/${planId}/charges`, PlanListChargesResponsesPage, { - query, - ...options, - }); + return this._client.get(`/planDetails/${planId}/charges`, { query, ...options }); } /** @@ -67,32 +56,20 @@ export class Plans extends APIResource { planId: string, query?: PlanListCustomersParams, options?: Core.RequestOptions, - ): Core.PagePromise; - listCustomers( - planId: string, - options?: Core.RequestOptions, - ): Core.PagePromise; + ): Core.APIPromise; + listCustomers(planId: string, options?: Core.RequestOptions): Core.APIPromise; listCustomers( planId: string, query: PlanListCustomersParams | Core.RequestOptions = {}, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { if (isRequestOptions(query)) { return this.listCustomers(planId, {}, query); } - return this._client.getAPIList(`/planDetails/${planId}/customers`, PlanListCustomersResponsesPage, { - query, - ...options, - }); + return this._client.get(`/planDetails/${planId}/customers`, { query, ...options }); } } -export class PlanListResponsesPage extends Page {} - -export class PlanListChargesResponsesPage extends Page {} - -export class PlanListCustomersResponsesPage extends Page {} - export interface PlanDetail { id: string; @@ -200,133 +177,324 @@ export namespace PlanDetail { } export interface PlanListResponse { - id: string; + data: Array; - description: string; + next_page: string | null; +} - name: string; +export namespace PlanListResponse { + export interface Data { + id: string; + + description: string; + + name: string; + } } export interface PlanGetDetailsResponse { - data: PlanDetail; + data: PlanGetDetailsResponse.Data; } -export interface PlanListChargesResponse { - id: string; +export namespace PlanGetDetailsResponse { + export interface Data { + id: string; - charge_type: 'usage' | 'fixed' | 'composite' | 'minimum' | 'seat'; + custom_fields: Record; - credit_type: PlanListChargesResponse.CreditType; + name: string; - custom_fields: Record; + credit_grants?: Array; - name: string; + description?: string; - prices: Array; + minimums?: Array; - product_name: string; + overage_rates?: Array; + } - quantity?: number; + export namespace Data { + export interface CreditGrant { + amount_granted: number; - /** - * Used in price ramps. Indicates how many billing periods pass before the charge - * applies. - */ - start_period?: number; + amount_granted_credit_type: CreditGrant.AmountGrantedCreditType; - /** - * Specifies how quantities for usage based charges will be converted. - */ - unit_conversion?: PlanListChargesResponse.UnitConversion; + amount_paid: number; + + amount_paid_credit_type: CreditGrant.AmountPaidCreditType; + + effective_duration: number; + + name: string; + + priority: string; + + send_invoice: boolean; + + reason?: string; + + recurrence_duration?: number; + + recurrence_interval?: number; + } + + export namespace CreditGrant { + export interface AmountGrantedCreditType { + id: string; + + name: string; + } + + export interface AmountPaidCreditType { + id: string; + + name: string; + } + } + + export interface Minimum { + credit_type: Minimum.CreditType; + + name: string; + + /** + * Used in price ramps. Indicates how many billing periods pass before the charge + * applies. + */ + start_period: number; + + value: number; + } + + export namespace Minimum { + export interface CreditType { + id: string; + + name: string; + } + } + + export interface OverageRate { + credit_type: OverageRate.CreditType; + + fiat_credit_type: OverageRate.FiatCreditType; + + /** + * Used in price ramps. Indicates how many billing periods pass before the charge + * applies. + */ + start_period: number; + + to_fiat_conversion_factor: number; + } + + export namespace OverageRate { + export interface CreditType { + id: string; + + name: string; + } + + export interface FiatCreditType { + id: string; + + name: string; + } + } + } +} + +export interface PlanListChargesResponse { + data: Array; + + next_page: string | null; } export namespace PlanListChargesResponse { - export interface CreditType { + export interface Data { id: string; - name: string; - } + charge_type: 'usage' | 'fixed' | 'composite' | 'minimum' | 'seat'; - export interface Price { - /** - * Used in pricing tiers. Indicates at what metric value the price applies. - */ - tier: number; + credit_type: Data.CreditType; - value: number; + custom_fields: Record; + + name: string; - collection_interval?: number; + prices: Array; - collection_schedule?: string; + product_id: string; + + product_name: string; quantity?: number; - } - /** - * Specifies how quantities for usage based charges will be converted. - */ - export interface UnitConversion { /** - * The conversion factor + * Used in price ramps. Indicates how many billing periods pass before the charge + * applies. + */ + start_period?: number; + + /** + * Specifies how quantities for usage based charges will be converted. */ - division_factor: number; + unit_conversion?: Data.UnitConversion; + } + + export namespace Data { + export interface CreditType { + id: string; + + name: string; + } + + export interface Price { + /** + * Used in pricing tiers. Indicates at what metric value the price applies. + */ + tier: number; + + value: number; + + collection_interval?: number; + + collection_schedule?: string; + + quantity?: number; + } /** - * Whether usage should be rounded down or up to the nearest whole number. If null, - * quantity will be rounded to 20 decimal places. + * Specifies how quantities for usage based charges will be converted. */ - rounding_behavior?: 'floor' | 'ceiling'; + export interface UnitConversion { + /** + * The conversion factor + */ + division_factor: number; + + /** + * Whether usage should be rounded down or up to the nearest whole number. If null, + * quantity will be rounded to 20 decimal places. + */ + rounding_behavior?: 'floor' | 'ceiling'; + } } } export interface PlanListCustomersResponse { - customer_details: CustomersAPI.CustomerDetail; + data: Array; - plan_details: PlanListCustomersResponse.PlanDetails; + next_page: string | null; } export namespace PlanListCustomersResponse { - export interface PlanDetails { - id: string; + export interface Data { + customer_details: Data.CustomerDetails; - custom_fields: Record; + plan_details: Data.PlanDetails; + } - customer_plan_id: string; + export namespace Data { + export interface CustomerDetails { + /** + * the Metronome ID of the customer + */ + id: string; - name: string; + current_billable_status: CustomerDetails.CurrentBillableStatus; - /** - * The start date of the plan - */ - starting_on: string; + custom_fields: Record; - /** - * The end date of the plan - */ - ending_before?: string | null; + customer_config: CustomerDetails.CustomerConfig; + + /** + * (deprecated, use ingest_aliases instead) the first ID (Metronome or ingest + * alias) that can be used in usage events + */ + external_id: string; + + /** + * aliases for this customer that can be used instead of the Metronome customer ID + * in usage events + */ + ingest_aliases: Array; + + name: string; + } + + export namespace CustomerDetails { + export interface CurrentBillableStatus { + value: 'billable' | 'unbillable'; + + effective_at?: string | null; + } + + export interface CustomerConfig { + /** + * The Salesforce account ID for the customer + */ + salesforce_account_id: string | null; + } + } + + export interface PlanDetails { + id: string; + + custom_fields: Record; + + customer_plan_id: string; + + name: string; + + /** + * The start date of the plan + */ + starting_on: string; + + /** + * The end date of the plan + */ + ending_before?: string | null; + } } } -export interface PlanListParams extends PageParams { +export interface PlanListParams { /** * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } -export interface PlanListChargesParams extends PageParams { +export interface PlanListChargesParams { /** * Max number of results that should be returned */ limit?: number; + + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; } -export interface PlanListCustomersParams extends PageParams { +export interface PlanListCustomersParams { /** * Max number of results that should be returned */ limit?: number; + /** + * Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Status of customers on a given plan. Defaults to `active`. * @@ -347,9 +515,6 @@ export namespace Plans { export import PlanGetDetailsResponse = PlansAPI.PlanGetDetailsResponse; export import PlanListChargesResponse = PlansAPI.PlanListChargesResponse; export import PlanListCustomersResponse = PlansAPI.PlanListCustomersResponse; - export import PlanListResponsesPage = PlansAPI.PlanListResponsesPage; - export import PlanListChargesResponsesPage = PlansAPI.PlanListChargesResponsesPage; - export import PlanListCustomersResponsesPage = PlansAPI.PlanListCustomersResponsesPage; export import PlanListParams = PlansAPI.PlanListParams; export import PlanListChargesParams = PlansAPI.PlanListChargesParams; export import PlanListCustomersParams = PlansAPI.PlanListCustomersParams; diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 56159bf..a95dacf 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -8,44 +8,58 @@ export interface Commit { type: 'PREPAID' | 'POSTPAID'; /** - * Only valid for "PREPAID" commits: The schedule that the customer will gain - * access to the credits purposed with this commit. + * The schedule that the customer will gain access to the credits purposed with + * this commit. */ access_schedule?: Commit.AccessSchedule; /** - * Only valid for "POSTPAID" commits: The total that the customer commits to - * consume. Must be >= 0. + * (deprecated) Only valid for "POSTPAID" commits: The total that the customer + * commits to consume. Must be > 0. */ amount?: number; + applicable_contract_ids?: Array; + applicable_product_ids?: Array; applicable_product_tags?: Array; + contract?: Commit.Contract; + + custom_fields?: Record; + description?: string; /** - * Only valid for "PREPAID" commits: The schedule that the customer will be - * invoiced for this commit. + * The contract that this commit will be billed on. + */ + invoice_contract?: Commit.InvoiceContract; + + /** + * The schedule that the customer will be invoiced for this commit. */ - invoice_schedule?: SchedulePointInTime; + invoice_schedule?: Commit.InvoiceSchedule; /** * A list of ordered events that impact the balance of a commit. For example, an * invoice deduction or a rollover. */ ledger?: Array< - | Commit.PrepaidCommitSegmentStartLedgerEntry - | Commit.PrepaidCommitAutomatedInvoiceDeductionLedgerEntry - | Commit.PrepaidCommitRolloverLedgerEntry - | Commit.PrepaidCommitExpirationLedgerEntry - | Commit.PrepaidCommitCanceledLedgerEntry - | Commit.PrepaidCommitCreditedLedgerEntry - | Commit.PostpaidCommitInitialBalanceLedgerEntry - | Commit.PostpaidCommitAutomatedInvoiceDeductionLedgerEntry - | Commit.PostpaidCommitTrueupLedgerEntry - | Commit.PrepaidCommitManualLedgerEntry + | Commit.UnionMember0 + | Commit.UnionMember1 + | Commit.UnionMember2 + | Commit.UnionMember3 + | Commit.UnionMember4 + | Commit.UnionMember5 + | Commit.UnionMember6 + | Commit.UnionMember7 + | Commit.UnionMember8 + | Commit.UnionMember9 + | Commit.UnionMember10 + | Commit.UnionMember11 + | Commit.UnionMember12 + | Commit.UnionMember13 >; name?: string; @@ -55,9 +69,20 @@ export interface Commit { */ netsuite_sales_order_id?: string; + /** + * If multiple commits are applicable, the one with the lower priority will apply + * first. + */ + priority?: number; + rolled_over_from?: Commit.RolledOverFrom; rollover_fraction?: number; + + /** + * This field's availability is dependent on your client's configuration. + */ + salesforce_opportunity_id?: string; } export namespace Commit { @@ -68,8 +93,8 @@ export namespace Commit { } /** - * Only valid for "PREPAID" commits: The schedule that the customer will gain - * access to the credits purposed with this commit. + * The schedule that the customer will gain access to the credits purposed with + * this commit. */ export interface AccessSchedule { schedule_items: Array; @@ -87,7 +112,41 @@ export namespace Commit { } } - export interface PrepaidCommitSegmentStartLedgerEntry { + export interface Contract { + id: string; + } + + /** + * The contract that this commit will be billed on. + */ + export interface InvoiceContract { + id: string; + } + + /** + * The schedule that the customer will be invoiced for this commit. + */ + export interface InvoiceSchedule { + schedule_items?: Array; + } + + export namespace InvoiceSchedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } + + export interface UnionMember0 { amount: number; segment_id: string; @@ -97,7 +156,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_SEGMENT_START'; } - export interface PrepaidCommitAutomatedInvoiceDeductionLedgerEntry { + export interface UnionMember1 { amount: number; invoice_id: string; @@ -109,7 +168,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION'; } - export interface PrepaidCommitRolloverLedgerEntry { + export interface UnionMember2 { amount: number; new_contract_id: string; @@ -121,7 +180,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_ROLLOVER'; } - export interface PrepaidCommitExpirationLedgerEntry { + export interface UnionMember3 { amount: number; segment_id: string; @@ -131,7 +190,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_EXPIRATION'; } - export interface PrepaidCommitCanceledLedgerEntry { + export interface UnionMember4 { amount: number; invoice_id: string; @@ -143,7 +202,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_CANCELED'; } - export interface PrepaidCommitCreditedLedgerEntry { + export interface UnionMember5 { amount: number; invoice_id: string; @@ -155,7 +214,7 @@ export namespace Commit { type: 'PREPAID_COMMIT_CREDITED'; } - export interface PostpaidCommitInitialBalanceLedgerEntry { + export interface UnionMember6 { amount: number; timestamp: string; @@ -163,17 +222,55 @@ export namespace Commit { type: 'POSTPAID_COMMIT_INITIAL_BALANCE'; } - export interface PostpaidCommitAutomatedInvoiceDeductionLedgerEntry { + export interface UnionMember7 { amount: number; invoice_id: string; + segment_id: string; + timestamp: string; type: 'POSTPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION'; } - export interface PostpaidCommitTrueupLedgerEntry { + export interface UnionMember8 { + amount: number; + + new_contract_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_ROLLOVER'; + } + + export interface UnionMember9 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_CANCELED'; + } + + export interface UnionMember10 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_CREDITED'; + } + + export interface UnionMember11 { amount: number; invoice_id: string; @@ -183,7 +280,7 @@ export namespace Commit { type: 'POSTPAID_COMMIT_TRUEUP'; } - export interface PrepaidCommitManualLedgerEntry { + export interface UnionMember12 { amount: number; reason: string; @@ -193,6 +290,16 @@ export namespace Commit { type: 'PREPAID_COMMIT_MANUAL'; } + export interface UnionMember13 { + amount: number; + + reason: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_MANUAL'; + } + export interface RolledOverFrom { commit_id: string; @@ -201,15 +308,15 @@ export namespace Commit { } export interface ContractWithoutAmendments { - commits: Array; + commits: Array; created_at: string; created_by: string; - overrides: Array; + overrides: Array; - scheduled_charges: Array; + scheduled_charges: Array; starting_at: string; @@ -220,7 +327,7 @@ export interface ContractWithoutAmendments { /** * This field's availability is dependent on your client's configuration. */ - discounts?: Array; + discounts?: Array; ending_before?: string; @@ -251,6 +358,407 @@ export interface ContractWithoutAmendments { } export namespace ContractWithoutAmendments { + export interface Commit { + id: string; + + product: Commit.Product; + + type: 'PREPAID' | 'POSTPAID'; + + /** + * The schedule that the customer will gain access to the credits purposed with + * this commit. + */ + access_schedule?: Commit.AccessSchedule; + + /** + * (deprecated) Only valid for "POSTPAID" commits: The total that the customer + * commits to consume. Must be > 0. + */ + amount?: number; + + applicable_contract_ids?: Array; + + applicable_product_ids?: Array; + + applicable_product_tags?: Array; + + contract?: Commit.Contract; + + custom_fields?: Record; + + description?: string; + + /** + * The contract that this commit will be billed on. + */ + invoice_contract?: Commit.InvoiceContract; + + /** + * The schedule that the customer will be invoiced for this commit. + */ + invoice_schedule?: Commit.InvoiceSchedule; + + /** + * A list of ordered events that impact the balance of a commit. For example, an + * invoice deduction or a rollover. + */ + ledger?: Array< + | Commit.UnionMember0 + | Commit.UnionMember1 + | Commit.UnionMember2 + | Commit.UnionMember3 + | Commit.UnionMember4 + | Commit.UnionMember5 + | Commit.UnionMember6 + | Commit.UnionMember7 + | Commit.UnionMember8 + | Commit.UnionMember9 + | Commit.UnionMember10 + | Commit.UnionMember11 + | Commit.UnionMember12 + | Commit.UnionMember13 + >; + + name?: string; + + /** + * This field's availability is dependent on your client's configuration. + */ + netsuite_sales_order_id?: string; + + /** + * If multiple commits are applicable, the one with the lower priority will apply + * first. + */ + priority?: number; + + rolled_over_from?: Commit.RolledOverFrom; + + rollover_fraction?: number; + + /** + * This field's availability is dependent on your client's configuration. + */ + salesforce_opportunity_id?: string; + } + + export namespace Commit { + export interface Product { + id: string; + + name: string; + } + + /** + * The schedule that the customer will gain access to the credits purposed with + * this commit. + */ + export interface AccessSchedule { + schedule_items: Array; + } + + export namespace AccessSchedule { + export interface ScheduleItem { + id: string; + + amount: number; + + ending_before: string; + + starting_at: string; + } + } + + export interface Contract { + id: string; + } + + /** + * The contract that this commit will be billed on. + */ + export interface InvoiceContract { + id: string; + } + + /** + * The schedule that the customer will be invoiced for this commit. + */ + export interface InvoiceSchedule { + schedule_items?: Array; + } + + export namespace InvoiceSchedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } + + export interface UnionMember0 { + amount: number; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_SEGMENT_START'; + } + + export interface UnionMember1 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION'; + } + + export interface UnionMember2 { + amount: number; + + new_contract_id: string; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_ROLLOVER'; + } + + export interface UnionMember3 { + amount: number; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_EXPIRATION'; + } + + export interface UnionMember4 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_CANCELED'; + } + + export interface UnionMember5 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_CREDITED'; + } + + export interface UnionMember6 { + amount: number; + + timestamp: string; + + type: 'POSTPAID_COMMIT_INITIAL_BALANCE'; + } + + export interface UnionMember7 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION'; + } + + export interface UnionMember8 { + amount: number; + + new_contract_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_ROLLOVER'; + } + + export interface UnionMember9 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_CANCELED'; + } + + export interface UnionMember10 { + amount: number; + + invoice_id: string; + + segment_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_CREDITED'; + } + + export interface UnionMember11 { + amount: number; + + invoice_id: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_TRUEUP'; + } + + export interface UnionMember12 { + amount: number; + + reason: string; + + timestamp: string; + + type: 'PREPAID_COMMIT_MANUAL'; + } + + export interface UnionMember13 { + amount: number; + + reason: string; + + timestamp: string; + + type: 'POSTPAID_COMMIT_MANUAL'; + } + + export interface RolledOverFrom { + commit_id: string; + + contract_id: string; + } + } + + export interface Override { + id: string; + + starting_at: string; + + applicable_product_tags?: Array; + + ending_before?: string; + + entitled?: boolean; + + multiplier?: number; + + overwrite_rate?: Override.OverwriteRate; + + product?: Override.Product; + + type?: 'OVERWRITE' | 'MULTIPLIER'; + } + + export namespace Override { + export interface OverwriteRate { + /** + * Default price. For FLAT rate_type, this must be >=0. For PERCENTAGE rate_type, + * this is a decimal fraction, e.g. use 0.1 for 10%; this must be >=0 and <=1. + */ + price: number; + + rate_type: 'FLAT' | 'flat' | 'PERCENTAGE' | 'percentage' | 'SUBSCRIPTION' | 'subscription'; + + /** + * Default proration configuration. Only vali for SUBSCRIPTION rate_type. + */ + is_prorated?: boolean; + + /** + * Default quantity. For SUBSCRIPTION rate_type, this must be >=0. + */ + quantity?: number; + } + + export interface Product { + id: string; + + name: string; + } + } + + export interface ScheduledCharge { + id: string; + + product: ScheduledCharge.Product; + + schedule: ScheduledCharge.Schedule; + + /** + * displayed on invoices + */ + name?: string; + + /** + * This field's availability is dependent on your client's configuration. + */ + netsuite_sales_order_id?: string; + } + + export namespace ScheduledCharge { + export interface Product { + id: string; + + name: string; + } + + export interface Schedule { + schedule_items?: Array; + } + + export namespace Schedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } + } + export interface Transition { from_contract_id: string; @@ -263,6 +771,49 @@ export namespace ContractWithoutAmendments { frequency: 'MONTHLY' | 'monthly' | 'QUARTERLY' | 'quarterly'; } + export interface Discount { + id: string; + + product: Discount.Product; + + schedule: Discount.Schedule; + + name?: string; + + /** + * This field's availability is dependent on your client's configuration. + */ + netsuite_sales_order_id?: string; + } + + export namespace Discount { + export interface Product { + id: string; + + name: string; + } + + export interface Schedule { + schedule_items?: Array; + } + + export namespace Schedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } + } + export interface ResellerRoyalty { fraction: number; @@ -272,6 +823,10 @@ export namespace ContractWithoutAmendments { starting_at: string; + applicable_product_ids?: Array; + + applicable_product_tags?: Array; + aws_account_number?: string; aws_offer_id?: string; @@ -327,7 +882,7 @@ export interface Discount { product: Discount.Product; - schedule: SchedulePointInTime; + schedule: Discount.Schedule; name?: string; @@ -343,6 +898,26 @@ export namespace Discount { name: string; } + + export interface Schedule { + schedule_items?: Array; + } + + export namespace Schedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } } export interface ID { @@ -449,7 +1024,7 @@ export interface ScheduledCharge { product: ScheduledCharge.Product; - schedule: SchedulePointInTime; + schedule: ScheduledCharge.Schedule; /** * displayed on invoices @@ -468,4 +1043,24 @@ export namespace ScheduledCharge { name: string; } + + export interface Schedule { + schedule_items?: Array; + } + + export namespace Schedule { + export interface ScheduleItem { + id: string; + + amount: number; + + invoice_id: string; + + quantity: number; + + timestamp: string; + + unit_price: number; + } + } } diff --git a/src/resources/usage.ts b/src/resources/usage.ts index ed23a1b..b167a4c 100644 --- a/src/resources/usage.ts +++ b/src/resources/usage.ts @@ -3,24 +3,15 @@ import * as Core from '@metronome-industries/metronome/core'; import { APIResource } from '@metronome-industries/metronome/resource'; import * as UsageAPI from '@metronome-industries/metronome/resources/usage'; -import { Page, type PageParams } from '@metronome-industries/metronome/pagination'; export class Usage extends APIResource { /** * Fetch aggregated usage data for multiple customers and billable-metrics, broken * into intervals of the specified length. */ - list( - params: UsageListParams, - options?: Core.RequestOptions, - ): Core.PagePromise { + list(params: UsageListParams, options?: Core.RequestOptions): Core.APIPromise { const { next_page, ...body } = params; - return this._client.getAPIList('/usage', UsageListResponsesPage, { - query: { next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/usage', { query: { next_page }, body, ...options }); } /** @@ -30,54 +21,61 @@ export class Usage extends APIResource { listWithGroups( params: UsageListWithGroupsParams, options?: Core.RequestOptions, - ): Core.PagePromise { + ): Core.APIPromise { const { limit, next_page, ...body } = params; - return this._client.getAPIList('/usage/groups', UsageListWithGroupsResponsesPage, { - query: { limit, next_page }, - body, - method: 'post', - ...options, - }); + return this._client.post('/usage/groups', { query: { limit, next_page }, body, ...options }); } } -export class UsageListResponsesPage extends Page {} +export interface UsageListResponse { + data: Array; -export class UsageListWithGroupsResponsesPage extends Page {} + next_page: string | null; +} -export interface UsageListResponse { - billable_metric_id: string; +export namespace UsageListResponse { + export interface Data { + billable_metric_id: string; - billable_metric_name: string; + billable_metric_name: string; - customer_id: string; + customer_id: string; - end_timestamp: string; + end_timestamp: string; - start_timestamp: string; + start_timestamp: string; - value: number | null; + value: number | null; - /** - * Values will be either a number or null. Null indicates that there were no - * matches for the group_by value. - */ - groups?: Record; + /** + * Values will be either a number or null. Null indicates that there were no + * matches for the group_by value. + */ + groups?: Record; + } } export interface UsageListWithGroupsResponse { - ending_before: string; + data: Array; - group_key: string | null; + next_page: string | null; +} - group_value: string | null; +export namespace UsageListWithGroupsResponse { + export interface Data { + ending_before: string; - starting_on: string; + group_key: string | null; + + group_value: string | null; - value: number | null; + starting_on: string; + + value: number | null; + } } -export interface UsageListParams extends PageParams { +export interface UsageListParams { /** * Body param: */ @@ -96,6 +94,11 @@ export interface UsageListParams extends PageParams { */ window_size: 'hour' | 'day' | 'none' | 'HOUR' | 'DAY' | 'NONE' | 'Hour' | 'Day' | 'None'; + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: A list of billable metrics to fetch usage for. If absent, all * billable metrics will be returned. @@ -132,7 +135,7 @@ export namespace UsageListParams { } } -export interface UsageListWithGroupsParams extends PageParams { +export interface UsageListWithGroupsParams { /** * Body param: */ @@ -156,6 +159,11 @@ export interface UsageListWithGroupsParams extends PageParams { */ limit?: number; + /** + * Query param: Cursor that indicates where the next page of results should start. + */ + next_page?: string; + /** * Body param: If true, will return the usage for the current billing period. Will * return an error if the customer is currently uncontracted or starting_on and @@ -197,8 +205,6 @@ export namespace UsageListWithGroupsParams { export namespace Usage { export import UsageListResponse = UsageAPI.UsageListResponse; export import UsageListWithGroupsResponse = UsageAPI.UsageListWithGroupsResponse; - export import UsageListResponsesPage = UsageAPI.UsageListResponsesPage; - export import UsageListWithGroupsResponsesPage = UsageAPI.UsageListWithGroupsResponsesPage; export import UsageListParams = UsageAPI.UsageListParams; export import UsageListWithGroupsParams = UsageAPI.UsageListWithGroupsParams; } diff --git a/src/uploads.ts b/src/uploads.ts index 2398baf..b138df3 100644 --- a/src/uploads.ts +++ b/src/uploads.ts @@ -146,8 +146,9 @@ async function getBytes(value: ToFileInput): Promise> { } } else { throw new Error( - `Unexpected data type: ${typeof value}; constructor: ${value?.constructor - ?.name}; props: ${propsForError(value)}`, + `Unexpected data type: ${typeof value}; constructor: ${ + value?.constructor?.name + }; props: ${propsForError(value)}`, ); } diff --git a/tests/api-resources/customers/customers.test.ts b/tests/api-resources/customers/customers.test.ts index 643b6f1..b6e6edc 100644 --- a/tests/api-resources/customers/customers.test.ts +++ b/tests/api-resources/customers/customers.test.ts @@ -223,7 +223,7 @@ describe('resource customers', () => { await expect( metronome.customers.updateConfig( 'd7abd0cd-4ae9-4db7-8676-e986a4ebd8dc', - { salesforce_account_id: '0015500001WO1ZiABL' }, + { leave_stripe_invoices_in_draft: true, salesforce_account_id: '0015500001WO1ZiABL' }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Metronome.NotFoundError); diff --git a/tests/index.test.ts b/tests/index.test.ts index afb518b..566e12c 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -223,17 +223,45 @@ describe('request building', () => { }); describe('retries', () => { - test('single retry', async () => { + test('retry on timeout', async () => { let count = 0; const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise => { - if (!count++) - return new Promise( - (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))), + if (count++ === 0) { + return new Promise((resolve, reject) => + signal?.addEventListener('abort', () => reject(new Error('timed out'))), ); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Metronome({ bearerToken: 'My Bearer Token', timeout: 10, fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + + test('retry on 429 with retry-after', async () => { + let count = 0; + const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Metronome({ bearerToken: 'My Bearer Token', timeout: 2000, fetch: testFetch }); + const client = new Metronome({ bearerToken: 'My Bearer Token', fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -244,5 +272,32 @@ describe('retries', () => { .then((r) => r.text()), ).toEqual(JSON.stringify({ a: 1 })); expect(count).toEqual(3); - }, 10000); + }); + + test('retry on 429 with retry-after-ms', async () => { + let count = 0; + const testFetch = async (url: RequestInfo, { signal }: RequestInit = {}): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After-Ms': '10', + }, + }); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Metronome({ bearerToken: 'My Bearer Token', fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); }); diff --git a/yarn.lock b/yarn.lock index 557e562..0972e9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1896,7 +1896,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== @@ -3058,14 +3058,15 @@ semver@^7.5.3, semver@^7.5.4: lru-cache "^6.0.0" set-function-length@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" + integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== dependencies: define-data-property "^1.1.1" - get-intrinsic "^1.2.1" + function-bind "^1.1.2" + get-intrinsic "^1.2.2" gopd "^1.0.1" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.1" shebang-command@^2.0.0: version "2.0.0"