Change relativeTo parameter to accept RRIs#4931
Conversation
Preview deploymentsHost Test Results 1 files 1 suites 1h 51m 39s ⏱️ Results for commit 0946549. Realm Server Test Results 1 files ± 0 1 suites ±0 10m 22s ⏱️ + 9m 0s Results for commit 0946549. ± Comparison against earlier commit bbfb441. |
Widens the BaseDef [relativeTo] symbol field and the cluster of related serialization-plumbing parameters from `URL | undefined` to `RealmResourceIdentifier | URL | undefined`. Most call sites previously wrapped raw RRIs in `cardIdToURL(...)` to coerce to URL form; with the parameter types now accepting RRI directly, those wrappers are dropped and the prefix-form / URL-form identifier flows through deserialization unchanged. The `.href` consumer sites in rich-markdown.gts and asset.gts handle both forms — branching on `typeof x === 'string'` to coerce via cardIdToURL only when needed. # store.ts:1862 — normalize non-resolvable instance ids Found via a matrix bisect (see CS-10966 PR for the full diagnostic methodology): a server-returned doc whose `data.id` is a bare local id (e.g. welcome-to-boxel.json's hardcoded `"welcome-to-boxel-sample"`) previously survived only because `cardIdToURL(doc.data.id!)` would throw on it, getting caught upstream and turned into a `CardErrorJSONAPI`. With the cardIdToURL wrapper removed, the bare id would slip into `instance.id` and later collide with the canonical URL form during re-deserialization, surfacing as a "cannot change the id for saved instance" realm-server 500. The fix extends the existing "missing id" normalization at store.ts to also catch non-resolvable ids, replacing them with the canonical URL form derived from the fetch URL. CS-10966. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ab1f1a9 to
4cd3f13
Compare
There was a problem hiding this comment.
Pull request overview
This PR advances the migration away from URL-only resolution by widening relativeTo to accept RealmResourceIdentifier (RRI) strings across runtime-common, base, and host codepaths, reducing reliance on cardIdToURL while keeping resolution behavior correct where new URL() is still required.
Changes:
- Widen
relativeToparameter types across serializers, card API, commands, and host store flows to acceptRealmResourceIdentifier | URL. - Update key call sites to pass RRIs (or raw
idstrings) instead of eagerly converting toURLviacardIdToURL. - Add host-side normalization to prevent non-resolvable/bare
data.idvalues from being assigned to instances and later colliding with canonical URL IDs.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/runtime-common/serializers/index.ts | Updates serializer interface to accept RealmResourceIdentifier in deserialize context. |
| packages/runtime-common/serializers/code-ref.ts | Widens relativeTo typing for code-ref deserialization/adjustments toward RRIs. |
| packages/runtime-common/realm-index-query-engine.ts | Switches relativeTo derivation for query-field population to use RRIs. |
| packages/runtime-common/index.ts | Widens public API types (create/choose/internalKeyFor) to accept RRI relativeTo. |
| packages/runtime-common/commands.ts | Widens command naming helper’s relativeTo to accept RRIs. |
| packages/host/app/services/store.ts | Passes RRIs through patched relationship loading; normalizes inbound doc IDs to avoid ID collisions. |
| packages/host/app/routes/render.ts | Passes RRI relativeTo into store.add during hydration. |
| packages/host/app/components/operator-mode/create-file-modal.gts | Stops coercing spec IDs to URL objects; passes ID/RRI as relativeTo. |
| packages/experiments-realm/asset.gts | Safely converts string relativeTo/id to URL only when needed for new URL(). |
| packages/base/spec.gts | Passes spec card IDs directly as relativeTo when loading definitions. |
| packages/base/rich-markdown.gts | Handles relativeTo as either string (RRI) or URL when computing base URLs. |
| packages/base/card-serialization.ts | Treats model relativeTo as `RealmResourceIdentifier |
| packages/base/card-api.gts | Widens relativeTo/field deserialize plumbing and stores RRIs in [relativeTo] where appropriate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Addresses PR #4931 review: deserialize / deserializeAbsolute were widened to RealmResourceIdentifier | URL, but serialize()'s opts.relativeTo was still URL-only and gated on instanceof URL. A caller passing an RRI string would have silently fallen through to the doc.data.id fallback, producing different serialization output than the RRI-aware deserialize path. Type widened, and the if/else chain explicitly handles URL, string-form RRI (resolved via cardIdToURL), and the doc.data.id fallback in that order. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses PR #4931 review: the rest of store.ts uses the rri() helper for branding strings as RealmResourceIdentifier (3 other call sites). Match that convention instead of the inline 'as RealmResourceIdentifier' cast. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The intermediate goal here on the way to
@cardstack/baseis to removeresolveCardReference, prefix mappings,cardIdToURL. This is a step toward that, whererelativeTowould then no longer accept URLs.