Skip to content

feat(projections): expose event creation timestamp#238

Open
yordis wants to merge 2 commits intomasterfrom
yordis/feat-projection-event-created
Open

feat(projections): expose event creation timestamp#238
yordis wants to merge 2 commits intomasterfrom
yordis/feat-projection-event-created

Conversation

@yordis
Copy link
Copy Markdown
Member

@yordis yordis commented May 8, 2026

  • Let JS projections make timestamp-aware decisions without requiring metadata workarounds.
  • Keep the documented handler event shape aligned with the runtime envelope.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 8, 2026

PR Summary

Medium Risk
Adds a new event.created field to the JavaScript projection event envelope and normalizes timestamp handling to UTC ISO-8601, which could affect projections that depend on the exact event shape or time formatting.

Overview
Exposes each processed event’s creation time to interpreted (Jint) JavaScript projections via a new event.created property, formatted as a UTC ISO-8601 string.

Updates the runtime envelope construction to carry ResolvedEvent.Timestamp through to JS, includes UTC/Unspecified normalization, and adds a regression test plus documentation updates to reflect the new handler event shape.

Reviewed by Cursor Bugbot for commit 3e818b1. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd810491-e4e9-4d5e-803b-e66896e7d3c9

📥 Commits

Reviewing files that changed from the base of the PR and between d7b50cf and 3e818b1.

📒 Files selected for processing (3)
  • docs/projections.md
  • src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs
  • src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs
✅ Files skipped from review due to trivial changes (1)
  • docs/projections.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs

Walkthrough

This PR surfaces an event's creation timestamp to JavaScript projection handlers via a new created property (ISO 8601 string), updates serialization and envelope creation, adds an NUnit test, and documents the field in the projections guide.

Changes

Event Created Timestamp Exposure

Layer / File(s) Summary
Event Envelope Contract
src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs
Added Created property and FormatCreated(DateTime) to normalize to UTC and format as ISO 8601 round‑trip.
Envelope Creation & Serialization
src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs
CreateEnvelope assigns envelope.Created from the resolved event timestamp; AsString updated to return null for JsUndefined and use Serialize(value) for general fallback.
Test Suite
src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs
New parameterized NUnit fixture validates event.created is emitted as an ISO 8601 string.
User Documentation
docs/projections.md
Added created: string (ISO 8601) to the event object properties reference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I tuck the moments in a string of light,
ISO whispers of a day and night,
Events now wear their birthtime true,
Hopped into state for me and you —
carrots, clocks, and code in view.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(projections): expose event creation timestamp' clearly and concisely summarizes the main change: adding event creation timestamp exposure to projections.
Description check ✅ Passed The description explains the rationale for the change: enabling timestamp-aware decisions in JS projections and aligning documentation with runtime behavior.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yordis/feat-projection-event-created

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.

@yordis yordis force-pushed the yordis/feat-projection-event-created branch from a5755be to d7b50cf Compare May 9, 2026 00:43
Copy link
Copy Markdown

@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

🧹 Nitpick comments (2)
src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs (2)

48-48: 💤 Low value

Use Assert.That instead of Assert.AreEqual for idiomatic NUnit 3.

-		Assert.AreEqual(ExpectedTimestamp.ToString("o"), state.RootElement.GetProperty("created").GetString());
+		Assert.That(state.RootElement.GetProperty("created").GetString(), Is.EqualTo(ExpectedTimestamp.ToString("o")));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs`
at line 48, Replace the NUnit assertion to use Assert.That for idiomatic NUnit3:
change the assertion that compares ExpectedTimestamp.ToString("o") with
state.RootElement.GetProperty("created").GetString() to use Assert.That(actual,
Is.EqualTo(expected)) referencing the existing symbols (ExpectedTimestamp and
state.RootElement.GetProperty("created").GetString()) and ensure the order is
Assert.That(state.RootElement.GetProperty("created").GetString(),
Is.EqualTo(ExpectedTimestamp.ToString("o"))).

13-13: ⚡ Quick win

Test only covers DateTimeKind.Utc — add a DateTimeKind.Unspecified case.

Given the DateTime.ToString("o") format-specifier behavior, a test with DateTimeKind.Unspecified would confirm (or reveal) the ambiguity described in the implementation concern above. A single additional [TestCase]-style variant would be sufficient.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs`
at line 13, The test only exercises DateTimeKind.Utc; add a second test variant
that constructs the same timestamp with DateTimeKind.Unspecified and asserts the
projection/js-access behavior matches expectations. Update the test in
when_accessing_event_created_property.cs to include a new [TestCase] (or
duplicate the existing test) that uses a DateTime like the existing
ExpectedTimestamp but with DateTimeKind.Unspecified (or add a new
ExpectedTimestampUnspecified constant) and verify the string produced by the
code under test (the projection/Jint access path referenced in the test) for
ToString("o")/serialization is asserted the same way as the Utc case. Ensure the
test name/existing method that references ExpectedTimestamp is reused or
duplicated so both DateTimeKind.Utc and DateTimeKind.Unspecified are covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs`:
- Around line 1124-1127: The Created property serializes a DateTime using
ToString("o") which yields unqualified timestamps for DateTimeKind.Unspecified;
change the setter in JintProjectionStateHandler (the Created property that calls
SetOwnProperty("created", ...)) to convert the incoming DateTime to UTC before
formatting (e.g., use value.ToUniversalTime() or otherwise ensure
DateTimeKind.Utc) so the generated ISO-8601 string includes the Z offset;
alternatively consider switching to DateTimeOffset handling for explicit
offsets.

---

Nitpick comments:
In
`@src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs`:
- Line 48: Replace the NUnit assertion to use Assert.That for idiomatic NUnit3:
change the assertion that compares ExpectedTimestamp.ToString("o") with
state.RootElement.GetProperty("created").GetString() to use Assert.That(actual,
Is.EqualTo(expected)) referencing the existing symbols (ExpectedTimestamp and
state.RootElement.GetProperty("created").GetString()) and ensure the order is
Assert.That(state.RootElement.GetProperty("created").GetString(),
Is.EqualTo(ExpectedTimestamp.ToString("o"))).
- Line 13: The test only exercises DateTimeKind.Utc; add a second test variant
that constructs the same timestamp with DateTimeKind.Unspecified and asserts the
projection/js-access behavior matches expectations. Update the test in
when_accessing_event_created_property.cs to include a new [TestCase] (or
duplicate the existing test) that uses a DateTime like the existing
ExpectedTimestamp but with DateTimeKind.Unspecified (or add a new
ExpectedTimestampUnspecified constant) and verify the string produced by the
code under test (the projection/Jint access path referenced in the test) for
ToString("o")/serialization is asserted the same way as the Utc case. Ensure the
test name/existing method that references ExpectedTimestamp is reused or
duplicated so both DateTimeKind.Utc and DateTimeKind.Unspecified are covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e8232b58-08c9-4dc7-9ce3-04dff1eef68f

📥 Commits

Reviewing files that changed from the base of the PR and between b093a01 and d7b50cf.

📒 Files selected for processing (3)
  • docs/projections.md
  • src/EventStore.Projections.Core.Tests/Services/Jint/when_accessing_event_created_property.cs
  • src/EventStore.Projections.Core/Services/Interpreted/JintProjectionStateHandler.cs

yordis added 2 commits May 9, 2026 12:10
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis yordis force-pushed the yordis/feat-projection-event-created branch from d7b50cf to 3e818b1 Compare May 9, 2026 16:13
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.

1 participant