Skip to content

[pull] main from tinacms:main#216

Merged
pull[bot] merged 2 commits into
code:mainfrom
tinacms:main
May 14, 2026
Merged

[pull] main from tinacms:main#216
pull[bot] merged 2 commits into
code:mainfrom
tinacms:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented May 14, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

18-th and others added 2 commits May 14, 2026 08:29
The generated client.ts and databaseClient.ts now import "./types.js"
unconditionally, and the CLI ships both types.ts and types.js side by
side for TypeScript projects.

Different consumers disagree on the right shape for that import string:
TypeScript wants ".ts" or extensionless, Node native ESM wants ".js",
bundlers don't care. Prior attempts (#6739, #6738) flipped between the
forms and each one broke a different consumer. This sidesteps the
string-choice problem by shipping both files on disk:

* TypeScript (bundler / node16 / nodenext, and TS 4.7+ classic node)
reads types.ts via the .js → .ts resolution rewrite.
* Node ESM reads types.js literally at runtime.
* Bundlers don't care which one they pick.

Added a fixture-driven regression test that spawns real `tsc --noEmit`
and `node --input-type=module` against the generator output. This is the
test that would have caught #6739 before merge. The prior unit tests
only string-matched the generated source.
…#6853)

## Summary

- `resolveMediaRelativeToCloud` previously treated every `image`-typed
value as a media-library path — wrapping it with the cloud assets prefix
on read. That corrupts any value that's already an absolute URL
(external link, `data:` URL, etc.), because the prefix gets concatenated
directly in front of the original URL with no separator.
- Adds a guard for absolute URLs (any RFC 3986 scheme, plus
protocol-relative `//`) so they round-trip identically in both
directions.
- Adds a self-heal: if stripping the configured media root from a stored
value reveals an absolute URL underneath (the shape of a
previously-corrupted round-trip), return the URL directly instead of
re-wrapping. Documents already on disk in the broken shape transparently
recover on next save.
- The save-side resolver already gated rewriting on a cloud-URL pattern
match, so no change there beyond inheriting cleaner inputs.

## Verification

Drove the full `parseMDX` → resolver → `serializeMDX` pipeline against a
rich-text body containing both a media-library src and an external URL,
on a feature branch with a staging prefix active:

| Phase | Local `src` | External `src` |
|---|---|---|
| Stored MDX | `/uploads/library/local.png` |
`https://cdn.example.com/external/image.png` |
| After read (editor sees) |
`https://<assetsHost>/<clientId>/__staging/<branch>/__file/library/local.png`
| `https://cdn.example.com/external/image.png` |
| After write (re-serialized MDX) | `/uploads/library/local.png` |
`https://cdn.example.com/external/image.png` |

Self-heal verified end-to-end: a corrupted stored src of the form
`/uploads<absolute-url>` is read as the clean absolute URL and
serialized back to disk in that form.

Confirmed the same demo fails against the unpatched resolver — the
external URL gets clobbered with a leading
`https://<assetsHost>/<clientId>/__staging/<branch>/__file` and then
mangled further on save.

## Test plan

- [x] `pnpm --filter @tinacms/graphql test` — 516/516 passing across 50
files
- [x] New `media-utils.test.ts` cases:
- [x] `it.each` over `https://`, `http://`, `//`, `data:`, `blob:`,
`file:` — identity in both directions on a feature branch with active
staging prefix
- [x] Mixed array — relative entries get the staging prefix, absolute
entries pass through untouched
- [x] `it.each` self-heal cases — `/uploads<url>` shapes for `https://`,
`http://`, `//`, `data:` recover to the underlying URL on read
- [x] Array self-heal — mixed clean + corrupted entries are all
normalized
- [x] New `media-rich-text.test.ts` end-to-end cases:
- [x] Rich-text body with a mix of local + external `imageEmbed` srcs —
full parse/serialize round-trip identity
  - [x] Protocol-relative and `http://` srcs — same identity guarantee
- [x] Corrupted src — read self-heals, save writes clean form back to
disk
- [ ] Smoke test in a branch-enabled site: open a document containing an
`image`-typed field whose stored value is an external URL, save without
touching it, confirm the stored value is unchanged

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators May 14, 2026
@pull pull Bot added the ⤵️ pull label May 14, 2026
@pull pull Bot merged commit 890108d into code:main May 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants