Skip to content

Commit 5bb1ff0

Browse files
committed
feat(db): enhance queryModifiers with comprehensive documentation and robust testing
Improved the queryModifiers utility with: - Detailed JSDoc documentation for QueryModifier type, composeQueryModifiers, and createStandardQueryModifier - Enhanced type safety and flexibility for query modification functions - Comprehensive test suite using pg-mem for in-memory database simulation - Added graceful handling of undefined modifier returns - Verified modifier composition order and individual modifier behaviors
1 parent 7119317 commit 5bb1ff0

2 files changed

Lines changed: 275 additions & 82 deletions

File tree

src/lib/db/queryModifiers/queryModifiers.ts

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,24 @@ import { applySort } from "./applySort.js";
77
import { applyWhere } from "./applyWhere.js";
88

99
/**
10-
* Type definition for a query modifier function
10+
* Type definition for a query modifier function.
11+
* Query modifiers are functions that take a query and arguments and return a modified query.
12+
* They are used to compose complex queries from simpler, reusable parts.
13+
*
14+
* @typeParam DB - The database type extending SupportedDatabases
15+
* @typeParam T - The table name type (must be a key of DB and a string)
16+
* @typeParam Args - The arguments type containing query modification parameters
17+
*
18+
* @param query - The Kysely SelectQueryBuilder instance to modify
19+
* @param args - The arguments containing modification parameters
20+
* @returns The modified SelectQueryBuilder instance
21+
*
22+
* @example
23+
* ```typescript
24+
* const sortModifier: QueryModifier<DB, "users", SortArgs> = (query, args) => {
25+
* return args.sortBy ? query.orderBy(args.sortBy) : query;
26+
* };
27+
* ```
1128
*/
1229
export type QueryModifier<
1330
DB extends SupportedDatabases,
@@ -19,29 +36,78 @@ export type QueryModifier<
1936
) => SelectQueryBuilder<DB, T, Selectable<DB[T]>>;
2037

2138
/**
22-
* Composes multiple query modifiers into a single function
23-
* @param modifiers The query modifiers to compose
39+
* Composes multiple query modifiers into a single function.
40+
* The modifiers are applied in sequence, with each modifier receiving the query
41+
* produced by the previous modifier.
42+
*
43+
* @typeParam DB - The database type extending SupportedDatabases
44+
* @typeParam T - The table name type (must be a key of DB and a string)
45+
* @typeParam Args - The arguments type containing query modification parameters
46+
*
47+
* @param modifiers - The query modifiers to compose, applied in order
2448
* @returns A function that applies all modifiers in sequence
49+
*
50+
* @remarks
51+
* - Modifiers are applied left to right
52+
* - Each modifier receives the query produced by the previous modifier
53+
* - If a modifier returns undefined or null, the original query is used
54+
* - The args object is passed unchanged to each modifier
55+
*
56+
* @example
57+
* ```typescript
58+
* const fullModifier = composeQueryModifiers(
59+
* applyWhere,
60+
* applySort,
61+
* applyPagination
62+
* );
63+
* const result = fullModifier(query, { where: {...}, sortBy: {...} });
64+
* ```
2565
*/
2666
export function composeQueryModifiers<
2767
DB extends SupportedDatabases,
2868
T extends keyof DB & string,
2969
Args,
3070
>(...modifiers: QueryModifier<DB, T, Args>[]) {
3171
return (query: SelectQueryBuilder<DB, T, Selectable<DB[T]>>, args: Args) =>
32-
modifiers.reduce((q, modifier) => modifier(q, args), query);
72+
modifiers.reduce((q, modifier) => {
73+
const result = modifier(q, args);
74+
return result ?? q; // Fall back to previous query if modifier returns null/undefined
75+
}, query);
3376
}
3477

3578
/**
36-
* Creates a composed query modifier that applies where, sort, and pagination
37-
* @param tableName The name of the table to query
38-
* @returns A function that applies where, sort, and pagination modifiers
79+
* Creates a composed query modifier that applies where, sort, and pagination in a standard order.
80+
* This is a convenience function that combines the most commonly used query modifiers.
81+
*
82+
* @typeParam DB - The database type extending SupportedDatabases
83+
* @typeParam T - The table name type (must be a key of DB and a string)
84+
* @typeParam Args - The arguments type extending BaseQueryArgsType
85+
*
86+
* @param tableName - The name of the table to query
87+
* @returns A function that applies where, sort, and pagination modifiers in sequence
88+
*
89+
* @remarks
90+
* - Modifiers are applied in this order: where → sort → pagination
91+
* - Where conditions are applied first to filter the dataset
92+
* - Sort is applied next to order the filtered results
93+
* - Pagination is applied last to limit the final result set
94+
* - Each modifier is optional and will be skipped if its args are not provided
95+
*
96+
* @example
97+
* ```typescript
98+
* const usersModifier = createStandardQueryModifier<DB, "users", UserQueryArgs>("users");
99+
* const result = usersModifier(query, {
100+
* where: { active: true },
101+
* sortBy: { created_at: SortOrder.descending },
102+
* first: 10,
103+
* offset: 0
104+
* });
105+
* ```
39106
*/
40107
export function createStandardQueryModifier<
41108
DB extends SupportedDatabases,
42109
T extends keyof DB & string,
43110
Args extends BaseQueryArgsType<
44-
// TODO better type definition than object
45111
object,
46112
{ [K in keyof DB[T]]?: SortOrder | null | undefined }
47113
>,

0 commit comments

Comments
 (0)