fix(invites): build share URL on the client, not the server

server/invites.ts derived the share URL from c.req.url — i.e., from
the API request's host. In production the API and SPA share an
origin so this happened to work; in dev where the SPA runs on :5173
and the API on :3000, the generated link pointed at the API
(http://localhost:3000/invite/<token>) which serves nothing.

Fix: the server no longer returns a `url` field. The token is the
canonical artefact; the SPA builds the share link itself via
`${window.location.origin}/invite/${token}`, which is always the
right origin regardless of split-process dev or single-process prod.

  - shared/types.ts: InviteEntry.url removed
  - server/invites.ts: drop originOf() and the URL field in toEntry()
  - frontend Profile.svelte: new inviteUrl() helper; the displayed
    <code> and the clipboard payload both use it
  - tests/social.test.ts: assertion checks token shape instead of
    the URL field

93 tests still pass.
This commit is contained in:
Ole-Morten Duesund 2026-05-25 16:25:55 +02:00
commit e64d5450f8
4 changed files with 27 additions and 16 deletions

View file

@ -42,12 +42,14 @@ export interface SettingsUpdateRequest {
// --- Invites ---------------------------------------------------------------
export interface InviteEntry {
/** The token itself. The shareable URL is built client-side as
* `${window.location.origin}/invite/${token}` server-side URL
* construction would point at the API host in split-process dev
* environments. */
token: string;
/** Absolute URL the inviter shares: <origin>/invite/<token>. */
url: string;
created_at: number;
claimed_at: number | null;
/** Display name (or email prefix) of the user who claimed it, if any. */
/** Display name (or username) of the user who claimed it, if any. */
claimed_by_display: string | null;
}