Skip to content

fix(blocks): infer the sole allowed type when _type is omitted - #3825

Open
khoinguyenpham04 wants to merge 3 commits into
noah/mcp-blocks/omitted-fieldsfrom
noah/mcp-blocks/infer-single-type
Open

khoinguyenpham04 wants to merge 3 commits into
noah/mcp-blocks/omitted-fieldsfrom
noah/mcp-blocks/infer-single-type

Conversation

@khoinguyenpham04

@khoinguyenpham04 khoinguyenpham04 commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Fixes content writes to a blocks field with exactly one allowed type rejecting a missing _type. Ordinary writes infer the allowed type, including nested Markdown conversion over MCP and the TypeScript client. Both client schema-cache paths retain the metadata needed for conversion.

The change preserves the existing safeguards: explicit null/empty/wrong types remain errors, fields with multiple allowed types require an explicit type, restores require an explicit type, and a stored block of a different type cannot silently switch to the newly allowed type. Keys, versions, defaults, and replacement intent retain their existing behavior.

Nine new regression cases failed before this fix; 125 controls passed. Added coverage includes actual SQLite/PostgreSQL content and MCP writes, persisted identity, restore/retired-type refusal, nested Markdown, cold/preloaded client caches, and inferred D1 writes. The field reference and package changeset describe the accepted input.

This is the second layer of the two-PR stack, based on PR #3824 (noah/mcp-blocks/omitted-fields). Merge #3824 first. Reported directly; no linked issue number.

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main.
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to an approved Discussion: not applicable to this backwards-compatible bug fix.
  • I have included screenshots below if this PR changes the UI

Translation and screenshot items are not applicable: this changes no admin UI or user-visible UI strings. The changeset applies to the published emdash package.

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Codex with GPT-6.1 Sol (gpt-6.1-sol); independent adversarial review with GPT-5.6 Sol (gpt-5.6-sol, xhigh).

Screenshots / test output

Not applicable: no UI changes.

  • pnpm format, root pnpm build, pnpm lint:quick, pnpm lint, and pnpm typecheck pass.
  • pnpm --silent lint:json | jq '.diagnostics | length': 0.
  • SQLite/PostgreSQL/client/MCP focused suite after restacking on the read-side follow-up: 137 passing tests.
  • Initial Workerd D1 block content/seed suite, before the read-side follow-up: 4 passing tests.
  • Initial pnpm --dir docs build, before the read-side follow-up: passes.
  • Persistent GPT-5.6 Sol (xhigh) review of this layer and the combined stack: clean, with no findings rejected or nits left.
  • Initial complete core suite, before the read-side follow-up, with SQLite and PostgreSQL and only one Vitest invocation using the worker databases: 10,992 passed, 8 skipped across 769 files.
  • The initial overlapping PostgreSQL full-suite run was interrupted after timeouts: concurrent Vitest invocations reuse worker databases. All five timed-out cases pass when isolated (10 passing dialect cases), and the final full run passes. No DB harness or media code changed.

@changeset-bot

changeset-bot Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 37a8804

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/plugin-test Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
docs 37a8804 Oct 08 2026, 01:30 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://noah-mcp-blocks-infer-single-type.try.emdashcms.com, https://noah-mcp-blocks-infer-single-type-emdash-playground.emdash-cms.workers.dev (commit 37a8804)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://cb59f2c6.try.emdashcms.com, https://cb59f2c6-emdash-playground.emdash-cms.workers.dev 37a8804 2026-10-08T13:31:49.386Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://23516ed4.try.emdashcms.com, https://23516ed4-emdash-playground.emdash-cms.workers.dev 6d8d813 2026-10-04T20:25:06.753Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://3846c646.try.emdashcms.com, https://3846c646-emdash-playground.emdash-cms.workers.dev 66b9014 2026-10-04T10:13:26.098Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://f97ce38d.try.emdashcms.com, https://f97ce38d-emdash-playground.emdash-cms.workers.dev ac9976c 2026-10-03T19:27:49.158Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://5ad1af75.try.emdashcms.com, https://5ad1af75-emdash-playground.emdash-cms.workers.dev 74c0eef 2026-10-03T17:43:45.993Z Visit the dashboard ↗

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This PR fixes the right problem in the right places. Inferring the single allowed block type on ordinary writes is a small, backwards-compatible change that matches the documented intent of single-type blocks fields. The server normalization in block-values.ts and the client-side Markdown-to-Portable-Text conversion in client/portable-text.ts both handle the omitted _type case, and the safeguards described in the PR (multi-type fields, restores, retired/different stored types, explicit invalid types) are all preserved by the implementation.

I checked:

  • packages/core/src/schema/block-values.ts — normalizeBlockArray now infers the sole allowed type before validation, while still requiring an explicit _type for restores, multiple allowed types, and existing blocks whose stored type differs.
  • packages/core/src/client/portable-text.ts — convertNestedBlockPortableText infers the sole allowed type on writes so nested Markdown conversion works when _type is omitted.
  • packages/core/src/client/index.ts — the field-schema cache now retains validation/blockTypes, so both preloaded and on-demand schema fetches have the metadata needed for client-side conversion.
  • Tests — new regression coverage spans SQLite/PostgreSQL create/update, identity preservation, restore refusal, retired-type refusal, nested Markdown via MCP, and both cold/preloaded client caches.
  • Docs and changeset — the field-types.mdx addition accurately describes the new behavior, and the changeset explains the released behavior for package consumers.

No blocking issues found. The change is clean, well-tested, and consistent with EmDash conventions.

@github-actions github-actions Bot added review/approved Approved; no new commits since cla: signed and removed review/needs-review No maintainer or bot review yet labels Oct 3, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@3825

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@3825

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@3825

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@3825

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@3825

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@3825

emdash

npm i https://pkg.pr.new/emdash@3825

create-emdash

npm i https://pkg.pr.new/create-emdash@3825

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@3825

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@3825

@emdash-cms/plugin-test

npm i https://pkg.pr.new/@emdash-cms/plugin-test@3825

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@3825

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@3825

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@3825

@emdash-cms/registry-loader

npm i https://pkg.pr.new/@emdash-cms/registry-loader@3825

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@3825

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@3825

upgrade-emdash

npm i https://pkg.pr.new/upgrade-emdash@3825

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@3825

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@3825

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@3825

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@3825

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@3825

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@3825

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@3825

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@3825

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@3825

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@3825

commit: 37a8804

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@khoinguyenpham04
khoinguyenpham04 force-pushed the noah/mcp-blocks/infer-single-type branch from 74c0eef to ac9976c Compare October 3, 2026 19:24
@github-actions github-actions Bot added review/needs-rereview New commits since the last review and removed review/approved Approved; no new commits since labels Oct 3, 2026
@khoinguyenpham04
khoinguyenpham04 force-pushed the noah/mcp-blocks/infer-single-type branch from ac9976c to 66b9014 Compare October 4, 2026 10:08
@khoinguyenpham04
khoinguyenpham04 force-pushed the noah/mcp-blocks/infer-single-type branch from 66b9014 to 6d8d813 Compare October 4, 2026 20:23
Seed application is the only write path that uses restoreBlocks, so readers could not map "restoring block values" to anything. Also note that adding a second allowed type breaks writes that omit _type.
Inference runs before any SQL and is covered on SQLite and PostgreSQL by the integration suite; the D1 variant only re-indented the existing test.
@github-actions github-actions Bot added review/needs-review No maintainer or bot review yet and removed review/needs-rereview New commits since the last review labels Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant