From 0a4a963635409cec72c99c9e723d6bde061cb4f8 Mon Sep 17 00:00:00 2001 From: "sdk-github-actions[bot]" Date: Mon, 7 Sep 2026 06:28:29 +0000 Subject: [PATCH] chore(release): auto --- .sdk.json | 50 ++++++- README.md | 4 + package-lock.json | 4 +- package.json | 2 +- src/README.md | 1 + src/environment.ts | 2 +- src/resources/v1/README.md | 1 + src/resources/v1/account/README.md | 30 +++++ src/resources/v1/account/index.ts | 1 + src/resources/v1/account/resource-client.ts | 33 +++++ src/resources/v1/index.ts | 1 + src/resources/v1/resource-client.ts | 13 ++ src/types/index.ts | 7 + ...onse-subscription-billing-interval-enum.ts | 6 + ...unt-list-response-subscription-discount.ts | 70 ++++++++++ ...ccount-list-response-subscription-price.ts | 70 ++++++++++ ...-list-response-subscription-status-enum.ts | 6 + .../v1-account-list-response-subscription.ts | 127 ++++++++++++++++++ .../v1-account-list-response-tier-enum.ts | 8 ++ src/types/v1-account-list-response.ts | 105 +++++++++++++++ test/v1-account.test.ts | 21 +++ 21 files changed, 557 insertions(+), 5 deletions(-) create mode 100644 src/resources/v1/account/README.md create mode 100644 src/resources/v1/account/index.ts create mode 100644 src/resources/v1/account/resource-client.ts create mode 100644 src/types/v1-account-list-response-subscription-billing-interval-enum.ts create mode 100644 src/types/v1-account-list-response-subscription-discount.ts create mode 100644 src/types/v1-account-list-response-subscription-price.ts create mode 100644 src/types/v1-account-list-response-subscription-status-enum.ts create mode 100644 src/types/v1-account-list-response-subscription.ts create mode 100644 src/types/v1-account-list-response-tier-enum.ts create mode 100644 src/types/v1-account-list-response.ts create mode 100644 test/v1-account.test.ts diff --git a/.sdk.json b/.sdk.json index a288390..4c020c5 100644 --- a/.sdk.json +++ b/.sdk.json @@ -1,5 +1,5 @@ { - "id": "88c7735c-a5b9-4bd6-aac7-a4e1dbdd3200", + "id": "a3774c17-32bb-4640-bcac-f894d270aca5", "tracked_paths": [ { "editable": true, @@ -49,6 +49,22 @@ "editable": true, "path": "src/resources/v1/README.md" }, + { + "editable": true, + "path": "src/resources/v1/account/README.md" + }, + { + "editable": true, + "path": "src/resources/v1/account/index.ts" + }, + { + "editable": false, + "path": "src/resources/v1/account/request-types.ts" + }, + { + "editable": true, + "path": "src/resources/v1/account/resource-client.ts" + }, { "editable": true, "path": "src/resources/v1/ai-clothes-changer/README.md" @@ -593,6 +609,34 @@ "editable": true, "path": "src/types/index.ts" }, + { + "editable": false, + "path": "src/types/v1-account-list-response-subscription-billing-interval-enum.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response-subscription-discount.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response-subscription-price.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response-subscription-status-enum.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response-subscription.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response-tier-enum.ts" + }, + { + "editable": false, + "path": "src/types/v1-account-list-response.ts" + }, { "editable": false, "path": "src/types/v1-ai-clothes-changer-create-body-assets-garment-type-enum.ts" @@ -1285,6 +1329,10 @@ "editable": false, "path": "src/types/v1-video-to-video-create-response.ts" }, + { + "editable": false, + "path": "test/v1-account.test.ts" + }, { "editable": false, "path": "test/v1-ai-clothes-changer.test.ts" diff --git a/README.md b/README.md index ac828e4..2e05c57 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,10 @@ Valid values are: `none`, `error`, `warn`, `info`, `debug` (case insensitive). I ## Module Documentation and Snippets +### [v1.account](src/resources/v1/account/README.md) + +- [list](src/resources/v1/account/README.md#list) - Get account details + ### [v1.aiClothesChanger](src/resources/v1/ai-clothes-changer/README.md) - [create](src/resources/v1/ai-clothes-changer/README.md#create) - AI Clothes Changer diff --git a/package-lock.json b/package-lock.json index 2c42678..a6848a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magic-hour", - "version": "0.74.1", + "version": "0.75.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magic-hour", - "version": "0.74.1", + "version": "0.75.0", "license": "MIT", "dependencies": { "make-api-request-js": "^0.2.1", diff --git a/package.json b/package.json index 7525a28..4326601 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magic-hour", - "version": "0.74.1", + "version": "0.75.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/src/README.md b/src/README.md index 9da01a7..918c235 100644 --- a/src/README.md +++ b/src/README.md @@ -2,6 +2,7 @@ ## Submodules +- [account](resources/v1/account/README.md) - account - [ai-clothes-changer](resources/v1/ai-clothes-changer/README.md) - ai-clothes-changer - [ai-face-editor](resources/v1/ai-face-editor/README.md) - ai-face-editor - [ai-gif-generator](resources/v1/ai-gif-generator/README.md) - ai-gif-generator diff --git a/src/environment.ts b/src/environment.ts index 87e73f7..479a40f 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -1,4 +1,4 @@ export enum Environment { Environment = "https://api.magichour.ai", - MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.78.1", + MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.79.0", } diff --git a/src/resources/v1/README.md b/src/resources/v1/README.md index adf38aa..2488fd8 100644 --- a/src/resources/v1/README.md +++ b/src/resources/v1/README.md @@ -2,6 +2,7 @@ ## Submodules +- [account](account/README.md) - account - [ai-clothes-changer](ai-clothes-changer/README.md) - ai-clothes-changer - [ai-face-editor](ai-face-editor/README.md) - ai-face-editor - [ai-gif-generator](ai-gif-generator/README.md) - ai-gif-generator diff --git a/src/resources/v1/account/README.md b/src/resources/v1/account/README.md new file mode 100644 index 0000000..b33a0e5 --- /dev/null +++ b/src/resources/v1/account/README.md @@ -0,0 +1,30 @@ +# v1.account + +## Module Functions + +### Get account details + +Get the current credit balance and subscription details of the account that owns the API key. + +**API Endpoint**: `GET /v1/account` + +#### Example Snippet + +```typescript +import { Client } from "magic-hour"; + +const client = new Client({ token: process.env["API_TOKEN"]!! }); +const res = await client.v1.account.list(); +``` + +#### Response + +##### Type + +[V1AccountListResponse](/src/types/v1-account-list-response.ts) + +##### Example + +```typescript +{"credits": 12500, "email": "user@example.com", "id": "cuid-example", "subscription": {"billingInterval": "month", "cancelAtPeriodEnd": false, "currentPeriodEnd": "2026-10-01T00:00:00.000Z", "discount": {"amountOff": 123, "percentOff": 20.0}, "name": "Pro", "price": {"amount": 4900, "currency": "usd"}, "status": "active"}, "tier": "pro"} +``` diff --git a/src/resources/v1/account/index.ts b/src/resources/v1/account/index.ts new file mode 100644 index 0000000..de1a56d --- /dev/null +++ b/src/resources/v1/account/index.ts @@ -0,0 +1 @@ +export { AccountClient } from "./resource-client"; diff --git a/src/resources/v1/account/resource-client.ts b/src/resources/v1/account/resource-client.ts new file mode 100644 index 0000000..e886683 --- /dev/null +++ b/src/resources/v1/account/resource-client.ts @@ -0,0 +1,33 @@ +import { + ApiPromise, + CoreClient, + CoreResourceClient, + RequestOptions, + ResourceClientOptions, +} from "make-api-request-js"; + +import * as types from "magic-hour/types"; +import { Schemas$V1AccountListResponse } from "magic-hour/types/v1-account-list-response"; + +export class AccountClient extends CoreResourceClient { + constructor(coreClient: CoreClient, opts: ResourceClientOptions) { + super(coreClient, opts); + } + + /** + * Get account details + * + * Get the current credit balance and subscription details of the account that owns the API key. + * + * GET /v1/account + */ + list(opts?: RequestOptions): ApiPromise { + return this._client.makeRequest({ + method: "get", + path: "/v1/account", + auth: ["bearerAuth"], + responseSchema: Schemas$V1AccountListResponse.in, + opts, + }); + } +} diff --git a/src/resources/v1/index.ts b/src/resources/v1/index.ts index ac5d7f3..0c5afec 100644 --- a/src/resources/v1/index.ts +++ b/src/resources/v1/index.ts @@ -1,3 +1,4 @@ +export * as account from "./account"; export * as aiClothesChanger from "./ai-clothes-changer"; export * as aiFaceEditor from "./ai-face-editor"; export * as aiGifGenerator from "./ai-gif-generator"; diff --git a/src/resources/v1/resource-client.ts b/src/resources/v1/resource-client.ts index f829e3a..dd3238f 100644 --- a/src/resources/v1/resource-client.ts +++ b/src/resources/v1/resource-client.ts @@ -4,6 +4,7 @@ import { ResourceClientOptions, } from "make-api-request-js"; +import { AccountClient } from "magic-hour/resources/v1/account"; import { AiClothesChangerClient } from "magic-hour/resources/v1/ai-clothes-changer"; import { AiFaceEditorClient } from "magic-hour/resources/v1/ai-face-editor"; import { AiGifGeneratorClient } from "magic-hour/resources/v1/ai-gif-generator"; @@ -38,6 +39,7 @@ import { VideoProjectsClient } from "magic-hour/resources/v1/video-projects"; import { VideoToVideoClient } from "magic-hour/resources/v1/video-to-video"; export class V1Client extends CoreResourceClient { + private _accountLazy?: AccountClient; // lazy-loading cache private _characterReplaceLazy?: CharacterReplaceClient; // lazy-loading cache private _aiVideoEditorLazy?: AiVideoEditorClient; // lazy-loading cache private _audioToVideoLazy?: AudioToVideoClient; // lazy-loading cache @@ -75,6 +77,7 @@ export class V1Client extends CoreResourceClient { constructor(coreClient: CoreClient, opts: ResourceClientOptions) { super(coreClient, opts); if (this._opts.lazyLoad === false) { + this.account; this.aiClothesChanger; this.aiFaceEditor; this.aiGifGenerator; @@ -455,4 +458,14 @@ export class V1Client extends CoreResourceClient { )) ); } + + get account(): AccountClient { + return ( + this._accountLazy ?? + (this._accountLazy = new (require("./account").AccountClient)( + this._client, + this._opts, + )) + ); + } } diff --git a/src/types/index.ts b/src/types/index.ts index af86115..f0a22df 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,10 @@ +export { V1AccountListResponse } from "./v1-account-list-response"; +export { V1AccountListResponseSubscription } from "./v1-account-list-response-subscription"; +export { V1AccountListResponseSubscriptionBillingIntervalEnum } from "./v1-account-list-response-subscription-billing-interval-enum"; +export { V1AccountListResponseSubscriptionDiscount } from "./v1-account-list-response-subscription-discount"; +export { V1AccountListResponseSubscriptionPrice } from "./v1-account-list-response-subscription-price"; +export { V1AccountListResponseSubscriptionStatusEnum } from "./v1-account-list-response-subscription-status-enum"; +export { V1AccountListResponseTierEnum } from "./v1-account-list-response-tier-enum"; export { V1AiClothesChangerCreateBody } from "./v1-ai-clothes-changer-create-body"; export { V1AiClothesChangerCreateBodyAssets } from "./v1-ai-clothes-changer-create-body-assets"; export { V1AiClothesChangerCreateBodyAssetsGarmentTypeEnum } from "./v1-ai-clothes-changer-create-body-assets-garment-type-enum"; diff --git a/src/types/v1-account-list-response-subscription-billing-interval-enum.ts b/src/types/v1-account-list-response-subscription-billing-interval-enum.ts new file mode 100644 index 0000000..7be625e --- /dev/null +++ b/src/types/v1-account-list-response-subscription-billing-interval-enum.ts @@ -0,0 +1,6 @@ +/** + * How often the subscription is billed. `null` if unknown. + */ +export type V1AccountListResponseSubscriptionBillingIntervalEnum = + | "month" + | "year"; diff --git a/src/types/v1-account-list-response-subscription-discount.ts b/src/types/v1-account-list-response-subscription-discount.ts new file mode 100644 index 0000000..9a94495 --- /dev/null +++ b/src/types/v1-account-list-response-subscription-discount.ts @@ -0,0 +1,70 @@ +import { zodTransform } from "make-api-request-js"; +import * as z from "zod"; + +/** + * Discount applied to the subscription. `null` if no discount is applied. + */ +export type V1AccountListResponseSubscriptionDiscount = { + /** + * Fixed amount taken off `price.amount` each billing interval, in the smallest unit of the currency. `null` if the discount is a percentage. + */ + amountOff: number | null; + /** + * Percentage taken off `price.amount` each billing interval. `null` if the discount is a fixed amount. + */ + percentOff: number | null; +}; + +/** + * @internal + * V1AccountListResponseSubscriptionDiscount without any key transformation, this is what + * we expect to come in as network data + */ +export type External$V1AccountListResponseSubscriptionDiscount = { + amount_off: number | null; + percent_off: number | null; +}; + +/** + * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscriptionDiscount + */ +const SchemaIn$V1AccountListResponseSubscriptionDiscount: z.ZodType< + V1AccountListResponseSubscriptionDiscount, // output type of this zod object + z.ZodTypeDef, + unknown +> = z + .object({ + amount_off: z.number().int().nullable(), + percent_off: z.number().nullable(), + }) + .transform((obj) => { + return zodTransform(obj, { + amount_off: "amountOff", + percent_off: "percentOff", + }); + }); + +/** + * @internal + * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscriptionDiscount + */ +const SchemaOut$V1AccountListResponseSubscriptionDiscount: z.ZodType< + External$V1AccountListResponseSubscriptionDiscount, // output type of this zod object + z.ZodTypeDef, + V1AccountListResponseSubscriptionDiscount // the object to be transformed +> = z + .object({ + amountOff: z.number().int().nullable(), + percentOff: z.number().nullable(), + }) + .transform((obj) => { + return zodTransform(obj, { + amountOff: "amount_off", + percentOff: "percent_off", + }); + }); + +export const Schemas$V1AccountListResponseSubscriptionDiscount = { + in: SchemaIn$V1AccountListResponseSubscriptionDiscount, + out: SchemaOut$V1AccountListResponseSubscriptionDiscount, +}; diff --git a/src/types/v1-account-list-response-subscription-price.ts b/src/types/v1-account-list-response-subscription-price.ts new file mode 100644 index 0000000..bac6ee1 --- /dev/null +++ b/src/types/v1-account-list-response-subscription-price.ts @@ -0,0 +1,70 @@ +import { zodTransform } from "make-api-request-js"; +import * as z from "zod"; + +/** + * V1AccountListResponseSubscriptionPrice + */ +export type V1AccountListResponseSubscriptionPrice = { + /** + * Price charged per billing interval, in the smallest unit of the currency (e.g. 4900 is $49.00 for `usd`). Discounts are not applied. + */ + amount: number; + /** + * Three-letter ISO 4217 currency code, lowercase. + */ + currency: string; +}; + +/** + * @internal + * V1AccountListResponseSubscriptionPrice without any key transformation, this is what + * we expect to come in as network data + */ +export type External$V1AccountListResponseSubscriptionPrice = { + amount: number; + currency: string; +}; + +/** + * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscriptionPrice + */ +const SchemaIn$V1AccountListResponseSubscriptionPrice: z.ZodType< + V1AccountListResponseSubscriptionPrice, // output type of this zod object + z.ZodTypeDef, + unknown +> = z + .object({ + amount: z.number().int(), + currency: z.string(), + }) + .transform((obj) => { + return zodTransform(obj, { + amount: "amount", + currency: "currency", + }); + }); + +/** + * @internal + * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscriptionPrice + */ +const SchemaOut$V1AccountListResponseSubscriptionPrice: z.ZodType< + External$V1AccountListResponseSubscriptionPrice, // output type of this zod object + z.ZodTypeDef, + V1AccountListResponseSubscriptionPrice // the object to be transformed +> = z + .object({ + amount: z.number().int(), + currency: z.string(), + }) + .transform((obj) => { + return zodTransform(obj, { + amount: "amount", + currency: "currency", + }); + }); + +export const Schemas$V1AccountListResponseSubscriptionPrice = { + in: SchemaIn$V1AccountListResponseSubscriptionPrice, + out: SchemaOut$V1AccountListResponseSubscriptionPrice, +}; diff --git a/src/types/v1-account-list-response-subscription-status-enum.ts b/src/types/v1-account-list-response-subscription-status-enum.ts new file mode 100644 index 0000000..b5dfdd3 --- /dev/null +++ b/src/types/v1-account-list-response-subscription-status-enum.ts @@ -0,0 +1,6 @@ +/** + * Status of the subscription. + * - `active`: payments are up to date. + * - `past_due`: the latest payment failed. `tier` is `free` until payment succeeds. The subscription is canceled if payment keeps failing. + */ +export type V1AccountListResponseSubscriptionStatusEnum = "active" | "past_due"; diff --git a/src/types/v1-account-list-response-subscription.ts b/src/types/v1-account-list-response-subscription.ts new file mode 100644 index 0000000..5116a6d --- /dev/null +++ b/src/types/v1-account-list-response-subscription.ts @@ -0,0 +1,127 @@ +import { zodTransform } from "make-api-request-js"; +import * as z from "zod"; + +import { + External$V1AccountListResponseSubscriptionDiscount, + Schemas$V1AccountListResponseSubscriptionDiscount, + V1AccountListResponseSubscriptionDiscount, +} from "./v1-account-list-response-subscription-discount"; +import { + External$V1AccountListResponseSubscriptionPrice, + Schemas$V1AccountListResponseSubscriptionPrice, + V1AccountListResponseSubscriptionPrice, +} from "./v1-account-list-response-subscription-price"; + +/** + * Details of the account's subscription plan. `null` if the account has no subscription, e.g. a free account, an account that only purchased credit packs, or an account on usage-based API pricing. + * + * Reflects the plan currently configured on the subscription. If a plan change is scheduled, `tier` stays on the current plan until the next payment succeeds, so `tier` and `name` can briefly disagree. + */ +export type V1AccountListResponseSubscription = { + /** + * How often the subscription is billed. `null` if unknown. + */ + billingInterval: ("month" | "year") | null; + /** + * Whether the subscription is scheduled to end at `current_period_end` instead of renewing. The subscription stays usable until then. + */ + cancelAtPeriodEnd: boolean; + /** + * End of the current billing period, in ISO 8601 format. The subscription renews at this time, or ends if `cancel_at_period_end` is `true`. + */ + currentPeriodEnd: string | null; + /** + * Discount applied to the subscription. `null` if no discount is applied. + */ + discount: V1AccountListResponseSubscriptionDiscount | null; + /** + * Name of the current subscription plan, e.g. `Creator`, `Pro`, `Pro Plus`, `Business`. `null` if the plan cannot be determined. Use `tier` for a machine-readable value. + */ + name: string | null; + price: V1AccountListResponseSubscriptionPrice; + /** + * Status of the subscription. + * - `active`: payments are up to date. + * - `past_due`: the latest payment failed. `tier` is `free` until payment succeeds. The subscription is canceled if payment keeps failing. + */ + status: "active" | "past_due"; +}; + +/** + * @internal + * V1AccountListResponseSubscription without any key transformation, this is what + * we expect to come in as network data + */ +export type External$V1AccountListResponseSubscription = { + billing_interval: ("month" | "year") | null; + cancel_at_period_end: boolean; + current_period_end: string | null; + discount: External$V1AccountListResponseSubscriptionDiscount | null; + name: string | null; + price: External$V1AccountListResponseSubscriptionPrice; + status: "active" | "past_due"; +}; + +/** + * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponseSubscription + */ +const SchemaIn$V1AccountListResponseSubscription: z.ZodType< + V1AccountListResponseSubscription, // output type of this zod object + z.ZodTypeDef, + unknown +> = z + .object({ + billing_interval: z.enum(["month", "year"]).nullable(), + cancel_at_period_end: z.boolean(), + current_period_end: z.string().nullable(), + discount: Schemas$V1AccountListResponseSubscriptionDiscount.in.nullable(), + name: z.string().nullable(), + price: Schemas$V1AccountListResponseSubscriptionPrice.in, + status: z.enum(["active", "past_due"]), + }) + .transform((obj) => { + return zodTransform(obj, { + billing_interval: "billingInterval", + cancel_at_period_end: "cancelAtPeriodEnd", + current_period_end: "currentPeriodEnd", + discount: "discount", + name: "name", + price: "price", + status: "status", + }); + }); + +/** + * @internal + * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponseSubscription + */ +const SchemaOut$V1AccountListResponseSubscription: z.ZodType< + External$V1AccountListResponseSubscription, // output type of this zod object + z.ZodTypeDef, + V1AccountListResponseSubscription // the object to be transformed +> = z + .object({ + billingInterval: z.enum(["month", "year"]).nullable(), + cancelAtPeriodEnd: z.boolean(), + currentPeriodEnd: z.string().nullable(), + discount: Schemas$V1AccountListResponseSubscriptionDiscount.out.nullable(), + name: z.string().nullable(), + price: Schemas$V1AccountListResponseSubscriptionPrice.out, + status: z.enum(["active", "past_due"]), + }) + .transform((obj) => { + return zodTransform(obj, { + billingInterval: "billing_interval", + cancelAtPeriodEnd: "cancel_at_period_end", + currentPeriodEnd: "current_period_end", + discount: "discount", + name: "name", + price: "price", + status: "status", + }); + }); + +export const Schemas$V1AccountListResponseSubscription = { + in: SchemaIn$V1AccountListResponseSubscription, + out: SchemaOut$V1AccountListResponseSubscription, +}; diff --git a/src/types/v1-account-list-response-tier-enum.ts b/src/types/v1-account-list-response-tier-enum.ts new file mode 100644 index 0000000..a45b1a1 --- /dev/null +++ b/src/types/v1-account-list-response-tier-enum.ts @@ -0,0 +1,8 @@ +/** + * Subscription tier in effect for the account. `free` if there is no active subscription, including while a subscription is `past_due`. + */ +export type V1AccountListResponseTierEnum = + | "business" + | "creator" + | "free" + | "pro"; diff --git a/src/types/v1-account-list-response.ts b/src/types/v1-account-list-response.ts new file mode 100644 index 0000000..254b4d0 --- /dev/null +++ b/src/types/v1-account-list-response.ts @@ -0,0 +1,105 @@ +import { zodTransform } from "make-api-request-js"; +import * as z from "zod"; + +import { + External$V1AccountListResponseSubscription, + Schemas$V1AccountListResponseSubscription, + V1AccountListResponseSubscription, +} from "./v1-account-list-response-subscription"; + +/** + * V1AccountListResponse + */ +export type V1AccountListResponse = { + /** + * Credits currently available to spend. Includes subscription credits and any purchased credit packs. + */ + credits: number; + /** + * Email address of the account. + */ + email: string | null; + /** + * Unique ID of the account that owns the API key. + */ + id: string; + /** + * Details of the account's subscription plan. `null` if the account has no subscription, e.g. a free account, an account that only purchased credit packs, or an account on usage-based API pricing. + * + * Reflects the plan currently configured on the subscription. If a plan change is scheduled, `tier` stays on the current plan until the next payment succeeds, so `tier` and `name` can briefly disagree. + */ + subscription: V1AccountListResponseSubscription | null; + /** + * Subscription tier in effect for the account. `free` if there is no active subscription, including while a subscription is `past_due`. + */ + tier: "business" | "creator" | "free" | "pro"; +}; + +/** + * @internal + * V1AccountListResponse without any key transformation, this is what + * we expect to come in as network data + */ +export type External$V1AccountListResponse = { + credits: number; + email: string | null; + id: string; + subscription: External$V1AccountListResponseSubscription | null; + tier: "business" | "creator" | "free" | "pro"; +}; + +/** + * Takes network data, validates it, and transforms keys to match typescript object V1AccountListResponse + */ +const SchemaIn$V1AccountListResponse: z.ZodType< + V1AccountListResponse, // output type of this zod object + z.ZodTypeDef, + unknown +> = z + .object({ + credits: z.number().int(), + email: z.string().nullable(), + id: z.string(), + subscription: Schemas$V1AccountListResponseSubscription.in.nullable(), + tier: z.enum(["business", "creator", "free", "pro"]), + }) + .transform((obj) => { + return zodTransform(obj, { + credits: "credits", + email: "email", + id: "id", + subscription: "subscription", + tier: "tier", + }); + }); + +/** + * @internal + * Takes typescript data, validates it, and maps keys to match the expected external object External$V1AccountListResponse + */ +const SchemaOut$V1AccountListResponse: z.ZodType< + External$V1AccountListResponse, // output type of this zod object + z.ZodTypeDef, + V1AccountListResponse // the object to be transformed +> = z + .object({ + credits: z.number().int(), + email: z.string().nullable(), + id: z.string(), + subscription: Schemas$V1AccountListResponseSubscription.out.nullable(), + tier: z.enum(["business", "creator", "free", "pro"]), + }) + .transform((obj) => { + return zodTransform(obj, { + credits: "credits", + email: "email", + id: "id", + subscription: "subscription", + tier: "tier", + }); + }); + +export const Schemas$V1AccountListResponse = { + in: SchemaIn$V1AccountListResponse, + out: SchemaOut$V1AccountListResponse, +}; diff --git a/test/v1-account.test.ts b/test/v1-account.test.ts new file mode 100644 index 0000000..e78fa57 --- /dev/null +++ b/test/v1-account.test.ts @@ -0,0 +1,21 @@ +import { Client, Environment } from "magic-hour"; + +describe("tests client.v1.account.list", () => { + test.concurrent( + "GET /v1/account | testId: success_all_params | Success test with response schema validation. Expects status code 200", + async () => { + const client = new Client({ + token: "API_TOKEN", + environment: Environment.MockServer, + }); + // Get both raw response for status and parsed response for data + const [rawResponse, response] = await Promise.all([ + client.v1.account.list().asResponse(), + client.v1.account.list(), + ]); + expect(rawResponse.status).toBe(200); // Exact status code match + // Response body automatically validated by Zod schema during deserialization + expect(response).toBeDefined(); + }, + ); +});