Skip to content

feat(events): expose personal RSVP (myRsvp) in events list; fix isHost - #58

Merged
KalebCole merged 2 commits into
mainfrom
feat/events-my-rsvp
Jul 5, 2026
Merged

feat(events): expose personal RSVP (myRsvp) in events list; fix isHost#58
KalebCole merged 2 commits into
mainfrom
feat/events-my-rsvp

Conversation

@KalebCole

@KalebCole KalebCole commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #56.

partiful events list dropped each event's personal guest object, so callers couldn't see their own RSVP. It also computed isHost from config.userId, which is undefined in most auth.json files — making isHost always false.

Both stem from not resolving "who am I". This PR resolves the authenticated user's ID by decoding the Firebase token and uses it for both.

Changes

  • src/lib/auth.js — add decodeJwtPayload() + getUserIdFromToken() (reads user_id, falls back to sub; null-safe, never throws). Backfill config.userId on the token-refresh path so older credential files self-heal.
  • src/lib/events.js — extract a pure, unit-testable mapEventSummary(e, me) that adds:
    • myRsvp — your own RSVP: GOING / MAYBE / DECLINED / SENT, or null on events you host (e.guest?.status ?? null).
    • fixed isHost — checks ownerIds against the resolved id, guarded so a null id can never match.
  • src/commands/events.js — resolve me = config.userId || getUserIdFromToken(token) (the fallback covers the PARTIFUL_TOKEN env path) and map via the helper.
  • Docs: README JSON output example, partiful-events skill, AGENTS.md.

Compatibility

Purely additive. Every pre-existing field keeps its name, order, and defaults — asserted with an exact-shape toEqual test. Version 2.0.0 → 2.1.0 (minor).

Testing

  • Unit tests: tests/jwt-identity.test.js, tests/map-event-summary.test.js (base64url edge cases, non-object payloads, all four RSVP statuses, hosted/guest/missing-status/missing-ownerIds, null & undefined identity, full backward-compat shape). Suite 106 → 129, all green.
  • Live-verified against a real account: myRsvp populated correctly across GOING/MAYBE/DECLINED/SENT and null on hosted events; isHost true only for the 3 events I actually host (was always false before).
$ partiful events list | jq '.data[] | {title, myRsvp, isHost}'
# myRsvp: SENT×5, DECLINED×3, MAYBE×2, null×3  |  isHost=true only on my 3 hosted events

Unblocks selective Partiful → Google Calendar sync (sync only myRsvp == "GOING").

Summary by CodeRabbit

  • New Features

    • events list now shows more accurate per-event details, including whether you’re the host and your RSVP status.
    • Older saved sign-in data is automatically updated so event results work without re-login.
  • Bug Fixes

    • Improved handling of missing account details and event fields, with sensible fallbacks for counts and empty values.
  • Documentation

    • Updated docs and examples to explain the JSON output and new event summary fields.
  • Tests

    • Added coverage for identity decoding and event summary formatting.

`events list` dropped the per-event `guest` object returned by the Partiful
home-page endpoints, so a caller could not see their own RSVP. It also
computed `isHost` from `config.userId`, which is undefined in most auth.json
files, making `isHost` always false.

Both stem from not resolving "who am I". Fix:

- auth.js: add decodeJwtPayload() + getUserIdFromToken() to read the user id
  from the Firebase token (user_id, falling back to sub). Backfill
  config.userId on token refresh so it self-heals for older auth.json files.
- events.js (lib): extract a pure, unit-testable mapEventSummary(e, me) that
  adds `myRsvp` (e.guest.status: GOING|MAYBE|DECLINED|SENT, null when hosting)
  and fixes `isHost` to check ownerIds against the resolved id.
- events.js (command): resolve `me` from config.userId, falling back to
  decoding the token (covers the PARTIFUL_TOKEN env path), then map via the
  helper.

Additive and backward-compatible: existing fields keep their names, order,
and defaults. Verified against a live account (myRsvp populated across
GOING/MAYBE/DECLINED/SENT; isHost true only for owned events).

Docs: README JSON output example, partiful-events skill, AGENTS.md.
Tests: 21 new unit tests (jwt-identity, map-event-summary); suite 106 -> 127.

Closes #56
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KalebCole, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7abfa420-8a6b-4574-999a-642711c8286c

📥 Commits

Reviewing files that changed from the base of the PR and between 244da38 and 53db012.

📒 Files selected for processing (2)
  • src/lib/events.js
  • tests/map-event-summary.test.js
📝 Walkthrough

Walkthrough

Adds JWT payload decoding and user id extraction to auth.js, backfilling config.userId during token refresh. Introduces a pure mapEventSummary helper exposing myRsvp and fixing isHost, wires it into the events list command, adds corresponding tests, and updates documentation and version.

Changes

myRsvp and isHost fix via JWT identity

Layer / File(s) Summary
JWT decode and userId backfill
src/lib/auth.js
Adds decodeJwtPayload and getUserIdFromToken exports, and backfills config.userId from the access token during getValidToken refresh when missing.
JWT decode tests
tests/jwt-identity.test.js
Adds a JWT-building test helper and Vitest coverage for decode/extraction success cases, base64url edge cases, and null-return failure cases.
mapEventSummary helper
src/lib/events.js
Adds exported mapEventSummary(e, me) that derives myRsvp, isHost, going, maybe, and a canonical URL with defaulting for missing fields.
mapEventSummary tests
tests/map-event-summary.test.js
Adds Vitest coverage for RSVP derivation, host derivation, and backward-compatible field defaults.
events list command wiring
src/commands/events.js
Imports getUserIdFromToken and mapEventSummary, derives me from config or token, and replaces inline mapping with mapEventSummary calls.
Documentation and version bump
AGENTS.md, README.md, skills/partiful-events/SKILL.md, package.json
Documents the myRsvp/isHost behavior and userId backfill, and bumps package version to 2.1.0.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant EventsCommand
  participant getUserIdFromToken
  participant mapEventSummary

  User->>EventsCommand: partiful events list
  EventsCommand->>EventsCommand: check config.userId
  alt userId missing
    EventsCommand->>getUserIdFromToken: decode token
    getUserIdFromToken-->>EventsCommand: me
  end
  loop each event
    EventsCommand->>mapEventSummary: map(event, me)
    mapEventSummary-->>EventsCommand: summary with myRsvp, isHost
  end
  EventsCommand-->>User: event summaries JSON
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: exposing myRsvp in events list and fixing isHost.
Linked Issues check ✅ Passed The code, tests, and docs implement myRsvp, fix isHost via token-derived identity, and add the requested helpers.
Out of Scope Changes check ✅ Passed No unrelated code changes stand out; the version bump and docs updates are part of the stated release scope.
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
  • Commit unit tests in branch feat/events-my-rsvp

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/events.js (1)

207-207: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor duplication: event URL template repeated across files.

The https://partiful.com/e/${e.id} construction here duplicates the identical pattern in the get command handler (src/commands/events.js, url: \https://partiful.com/e/${eventId}\`` per the provided graph context). Consider extracting a small buildEventUrl(id) helper in src/lib/events.js to keep the URL format in one place.

🤖 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/lib/events.js` at line 207, The event URL template is duplicated in the
event helpers and the get command handler, so centralize it in
src/lib/events.js. Add a small buildEventUrl(id) helper there and update the
existing url assignment in the events logic and the get command path to call
that helper instead of inlining https://partiful.com/e/${...}. Use the existing
events-related symbols like the URL field in the event object and the get
command’s eventId usage to locate the repeated construction.
🤖 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.

Nitpick comments:
In `@src/lib/events.js`:
- Line 207: The event URL template is duplicated in the event helpers and the
get command handler, so centralize it in src/lib/events.js. Add a small
buildEventUrl(id) helper there and update the existing url assignment in the
events logic and the get command path to call that helper instead of inlining
https://partiful.com/e/${...}. Use the existing events-related symbols like the
URL field in the event object and the get command’s eventId usage to locate the
repeated construction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 39537cc4-116d-431a-8749-560e00015f57

📥 Commits

Reviewing files that changed from the base of the PR and between a4bb263 and 244da38.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • AGENTS.md
  • README.md
  • package.json
  • skills/partiful-events/SKILL.md
  • src/commands/events.js
  • src/lib/auth.js
  • src/lib/events.js
  • tests/jwt-identity.test.js
  • tests/map-event-summary.test.js

CodeRabbit flagged the duplicated `https://partiful.com/e/${id}` template.
Add a canonical buildEventUrl(id) in src/lib/events.js and use it in
mapEventSummary; add unit tests. Pre-existing duplicate call sites in other
commands are left for a dedicated cleanup to keep this PR scoped.
@KalebCole

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@KalebCole
KalebCole merged commit d4c2e90 into main Jul 5, 2026
1 check passed
@KalebCole
KalebCole deleted the feat/events-my-rsvp branch July 5, 2026 21:43
KalebCole added a commit that referenced this pull request Jul 5, 2026
The version was hardcoded as '2.0.0' in src/cli.js, separate from
package.json. The 2.1.0 bump in #58 updated package.json but not this
string, so `partiful --version` misreported 2.0.0 while the package was
2.1.0. Read the version from package.json via createRequire so the two can
never drift again.
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.

feat(events): expose my personal RSVP (myRsvp) in events list + fix isHost via JWT identity

1 participant