/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { z } from 'zod' import type { TFunction } from 'i18next' import { parseQuotaFromDollars, quotaUnitsToDollars } from '@/lib/format' import { DEFAULT_GROUP } from '../constants' import { type ApiKeyFormData, type ApiKey } from '../types' // ============================================================================ // Form Schema // ============================================================================ export function getApiKeyFormSchema(t: TFunction) { return z .object({ name: z.string().min(1, t('Please enter a name')), remain_quota_dollars: z.number().optional(), expired_time: z.date().optional(), unlimited_quota: z.boolean(), model_limits: z.array(z.string()), allow_ips: z.string().optional(), group: z.string().optional(), cross_group_retry: z.boolean().optional(), tokenCount: z.number().min(1).optional(), }) .superRefine((data, ctx) => { if (data.unlimited_quota) { return } if ( data.remain_quota_dollars === undefined || data.remain_quota_dollars < 0 ) { ctx.addIssue({ code: 'custom', path: ['remain_quota_dollars'], message: t('Quota must be zero or greater'), }) } }) } export type ApiKeyFormValues = z.infer< ReturnType > // ============================================================================ // Form Defaults // ============================================================================ export const API_KEY_FORM_DEFAULT_VALUES: ApiKeyFormValues = { name: '', remain_quota_dollars: 10, expired_time: undefined, unlimited_quota: true, model_limits: [], allow_ips: '', group: DEFAULT_GROUP, cross_group_retry: true, tokenCount: 1, } export function getApiKeyFormDefaultValues( defaultUseAutoGroup: boolean ): ApiKeyFormValues { return { ...API_KEY_FORM_DEFAULT_VALUES, group: defaultUseAutoGroup ? 'auto' : DEFAULT_GROUP, cross_group_retry: defaultUseAutoGroup, } } // ============================================================================ // Form Data Transformation // ============================================================================ /** * Transform form data to API payload */ export function transformFormDataToPayload( data: ApiKeyFormValues ): ApiKeyFormData { return { name: data.name, remain_quota: data.unlimited_quota ? 0 : parseQuotaFromDollars(data.remain_quota_dollars || 0), expired_time: data.expired_time ? Math.floor(data.expired_time.getTime() / 1000) : -1, unlimited_quota: data.unlimited_quota, model_limits_enabled: data.model_limits.length > 0, model_limits: data.model_limits.join(','), allow_ips: data.allow_ips || '', group: data.group || '', cross_group_retry: data.group === 'auto' ? !!data.cross_group_retry : false, } } /** * Transform API key data to form defaults */ export function transformApiKeyToFormDefaults( apiKey: ApiKey ): ApiKeyFormValues { return { name: apiKey.name, remain_quota_dollars: apiKey.unlimited_quota ? 0 : quotaUnitsToDollars(apiKey.remain_quota), expired_time: apiKey.expired_time > 0 ? new Date(apiKey.expired_time * 1000) : undefined, unlimited_quota: apiKey.unlimited_quota, model_limits: apiKey.model_limits ? apiKey.model_limits.split(',').filter(Boolean) : [], allow_ips: apiKey.allow_ips || '', group: apiKey.group || DEFAULT_GROUP, cross_group_retry: !!apiKey.cross_group_retry, tokenCount: 1, } }