134 lines
3.1 KiB
TypeScript
134 lines
3.1 KiB
TypeScript
|
|
/* 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),
|
||
|
|
});
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|