link-stack/metamigo-common/records/record-info.ts

134 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-02-13 12:41:30 +00:00
/* eslint-disable @typescript-eslint/ban-types,@typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types */
import at from "lodash/at";
import pick from "lodash/pick";
export interface EntityType<
TUnsaved = any,
TSaved = any,
TIds extends object = any
> {
_saved: TSaved;
_unsaved: TUnsaved;
_idKeys: TIds;
idOf: (rec: TSaved) => TIds;
}
export type UnsavedR<T extends { _unsaved: any }> = T["_unsaved"];
export type SavedR<T extends { _saved: any }> = T["_saved"];
export type KeyType<R extends EntityType> = R["_idKeys"];
export interface PgRecordInfo<
Unsaved = any,
Saved extends Unsaved & IdType = any,
IdType extends object = any
> extends EntityType<Unsaved, Saved, IdType> {
tableName: string;
schemaName: string;
idKeys: (keyof Saved)[];
}
/**
* Extract the runtime key name from a recordInfo
*/
export function idKeysOf<RI extends PgRecordInfo>(
recordInfoWithIdKey: RI
): string[] {
return recordInfoWithIdKey.idKeys as any;
}
/**
* Turns a record type with possibly more fields than "id" into an array
*/
export function collectIdValues<RecordT extends PgRecordInfo>(
idObj: KeyType<RecordT>,
knexRecordType: RecordT
): string[] {
return at(idObj, idKeysOf(knexRecordType));
}
function castToRecordInfo(
runtimeData: Omit<PgRecordInfo, "_idKeys" | "_saved" | "_unsaved">
): PgRecordInfo {
return runtimeData as PgRecordInfo;
}
/**
*
* Creates a record descriptor that captures the table name, primary key name,
* unsaved type, and saved type of a database record type. Assumes "id" as the
* primary key name
*
*/
export function recordInfo<Unsaved, Saved extends Unsaved & { id: any }>(
schemaName: string,
tableName: string
): PgRecordInfo<Unsaved, Saved, Pick<Saved, "id">>;
export function recordInfo<Type extends { id: string }>(
schemaName: string,
tableName: string
): PgRecordInfo<Type, Type, Pick<Type, "id">>;
/**
*
* Creates a record descriptor that captures the table name, primary key name,
* unsaved type, and saved type of a database record type.
*
*/
export function recordInfo<
Unsaved,
Saved extends Unsaved,
Id extends keyof Saved
>(
schemaName: string,
tableName: string,
idKey: Id[]
): PgRecordInfo<Unsaved, Saved, Pick<Saved, Id>>;
/**
*
* Don't use this signature be sure to provide unsaved and saved types.
*
*/
export function recordInfo(
schemaName: string,
tableName: string,
idKeys?: string[]
) {
idKeys = idKeys || ["id"];
return castToRecordInfo({
schemaName,
tableName,
idKeys,
idOf: (rec) => pick(rec, idKeys as any),
});
}
/**
*
* Creates a record descriptor for records with composite primary keys
*
*/
export function compositeRecordType<
TUnsaved,
TSaved extends TUnsaved = TUnsaved
>(
schemaName: string,
tableName: string
): {
withCompositeKeys<TKeys extends keyof TSaved>(
keys: TKeys[]
): PgRecordInfo<TUnsaved, TSaved, Pick<TSaved, TKeys>>;
} {
return {
withCompositeKeys(keys) {
return castToRecordInfo({
schemaName,
tableName,
idKeys: keys,
idOf: (rec) => pick(rec, keys),
});
},
};
}