fix(utils): isEmpty reads a Date as a value, not as an empty object

Merged
EV
10d ago
+91-0

What

isEmpty from @gauzy/utils (and isNotEmpty, its negation) decides "is there a value" for about 300 call sites in the API and the plugins. A Date has no own enumerable property, so the object rule ("empty when no member holds anything") read every date as empty, and a list of dates as an empty list.

A valid Date is now a value, and only an invalid date (one whose getTime() is NaN) is empty. Every other input answers exactly what it answered before.

Why it mattered

  • getFilterTimeLogQuery (TypeORM and MikroORM) guards the time-log date range with isNotEmpty(request.startDate) && isNotEmpty(request.endDate). Handed Dates, every report and list query ran with no date range at all. Today REST passes strings and the GraphQL DateTime scalar passes strings or numbers, so only an internal caller could hit it: a latent trap, recorded in the 10-15 follow-ups handover.
  • #10763's slot release returned early on isEmpty([date]) until it switched to a length check.
  • Audit: no call site passes an entity *At column today. Develop's changes since this was cut add no isEmpty calls.

Red first (develop 77b47e8e728, rebased onto 496b3664b71)

  • packages/utils/src/lib/is-empty.spec.ts (new) failed 2 of 21 tests (a Date, and a list of Dates, read as empty) and now passes 21/21.
    • Its controls pin every other behaviour: null, undefined, '', 'null'/'undefined' in any case, 0, false and NaN are empty; non-empty strings, numbers and true are values; lists are judged by their non-empty members; objects by their members that hold something; the input is not mutated.
  • time-log.service.spec.ts › "applies the date range when it is given as Date objects" failed 1 of 56 (no startedAt predicate) and now passes 56/56.

Verification

  • utils package 104/104; all packages/core/src/lib/time-tracking specs, 50 suites / 637 tests.
  • Full packages/core jest suite on the original base: 11,582 / 11,583. The 1 is pre-existing on develop and unrelated: export-redact.entities.spec.ts flags EverWorksConnection.apiKeyEncrypted / webhookSecretEncrypted without export marks. It is red on plain develop too, and has been reported to the integration lane.
  • tsc -p packages/utils/tsconfig.lib.json 0 errors, tsc -p packages/core/tsconfig.lib.json 0 errors, and the 30 static gates pass.

Not in this PR

The Angular copy in packages/ui-core/common/src/lib/utils/shared-utils.ts has the same flaw. The UI hands it Dates from date pickers, so it needs its own audit and a browser check. It's recorded as a follow-up.

is-empty.ts keeps its existing 4-space indentation. Prettier would want tabs, but reformatting the whole file is out of scope, and only these lines are new.

🤖 Generated with Claude Code


Summary by cubic

Fixes isEmpty in @gauzy/utils reading every Date as empty, which silently dropped the date range in time-log report and list queries through getFilterTimeLogQuery (and forced a workaround in #10763). A Date is now a value whenever it holds a time; only an invalid date (one whose getTime() is NaN) is empty. Every other input answers exactly as before, pinned by new coverage, and isEmpty's doc comment now states the rule as it is.

  • Adds a spec covering a Date in isolation, inside lists, and inside objects, plus controls for all other input kinds.
  • Adds a regression test for getDailyReport applying the date range when given Date objects.