Skip to content

Instantly share code, notes, and snippets.

@GrantJamesPowell
Created December 6, 2022 22:20
Show Gist options
  • Save GrantJamesPowell/c0416d79cf0f265edccd97be6e8042a5 to your computer and use it in GitHub Desktop.
Save GrantJamesPowell/c0416d79cf0f265edccd97be6e8042a5 to your computer and use it in GitHub Desktop.
Typeorm Select
import { Primitive, Simplify } from 'type-fest';
import {
EntityManager,
EntityTarget,
FindOptionsOrder,
FindOptionsRelations,
FindOptionsWhere,
ObjectLiteral,
} from 'typeorm';
export type Defined<T> = T extends undefined ? never : T;
declare const embeddedMarker: unique symbol;
export type Embedded<T = {}> = T & { [embeddedMarker]: true };
export const embed = <T extends {}>(x: T): Embedded<T> => x as Embedded<T>;
type NonRelationProperty = Primitive | Function | Date | Embedded;
export type Selection<Entity> = FindOptionsRelations<Entity>;
export type ShouldKeepProperty<
Entity,
Relations extends FindOptionsRelations<Entity>
> = keyof {
[Property in keyof Entity as NonNullable<Entity[Property]> extends
| NonRelationProperty
| NonRelationProperty[]
? Property
: Relations[Property] extends true | object
? Property
: never]-?: unknown;
};
export type SelectProperty<
Entity,
Relations extends Selection<Entity>,
Property extends keyof Entity
> = NonNullable<Entity[Property]> extends
| NonRelationProperty
| NonRelationProperty[]
? Defined<Entity[Property]>
: NonNullable<Entity[Property]> extends (infer Relation)[]
? Relations[Property] extends true
? Select<Relation, {}>[]
: Relations[Property] extends FindOptionsRelations<NonNullable<Relation>>
? Select<Relation, Relations[Property]>[]
: unknown
: Relations[Property] extends true
? Select<Defined<Entity[Property]>, {}>
: Relations[Property] extends FindOptionsRelations<
NonNullable<Defined<Entity[Property]>>
>
? Select<Defined<Entity[Property]>, Relations[Property]>
: unknown;
export type Select<
Entity,
Relations extends Selection<Entity> = {}
> = Simplify<{
[Property in keyof Entity as Property extends ShouldKeepProperty<
Entity,
Relations
>
? Property
: never]-?: SelectProperty<Entity, Relations, Property>;
}>;
type Options<Entity, Relations extends FindOptionsRelations<Entity>> = {
relations?: Relations;
where?: FindOptionsWhere<Entity>;
order?: FindOptionsOrder<Entity>;
};
export const select = async <
Entity extends ObjectLiteral,
Relations extends FindOptionsRelations<Entity> = {}
>(
db: EntityManager,
entity: EntityTarget<Entity>,
options?: Options<Entity, Relations>
): Promise<Select<Entity, Relations>[]> =>
db.find(entity, options ?? {}) as any;
export const selectOne = async <
Entity extends ObjectLiteral,
Relations extends FindOptionsRelations<Entity> = {}
>(
db: EntityManager,
entity: EntityTarget<Entity>,
options?: Options<Entity, Relations>
): Promise<Select<Entity, Relations> | null> =>
db.findOne(entity, options ?? {}) as any;
export const selectOneOrFail = async <
Entity extends ObjectLiteral,
Relations extends FindOptionsRelations<Entity> = {}
>(
db: EntityManager,
entity: EntityTarget<Entity>,
options?: Options<Entity, Relations>
): Promise<Select<Entity, Relations>> =>
db.findOneOrFail(entity, options ?? {}) as any;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment