Spaces:
Runtime error
Runtime error
File size: 2,763 Bytes
cd8bd0a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | /**
* db/caseMapping.ts β pure snake_case β camelCase column mapping.
*
* Extracted from db/core.ts (god-file decomposition): the column-name conversion
* helpers that translate raw SQLite rows (snake_case columns, 0/1 booleans, `_json`
* TEXT columns) into the camelCase shapes the domain modules consume. Pure β no DB
* handle, no module state β so they live as a co-located leaf that every db/ module
* (and core.ts itself) imports. core.ts re-exports all five so existing call sites that
* pull these helpers off the core module keep working unchanged.
*/
type JsonRecord = Record<string, unknown>;
export function toSnakeCase(str: string): string {
return str.replace(/([A-Z])/g, "_$1").toLowerCase();
}
export function toCamelCase(str: string): string {
return str.replace(/_([a-z])/g, (_: string, c: string) => c.toUpperCase());
}
export function objToSnake(obj: unknown): unknown {
if (!obj || typeof obj !== "object") return obj;
const result: JsonRecord = {};
for (const [k, v] of Object.entries(obj as JsonRecord)) {
result[toSnakeCase(k)] = v;
}
return result;
}
export function rowToCamel(row: unknown): JsonRecord | null {
if (!row) return null;
const result: JsonRecord = {};
for (const [k, v] of Object.entries(row as JsonRecord)) {
const camelKey = toCamelCase(k);
if (
camelKey === "isActive" ||
camelKey === "rateLimitProtection" ||
camelKey === "proxyEnabled" ||
camelKey === "perKeyProxyEnabled"
) {
result[camelKey] = v === 1 || v === true;
} else if (camelKey === "providerSpecificData" && typeof v === "string") {
try {
result[camelKey] = JSON.parse(v);
} catch {
result[camelKey] = v;
}
} else if (camelKey.endsWith("Json")) {
// Convention: any column with a `_json` suffix is JSON-encoded TEXT.
// Surface the parsed object under the friendlier name (key minus the
// "Json" suffix) β e.g. quotaWindowThresholdsJson β quotaWindowThresholds.
// A NULL/absent column normalizes to `baseKey: null` (not the suffixed
// key) so read and write paths expose a consistent shape.
const baseKey = camelKey.slice(0, -"Json".length);
if (typeof v === "string") {
try {
result[baseKey] = JSON.parse(v);
} catch {
result[baseKey] = null;
}
} else {
result[baseKey] = v == null ? null : v;
}
} else {
result[camelKey] = v;
}
}
return result;
}
export function cleanNulls(obj: unknown): JsonRecord {
const result: JsonRecord = {};
for (const [k, v] of Object.entries((obj as JsonRecord) || {})) {
if (v !== null && v !== undefined) {
result[k] = v;
}
}
return result;
}
|