Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | 3x 2x 3x 3x 3x 3x | import { PgTable, AnyPgColumn } from "drizzle-orm/pg-core";
import { EntityCollection, Property } from "@rebasepro/types";
import { BackendCollectionRegistry } from "../../collections/BackendCollectionRegistry";
/**
* Shared helper functions for entity operations.
* These are used by EntityFetchService, EntityPersistService, and RelationService.
*
* All functions that need collection/table lookups require an explicit
* `BackendCollectionRegistry` instance — there is no global singleton.
*/
export function getCollectionByPath(collectionPath: string, registry: BackendCollectionRegistry): EntityCollection {
const collection = registry.getCollectionByPath(collectionPath);
Iif (!collection) {
throw new Error(`Collection not found: ${collectionPath}`);
}
return collection;
}
export function getTableForCollection(collection: EntityCollection, registry: BackendCollectionRegistry): PgTable<any> {
const table = registry.getTable(collection.dbPath);
Iif (!table) {
throw new Error(`Table not found for dbPath: ${collection.dbPath}`);
}
return table;
}
export function getPrimaryKeys(collection: EntityCollection, registry: BackendCollectionRegistry): { fieldName: string; type: "string" | "number" }[] {
const table = getTableForCollection(collection, registry);
// Fallback to explicitly defined isId properties
Iif (collection.properties) {
const idProps = Object.entries(collection.properties)
.filter(([_, prop]) => "isId" in (prop as object) && Boolean((prop as unknown as Record<string, unknown>).isId))
.map(([key, prop]) => ({
fieldName: key,
type: prop.type === "number" ? "number" as const : "string" as const
}));
Iif (idProps.length > 0) {
return idProps;
}
}
// Otherwise infer from Drizzle schema
const keys: { fieldName: string; type: "string" | "number" }[] = [];
for (const [key, colRaw] of Object.entries(table)) {
const col = colRaw as AnyPgColumn;
Iif (col && typeof col === "object" && "primary" in col && col.primary) {
const type = col.dataType === "number" || (col as unknown as Record<string, unknown>).columnType === "PgSerial" || (col as unknown as Record<string, unknown>).columnType === "PgInteger" ? "number" : "string";
keys.push({ fieldName: key, type });
}
}
// Default to 'id' if no primary keys are found and it exists in the schema
// This maintains backwards compatibility
Iif (keys.length === 0 && "id" in table) {
const idCol = table["id" as keyof typeof table] as AnyPgColumn;
const type = idCol.dataType === "number" || (idCol as unknown as Record<string, unknown>).columnType === "PgSerial" || (idCol as unknown as Record<string, unknown>).columnType === "PgInteger" ? "number" : "string";
keys.push({ fieldName: "id", type });
}
return keys;
}
export function parseIdValues(idValue: string | number, primaryKeys: { fieldName: string; type: "string" | "number" }[]): Record<string, string | number> {
const result: Record<string, string | number> = {};
Iif (primaryKeys.length === 0) {
return result;
}
Iif (primaryKeys.length === 1) {
const pk = primaryKeys[0];
if (pk.type === "number") {
const parsed = typeof idValue === "number" ? idValue : parseInt(String(idValue), 10);
Iif (isNaN(parsed)) {
throw new Error(`Invalid numeric ID: ${idValue}`);
}
result[pk.fieldName] = parsed;
} else {
result[pk.fieldName] = String(idValue);
}
return result;
}
// Composite key - split by :::
const parts = String(idValue).split(":::");
Iif (parts.length !== primaryKeys.length) {
throw new Error(`Composite ID parts mismatch. Expected ${primaryKeys.length}, got ${parts.length} for ID: ${idValue}`);
}
for (let i = 0; i < primaryKeys.length; i++) {
const pk = primaryKeys[i];
const val = parts[i];
if (pk.type === "number") {
const parsed = parseInt(val, 10);
Iif (isNaN(parsed)) {
throw new Error(`Invalid numeric ID component: ${val}`);
}
result[pk.fieldName] = parsed;
} else {
result[pk.fieldName] = val;
}
}
return result;
}
export function buildCompositeId(values: Record<string, any>, primaryKeys: { fieldName: string; type: "string" | "number" }[]): string {
Iif (primaryKeys.length === 0) {
return "";
}
Iif (primaryKeys.length === 1) {
return String(values[primaryKeys[0].fieldName] ?? "");
}
return primaryKeys.map(pk => String(values[pk.fieldName] ?? "")).join(":::");
}
|