refactor(db): extrai row-parsers + tipos compartilhados de db/apiKeys.ts (#4943)

Integrated into release/v3.8.36
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-24 11:51:33 -03:00
committed by GitHub
parent f1589801ee
commit ca0fdddebf
4 changed files with 292 additions and 171 deletions

View File

@@ -27,6 +27,24 @@ import {
hasClaudeCodeWildcardPermission,
matchesWildcardPattern,
} from "./apiKeys/modelPermissions";
import {
parseAllowedModels,
parseAllowedCombos,
parseNoLog,
parseAutoResolve,
parseDisableNonPublicModels,
parseAllowUsageCommand,
parseIsActive,
parseAccessSchedule,
parseRateLimits,
parseAllowedConnections,
parseAllowedQuotas,
parseStringList,
parseNullableTimestamp,
parseIsBanned,
parseStreamDefaultMode,
} from "./apiKeys/rowParsers";
import type { AccessSchedule, RateLimitRule } from "./apiKeys/types";
// ──────────────── Performance Optimizations ────────────────
@@ -40,18 +58,8 @@ interface CacheEntry<TValue> {
value: TValue;
}
export interface RateLimitRule {
limit: number;
window: number;
}
export interface AccessSchedule {
enabled: boolean;
from: string;
until: string;
days: number[];
tz: string;
}
// Re-exported for the historical public surface (moved to ./apiKeys/types).
export type { AccessSchedule, RateLimitRule } from "./apiKeys/types";
interface ApiKeyMetadata {
id: string;
@@ -277,11 +285,6 @@ function evictIfNeeded<TKey, TValue>(cache: Map<TKey, TValue>) {
}
}
async function getModelPermissionCandidates(modelId: string): Promise<string[]> {
const candidates = new Set<string>();
addModelCandidate(candidates, modelId);
@@ -312,8 +315,6 @@ async function getModelPermissionCandidates(modelId: string): Promise<string[]>
return Array.from(candidates);
}
async function getPublishedModelLookupTarget(
modelId: string
): Promise<{ providerId: string; modelId: string } | null> {
@@ -341,8 +342,6 @@ async function getPublishedModelLookupTarget(
return null;
}
function ensureApiKeyColumn(
db: ApiKeysDbLike,
columnNames: Set<string>,
@@ -486,156 +485,6 @@ export async function getApiKeyById(id: string) {
return camelRow;
}
/**
* Helper function to safely parse allowed_models JSON
*/
function parseAllowedModels(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
function parseAllowedCombos(value: unknown): string[] {
return parseStringList(value);
}
function parseNoLog(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
function parseAutoResolve(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
function parseDisableNonPublicModels(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
function parseAllowUsageCommand(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
function parseIsActive(value: unknown): boolean {
// DEFAULT 1 — active unless explicitly set to 0
if (value === 0 || value === "0" || value === false) return false;
return true;
}
function parseAccessSchedule(value: unknown): AccessSchedule | null {
if (!value || typeof value !== "string" || value.trim() === "") return null;
try {
const parsed: unknown = JSON.parse(value);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
const obj = parsed as Record<string, unknown>;
if (
typeof obj["enabled"] !== "boolean" ||
typeof obj["from"] !== "string" ||
typeof obj["until"] !== "string" ||
!Array.isArray(obj["days"]) ||
typeof obj["tz"] !== "string"
) {
return null;
}
const days = (obj["days"] as unknown[]).filter(
(d): d is number => typeof d === "number" && Number.isInteger(d) && d >= 0 && d <= 6
);
return {
enabled: obj["enabled"],
from: obj["from"],
until: obj["until"],
days,
tz: obj["tz"],
};
} catch {
return null;
}
}
function parseRateLimits(value: unknown): RateLimitRule[] | null {
if (!value || typeof value !== "string" || value.trim() === "") return null;
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) return null;
return parsed.filter(
(rule: RateLimitRule) =>
typeof rule === "object" &&
rule !== null &&
typeof rule.limit === "number" &&
typeof rule.window === "number"
) as RateLimitRule[];
} catch {
return null;
}
}
/**
* Helper function to safely parse allowed_connections JSON
*/
function parseAllowedConnections(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
/**
* Helper function to safely parse allowed_quotas JSON
*/
function parseAllowedQuotas(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
function parseStringList(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") return [];
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
function parseNullableTimestamp(value: unknown): string | null {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed === "" ? null : trimmed;
}
function parseIsBanned(value: unknown): boolean {
return value === 1 || value === "1" || value === true;
}
function parseStreamDefaultMode(value: unknown): "legacy" | "json" {
return value === "json" ? "json" : "legacy";
}
async function hashKey(key: string): Promise<string> {
if (!key || typeof key !== "string") return "";
// CodeQL: This is intentionally SHA-256, NOT password hashing. API keys are

View File

@@ -0,0 +1,161 @@
/**
* db/apiKeys/rowParsers.ts — pure column parsers for persisted api_keys rows.
*
* Extracted verbatim from db/apiKeys.ts (god-file decomposition): the family of
* functions that coerce raw SQLite column values (JSON strings, 0/1 flags, nullable
* timestamps) into the typed shapes the host hydrates rows with. Pure — no DB handle,
* no caches, no side effects — so they live as a co-located leaf. Behavior-preserving
* move; apiKeys.ts imports them back for getApiKeys/getApiKeyById/getApiKeyMetadata.
*/
import type { AccessSchedule, RateLimitRule } from "./types";
/**
* Helper function to safely parse allowed_models JSON
*/
export function parseAllowedModels(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
export function parseAllowedCombos(value: unknown): string[] {
return parseStringList(value);
}
export function parseNoLog(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
export function parseAutoResolve(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
export function parseDisableNonPublicModels(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
export function parseAllowUsageCommand(value: unknown): boolean {
return value === true || value === 1 || value === "1";
}
export function parseIsActive(value: unknown): boolean {
// DEFAULT 1 — active unless explicitly set to 0
if (value === 0 || value === "0" || value === false) return false;
return true;
}
export function parseAccessSchedule(value: unknown): AccessSchedule | null {
if (!value || typeof value !== "string" || value.trim() === "") return null;
try {
const parsed: unknown = JSON.parse(value);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
const obj = parsed as Record<string, unknown>;
if (
typeof obj["enabled"] !== "boolean" ||
typeof obj["from"] !== "string" ||
typeof obj["until"] !== "string" ||
!Array.isArray(obj["days"]) ||
typeof obj["tz"] !== "string"
) {
return null;
}
const days = (obj["days"] as unknown[]).filter(
(d): d is number => typeof d === "number" && Number.isInteger(d) && d >= 0 && d <= 6
);
return {
enabled: obj["enabled"],
from: obj["from"],
until: obj["until"],
days,
tz: obj["tz"],
};
} catch {
return null;
}
}
export function parseRateLimits(value: unknown): RateLimitRule[] | null {
if (!value || typeof value !== "string" || value.trim() === "") return null;
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) return null;
return parsed.filter(
(rule: RateLimitRule) =>
typeof rule === "object" &&
rule !== null &&
typeof rule.limit === "number" &&
typeof rule.window === "number"
) as RateLimitRule[];
} catch {
return null;
}
}
/**
* Helper function to safely parse allowed_connections JSON
*/
export function parseAllowedConnections(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
/**
* Helper function to safely parse allowed_quotas JSON
*/
export function parseAllowedQuotas(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") {
return [];
}
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
export function parseStringList(value: unknown): string[] {
if (!value || typeof value !== "string" || value.trim() === "") return [];
try {
const parsed = JSON.parse(value);
return Array.isArray(parsed)
? parsed.filter((entry): entry is string => typeof entry === "string")
: [];
} catch {
return [];
}
}
export function parseNullableTimestamp(value: unknown): string | null {
if (typeof value !== "string") return null;
const trimmed = value.trim();
return trimmed === "" ? null : trimmed;
}
export function parseIsBanned(value: unknown): boolean {
return value === 1 || value === "1" || value === true;
}
export function parseStreamDefaultMode(value: unknown): "legacy" | "json" {
return value === "json" ? "json" : "legacy";
}

View File

@@ -0,0 +1,21 @@
/**
* db/apiKeys/types.ts — shared API-key value types.
*
* Extracted from db/apiKeys.ts (god-file decomposition): the persisted-row shapes
* that both the host module and the row-parser leaf need. Kept as a neutral leaf so
* apiKeys.ts and apiKeys/rowParsers.ts can import them without a cycle. apiKeys.ts
* re-exports both interfaces to preserve its historical public surface.
*/
export interface RateLimitRule {
limit: number;
window: number;
}
export interface AccessSchedule {
enabled: boolean;
from: string;
until: string;
days: number[];
tz: string;
}