diff --git a/CHANGELOG.md b/CHANGELOG.md index d2e46b444..ce237e1d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog +## v1.0.0-40 + + +### 🩹 Fixes + +- Fix date filter ([a3aff5a](https://github.com/undb-io/undb/commit/a3aff5a)) + +### ❤️ Contributors + +- Nichenqin ([@nichenqin](http://github.com/nichenqin)) + ## v1.0.0-39 diff --git a/package.json b/package.json index 17822206e..1d975c496 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "undb", - "version": "1.0.0-39", + "version": "1.0.0-40", "private": true, "scripts": { "build": "NODE_ENV=production bun --bun turbo build", diff --git a/packages/persistence/src/record/record-query-spec-creator-visitor.ts b/packages/persistence/src/record/record-query-spec-creator-visitor.ts index 7e75a20b7..722e65285 100644 --- a/packages/persistence/src/record/record-query-spec-creator-visitor.ts +++ b/packages/persistence/src/record/record-query-spec-creator-visitor.ts @@ -1,4 +1,5 @@ import { + DateIsEmpty, ID_TYPE, JsonContains, LongTextEqual, @@ -106,6 +107,7 @@ export class RecordQuerySpecCreatorVisitor implements IRecordVisitor { urlEqual(s: UrlEqual): void {} attachmentEqual(s: AttachmentEqual): void {} attachmentEmpty(s: AttachmentEmpty): void {} + dateIsEmpty(spec: DateIsEmpty): void {} dateEqual(spec: DateEqual): void {} jsonEqual(spec: JsonEqual): void {} jsonContains(spec: JsonContains): void {} diff --git a/packages/persistence/src/record/record-spec-reference-visitor.ts b/packages/persistence/src/record/record-spec-reference-visitor.ts index 37d169620..668b1c200 100644 --- a/packages/persistence/src/record/record-spec-reference-visitor.ts +++ b/packages/persistence/src/record/record-spec-reference-visitor.ts @@ -6,6 +6,7 @@ import { DateEqual, DateIsAfter, DateIsBefore, + DateIsEmpty, DateIsSameDay, DateIsToday, DateIsTomorrow, @@ -75,6 +76,7 @@ export class RecordSpecReferenceVisitor implements IRecordVisitor { dateIsYesterday(spec: DateIsTomorrow): void {} dateIsBefore(spec: DateIsBefore): void {} dateIsAfter(spec: DateIsAfter): void {} + dateIsEmpty(spec: DateIsEmpty): void {} userEqual(spec: UserEqual): void userEqual(spec: UserEqual): void {} userEmpty(spec: UserEmpty): void diff --git a/packages/persistence/src/record/record.filter-visitor.ts b/packages/persistence/src/record/record.filter-visitor.ts index 8dbdde899..77edd6580 100644 --- a/packages/persistence/src/record/record.filter-visitor.ts +++ b/packages/persistence/src/record/record.filter-visitor.ts @@ -1,5 +1,6 @@ import { NotImplementException } from "@undb/domain" import { + DateIsEmpty, JsonContains, LongTextEqual, SelectField, @@ -90,8 +91,12 @@ export class RecordFilterVisitor extends AbstractQBVisitor implements jsonEmpty(spec: JsonEmpty): void { this.addCond(this.eb.eb(this.getFieldId(spec), "is", null)) } + dateIsEmpty(spec: DateIsEmpty): void { + const cond = this.eb.eb(this.getFieldId(spec), "is", null) + this.addCond(cond) + } dateEqual(spec: DateEqual): void { - this.addCond(this.eb.eb(this.getFieldId(spec), "=", spec.date?.toISOString() ?? null)) + this.addCond(this.eb.eb(this.getFieldId(spec), "=", spec.date?.getTime() ?? null)) } attachmentEqual(s: AttachmentEqual): void { throw new Error("Method not implemented.") @@ -132,35 +137,27 @@ export class RecordFilterVisitor extends AbstractQBVisitor implements this.addCond(cond) } dateIsBefore(spec: DateIsBefore): void { - const cond = this.eb.eb(this.getFieldId(spec), "<", startOfDay(spec.date).toISOString()) + const cond = this.eb.eb(this.getFieldId(spec), "<", startOfDay(spec.date).getTime()) this.addCond(cond) } dateIsAfter(spec: DateIsAfter): void { - const cond = this.eb.eb(this.getFieldId(spec), ">", endOfDay(spec.date).toISOString()) + const cond = this.eb.eb(this.getFieldId(spec), ">", endOfDay(spec.date).getTime()) this.addCond(cond) } dateIsTomorrow(spec: DateIsTomorrow): void { - const cond = this.eb.between(this.getFieldId(spec), startOfTomorrow().toISOString(), endOfTomorrow().toISOString()) + const cond = this.eb.between(this.getFieldId(spec), startOfTomorrow().getTime(), endOfTomorrow().getTime()) this.addCond(cond) } dateIsYesterday(spec: DateIsTomorrow): void { - const cond = this.eb.between( - this.getFieldId(spec), - startOfYesterday().toISOString(), - endOfYesterday().toISOString(), - ) + const cond = this.eb.between(this.getFieldId(spec), startOfYesterday().getTime(), endOfYesterday().getTime()) this.addCond(cond) } dateIsToday(spec: DateIsToday): void { - const cond = this.eb.between(this.getFieldId(spec), startOfToday().toISOString(), endOfToday().toISOString()) + const cond = this.eb.between(this.getFieldId(spec), startOfToday().getTime(), endOfToday().getTime()) this.addCond(cond) } dateIsSameDate(spec: DateIsSameDay): void { - const cond = this.eb.between( - this.getFieldId(spec), - startOfDay(spec.date).toISOString(), - endOfDay(spec.date).toISOString(), - ) + const cond = this.eb.between(this.getFieldId(spec), startOfDay(spec.date).getTime(), endOfDay(spec.date).getTime()) this.addCond(cond) } idEqual(spec: IdEqual): void { diff --git a/packages/persistence/src/record/record.mutate-visitor.ts b/packages/persistence/src/record/record.mutate-visitor.ts index 2082106ff..35cc61a37 100644 --- a/packages/persistence/src/record/record.mutate-visitor.ts +++ b/packages/persistence/src/record/record.mutate-visitor.ts @@ -1,6 +1,7 @@ import { getCurrentUserId, mustGetCurrentSpaceId } from "@undb/context/server" import type { ISpecification, ISpecVisitor } from "@undb/domain" import { + DateIsEmpty, ID_TYPE, JsonContains, LongTextEqual, @@ -81,6 +82,9 @@ export class RecordMutateVisitor extends AbstractQBMutationVisitor implements IR jsonEmpty(spec: JsonEmpty): void { this.setData(spec.fieldId.value, null) } + dateIsEmpty(spec: DateIsEmpty): void { + this.setData(spec.fieldId.value, null) + } dateEqual(spec: DateEqual): void { this.setData(spec.fieldId.value, spec.date?.getTime() ?? null) } diff --git a/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-field.condition.ts b/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-field.condition.ts index 1e2bab1a3..9893f7534 100644 --- a/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-field.condition.ts +++ b/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-field.condition.ts @@ -11,6 +11,7 @@ import type { FieldId } from "../../field-id.vo" import { DateIsAfter, DateIsBefore, + DateIsEmpty, DateIsSameDay, DateIsToday, DateIsTomorrow, @@ -54,6 +55,9 @@ export function createAbstractDateFieldCondition( z.object({ op: z.literal("is_not_before"), value: dateValue }).merge(base), z.object({ op: z.literal("is_after"), value: dateValue }).merge(base), z.object({ op: z.literal("is_not_after"), value: dateValue }).merge(base), + + z.object({ op: z.literal("is_empty"), value: z.undefined() }).merge(base), + z.object({ op: z.literal("is_not_empty"), value: z.undefined() }).merge(base), ]) } @@ -80,3 +84,5 @@ export const createAbstractDateConditionMather = ( .with({ op: "is_after_tomorrow" }, () => new DateIsAfter(endOfTomorrow(), fieldId)) .with({ op: "is_after_yesterday" }, () => new DateIsAfter(endOfYesterday(), fieldId)) .with({ op: "is_not_after" }, ({ value }) => new DateIsAfter(new Date(value), fieldId).not()) + .with({ op: "is_empty" }, () => new DateIsEmpty(fieldId)) + .with({ op: "is_not_empty" }, () => new DateIsEmpty(fieldId).not()) diff --git a/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-value.specification.ts b/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-value.specification.ts index a1d205a0e..d27e5ea55 100644 --- a/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-value.specification.ts +++ b/packages/table/src/modules/schema/fields/variants/abstractions/abstract-date-value.specification.ts @@ -4,7 +4,7 @@ import { isToday } from "date-fns/isToday" import type { IRecordVisitor, RecordDO } from "../../../../records" import { RecordComositeSpecification } from "../../../../records/record/record.composite-specification" import type { FieldId } from "../../field-id.vo" -import { startOfToday } from "date-fns/startOfToday" +import { DateFieldValue } from "../date-field" export class DateIsSameDay extends RecordComositeSpecification { constructor( @@ -120,3 +120,17 @@ export class DateIsAfter extends RecordComositeSpecification { return Ok(undefined) } } + +export class DateIsEmpty extends RecordComositeSpecification { + isSatisfiedBy(t: RecordDO): boolean { + throw new Error("Method not implemented.") + } + mutate(t: RecordDO): Result { + t.values.setValue(this.fieldId, new DateFieldValue(null)) + return Ok(t) + } + accept(v: IRecordVisitor): Result { + v.dateIsEmpty(this) + return Ok(undefined) + } +} diff --git a/packages/table/src/modules/schema/fields/variants/date-field/date-field-value.visitor.ts b/packages/table/src/modules/schema/fields/variants/date-field/date-field-value.visitor.ts index af3c05c6e..ac9a2f7fc 100644 --- a/packages/table/src/modules/schema/fields/variants/date-field/date-field-value.visitor.ts +++ b/packages/table/src/modules/schema/fields/variants/date-field/date-field-value.visitor.ts @@ -1,6 +1,8 @@ +import type { DateIsEmpty } from "../abstractions/abstract-date-value.specification" import type { IAbstractDateFieldValueVisitor } from "../abstractions/abstract-date-value.visitor" import type { DateEqual } from "./date-field.specification" export interface IDateFieldValueVisitor extends IAbstractDateFieldValueVisitor { dateEqual(spec: DateEqual): void + dateIsEmpty(spec: DateIsEmpty): void } diff --git a/packages/table/src/modules/schema/fields/variants/string-field/string-field-value.specification.ts b/packages/table/src/modules/schema/fields/variants/string-field/string-field-value.specification.ts index d02662ba9..001467fdb 100644 --- a/packages/table/src/modules/schema/fields/variants/string-field/string-field-value.specification.ts +++ b/packages/table/src/modules/schema/fields/variants/string-field/string-field-value.specification.ts @@ -34,7 +34,7 @@ export class StringContains extends RecordComositeSpecification { } isSatisfiedBy(t: RecordDO): boolean { const value = t.getValue(this.fieldId) - return value.mapOr(false, (v) => v instanceof StringFieldValue && v.value.includes(this.value)) + return value.mapOr(false, (v) => v instanceof StringFieldValue && !!v.value?.includes(this.value)) } mutate(t: RecordDO): Result { throw new Error("Method not implemented.") @@ -54,7 +54,7 @@ export class StringStartsWith extends RecordComositeSpecification { } isSatisfiedBy(t: RecordDO): boolean { const value = t.getValue(this.fieldId) - return value.mapOr(false, (v) => v instanceof StringFieldValue && v.value.startsWith(this.value)) + return value.mapOr(false, (v) => v instanceof StringFieldValue && !!v.value?.startsWith(this.value)) } mutate(t: RecordDO): Result { throw new Error("Method not implemented.") @@ -74,7 +74,7 @@ export class StringEndsWith extends RecordComositeSpecification { } isSatisfiedBy(t: RecordDO): boolean { const value = t.getValue(this.fieldId) - return value.mapOr(false, (v) => v instanceof StringFieldValue && v.value.endsWith(this.value)) + return value.mapOr(false, (v) => v instanceof StringFieldValue && !!v.value?.endsWith(this.value)) } mutate(t: RecordDO): Result { throw new Error("Method not implemented.") @@ -111,7 +111,7 @@ export class StringMin extends RecordComositeSpecification { } isSatisfiedBy(t: RecordDO): boolean { const value = t.getValue(this.fieldId) - return value.mapOr(false, (v) => v instanceof StringFieldValue && v.value.length >= this.min) + return value.mapOr(false, (v) => v instanceof StringFieldValue && (v.value?.length ?? 0) >= this.min) } mutate(t: RecordDO): Result { throw new Error("Method not implemented.") @@ -131,7 +131,7 @@ export class StringMax extends RecordComositeSpecification { } isSatisfiedBy(t: RecordDO): boolean { const value = t.getValue(this.fieldId) - return value.mapOr(false, (v) => v instanceof StringFieldValue && v.value.length <= this.max) + return value.mapOr(false, (v) => v instanceof StringFieldValue && (v.value?.length ?? 0) <= this.max) } mutate(t: RecordDO): Result { throw new Error("Method not implemented.")