Skip to content

✨ feat(timeline): intuitive since/until window bounds for queryTimeline (BREAKING)#77

Merged
marcelsamyn merged 10 commits into
mainfrom
feat/timeline-since-until
Jun 18, 2026
Merged

✨ feat(timeline): intuitive since/until window bounds for queryTimeline (BREAKING)#77
marcelsamyn merged 10 commits into
mainfrom
feat/timeline-since-until

Conversation

@marcelsamyn

@marcelsamyn marcelsamyn commented Jun 18, 2026

Copy link
Copy Markdown
Owner

What & why

queryTimeline's date bounds were named and defaulted backwards: startDate was the newest edge (default today), endDate the oldest (default 90 days ago) — the reverse of the universal start ≤ end convention. Petals, reading the names the obvious way, sent { endDate: today }, which the backend resolved to the window [today, today] and starved every past period — so every week/month/year recap in the memory timeline showed "no recap" even though the rollup nodes (e.g. 2026-W23) existed with real summaries.

queryTimeline is consumed only by Petals (no n8n node, no other repo), so this corrects the contract cleanly instead of working around it.

Changes

  • Rename bounds startDate/endDatesince/until with conventional, optional semantics: since = earliest day inclusive, until = latest day inclusive; both optional; an omitted bound is open on that side. No implicit today/90-days-ago defaults, no defensive min/max swap.
  • includePeriods derives rollup periods from the day nodes actually in rangeloadTimelinePeriods collects the week/month/year keys of the in-range YYYY-MM-DD day nodes and loads exactly those rollups (deleting the old periodKeysForWindow calendar-enumeration). Open bounds work for free, and an open { until: today } feed now returns past-period summaries. Regression test pins this.
  • prepublishOnly hook runs pnpm run build-sdk before pnpm publish, closing the stale-dist publishing footgun.
  • Docs: CHANGELOG BREAKING entry + SDK consumer migration note.
  • Drive-by: fixed pre-existing build:check type errors in src/lib/query/sample-nodes.{ts,test.ts} that shipped on main (1.30.0) — see note below.

Breaking change

This renames public @marcelsamyn/memory SDK request fields → major version bump (next release 2.0.0). Petals is the sole consumer and is updated in a follow-on PR once 2.0.0 publishes; the n8n node is unaffected.

How to test

pnpm run lint && pnpm run format && pnpm run build:check && pnpm run build-sdk && pnpm test --run

All green (DB-backed tests run against Postgres on localhost:5431). Full suite: 546 tests passing.

Drive-by: sample-nodes build:check fix

build:check was already failing on main (1.30.0) with type errors in src/lib/query/sample-nodes.ts + sample-nodes.test.ts (nullable objectNodeId breaking unionAll branch-type matching; string[] vs the NodeType union; a Client vs Pool test-helper annotation; and an invalid assertedByKind: "user_stated" value that isn't in the enum). Folded type-only fixes in here so CI goes green — no runtime/query behavior change; the sample-nodes DB test runs and passes.

Checklist

  • lint
  • prettier
  • build:check
  • build-sdk (verify-sdk-build green)
  • tests (546 passing)

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a breaking change to the queryTimeline endpoint and SDK by renaming the date bounds from startDate/endDate to since/until with conventional, optional semantics. It rewrites loadTimelinePeriods to dynamically derive week, month, and year rollup periods from the day nodes actually present in the database within the specified range, which resolves a bug where past periods were incorrectly excluded. Additionally, it updates documentation, migration guides, and tests, and adds a prepublishOnly script to package.json to automate SDK builds before publishing. The reviewer suggested relaxing the strict regex validation on the optional since and until fields in the Zod schema to prevent validation failures when empty strings are passed, recommending that validation be handled in the resolver instead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +9 to 16
since: z
.string()
.regex(dateRegex, "startDate must be in YYYY-MM-DD format")
.regex(dateRegex, "since must be in YYYY-MM-DD format")
.optional(),
endDate: z
until: z
.string()
.regex(dateRegex, "endDate must be in YYYY-MM-DD format")
.regex(dateRegex, "until must be in YYYY-MM-DD format")
.optional(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To prevent the entire schema validation from failing when empty strings are passed for the optional since or until fields, we should avoid strict validation directly on these optional fields in the schema. Instead, we should allow any string in the schema and handle trimming, empty string checks, and date format validation in the resolver function. This prevents discarding other valid fields if these optional fields are empty.

  since: z.string().optional(),
  until: z.string().optional(),
References
  1. Avoid using strict validation like .min(1) on optional fields in Zod schemas when an empty string could cause the entire schema validation to fail. Instead, allow any string in the schema and handle trimming and non-empty checks in the resolver function to prevent discarding other valid fields.

@marcelsamyn marcelsamyn merged commit f90e04f into main Jun 18, 2026
1 check passed
@marcelsamyn marcelsamyn deleted the feat/timeline-since-until branch June 18, 2026 08: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.

1 participant