mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 05:45:04 +03:00
128 lines
3.9 KiB
TypeScript
128 lines
3.9 KiB
TypeScript
import { getDbInstance, isBuildPhase, isCloud } from "./core";
|
|
|
|
type JsonRecord = Record<string, unknown>;
|
|
|
|
interface StatementLike<TRow = unknown> {
|
|
all: (...params: unknown[]) => TRow[];
|
|
get: (...params: unknown[]) => TRow | undefined;
|
|
run: (...params: unknown[]) => { changes?: number };
|
|
}
|
|
|
|
interface DbLike {
|
|
prepare: <TRow = unknown>(sql: string) => StatementLike<TRow>;
|
|
transaction: <T extends (...args: any[]) => unknown>(fn: T) => T;
|
|
}
|
|
|
|
interface KeyValueRow {
|
|
key: string;
|
|
value: string;
|
|
}
|
|
|
|
export interface ProviderLimitsCacheEntry {
|
|
quotas: JsonRecord | null;
|
|
plan: unknown;
|
|
message: string | null;
|
|
fetchedAt: string;
|
|
source?: string | null;
|
|
}
|
|
|
|
const PROVIDER_LIMITS_CACHE_NAMESPACE = "providerLimitsCache";
|
|
|
|
function parseJson(raw: string): unknown {
|
|
try {
|
|
return JSON.parse(raw) as unknown;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function toRecord(value: unknown): JsonRecord | null {
|
|
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : null;
|
|
}
|
|
|
|
function normalizeCacheEntry(value: unknown): ProviderLimitsCacheEntry | null {
|
|
const record = toRecord(value);
|
|
if (!record) return null;
|
|
|
|
const fetchedAt =
|
|
typeof record.fetchedAt === "string" && record.fetchedAt.trim() ? record.fetchedAt : null;
|
|
if (!fetchedAt) return null;
|
|
|
|
return {
|
|
quotas: toRecord(record.quotas),
|
|
plan: record.plan ?? null,
|
|
message: typeof record.message === "string" ? record.message : null,
|
|
fetchedAt,
|
|
source: typeof record.source === "string" ? record.source : null,
|
|
};
|
|
}
|
|
|
|
export function getProviderLimitsCache(connectionId: string): ProviderLimitsCacheEntry | null {
|
|
if (isBuildPhase || isCloud) return null;
|
|
const db = getDbInstance() as unknown as DbLike;
|
|
const row = db
|
|
.prepare("SELECT value FROM key_value WHERE namespace = ? AND key = ?")
|
|
.get(PROVIDER_LIMITS_CACHE_NAMESPACE, connectionId) as KeyValueRow | undefined;
|
|
if (!row?.value) return null;
|
|
return normalizeCacheEntry(parseJson(row.value));
|
|
}
|
|
|
|
export function getAllProviderLimitsCache(): Record<string, ProviderLimitsCacheEntry> {
|
|
if (isBuildPhase || isCloud) return {};
|
|
const db = getDbInstance() as unknown as DbLike;
|
|
const rows = db
|
|
.prepare("SELECT key, value FROM key_value WHERE namespace = ?")
|
|
.all(PROVIDER_LIMITS_CACHE_NAMESPACE) as KeyValueRow[];
|
|
|
|
const result: Record<string, ProviderLimitsCacheEntry> = {};
|
|
for (const row of rows) {
|
|
const parsed = normalizeCacheEntry(parseJson(row.value));
|
|
if (parsed) {
|
|
result[row.key] = parsed;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
export function setProviderLimitsCache(
|
|
connectionId: string,
|
|
entry: ProviderLimitsCacheEntry
|
|
): ProviderLimitsCacheEntry {
|
|
if (isBuildPhase || isCloud) return entry;
|
|
const db = getDbInstance() as unknown as DbLike;
|
|
db.prepare("INSERT OR REPLACE INTO key_value (namespace, key, value) VALUES (?, ?, ?)").run(
|
|
PROVIDER_LIMITS_CACHE_NAMESPACE,
|
|
connectionId,
|
|
JSON.stringify(entry)
|
|
);
|
|
return entry;
|
|
}
|
|
|
|
export function setProviderLimitsCacheBatch(
|
|
entries: Array<{ connectionId: string; entry: ProviderLimitsCacheEntry }>
|
|
): number {
|
|
if (isBuildPhase || isCloud || entries.length === 0) return 0;
|
|
const db = getDbInstance() as unknown as DbLike;
|
|
const insert = db.prepare(
|
|
"INSERT OR REPLACE INTO key_value (namespace, key, value) VALUES (?, ?, ?)"
|
|
);
|
|
const tx = db.transaction(
|
|
(items: Array<{ connectionId: string; entry: ProviderLimitsCacheEntry }>) => {
|
|
for (const item of items) {
|
|
insert.run(PROVIDER_LIMITS_CACHE_NAMESPACE, item.connectionId, JSON.stringify(item.entry));
|
|
}
|
|
}
|
|
);
|
|
tx(entries);
|
|
return entries.length;
|
|
}
|
|
|
|
export function deleteProviderLimitsCache(connectionId: string): void {
|
|
if (isBuildPhase || isCloud) return;
|
|
const db = getDbInstance() as unknown as DbLike;
|
|
db.prepare("DELETE FROM key_value WHERE namespace = ? AND key = ?").run(
|
|
PROVIDER_LIMITS_CACHE_NAMESPACE,
|
|
connectionId
|
|
);
|
|
}
|