Skip to content

Commit

Permalink
feat(prisma): Add 'isSet' filter to prisma filters
Browse files Browse the repository at this point in the history
Add a new 'isSet' field instruction to PrismaQueryParser.
The 'isSet' instruction checks if an object value is defined when using the 'isSet' condition in a query.
Update the interpretPrismaQuery function to handle the new 'isSet' instruction.
  • Loading branch information
p0thi committed Sep 8, 2024
1 parent f656312 commit 380a73a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/casl-prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ model User {
firstName String
lastName String
age Int
verified Boolean?
posts Post[]
}

Expand Down
16 changes: 16 additions & 0 deletions packages/casl-prisma/spec/prismaQuery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ describe('PrismaQuery evaluation', () => {
expect(test({ name: 'Jane Doe' })).toBe(false)
})
})
describe('isSet', () => {
it('throws if value is not a boolean', () => {
expect(() => prismaQuery({ items: { isSet: 1 } })).toThrow(/expects to receive a boolean/)
expect(() => prismaQuery({ items: { isSet: {} } })).toThrow(/expects to receive a boolean/)
expect(() => prismaQuery({ items: { isSet: true } })).not.toThrow()
})

it('checks that object value is not defined when using "isSet"', () => {
const test = prismaQuery({ verified: { isSet: true } })
expect(test({ verified: true })).toBe(true)
expect(test({ verified: false })).toBe(true)
expect(test({ verified: null })).toBe(true)
expect(test({ verified: undefined })).toBe(false)
expect(test({})).toBe(false)
})
})

describe('in', () => {
it('throws if passed value is not an array', () => {
Expand Down
10 changes: 10 additions & 0 deletions packages/casl-prisma/src/prisma/PrismaQueryParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ const not: FieldInstruction<unknown, ObjectQueryFieldParsingContext> = {
}
};

const isSet: FieldInstruction<boolean> = {
type: 'field',
validate(instruction, value) {
if (typeof value !== 'boolean') {
throw ParsingQueryError.invalidArgument(instruction.name, value, 'a boolean');
}
}
}

const within: FieldInstruction<unknown[]> = {
type: 'field',
validate(instruction, value) {
Expand Down Expand Up @@ -195,6 +204,7 @@ const instructions = {
none: inverted('some', relation),
is: relation,
isNot: inverted('is', relation),
isSet
};

export interface ParseOptions {
Expand Down
6 changes: 6 additions & 0 deletions packages/casl-prisma/src/prisma/interpretPrismaQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ const not: JsInterpreter<CompoundCondition> = (condition, object, { interpret })
return condition.value.every(subCondition => !interpret(subCondition, object));
};

const isSet: JsInterpreter<FieldCondition<Condition>> = (condition, object, { get }) => {
const item = get(object, condition.field);
return item !== undefined;
}

function toComparable(value: unknown) {
return value && typeof value === 'object' ? value.valueOf() : value;
}
Expand Down Expand Up @@ -112,6 +117,7 @@ export const interpretPrismaQuery = createJsInterpreter({
every,
some,
is,
isSet,
}, {
get: (object, field) => object[field],
compare: compareValues,
Expand Down

0 comments on commit 380a73a

Please sign in to comment.