Skip to content

Commit

Permalink
fix: support excludes syntax from latest v6 alpha (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
darkbasic authored Dec 19, 2023
1 parent 34048ce commit bbe8222
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 195 deletions.
5 changes: 5 additions & 0 deletions .changeset/metal-toys-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"mikro-orm-find-dataloader": minor
---

fix: support excludes syntax from latest v6 alpha
4 changes: 2 additions & 2 deletions examples/graphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
},
"dependencies": {
"@graphql-tools/executor-http": "^1.0.5",
"@mikro-orm/core": "6.0.0-dev.261",
"@mikro-orm/sqlite": "6.0.0-dev.261",
"@mikro-orm/core": "6.0.0-dev.283",
"@mikro-orm/sqlite": "6.0.0-dev.283",
"graphql": "16.8.1",
"graphql-tag": "^2.12.6",
"graphql-yoga": "5.0.2",
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
"@changesets/cli": "^2.27.1",
"@types/eslint": "^8.44.9",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.4",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"eslint": "^8.55.0",
"@types/node": "^20.10.5",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard-with-typescript": "^42.0.0",
"eslint-plugin-import": "^2.29.0",
"eslint-config-standard-with-typescript": "^43.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-n": "^16.4.0",
"eslint-plugin-prettier": "^5.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/find/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"tslib": "2.6.2"
},
"devDependencies": {
"@mikro-orm/core": "6.0.0-dev.261",
"@mikro-orm/sqlite": "6.0.0-dev.261"
"@mikro-orm/core": "6.0.0-dev.283",
"@mikro-orm/sqlite": "6.0.0-dev.283"
}
}
30 changes: 19 additions & 11 deletions packages/find/src/findDataloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
type FilterItemValue,
type Scalar,
type ExpandProperty,
type ExpandQuery,
type ExpandScalar,
type EntityProps,
type EntityManager,
Expand All @@ -25,12 +24,15 @@ import type DataLoader from "dataloader";

export interface OperatorMapDataloader<T> {
// $and?: ExpandQuery<T>[];
$or?: Array<ExpandQuery<T>>;
$or?: Array<ExpandQueryDataloader<T>>;
// $eq?: ExpandScalar<T> | ExpandScalar<T>[];
// $ne?: ExpandScalar<T>;
// $in?: ExpandScalar<T>[];
// $nin?: ExpandScalar<T>[];
// $not?: ExpandQuery<T>;
// $none?: ExpandQuery<T>;
// $some?: ExpandQuery<T>;
// $every?: ExpandQuery<T>;
// $gt?: ExpandScalar<T>;
// $gte?: ExpandScalar<T>;
// $lt?: ExpandScalar<T>;
Expand All @@ -39,34 +41,36 @@ export interface OperatorMapDataloader<T> {
// $re?: string;
// $ilike?: string;
// $fulltext?: string;
// $overlap?: string[];
// $contains?: string[];
// $contained?: string[];
// $overlap?: string[] | object;
// $contains?: string[] | object;
// $contained?: string[] | object;
// $exists?: boolean;
}

export type FilterValueDataloader<T> =
/* OperatorMapDataloader<FilterItemValue<T>> | */
FilterItemValue<T> | FilterItemValue<T>[] | null;

export type QueryDataloader<T> = T extends object
export type ExpandQueryDataloader<T> = T extends object
? T extends Scalar
? never
: FilterQueryDataloader<T>
: FilterValueDataloader<T>;

export type FilterObjectDataloader<T> = {
-readonly [K in EntityKey<T>]?:
| QueryDataloader<ExpandProperty<T[K]>>
| ExpandQueryDataloader<ExpandProperty<T[K]>>
| FilterValueDataloader<ExpandProperty<T[K]>>
| null;
};

export type Compute<T> = {
[K in keyof T]: T[K];
} & {};
export type ExpandObjectDataloader<T> = T extends object
? T extends Scalar
? never
: FilterObjectDataloader<T>
: never;

export type ObjectQueryDataloader<T> = Compute<OperatorMapDataloader<T> & FilterObjectDataloader<T>>;
export type ObjectQueryDataloader<T> = OperatorMapDataloader<T> & ExpandObjectDataloader<T>;

// FilterQuery<T>
export type FilterQueryDataloader<T extends object> =
Expand Down Expand Up @@ -360,6 +364,7 @@ function updateQueryFilter<K extends object, P extends string = never>(
const curValue = (cur as Record<string, any[]>)[key]!;
if (Array.isArray(value)) {
// value.push(...curValue.reduce<any[]>((acc, cur) => acc.concat(cur), []));
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
value.push(...structuredClone(curValue));
} else {
updateQueryFilter([value], curValue);
Expand Down Expand Up @@ -465,6 +470,7 @@ export function getFindBatchLoadFn<Entity extends object>(
const res = entities[many ? "filter" : "find"]((entity) => {
return filterResult(entity, newFilter);
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
acc.push(...(Array.isArray(res) ? res : [res]));
return acc;
}, []);
Expand Down Expand Up @@ -493,6 +499,7 @@ export function getFindBatchLoadFn<Entity extends object>(
if (!entityValue.getItems().some((entity) => filterResult(entity, value))) {
return false;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
} else if (!filterResult(entityValue as object, value)) {
return false;
}
Expand All @@ -514,6 +521,7 @@ export function optsMapToQueries<Entity extends object>(
populate: options.populate === true ? ["*"] : Array.from(options.populate),
}),
} satisfies Pick<FindOptions<any, any>, "populate">;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const entities = await em.find(entityName, filter, findOptions);
return [key, entities];
});
Expand Down
100 changes: 52 additions & 48 deletions packages/find/src/findRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,50 @@ export interface IFindDataloaderEntityRepository<Entity extends object, D extend
extends EntityRepository<Entity> {
readonly dataloader: D;

find<Hint extends string = never, Fields extends string = never>(
find<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQuery<Entity>,
options?: { dataloader: false } & FindOptions<Entity, Hint, Fields>,
): Promise<Array<Loaded<Entity, Hint, Fields>>>;
find<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: false } & FindOptions<Entity, Hint, Fields, Excludes>,
): Promise<Array<Loaded<Entity, Hint, Fields, Excludes>>>;
find<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity>,
options?: { dataloader: boolean } & Pick<FindOptions<Entity, Hint, Fields>, "populate">,
): Promise<Array<Loaded<Entity, Hint, Fields>>>;
find<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: boolean } & Pick<FindOptions<Entity, Hint, Fields, Excludes>, "populate">,
): Promise<Array<Loaded<Entity, Hint, Fields, Excludes>>>;
find<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: D extends true ? FilterQueryDataloader<Entity> : FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: undefined } & (D extends true
? Pick<FindOptions<Entity, Hint, Fields>, "populate">
: FindOptions<Entity, Hint, Fields>),
): Promise<Array<Loaded<Entity, Hint, Fields>>>;
? Pick<FindOptions<Entity, Hint, Fields, Excludes>, "populate">
: FindOptions<Entity, Hint, Fields, Excludes>),
): Promise<Array<Loaded<Entity, Hint, Fields, Excludes>>>;

findOne<Hint extends string = never, Fields extends string = never>(
findOne<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQuery<Entity>,
options?: { dataloader: false } & FindOneOptions<Entity, Hint, Fields>,
): Promise<Loaded<Entity, Hint, Fields> | null>;
findOne<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: false } & FindOneOptions<Entity, Hint, Fields, Excludes>,
): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
findOne<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity>,
options?: { dataloader: boolean } & Pick<FindOneOptions<Entity, Hint, Fields>, "populate">,
): Promise<Loaded<Entity, Hint, Fields> | null>;
findOne<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: boolean } & Pick<FindOneOptions<Entity, Hint, Fields, Excludes>, "populate">,
): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
findOne<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: D extends true ? FilterQueryDataloader<Entity> : FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: undefined } & (D extends true
? Pick<FindOneOptions<Entity, Hint, Fields>, "populate">
: FindOneOptions<Entity, Hint, Fields>),
): Promise<Loaded<Entity, Hint, Fields> | null>;
? Pick<FindOneOptions<Entity, Hint, Fields, Excludes>, "populate">
: FindOneOptions<Entity, Hint, Fields, Excludes>),
): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;

findOneOrFail<Hint extends string = never, Fields extends string = never>(
findOneOrFail<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQuery<Entity>,
options?: { dataloader: false } & FindOneOrFailOptions<Entity, Hint, Fields>,
): Promise<Loaded<Entity, Hint, Fields>>;
findOneOrFail<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: false } & FindOneOrFailOptions<Entity, Hint, Fields, Excludes>,
): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
findOneOrFail<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity>,
options?: { dataloader: boolean } & Pick<FindOneOrFailOptions<Entity, Hint, Fields>, "populate">,
): Promise<Loaded<Entity, Hint, Fields>>;
findOneOrFail<Hint extends string = never, Fields extends string = never>(
options?: { dataloader: boolean } & Pick<FindOneOrFailOptions<Entity, Hint, Fields, Excludes>, "populate">,
): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
findOneOrFail<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: D extends true ? FilterQueryDataloader<Entity> : FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: undefined } & (D extends true
? Pick<FindOneOrFailOptions<Entity, Hint, Fields>, "populate">
: FindOneOrFailOptions<Entity, Hint, Fields>),
): Promise<Loaded<Entity, Hint, Fields>>;
? Pick<FindOneOrFailOptions<Entity, Hint, Fields, Excludes>, "populate">
: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>),
): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
}

export type FindDataloaderEntityRepositoryCtor<Entity extends object, D extends boolean> = new (
Expand All @@ -78,13 +78,13 @@ export function getFindDataloaderEntityRepository<Entity extends object, D exten
readonly dataloader = defaultEnabled;
private readonly findLoader = new DataLoader(getFindBatchLoadFn(this.em, this.entityName));

async find<Hint extends string = never, Fields extends string = never>(
async find<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: boolean } & (
| Pick<FindOptions<Entity, Hint, Fields>, "populate">
| FindOptions<Entity, Hint, Fields>
| Pick<FindOptions<Entity, Hint, Fields, Excludes>, "populate">
| FindOptions<Entity, Hint, Fields, Excludes>
),
): Promise<Array<Loaded<Entity, Hint, Fields>>> {
): Promise<Array<Loaded<Entity, Hint, Fields, Excludes>>> {
const entityName = Utils.className(this.entityName);
const res = await (options?.dataloader ?? this.dataloader
? this.findLoader.load({
Expand All @@ -94,17 +94,17 @@ export function getFindDataloaderEntityRepository<Entity extends object, D exten
options,
many: true,
})
: this.em.find<Entity, Hint, Fields>(this.entityName, where as FilterQuery<Entity>, options));
return res as Array<Loaded<Entity, Hint, Fields>>;
: this.em.find<Entity, Hint, Fields, Excludes>(this.entityName, where as FilterQuery<Entity>, options));
return res as Array<Loaded<Entity, Hint, Fields, Excludes>>;
}

async findOne<Hint extends string = never, Fields extends string = never>(
async findOne<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: boolean } & (
| Pick<FindOneOptions<Entity, Hint, Fields>, "populate">
| FindOneOptions<Entity, Hint, Fields>
| Pick<FindOneOptions<Entity, Hint, Fields, Excludes>, "populate">
| FindOneOptions<Entity, Hint, Fields, Excludes>
),
): Promise<Loaded<Entity, Hint, Fields> | null> {
): Promise<Loaded<Entity, Hint, Fields, Excludes> | null> {
const entityName = Utils.className(this.entityName);
const res = await (options?.dataloader ?? this.dataloader
? this.findLoader.load({
Expand All @@ -114,17 +114,17 @@ export function getFindDataloaderEntityRepository<Entity extends object, D exten
options,
many: false,
})
: this.em.findOne<Entity, Hint, Fields>(this.entityName, where as FilterQuery<Entity>, options));
return res as Loaded<Entity, Hint, Fields> | null;
: this.em.findOne<Entity, Hint, Fields, Excludes>(this.entityName, where as FilterQuery<Entity>, options));
return res as Loaded<Entity, Hint, Fields, Excludes> | null;
}

async findOneOrFail<Hint extends string = never, Fields extends string = never>(
async findOneOrFail<Hint extends string = never, Fields extends string = "*", Excludes extends string = never>(
where: FilterQueryDataloader<Entity> | FilterQuery<Entity>,
options?: { dataloader?: boolean } & (
| Pick<FindOneOrFailOptions<Entity, Hint, Fields>, "populate">
| FindOneOrFailOptions<Entity, Hint, Fields>
| Pick<FindOneOrFailOptions<Entity, Hint, Fields, Excludes>, "populate">
| FindOneOrFailOptions<Entity, Hint, Fields, Excludes>
),
): Promise<Loaded<Entity, Hint, Fields>> {
): Promise<Loaded<Entity, Hint, Fields, Excludes>> {
const entityName = Utils.className(this.entityName);
const res = await (options?.dataloader ?? this.dataloader
? this.findLoader.load({
Expand All @@ -134,11 +134,15 @@ export function getFindDataloaderEntityRepository<Entity extends object, D exten
options,
many: false,
})
: this.em.findOneOrFail<Entity, Hint, Fields>(this.entityName, where as FilterQuery<Entity>, options));
: this.em.findOneOrFail<Entity, Hint, Fields, Excludes>(
this.entityName,
where as FilterQuery<Entity>,
options,
));
if (res == null) {
throw new Error("Cannot find result");
}
return res as Loaded<Entity, Hint, Fields>;
return res as Loaded<Entity, Hint, Fields, Excludes>;
}
}

Expand Down
Loading

0 comments on commit bbe8222

Please sign in to comment.