Skip to content

Commit 492915e

Browse files
authored
Enhance query functionality with refined whereSome and whereEvery overloads (#263)
* feat: Enhance query functionality with refined whereSome and whereEvery implementations * changeset * nvm
1 parent 5bd6efc commit 492915e

3 files changed

Lines changed: 182 additions & 43 deletions

File tree

.changeset/slow-cups-refuse.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@effect-app/infra": patch
3+
---
4+
5+
add more overloads for whereSome and whereEvery (DX)

packages/infra/src/Model/query/dsl.ts

Lines changed: 170 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -232,28 +232,30 @@ export const and: FilterContinuationAnd = (...operation: any[]) => (current: any
232232
export const or: FilterContinuationOr = (...operation: any[]) => (current: any) =>
233233
new Or({ current, operation: typeof operation[0] === "function" ? flow(...operation as [any]) : operation } as any)
234234

235-
// TODO: make nice.
236-
export type WhereEveryOrSome = {
237-
<
238-
TFieldValues extends FieldValues,
239-
TFieldName extends FieldPath<TFieldValues>
240-
>(
241-
path: TFieldName,
242-
dude: (
243-
current: Query<TFieldValues[TFieldName][number]>
244-
) => QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>,
245-
...dudes: ((
246-
current: QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>
247-
) => QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>)[]
248-
): (
249-
current: Query<TFieldValues>
250-
) => QueryWhere<TFieldValues, TFieldValues, false>
251-
}
252-
253-
export const whereEvery: WhereEveryOrSome = (subPath, ...operations) => (current) =>
254-
new Where({ current, operation: flow(...operations as [any]), relation: "every", subPath } as any)
255-
export const whereSome: WhereEveryOrSome = (subPath, ...operations) => (current) =>
256-
new Where({ current, operation: flow(...operations as [any]), relation: "some", subPath } as any)
235+
export const whereEvery: WhereEveryOrSome =
236+
((subPath: string, ...[first, ...rest]: any[]) => (current: any) =>
237+
new Where(
238+
{
239+
current,
240+
operation: typeof first === "function"
241+
? flow(...[first, ...rest] as [any])
242+
: [`${subPath}.-1.${first}`, ...rest],
243+
relation: "every",
244+
subPath
245+
} as any
246+
)) as unknown as WhereEveryOrSome
247+
export const whereSome: WhereEveryOrSome =
248+
((subPath: string, ...[first, ...rest]: any[]) => (current: any) =>
249+
new Where(
250+
{
251+
current,
252+
operation: typeof first === "function"
253+
? flow(...[first, ...rest] as [any])
254+
: [`${subPath}.-1.${first}`, ...rest],
255+
relation: "some",
256+
subPath
257+
} as any
258+
)) as unknown as WhereEveryOrSome
257259

258260
export const order: {
259261
<
@@ -409,30 +411,11 @@ export type FilterContinuations<IsCurrentInitial extends boolean = false> = {
409411
E extends boolean = false
410412
>(
411413
path: TFieldName,
412-
op: "in",
414+
op: "in" | "notIn",
413415
value: V
414416
): (
415417
current: IsCurrentInitial extends true ? Query<TFieldValues>
416418
: QueryWhere<TFieldValues, TFieldValuesRefined, E>
417-
) => QueryWhere<
418-
TFieldValues,
419-
// @ts-expect-error it's TS
420-
RefineWithLiteral<TFieldValuesRefined, TFieldName, NonNullable<V[number]>>,
421-
E
422-
>
423-
<
424-
TFieldValues extends FieldValues,
425-
TFieldName extends FieldPath<TFieldValues>,
426-
V extends FieldPathValue<TFieldValues, TFieldName>,
427-
TFieldValuesRefined extends TFieldValues = TFieldValues,
428-
E extends boolean = false
429-
>(
430-
path: TFieldName,
431-
op: "notIn",
432-
value: readonly V[]
433-
): (
434-
current: IsCurrentInitial extends true ? Query<TFieldValues>
435-
: QueryWhere<TFieldValues, TFieldValuesRefined, E>
436419
) => IsCurrentInitial extends true ? QueryWhere<TFieldValues>
437420
: QueryWhere<TFieldValues, TFieldValuesRefined, E>
438421
<
@@ -479,7 +462,7 @@ export type FilterContinuations<IsCurrentInitial extends boolean = false> = {
479462
E extends boolean = false
480463
>(f: {
481464
path: TFieldName
482-
op: Ops
465+
op: "eq"
483466
value: V
484467
}): (
485468
current: IsCurrentInitial extends true ? Query<TFieldValues>
@@ -488,6 +471,111 @@ export type FilterContinuations<IsCurrentInitial extends boolean = false> = {
488471
: QueryWhere<TFieldValues, TFieldValuesRefined, E>
489472
}
490473

474+
export type FilterContinuationsWithSubpath = {
475+
<
476+
TFieldValues extends FieldValues,
477+
TFieldName extends FieldPath<TFieldValues>,
478+
TFieldValuesSub extends TFieldValues[TFieldName][number],
479+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
480+
V extends FieldPathValue<TFieldValuesSub, TFieldNameSub>
481+
>(
482+
subPath: TFieldName,
483+
restPath: TFieldNameSub,
484+
value: V
485+
): (
486+
current: Query<TFieldValues>
487+
) => QueryWhere<TFieldValues>
488+
<
489+
TFieldValues extends FieldValues,
490+
TFieldName extends FieldPath<TFieldValues>,
491+
TFieldValuesSub extends TFieldValues[TFieldName][number],
492+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
493+
V extends FieldPathValue<TFieldValuesSub, TFieldNameSub>
494+
>(
495+
subPath: TFieldName,
496+
restPath: TFieldNameSub,
497+
op: "gt" | "gte" | "lt" | "lte" | "neq",
498+
value: V // only numbers?
499+
): (
500+
current: Query<TFieldValues>
501+
) => QueryWhere<TFieldValues>
502+
<
503+
TFieldValues extends FieldValues,
504+
TFieldName extends FieldPath<TFieldValues>,
505+
TFieldValuesSub extends TFieldValues[TFieldName][number],
506+
TFieldNameSub extends FieldPath<TFieldValuesSub>
507+
>(
508+
subPath: TFieldName,
509+
restPath: TFieldNameSub,
510+
op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
511+
value: FieldPathValue<TFieldValuesSub, TFieldNameSub> extends string ? string : never
512+
): (
513+
current: Query<TFieldValues>
514+
) => QueryWhere<TFieldValues>
515+
<
516+
TFieldValues extends FieldValues,
517+
TFieldName extends FieldPath<TFieldValues>,
518+
TFieldValuesSub extends TFieldValues[TFieldName][number],
519+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
520+
const V extends readonly FieldPathValue<TFieldValuesSub, TFieldNameSub>[]
521+
>(
522+
subPath: TFieldName,
523+
restPath: TFieldNameSub,
524+
op: "in" | "notIn",
525+
value: V
526+
): (
527+
current: Query<TFieldValues>
528+
) => QueryWhere<TFieldValues>
529+
<
530+
TFieldValues extends FieldValues,
531+
TFieldName extends FieldPath<TFieldValues>,
532+
TFieldValuesSub extends TFieldValues[TFieldName][number],
533+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
534+
V extends FieldPathValue<TFieldValuesSub, TFieldNameSub>
535+
>(
536+
subPath: TFieldName,
537+
restPath: TFieldNameSub,
538+
op:
539+
| "includes"
540+
| "notIncludes",
541+
value: GetArV<V>
542+
): (
543+
current: Query<TFieldValues>
544+
) => QueryWhere<TFieldValues>
545+
<
546+
TFieldValues extends FieldValues,
547+
TFieldName extends FieldPath<TFieldValues>,
548+
TFieldValuesSub extends TFieldValues[TFieldName][number],
549+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
550+
V extends FieldPathValue<TFieldValuesSub, TFieldNameSub>
551+
>(
552+
subPath: TFieldName,
553+
restPath: TFieldNameSub,
554+
op:
555+
| "includes-any"
556+
| "notIncludes-any"
557+
| "includes-all"
558+
| "notIncludes-all",
559+
value: readonly GetArV<V>[]
560+
): (
561+
current: Query<TFieldValues>
562+
) => QueryWhere<TFieldValues>
563+
<
564+
TFieldValues extends FieldValues,
565+
TFieldName extends FieldPath<TFieldValues>,
566+
TFieldValuesSub extends TFieldValues[TFieldName][number],
567+
TFieldNameSub extends FieldPath<TFieldValuesSub>,
568+
V extends FieldPathValue<TFieldValuesSub, TFieldNameSub>
569+
>(f: {
570+
subPath: TFieldName
571+
restPath: TFieldNameSub
572+
op: "eq"
573+
value: V
574+
}): (
575+
current: Query<TFieldValues>
576+
) => QueryWhere<TFieldValues>
577+
}
578+
491579
/* dprint-ignore-start */
492580
export type RefineWithLiteral<
493581
TFieldValues extends FieldValues,
@@ -539,6 +627,25 @@ export type FilteringRefinements<IsCurrentInitial extends boolean = false> = {
539627
RefineWithLiteral<TFieldValuesRefined, TFieldName, V, true>,
540628
E
541629
>
630+
<
631+
TFieldValues extends FieldValues,
632+
TFieldName extends FieldPath<TFieldValues>,
633+
const V extends readonly FieldPathValue<TFieldValues, TFieldName>[],
634+
TFieldValuesRefined extends TFieldValues = TFieldValues,
635+
E extends boolean = false
636+
>(
637+
path: TFieldName,
638+
op: "in",
639+
value: V
640+
): (
641+
current: IsCurrentInitial extends true ? Query<TFieldValues>
642+
: QueryWhere<TFieldValues, TFieldValuesRefined, E>
643+
) => QueryWhere<
644+
TFieldValues,
645+
// @ts-expect-error it's TS
646+
RefineWithLiteral<TFieldValuesRefined, TFieldName, NonNullable<V[number]>>,
647+
E
648+
>
542649
}
543650

544651
export type NestedQueriesFixedRefinement<IsCurrentInitial extends boolean = false> = {
@@ -1981,3 +2088,23 @@ export type FilterContinuationAnd =
19812088
export type FilterContinuationOr =
19822089
& NestedQueriesFreeDisjointRefinement
19832090
& FilterContinuations
2091+
2092+
// it does not support refinements by choice (for now)
2093+
export type WhereEveryOrSome =
2094+
& {
2095+
<
2096+
TFieldValues extends FieldValues,
2097+
TFieldName extends FieldPath<TFieldValues>
2098+
>(
2099+
subPath: TFieldName,
2100+
dude: (
2101+
current: Query<TFieldValues[TFieldName][number]>
2102+
) => QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>,
2103+
...dudes: ((
2104+
current: QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>
2105+
) => QueryWhere<TFieldValues[TFieldName][number], TFieldValues[TFieldName][number], false>)[]
2106+
): (
2107+
current: Query<TFieldValues>
2108+
) => QueryWhere<TFieldValues, TFieldValues, false>
2109+
}
2110+
& FilterContinuationsWithSubpath

packages/infra/test/rawQuery.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,13 @@ describe("1", () => {
292292
)
293293

294294
expect(items4).toStrictEqual(both)
295+
296+
const items5 = yield* repo.query(
297+
whereSome("items", "value", "gt", 10),
298+
project(projected)
299+
)
300+
301+
expect(items5).toStrictEqual(both)
295302
})
296303
.pipe(setupRequestContextFromCurrent())
297304

0 commit comments

Comments
 (0)