mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-10 22:20:25 +00:00
Add a Bun script to apply and normalize AGPL copyright headers across the default frontend source files. The script keeps headers idempotent, upgrades existing headers to the 2023-2026 QuantumNous range, and is exposed through `bun run copyright` for future maintenance.
132 lines
3.7 KiB
TypeScript
Vendored
132 lines
3.7 KiB
TypeScript
Vendored
/*
|
|
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 <https://www.gnu.org/licenses/>.
|
|
|
|
For commercial licensing, please contact support@quantumnous.com
|
|
*/
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { getSystemOptions } from '../api'
|
|
|
|
export function useSystemOptions() {
|
|
return useQuery({
|
|
queryKey: ['system-options'],
|
|
queryFn: getSystemOptions,
|
|
staleTime: 5 * 60 * 1000,
|
|
})
|
|
}
|
|
|
|
type ParseResult<T> =
|
|
| { success: true; value: T }
|
|
| { success: false; error: string; fallback: T }
|
|
|
|
function parseOptionValueSafe<T>(
|
|
value: string,
|
|
defaultValue: T
|
|
): ParseResult<T> {
|
|
if (typeof defaultValue === 'boolean') {
|
|
return {
|
|
success: true,
|
|
value: (value === 'true' || value === '1') as T,
|
|
}
|
|
}
|
|
|
|
if (typeof defaultValue === 'number') {
|
|
const trimmed = value.trim()
|
|
if (trimmed === '') {
|
|
return {
|
|
success: false,
|
|
error: 'Empty string for number field',
|
|
fallback: defaultValue,
|
|
}
|
|
}
|
|
const parsed = Number(trimmed)
|
|
if (Number.isNaN(parsed)) {
|
|
return {
|
|
success: false,
|
|
error: `Invalid number: "${value}"`,
|
|
fallback: defaultValue,
|
|
}
|
|
}
|
|
return { success: true, value: parsed as T }
|
|
}
|
|
|
|
if (Array.isArray(defaultValue)) {
|
|
try {
|
|
const parsed = JSON.parse(value)
|
|
if (!Array.isArray(parsed)) {
|
|
return {
|
|
success: false,
|
|
error: 'Expected array but got non-array JSON',
|
|
fallback: defaultValue,
|
|
}
|
|
}
|
|
|
|
if (defaultValue.length > 0) {
|
|
const expectedType = typeof defaultValue[0]
|
|
const invalidElement = parsed.find((el) => typeof el !== expectedType)
|
|
if (invalidElement !== undefined) {
|
|
return {
|
|
success: false,
|
|
error: `Array element type mismatch: expected ${expectedType}, got ${typeof invalidElement}`,
|
|
fallback: defaultValue,
|
|
}
|
|
}
|
|
}
|
|
|
|
return { success: true, value: parsed as T }
|
|
} catch (e) {
|
|
return {
|
|
success: false,
|
|
error: `JSON parse failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
fallback: defaultValue,
|
|
}
|
|
}
|
|
}
|
|
|
|
return { success: true, value: value as T }
|
|
}
|
|
|
|
export function getOptionValue<
|
|
T extends Record<string, string | number | boolean | unknown[]>,
|
|
>(options: Array<{ key: string; value: string }> | undefined, defaults: T): T {
|
|
if (!options) return defaults
|
|
|
|
const result = { ...defaults }
|
|
const errors: Array<{ key: string; error: string }> = []
|
|
|
|
options.forEach((option) => {
|
|
if (option.key in defaults) {
|
|
const parseResult = parseOptionValueSafe(
|
|
option.value,
|
|
defaults[option.key as keyof T]
|
|
)
|
|
|
|
if (parseResult.success) {
|
|
result[option.key as keyof T] = parseResult.value as T[keyof T]
|
|
} else {
|
|
result[option.key as keyof T] = parseResult.fallback as T[keyof T]
|
|
errors.push({ key: option.key, error: parseResult.error })
|
|
}
|
|
}
|
|
})
|
|
|
|
if (errors.length > 0 && import.meta.env.DEV) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn('[System Options] Parsing errors detected:', errors)
|
|
}
|
|
|
|
return result
|
|
}
|