Skip to content

Fix #404 Add temporal data#409

Merged
barakb merged 5 commits intomainfrom
temporal-data
Nov 24, 2025
Merged

Fix #404 Add temporal data#409
barakb merged 5 commits intomainfrom
temporal-data

Conversation

@Anchel123
Copy link
Copy Markdown
Contributor

@Anchel123 Anchel123 commented Sep 11, 2025

Summary by CodeRabbit

  • New Features

    • Native support for date, time, datetime, and duration values with automatic parsing and round-trip in queries, parameters, and results; public typings now expose Temporal types.
  • Chores

    • Added a Temporal polyfill dependency to enable temporal data handling.
  • Tests

    • Expanded suite-level tests for temporal types, read-only queries, execution plans, slow-log/caching, graph copy/metadata, indexes/constraints, and lifecycle handling.
  • Refactor

    • Modernized parsing, metadata resolution, and data-shape handling while preserving public API behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 11, 2025

Walkthrough

Adds the Temporal polyfill dependency; extends graph type system and parsing to support DATETIME/DATE/TIME/DURATION; refactors Graph internals to centralize metadata resolution and parsing; updates public typings to include Temporal types; and expands tests to validate temporal round-trips and related graph behaviors.

Changes

Cohort / File(s) Summary
Dependencies
package.json
Adds dependency @js-temporal/polyfill@^0.5.1.
Graph core & typing
src/graph.ts
Imports Temporal from @js-temporal/polyfill; adds value kinds DATETIME, DATE, TIME, DURATION; expands GraphRawValue and exported GraphValue unions to include Temporal.PlainDateTime, PlainDate, PlainTime, and Temporal.Duration; centralizes metadata lookup/parse/resolve flow; refactors private fields and parsing pipeline; updates raw tuple/map shapes and GraphReply typing.
Tests
tests/graphAndQuery.spec.ts
Moves DB setup/teardown to suite-level lifecycle; uses Temporal polyfill in tests; adds/expands tests for temporal durations/dates/times/datetimes, roQuery, explain/profile/slowLog, index/constraint ops, graph creation/copy/schema validation, and related assertions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor TestSuite as Test Suite
  participant Graph as Graph
  participant Client as Redis Client
  participant MetaCache as Metadata Cache
  participant Temporal as "@js-temporal/polyfill"

  TestSuite->>Graph: query(queryText, params)
  Graph->>Client: GRAPH.QUERY <graph>, queryText, params
  Client-->>Graph: Reply (headers, data, metaIds)

  rect rgb(245,250,255)
    note right of Graph: Metadata resolution (centralized)
    Graph->>MetaCache: lookup(metaIds)
    alt cache miss
      Graph->>Client: GRAPH.RO_QUERY ... (metadata request)
      Client-->>Graph: metadata names
      Graph->>MetaCache: update(cache)
    end
  end

  rect rgb(240,255,240)
    note right of Graph: Value parsing & conversion (per-cell)
    loop for each cell
      alt temporal type detected
        Graph->>Temporal: parse(encodedTemporal)
        Temporal-->>Graph: PlainDate / PlainTime / PlainDateTime / Duration
      else non-temporal
        Graph-->>Graph: parse per type (int/string/array/point/vector)
      end
    end
  end

  Graph-->>TestSuite: GraphReply (data?, stats, cached?)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Files needing extra attention:
    • src/graph.ts — Temporal parsing, expanded unions, metadata cache/resolution, and refactor correctness.
    • tests/graphAndQuery.spec.ts — suite lifecycle, many new temporal tests, and async cleanup stability.
    • package.json — ensure polyfill version and test/runtime compatibility.

Poem

A rabbit hops through date and tide,
PlainTime and PlainDate by my side.
Durations hum a steady tune,
Metadata blooms beneath the moon.
Queries return — carrot harvest soon. 🥕⏳

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main objective of the pull request: adding temporal data support to address issue #404.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch temporal-data

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d6ed76 and de690e5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Anchel123 Anchel123 requested a review from barakb September 11, 2025 12:08
@Anchel123 Anchel123 linked an issue Sep 11, 2025 that may be closed by this pull request
@Anchel123 Anchel123 changed the title commit Fix #404 Add temporal data Sep 11, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 11, 2025

Codecov Report

❌ Patch coverage is 94.94382% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.67%. Comparing base (1b4c2ab) to head (de690e5).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/graph.ts 94.94% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #409      +/-   ##
==========================================
+ Coverage   92.61%   92.67%   +0.05%     
==========================================
  Files          23       23              
  Lines         555      573      +18     
  Branches       87       91       +4     
==========================================
+ Hits          514      531      +17     
  Misses         41       41              
- Partials        0        1       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (6)
src/graph.ts (3)

301-303: Parse BOOLEAN case-insensitively.

Server casing shouldn’t matter; keep it robust.

Apply this diff:

-        return value === "true";
+        return value.toLowerCase() === "true";

322-333: Simplify MAP decoding loop for clarity.

Avoid index mutation inside the subscript.

Apply this diff:

-        for (let i = 0; i < value.length; i++) {
-          map[value[i++] as string] = this.#parseValue(
-            value[i] as GraphRawValue,
-            promises
-          );
-        }
+        for (let i = 0; i < value.length; i += 2) {
+          const key = value[i] as string;
+          map[key] = this.#parseValue(value[i + 1] as GraphRawValue, promises);
+        }

6-6: Optional: prefer top-level type import to avoid deep path coupling.

If @redis/client exports RedisCommandArgument, use:

-import { RedisCommandArgument } from "@redis/client/dist/lib/commands";
+import type { RedisCommandArgument } from "@redis/client";

Would you like me to verify current @redis/client typings across supported versions?

tests/graphAndQuery.spec.ts (3)

289-299: Assert directly instead of expecting an assertion to throw.

Cleaner and less confusing.

Apply this diff:

-    expect(() => {
-      expect(executionTime).toBeLessThan(1);
-    }).toThrow();
+    expect(executionTime).toBeGreaterThanOrEqual(1);

55-56: Drop unnecessary await.

selectGraph is synchronous.

Apply this diff:

-    const copyGraph = await clientInstance.selectGraph("graphcopy");
+    const copyGraph = clientInstance.selectGraph("graphcopy");

566-570: Remove debug logs from tests.

They add noise to CI output.

Apply this diff:

-        console.log(
-          (result.data as { time: Temporal.PlainTime }[])[0].time.toString()
-        );
-        console.log(timeObj.toString());
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61b8d80 and b554179.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/graph.ts (1 hunks)
  • tests/graphAndQuery.spec.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/graphAndQuery.spec.ts (3)
src/falkordb.ts (1)
  • FalkorDB (122-193)
tests/dbConnection.ts (1)
  • client (3-15)
src/graph.ts (1)
  • query (143-146)
src/graph.ts (4)
src/commands/QUERY.ts (1)
  • QueryReply (35-43)
src/clients/client.ts (1)
  • Client (8-80)
src/commands/index.ts (1)
  • QueryOptions (58-61)
index.ts (2)
  • ConstraintType (2-2)
  • EntityType (2-2)
🪛 Biome (2.1.2)
src/graph.ts

[error] 356-356: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 357-357: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (3)
package.json (1)

50-51: Temporal polyfill dependency looks good.

Adding "@js-temporal/polyfill" as a runtime dependency is appropriate given its use in src and tests.

tests/graphAndQuery.spec.ts (2)

275-287: Slow log assertions may be brittle; guard for empty logs.

Depending on server config, slow log might be empty. Add a length check to avoid index errors.

Apply this diff:

-    expect(slowLogResults).toBeDefined();
-    expect(slowLogResults[0].command).toBe("GRAPH.QUERY");
+    expect(slowLogResults).toBeDefined();
+    expect(slowLogResults.length).toBeGreaterThan(0);
+    expect(slowLogResults[0].command).toBe("GRAPH.QUERY");

1-6: Test imports LGTM.

Temporal polyfill is correctly imported; suite-scoped DB lifecycle is sensible.

Comment thread src/graph.ts
Comment thread src/graph.ts
Comment thread src/graph.ts
Comment thread src/graph.ts
Comment thread tests/graphAndQuery.spec.ts
Comment thread tests/graphAndQuery.spec.ts
Comment thread tests/graphAndQuery.spec.ts
@barakb
Copy link
Copy Markdown
Contributor

barakb commented Nov 3, 2025

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 3, 2025

✅ Actions performed

Full review triggered.

@Anchel123 Anchel123 requested a review from AviAvni November 18, 2025 08:12
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
src/graph.ts (4)

118-122: Fix POINT type: values are numbers, not strings.

This issue was flagged in a previous review and remains unresolved. The GraphValue type declares latitude and longitude as strings, but they are parsed as numbers (lines 343-344).

Apply this diff:

   | {
-      latitude: string;
-      longitude: string;
+      latitude: number;
+      longitude: number;
     }

272-275: Normalize empty-data replies to match the declared GraphReply shape.

This issue was flagged in a previous review and remains unresolved. Returning the raw reply when reply.data is falsy leaks the internal "headers" field, violating the GraphReply type contract.

Apply this diff:

-    if (!reply.data) return reply;
+    if (!reply.data) return { metadata: reply.metadata };

362-370: Wrap DURATION case declarations in a block to satisfy noSwitchDeclarations.

This issue was flagged in a previous review and by Biome static analysis. The const declarations on lines 363-364 can bleed through to other cases without block scoping.

Apply this diff:

-      case GraphValueTypes.DURATION:
-        const time = Temporal.Instant.fromEpochMilliseconds(value * 1000);
-        const epoch = Temporal.Instant.fromEpochMilliseconds(0);
-
-        return epoch
-          .toZonedDateTimeISO("UTC")
-          .until(time.toZonedDateTimeISO("UTC"), {
-            largestUnit: "years",
-          });
+      case GraphValueTypes.DURATION: {
+        const time = Temporal.Instant.fromEpochMilliseconds(value * 1000);
+        const epoch = Temporal.Instant.fromEpochMilliseconds(0);
+        return epoch
+          .toZonedDateTimeISO("UTC")
+          .until(time.toZonedDateTimeISO("UTC"), { largestUnit: "years" });
+      }

154-156: Invalidate metadata cache on delete operation.

This issue was flagged in a previous review and remains unresolved. When the graph is deleted, the metadata cache should be cleared to prevent stale data in subsequent operations.

Apply this diff:

   async delete() {
-    return this.#client.delete(this.#name);
+    const res = await this.#client.delete(this.#name);
+    this.#metadata = undefined;
+    return res;
   }

Also applies to: constraintCreate (176-189), constraintDrop (191-204), and query/index operations (479, 567)

🧹 Nitpick comments (1)
src/graph.ts (1)

450-480: Consider validating label and property names to prevent injection.

The createTypedIndex method builds Cypher queries using string interpolation with label and properties parameters. While typical usage involves literal strings, consider validating these inputs to prevent potential Cypher injection if user-controlled values are passed.

Example validation:

const VALID_IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*$/;

async createTypedIndex(
  idxType: string,
  entityType: "NODE" | "EDGE",
  label: string,
  properties: string[],
  options?: Record<string, string | number | boolean>
): Promise<QueryReply> {
  if (!VALID_IDENTIFIER.test(label)) {
    throw new Error(`Invalid label: ${label}`);
  }
  for (const prop of properties) {
    if (!VALID_IDENTIFIER.test(prop)) {
      throw new Error(`Invalid property: ${prop}`);
    }
  }
  // ... rest of implementation
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c1f39c and 2d6ed76.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json (1 hunks)
  • src/graph.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🧬 Code graph analysis (1)
src/graph.ts (4)
src/commands/QUERY.ts (1)
  • QueryReply (35-43)
src/clients/client.ts (1)
  • Client (9-86)
src/commands/index.ts (1)
  • QueryOptions (61-64)
index.ts (2)
  • ConstraintType (2-2)
  • EntityType (2-2)
🪛 Biome (2.1.2)
src/graph.ts

[error] 363-363: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 364-364: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (6)
src/graph.ts (6)

128-130: LGTM! Public API correctly hides internal headers.

The GraphReply type properly omits the internal "headers" field from QueryReply and replaces "data" with a typed version, providing a clean public API.


32-35: LGTM! Temporal types correctly added to enum.

The new DATETIME, DATE, TIME, and DURATION enum values follow the sequential numbering from FalkorDB's resultset_formatter.h and are properly integrated.


79-82: LGTM! Temporal raw value types correctly defined.

The temporal raw value types properly specify number as the underlying value type, consistent with the parsing logic that expects Unix timestamp values.


123-126: LGTM! GraphValue union properly extended with Temporal types.

The GraphValue union correctly includes the Temporal types that correspond to the parsing output, providing a type-safe public API for temporal data.


6-6: No issues found with the Temporal polyfill import.

Version 0.5.1 is the latest published version (March 31, 2025) and contains only bug fixes with no known vulnerabilities. The import is appropriate as-is.


350-361: Timezone semantics for DATETIME/DATE/TIME parsing are correct.

FalkorDB's temporal types (DATE, TIME, DATETIME) are "local" types—timezone-naive, not timezone-aware. The wire protocol sends these as epoch seconds. The parsing code correctly converts them: multiply by 1000 (seconds → milliseconds), create an Instant, normalize to UTC, then extract the Plain* type (which removes timezone information as intended, since these types are timezone-naive by design).

Tests confirm the behavior is correct and round-trip values match expectations. No changes needed.

Comment thread src/graph.ts
Copy link
Copy Markdown
Contributor

@barakb barakb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is ai comment that seems important

@barakb barakb merged commit c44368c into main Nov 24, 2025
10 checks passed
@barakb barakb deleted the temporal-data branch November 24, 2025 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support temporal data

2 participants