mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
feat: enhance query handling by ignoring undefined values
- Updated query conversion logic to skip undefined values, improving robustness. - Added tests to validate that undefined values are correctly ignored in query specifications.
This commit is contained in:
@@ -110,6 +110,9 @@ describe("query", () => {
|
|||||||
// @ts-expect-error only strings are allowed for $like
|
// @ts-expect-error only strings are allowed for $like
|
||||||
expect(() => validator.convert({ foo: { $like: 1 } })).toThrow();
|
expect(() => validator.convert({ foo: { $like: 1 } })).toThrow();
|
||||||
|
|
||||||
|
// undefined values are ignored
|
||||||
|
expect(validator.convert({ foo: undefined })).toEqual({});
|
||||||
|
|
||||||
expect(validator.convert({ foo: "bar" })).toEqual({ foo: { $eq: "bar" } });
|
expect(validator.convert({ foo: "bar" })).toEqual({ foo: { $eq: "bar" } });
|
||||||
expect(validator.convert({ foo: { $eq: "bar" } })).toEqual({ foo: { $eq: "bar" } });
|
expect(validator.convert({ foo: { $eq: "bar" } })).toEqual({ foo: { $eq: "bar" } });
|
||||||
expect(validator.convert({ foo: { $like: "bar" } })).toEqual({ foo: { $like: "bar" } });
|
expect(validator.convert({ foo: { $like: "bar" } })).toEqual({ foo: { $like: "bar" } });
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ function getExpression<Exps extends Expressions>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LiteralExpressionCondition<Exps extends Expressions> = {
|
type LiteralExpressionCondition<Exps extends Expressions> = {
|
||||||
[key: string]: Primitive | ExpressionCondition<Exps>;
|
[key: string]: undefined | Primitive | ExpressionCondition<Exps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const OperandOr = "$or" as const;
|
const OperandOr = "$or" as const;
|
||||||
@@ -96,6 +96,11 @@ function _convert<Exps extends Expressions>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries($query)) {
|
for (const [key, value] of Object.entries($query)) {
|
||||||
|
// skip undefined values
|
||||||
|
if (value === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// if $or, convert each value
|
// if $or, convert each value
|
||||||
if (key === "$or") {
|
if (key === "$or") {
|
||||||
invariant(isPlainObject(value), "$or must be an object");
|
invariant(isPlainObject(value), "$or must be an object");
|
||||||
@@ -171,6 +176,8 @@ function _build<Exps extends Expressions>(
|
|||||||
|
|
||||||
// check $and
|
// check $and
|
||||||
for (const [key, value] of Object.entries($and)) {
|
for (const [key, value] of Object.entries($and)) {
|
||||||
|
if (value === undefined) continue;
|
||||||
|
|
||||||
for (const [$op, $v] of Object.entries(value)) {
|
for (const [$op, $v] of Object.entries(value)) {
|
||||||
const objValue = options.value_is_kv ? key : getPath(options.object, key);
|
const objValue = options.value_is_kv ? key : getPath(options.object, key);
|
||||||
result.$and.push(__validate($op, $v, objValue, [key]));
|
result.$and.push(__validate($op, $v, objValue, [key]));
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { test, describe, expect } from "bun:test";
|
import { test, describe, expect } from "bun:test";
|
||||||
import * as q from "./query";
|
import * as q from "./query";
|
||||||
import { parse as $parse, type ParseOptions } from "bknd/utils";
|
import { parse as $parse, type ParseOptions } from "bknd/utils";
|
||||||
|
import type { PrimaryFieldType } from "modules";
|
||||||
|
import type { Generated } from "kysely";
|
||||||
|
|
||||||
const parse = (v: unknown, o: ParseOptions = {}) =>
|
const parse = (v: unknown, o: ParseOptions = {}) =>
|
||||||
$parse(q.repoQuery, v, {
|
$parse(q.repoQuery, v, {
|
||||||
@@ -186,4 +188,35 @@ describe("server/query", () => {
|
|||||||
decode({ with: { images: {}, comments: {} } }, output);
|
decode({ with: { images: {}, comments: {} } }, output);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("types", () => {
|
||||||
|
const id = 1 as PrimaryFieldType;
|
||||||
|
const id2 = "1" as unknown as Generated<string>;
|
||||||
|
|
||||||
|
const c: q.RepoQueryIn = {
|
||||||
|
where: {
|
||||||
|
// @ts-expect-error only primitives are allowed for $eq
|
||||||
|
something: [],
|
||||||
|
// this gets ignored
|
||||||
|
another: undefined,
|
||||||
|
// @ts-expect-error null is not a valid value
|
||||||
|
null_is_okay: null,
|
||||||
|
some_id: id,
|
||||||
|
another_id: id2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const d: q.RepoQuery = {
|
||||||
|
where: {
|
||||||
|
// @ts-expect-error only primitives are allowed for $eq
|
||||||
|
something: [],
|
||||||
|
// this gets ignored
|
||||||
|
another: undefined,
|
||||||
|
// @ts-expect-error null is not a valid value
|
||||||
|
null_is_okay: null,
|
||||||
|
some_id: id,
|
||||||
|
another_id: id2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -84,8 +84,6 @@ const where = s.anyOf([s.string(), s.object({})], {
|
|||||||
return WhereBuilder.convert(q);
|
return WhereBuilder.convert(q);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
//type WhereSchemaIn = s.Static<typeof where>;
|
|
||||||
//type WhereSchema = s.StaticCoerced<typeof where>;
|
|
||||||
|
|
||||||
// ------
|
// ------
|
||||||
// with
|
// with
|
||||||
@@ -128,7 +126,7 @@ const withSchema = <Type = unknown>(self: s.Schema): s.Schema<{}, Type, Type> =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value as unknown as any;
|
return value as any;
|
||||||
},
|
},
|
||||||
}) as any;
|
}) as any;
|
||||||
|
|
||||||
@@ -167,15 +165,3 @@ export type RepoQueryIn = {
|
|||||||
export type RepoQuery = s.StaticCoerced<typeof repoQuery> & {
|
export type RepoQuery = s.StaticCoerced<typeof repoQuery> & {
|
||||||
sort: SortSchema;
|
sort: SortSchema;
|
||||||
};
|
};
|
||||||
|
|
||||||
//export type RepoQuery = s.StaticCoerced<typeof repoQuery>;
|
|
||||||
// @todo: CURRENT WORKAROUND
|
|
||||||
/* export type RepoQuery = {
|
|
||||||
limit?: number;
|
|
||||||
offset?: number;
|
|
||||||
sort?: { by: string; dir: "asc" | "desc" };
|
|
||||||
select?: string[];
|
|
||||||
with?: Record<string, RepoQuery>;
|
|
||||||
join?: string[];
|
|
||||||
where?: WhereQuery;
|
|
||||||
}; */
|
|
||||||
|
|||||||
Reference in New Issue
Block a user