Read the calendar as days, weeks and years - #112
Merged
Conversation
A calendar's recordings and a period's are not the same answer. A calendar lists what it holds, and a recurring event is one row in it; a day, a week or a year expands that row into the occurrences that fall inside its window. Draw a week from a calendar's recordings and a weekly meeting shows up once, on the day it was created. So there are five reads here rather than one: a day, the window of days after a date, a week, the nine weeks around one, and a year. Every one of them is scoped to the calendars the reader has switched on, which is what ToggleCalendar changes -- and why it answers the selection it left behind, so a client does not have to read the calendars again to know what its next period read will cover. A year is the odd one out on purpose. It answers the grid it is drawn as -- one entry per day, plus the events that span more than one -- because a year of expanded occurrences is not what opening a year asks for. Every path here ends in a date, which Smithy cannot follow with `.json` inside one URI segment, so the operations are modelled without it and pick it up from withJSONExtension like the other label-terminated routes. The routes were already in the pinned route snapshot, serving HTML; what changed is that they answer JSON now. The pin and the API version stay where they are.
monorkin
force-pushed
the
calendar-periods
branch
from
August 22, 2026 14:56
1d61db9 to
1228845
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A calendar's recordings and a period's are not the same answer. A calendar lists what it
holds, and a recurring event is one row in it; a day, a week or a year expands that row
into the occurrences that fall inside its window. Draw a week from a calendar's recordings
and a weekly meeting shows up once, on the day it was created.
So there are five reads here rather than one, plus the toggle that decides what they cover:
CalendarPeriods().Day(date)GET /calendar/days/{date}.jsonnowworks as the dateCalendarPeriods().Days(startsAt)GET /calendar/days.jsonCalendarPeriods().Week(date)GET /calendar/weeks/{date}.jsonCalendarPeriods().Weeks(startsAt, centeredAt)GET /calendar/weeks.jsonCalendarPeriods().Year(date)GET /calendar/years/{date}.jsonCalendars().Toggle(id)POST /calendars/{id}/toggle.jsonEvery period read is scoped to the calendars the reader has switched on, which is what the
toggle changes — and why the toggle answers the selection rather than nothing, so a client
learns what its next period read will cover without reading the calendars again.
A year is the odd one out on purpose. It answers the grid it is drawn as — one entry per
day, plus the events that span more than one — because a year of expanded occurrences is
not what opening a year asks for.
Notes for review
No
.jsonin the modelled URIs for the three date-terminated routes. Smithy refuses{day}.json— a literal segment cannot contain braces. Those operations are modelledwithout the extension and pick it up from
withJSONExtensionper request, like the otherlabel-terminated routes already do. The tests assert the wire path, extension included.
Six exclusions dropped from
spec/excluded-routes.json, all of them "phase-2".GET /calendar/days/nowstays excluded and its reason is rewritten: it is the same actionas the day read, reachable by passing
nowas the date.The route snapshot and the API version stay pinned where they were. These routes were
already in the snapshot — they served HTML — and what changed is that they answer JSON now.
Re-pinning would pull in every unrelated route added since the pinned SHA and ask this PR
to write exclusions for work it knows nothing about.
AGENTS.mdties the service versiondate to the snapshot pin, so that stays put too.
Bumped to 0.16.0 — #111 took 0.15.0 while this was open.