Skip to content

fix(entities): honor configured baseUrl in entity links#10

Merged
scottlovegrove merged 2 commits into
mainfrom
fix/honor-baseurl-in-entity-links
May 22, 2026
Merged

fix(entities): honor configured baseUrl in entity links#10
scottlovegrove merged 2 commits into
mainfrom
fix/honor-baseurl-in-entity-links

Conversation

@scottlovegrove
Copy link
Copy Markdown
Collaborator

Summary

Port of Doist/twist-sdk-typescript#137 to comms-sdk.

When a consumer constructs new CommsApi(token, { baseUrl }), the .url field on every returned entity (Channel, Thread, Conversation, Comment, ConversationMessage, InboxThread) ignored the configured baseUrl and always pointed at the hardcoded https://comms.todoist.com. The url-building Zod schemas are module-level singletons, so the per-instance baseUrl never reached them.

What changed

  • src/types/entities.ts — each of the 6 entity schemas is now built by a createXxxSchema(linkBaseUrl?) factory that threads the base into getFullCommsURL. The exported XxxSchema = createXxxSchema() singletons and inferred types are unchanged (non-breaking). InboxThread.lastComment now uses createCommentSchema(linkBaseUrl) so the nested comment link honors the base too.
  • src/clients/base-client.ts — new getLinkBaseUrl(): returns the configured baseUrl as-is (trailing slash stripped), falling back to the default web app when unset.
  • 7 entity-producing clients (channels, comments, conversation-messages, conversations, inbox, threads, workspaces) — each holds a per-instance schema built from getLinkBaseUrl().
  • src/clients/add-comment-helper.tsClientContext gains schema, threaded from the comments and threads clients.

Difference from the twist PR

comms-sdk has no batch-descriptor pattern, so the batch paths the twist PR touched don't exist here — the port is smaller. The public module-level XxxListSchema exports are kept on the singletons for back-compat; clients use per-instance list schemas internally.

Behavior

  • baseUrl: 'https://x' → links like https://x/a/1/ch/.../
  • no baseUrl → unchanged https://comms.todoist.com/...

The base is used verbatim, matching the chosen "use baseUrl as-is" semantics.

Test plan

  • npm run type-check clean
  • npm run check (oxlint + oxfmt) clean
  • npm test — 124 pass: entity factory unit tests (base threading, default fallback, nested-comment propagation) + comments-client e2e for custom / trailing-slash bases

🤖 Generated with Claude Code

When a consumer constructs `new CommsApi(token, { baseUrl })`, the `.url`
field on returned entities (Channel, Thread, Conversation, Comment,
ConversationMessage, InboxThread) ignored the configured `baseUrl` and
always pointed at the hardcoded `https://comms.todoist.com`. The
url-building Zod schemas were module-level singletons, so the per-instance
`baseUrl` never reached them.

Each entity schema is now built by a `createXxxSchema(linkBaseUrl?)`
factory that threads the base into `getFullCommsURL`. The exported
`XxxSchema = createXxxSchema()` singletons and inferred types are
unchanged (non-breaking). Entity-producing clients hold a per-instance
schema built from a new `BaseClient.getLinkBaseUrl()`, which returns the
configured `baseUrl` as-is (trailing slash stripped), falling back to the
default web app when unset. `InboxThread.lastComment` uses
`createCommentSchema(linkBaseUrl)` so the nested link honors the base too.

Ported from Doist/twist-sdk-typescript#137.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove self-assigned this May 22, 2026
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

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

This PR successfully ports the fix to ensure entity links honor the configured baseUrl by transitioning Zod schemas to a factory pattern. It is a solid architectural adjustment that achieves the correct behavior while preserving backwards compatibility. A few refinements are suggested to optimize performance by reusing schemas on hot paths and default configurations, improve maintainability by leveraging Zod's built-in methods to reduce duplication, handle trailing slashes consistently, and ensure the new helper logic is fully tested.

Share FeedbackReview Logs

Comment thread src/types/entities.ts Outdated
Comment thread src/types/entities.ts
Comment thread src/clients/inbox-client.ts Outdated
Comment thread src/types/entities.ts
Comment thread src/types/entities.ts Outdated
Comment thread src/clients/comments-client.ts Outdated
Comment thread src/clients/channels-client.ts Outdated
Comment thread src/clients/add-comment-helper.test.ts
- Normalize a trailing slash in `getFullCommsURL` so direct schema
  consumers (`createXxxSchema('https://x/')`) get the same single-slash
  links as `CommsApi` clients; `getLinkBaseUrl` now returns the value
  verbatim.
- Reuse the exported singleton schemas/list schemas when no custom
  `baseUrl` is configured, so the common `new CommsApi(token)` path no
  longer builds duplicate Zod wrappers per client.
- Lift the `getone` wrapped-comment schema off the request hot path to a
  per-client field.
- Add `InboxThreadListSchema` and parse the inbox list through it.
- Export `createInboxThreadObjectSchema` per the all-schemas-exported rule.
- Tests: trailing-slash normalization for a direct schema consumer, and a
  base-bound schema assertion through the add-comment helper (close/reopen
  path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove requested a review from amix May 22, 2026 15:46
@scottlovegrove scottlovegrove merged commit 024d9cb into main May 22, 2026
4 checks passed
@scottlovegrove scottlovegrove deleted the fix/honor-baseurl-in-entity-links branch May 22, 2026 15:47
doist-release-bot Bot added a commit that referenced this pull request May 22, 2026
## [0.2.1](v0.2.0...v0.2.1) (2026-05-22)

### Bug Fixes

* **entities:** honor configured baseUrl in entity links ([#10](#10)) ([024d9cb](024d9cb))
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.2.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants