Files
cfw-autumn/shared/api/customers/cusFeatures/previousVersions/apiCusFeatureV3.ts
2026-02-18 18:46:19 +00:00

156 lines
5.3 KiB
TypeScript

import { ApiFeatureType } from "@api/features/prevVersions/apiFeatureV0";
import { EntInterval } from "@models/productModels/intervals/entitlementInterval";
import { z } from "zod/v4";
// Descriptions
const breakdownDescriptions = {
interval: "The reset interval for this feature breakdown",
interval_count: "The number of intervals between usage resets",
balance:
"The remaining available balance for this interval. Only present for metered features",
usage: "The total amount of usage consumed in the current cycle",
included_usage:
"The amount of usage included in the customer's plan for this interval",
next_reset_at:
"Unix timestamp (in milliseconds) when the usage counter will reset for the next billing period",
usage_limit:
"The maximum usage allowed for this feature. null if unlimited or no limit is set",
overage_allowed:
"Whether the customer can continue using the feature beyond the usage limit. If false, access is blocked when limit is reached",
expires_at:
"Unix timestamp (in milliseconds) when the balance will expire. Only present for loose entitlements",
};
const coreFeatureDescriptions = {
interval:
"The billing interval (e.g., 'month', 'year') or 'multiple' if the feature has different intervals across subscriptions",
interval_count: "The number of intervals between usage resets",
unlimited:
"Whether the feature has unlimited usage with no restrictions or limits",
balance:
"The remaining available balance across all subscriptions for this feature (or all time for allocated features)",
usage:
"The total cumulative usage consumed in the current cycle across all subscriptions (or all time for allocated features)",
included_usage:
"The total amount of usage included in the customer's plan(s) for this feature",
next_reset_at:
"Unix timestamp (in milliseconds) when the usage counter will reset for the next cycle",
overage_allowed:
"Whether the customer can continue using the feature beyond the included usage. If false, access is blocked when limit is reached",
breakdown:
"Detailed breakdown by interval for features with multiple reset intervals across different subscriptions",
usage_limit:
"If this feature has a price, the usage limit indicates the maximum amount of usage the customer can use of this feature.",
};
export const ApiCusFeatureV3RolloverSchema = z.object({
balance: z.number().meta({
internal: true,
}),
expires_at: z.number().meta({
internal: true,
}),
});
// Version 3 of cus feature response
export const ApiCusFeatureV3BreakdownSchema = z.object({
interval: z.enum(EntInterval).nullable().meta({
description: breakdownDescriptions.interval,
}),
interval_count: z.number().nullish().meta({
description: breakdownDescriptions.interval_count,
}),
balance: z.number().nullish().meta({
description: breakdownDescriptions.balance,
}),
usage: z.number().nullish().meta({
description: breakdownDescriptions.usage,
}),
included_usage: z.number().nullish().meta({
description: breakdownDescriptions.included_usage,
}),
next_reset_at: z.number().nullish().meta({
description: breakdownDescriptions.next_reset_at,
}),
usage_limit: z.number().nullish().meta({
description: breakdownDescriptions.usage_limit,
}),
expires_at: z.number().nullish().meta({
description: breakdownDescriptions.expires_at,
}),
overage_allowed: z.boolean().nullish().meta({
description: breakdownDescriptions.overage_allowed,
}),
});
export const CoreCusFeatureSchema = z.object({
interval: z.enum(EntInterval).or(z.literal("multiple")).nullish().meta({
description: coreFeatureDescriptions.interval,
}),
interval_count: z.number().nullish().meta({
description: coreFeatureDescriptions.interval_count,
}),
unlimited: z.boolean().nullish().meta({
description: coreFeatureDescriptions.unlimited,
}),
balance: z.number().nullish().meta({
description: coreFeatureDescriptions.balance,
}),
usage: z.number().nullish().meta({
description: coreFeatureDescriptions.usage,
}),
included_usage: z.number().nullish().meta({
description: coreFeatureDescriptions.included_usage,
}),
next_reset_at: z.number().nullish().meta({
description: coreFeatureDescriptions.next_reset_at,
}),
overage_allowed: z.boolean().nullish().meta({
description: coreFeatureDescriptions.overage_allowed,
}),
breakdown: z.array(ApiCusFeatureV3BreakdownSchema).nullish().meta({
description:
"Detailed breakdown by interval for features with multiple intervals",
}),
credit_schema: z
.array(
z.object({
feature_id: z.string(),
credit_amount: z.number(),
}),
)
.nullish()
.meta({ internal: true }),
usage_limit: z.number().nullish().meta({
description: coreFeatureDescriptions.usage_limit,
}),
rollovers: z.array(ApiCusFeatureV3RolloverSchema).nullish().meta({
internal: true,
}),
});
export const ApiCusFeatureV3Schema = z
.object({
id: z.string().meta({
description: "The ID of the feature",
}),
type: z.enum(ApiFeatureType).meta({
description: "The type of the feature",
}),
name: z.string().nullish().meta({
description: "The name of the feature",
}),
})
.extend(CoreCusFeatureSchema.shape);
export type ApiCusFeatureV3 = z.infer<typeof ApiCusFeatureV3Schema>;
export type ApiCusFeatureV3Rollover = z.infer<
typeof ApiCusFeatureV3RolloverSchema
>;
export type ApiCusFeatureV3Breakdown = z.infer<
typeof ApiCusFeatureV3BreakdownSchema
>;