ci: release#560
Merged
Merged
Conversation
Contributor
Scope checkThis PR touches 21 files. PRs with a broad scope are harder to review. Please confirm the scope hasn't drifted beyond the intended change. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-playground | aa9fd68 | Apr 20 2026, 03:23 PM |
7669318 to
803f62d
Compare
Contributor
Overlapping PRsThis PR modifies files that are also changed by other open PRs:
This may cause merge conflicts or duplicated work. A maintainer will coordinate. |
18 tasks
bf64c5f to
9c0aacb
Compare
c60aeea to
0ab83af
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@emdash-cms/admin@0.6.0
Minor Changes
913cb62Thanks @ophirbucai! - Adds full RTL (right-to-left) support to the admin UI by converting all directional Tailwind classes to their direction-aware equivalents.Patch Changes
#610
dfcb0cdThanks @drudge! - Passes plugin block definitions into thePortableTextEditornested insideWidgetEditor, so custom plugin-registered block types (image blocks, marker blocks, etc.) can be inserted and rendered inside content-type widgets. The manifest is fetched with react-query in the top-levelWidgetscomponent, flattened into aPluginBlockDef[]list, and threaded throughWidgetAreaPanel→WidgetItem→WidgetEditor.#568
cf63b02Thanks @Vallhalen! - Fix document outline not showing headings on initial load. The outline now defers initial extraction to next tick (so TipTap finishes hydrating) and also listens for transaction events to catch programmatic content changes.#564
0b32b2fThanks @ascorbic! - Replaces the horizontal language-switch button bar on the admin login page with a dropdown, so the selector stays usable as more locales are added.#592
6c92d58Thanks @asdfgl98! - Adds Korean locale support to the admin UI.#559
a2d5afbThanks @ayfl269! - Adds Chinese (Traditional) translation for the admin UI, including login page, settings page, and locale switching.#604
39d285eThanks @all3f0r1! - Fixes loading spinner not centered under logo on the login page.Updated dependencies []:
emdash@0.6.0
Minor Changes
#626
1859347Thanks @ascorbic! - Adds eager hydration of taxonomy terms ongetEmDashCollectionandgetEmDashEntryresults. Each entry now exposes adata.termsfield keyed by taxonomy name (e.g.post.data.terms.tag,post.data.terms.category), populated via a single batched JOIN query alongside byline hydration. Templates that previously looped and calledgetEntryTerms(collection, id, taxonomy)per entry can readentry.data.termsdirectly and skip the N+1 round-trip.New exports:
getAllTermsForEntries,invalidateTermCache.Reserved field slugs now also block
terms,bylines, andbylineat schema-creation time to prevent new fields shadowing the hydrated values. Existing installs that already have a user-defined field with any of those slugs will see the hydrated value overwrite the stored value on read (consistent with the pre-existing behavior ofbylines/bylinehydration); rename the field to keep its data accessible.#600
9295cc1Thanks @ascorbic! - Adds Noto Sans as the default admin UI font via the Astro Font API. Fonts are downloaded from Google at build time and self-hosted. The base font covers Latin, Cyrillic, Greek, Devanagari, and Vietnamese. Additional scripts (Arabic, CJK, Hebrew, Thai, etc.) can be added via the newfonts.scriptsconfig option. Setfonts: falseto disable and use system fonts.Patch Changes
#648
ada4ac7Thanks @CacheMeOwside! - Adds the missingurlfield type for seed files, content type builder, and content editor with client-side URL validation.#658
f279320Thanks @ascorbic! - Addsafter(fn)— a helper for deferring bookkeeping work past the HTTP response. On Cloudflare it hands off towaitUntil(extending the worker's lifetime); on Node it fire-and-forgets (the event loop keeps the process alive for the next request anyway). Host binding is plumbed through a newvirtual:emdash/wait-untilvirtual module so core stays runtime-neutral — Cloudflare-specific imports live in the integration layer, not in request-handling code.First use: cron stale-lock recovery (
_emdash_cron_tasksUPDATE) now runs after the response ships instead of blocking it. On D1 this shaves a primary-routed write off the cold-start critical path.Usage:
#642
7f75193Thanks @Pouf5! - AddsmaxUploadSizeconfig option to set the maximum media file upload size in bytes. Defaults to 52_428_800 (50 MB) — existing behaviour is unchanged.#595
cfd01f3Thanks @ascorbic! - Fixes playground initialization crash caused by syncSearchState attempting first-time FTS enablement during field creation.#663
38d637bThanks @ascorbic! - CachegetSiteSetting(key)per-request. It was firing an uncachedoptionstable read on every call, so templates that pull several settings (orEmDashHeadreadingseoon every page render) paid N round-trips to the D1 primary instead of sharing one. Noticeable on colos far from the primary — APS/APE were seeing ~30–100 ms of avoidable warm-render latency per page.Wraps each key in
requestCached("siteSetting:${key}", ...)so concurrent callers in a single render share the in-flight query.#631
31d2f4eThanks @ascorbic! - Improves cold-start performance for anonymous page requests. Sites with D1 replicas far from the worker colo should see the biggest improvement; on the blog-demo the homepage cold request on Asia colos dropped from several seconds to under a second.Three underlying changes:
rt.db,rt.plugins, etc.) so further regressions are easier to diagnose.#605
445b3bfThanks @ascorbic! - Fixes D1 read replicas being bypassed for anonymous public page traffic. The middleware fast path now asks the database adapter for a per-request scoped Kysely, so anonymous reads land on the nearest replica instead of the primary-pinned singleton binding.All D1-specific semantics (Sessions API, constraint selection, bookmark cookie) live in
@emdash-cms/cloudflare/db/d1behind a singlecreateRequestScopedDb(opts)function. Core middleware has no D1-specific logic. Adapters opt in via a newsupportsRequestScope: booleanflag onDatabaseDescriptor;d1()sets it to true.Other fixes in the same change:
runWithContextcalls in the request-context middleware now merge the parent context instead of replacing it, so an outer per-request db override is preserved through edit/preview flows.cookies.set()calls in middleware survive.first-primary, so an anonymous form/comment POST isn't racing across replicas.!configbail-out now still applies baseline security headers.__ec_d1_bookmarkreferences aligned to__em_d1_bookmarkacross runtime, docs, and JSDoc.#654
943d540Thanks @ascorbic! - Dedups repeat DB queries within a single page render. Measured against the query-count fixture:globalThiswith a Symbol key (same pattern asrequest-context.ts), so a single value is shared across all chunks now.getCollectionInfo,getTaxonomyDef,getTaxonomyTerms, andgetEmDashCollectionin the request-scoped cache so two callers with the same arguments in the same render share a single query.Biggest wins land on pages that render multiple content-heavy components (a post detail page with comments, byline credits, and sidebar widgets). On the fixture post page: -3 queries cold / -1 warm under SQLite, -2 queries cold under D1.
#668
2cb3165Thanks @CacheMeOwside! - Fixes boolean field checkbox displaying as unchecked after publish in the admin UI.#500
14c923bThanks @all3f0r1! - Adds inline term creation in the post editor taxonomy sidebar. Tags show a "Create" option when no match exists; categories get an "Add new" button below the list.#606
c5ef0f5Thanks @ascorbic! - Caches the manifest in memory and in the database to eliminate N+1 schema queries per request. Batches site info queries during initialization. Cold starts read 1 cached row instead of rebuilding from scratch.#671
f839381Thanks @jcheese1! - Fixes MCP OAuth discovery and dynamic client registration so EmDash only advertises supported client registration mechanisms and rejects unsupported redirect URIs or token endpoint auth methods during client registration. Also exempts OAuth protocol endpoints (token, register, device code, device token) from the Origin-based CSRF check, since these endpoints are called cross-origin by design (MCP clients, CLIs, native apps) and carry no ambient credentials, and sends the required CORS headers so browser-based MCP clients can reach them.#664
002d0acThanks @ascorbic! -getSiteSetting(key)now transparently piggybacks ongetSiteSettings()when the batch has already been loaded in the current request. If a parent template has calledgetSiteSettings()(which is request-cached), a latergetSiteSetting("seo")— fromEmDashHead, a plugin, or user code — reads the key from that cached result instead of firing its own round-trip. Falls back to a per-key cached query when nothing has been primed.Exposes
peekRequestCache(key)for internal use by other helpers that want the same "read from a broader cached query if available" pattern.On the blog-demo fixture: the SEO call added in PR fix(seo): emit google/bing verification meta tags from site settings #613 now costs zero extra queries per page (it reads from the Base layout's existing
getSiteSettings()result).#465
0a61ef4Thanks @Pouf5! - Fixes FTS5 tables not being created when a searchable collection is created or updated via the Admin UI.#636
6d41fe1Thanks @ascorbic! - Fixes two correctness issues from the perf: cut anonymous cold-start runtime init roughly in half #631 cold-start work:ensureSearchHealthy()now runs against the runtime's singleton database instead of the per-request session-bound one. The verify step reads, but a corrupted index triggers a rebuild write, and D1 Sessions on a GET request usesfirst-unconstrainedrouting that's free to land on a replica. The singleton goes through the default binding, which the adapter correctly promotes tofirst-primaryfor writes.dbIsIsolated: true. Without it, schema-derived caches (manifest, taxonomy defs, byline/term existence probes) could carry values across playground sessions that have independent schemas.#627
b158e40Thanks @ascorbic! - Prime the request-scoped cache forgetEntryTermsduring collection and entry hydration.getEmDashCollectionandgetEmDashEntryalready fetch taxonomy terms for their results via a single batched JOIN; now the same data is seeded into the per-request cache under the same keysgetEntryTermsuses, so existing templates that still callgetEntryTerms(collection, id, taxonomy)in a loop get cache hits instead of a serial DB round-trip per iteration.Empty-result entries are seeded with
[]for every taxonomy that applies to the collection so "this post has no tags" also short-circuits without a query. Cache entries are scoped to the request context via ALS and GC'd with it.#653
f97d6abThanks @ascorbic! - Adds opt-in query instrumentation for performance regression testing. SettingEMDASH_QUERY_LOG=1causes the Kysely log hook to emit[emdash-query-log]-prefixed NDJSON on stdout for every DB query executed inside a request, tagged with the route, method, and anX-Perf-Phaseheader value. Zero runtime overhead when the flag is unset — the log option is only attached to Kysely when enabled.Also exposes the helpers at
emdash/database/instrumentationso first-party adapters (e.g.@emdash-cms/cloudflare) can wire the same hook into their per-request Kysely instances.#613
e67b940Thanks @nickgraynews! - Fixes site SEO settingsgoogleVerificationandbingVerificationnot being emitted into<head>. The fields were stored in the database and editable in the admin UI but were never rendered as<meta name="google-site-verification">or<meta name="msvalidate.01">tags, making meta-tag verification with Google Search Console and Bing Webmaster Tools impossible. EmDashHead now loads site SEO settings and renders these tags on every page.#659
0896ec8Thanks @ascorbic! - Two query-count reductions on the request hot path:getWidgetArea(name)used to do two round-trips — one for the area, one for its widgets. Single left-join now. Saves one query per<WidgetArea>rendered on a page.isMissingTableErrorcatch. Saves two queries per render on pages that hydrate bylines and taxonomy terms.On the fixture post-detail page: SQLite
/posts/[slug]drops from 34 → 32, D1 from 43 → 39. The widget-area JOIN shaves one off every page that renders a widget area.invalidateBylineCache()andinvalidateTermCache()are preserved as no-op exports so callers don't break.#558
629fe1dThanks @csfalcao! - Fixes/_emdash/api/search/suggest500 error.getSuggestionsno longer double-appends the FTS5 prefix operator*on top of the oneescapeQueryalready adds, so autocomplete queries like?q=desnow return results instead of raisingSqliteError: fts5: syntax error near "*".#552
f52154dThanks @masonjames! - Fixes passkey login failures so unregistered or invalid credentials return an authentication failure instead of an internal server error.#601
8221c2aThanks @CacheMeOwside! - Fixes the Save Changes button on the Content Type editor failing silently with a 400 error#598
8fb93ebThanks @maikunari! - Fixes WordPress import error reporting to surface the real exception message instead of a generic "Failed to import item" string, making import failures diagnosable.#629
6d7f288Thanks @CacheMeOwside! - Adds toast feedback when taxonomy assignments are saved or fail on content items.#638
4ffa141Thanks @auggernaut! - Fixes repeated FTS startup rebuilds on SQLite by verifying indexed row counts against the FTS shadow table.#582
04e6ccaThanks @all3f0r1! - Improves the "Failed to create database" error to detect NODE_MODULE_VERSION mismatches from better-sqlite3 and surface an actionable message telling the user to rebuild the native module.Updated dependencies [
dfcb0cd,cf63b02,0b32b2f,913cb62,6c92d58,a2d5afb,39d285e,f52154d]:@emdash-cms/auth@0.6.0
Patch Changes
f52154dThanks @masonjames! - Fixes passkey login failures so unregistered or invalid credentials return an authentication failure instead of an internal server error.@emdash-cms/cloudflare@0.6.0
Patch Changes
#605
445b3bfThanks @ascorbic! - Fixes D1 read replicas being bypassed for anonymous public page traffic. The middleware fast path now asks the database adapter for a per-request scoped Kysely, so anonymous reads land on the nearest replica instead of the primary-pinned singleton binding.All D1-specific semantics (Sessions API, constraint selection, bookmark cookie) live in
@emdash-cms/cloudflare/db/d1behind a singlecreateRequestScopedDb(opts)function. Core middleware has no D1-specific logic. Adapters opt in via a newsupportsRequestScope: booleanflag onDatabaseDescriptor;d1()sets it to true.Other fixes in the same change:
runWithContextcalls in the request-context middleware now merge the parent context instead of replacing it, so an outer per-request db override is preserved through edit/preview flows.cookies.set()calls in middleware survive.first-primary, so an anonymous form/comment POST isn't racing across replicas.!configbail-out now still applies baseline security headers.__ec_d1_bookmarkreferences aligned to__em_d1_bookmarkacross runtime, docs, and JSDoc.#569
134f776Thanks @Yusaku01! - Fixes the playground toolbar layout on small screens.#653
f97d6abThanks @ascorbic! - Adds opt-in query instrumentation for performance regression testing. SettingEMDASH_QUERY_LOG=1causes the Kysely log hook to emit[emdash-query-log]-prefixed NDJSON on stdout for every DB query executed inside a request, tagged with the route, method, and anX-Perf-Phaseheader value. Zero runtime overhead when the flag is unset — the log option is only attached to Kysely when enabled.Also exposes the helpers at
emdash/database/instrumentationso first-party adapters (e.g.@emdash-cms/cloudflare) can wire the same hook into their per-request Kysely instances.Updated dependencies [
ada4ac7,f279320,7f75193,cfd01f3,38d637b,31d2f4e,445b3bf,943d540,2cb3165,1859347,14c923b,c5ef0f5,f839381,002d0ac,0a61ef4,6d41fe1,b158e40,f97d6ab,e67b940,0896ec8,629fe1d,f52154d,8221c2a,8fb93eb,6d7f288,4ffa141,04e6cca,9295cc1]:@emdash-cms/plugin-embeds@0.1.6
Patch Changes
ada4ac7,f279320,7f75193,cfd01f3,38d637b,31d2f4e,445b3bf,943d540,2cb3165,1859347,14c923b,c5ef0f5,f839381,002d0ac,0a61ef4,6d41fe1,b158e40,f97d6ab,e67b940,0896ec8,629fe1d,f52154d,8221c2a,8fb93eb,6d7f288,4ffa141,04e6cca,9295cc1]:@emdash-cms/blocks@0.6.0
create-emdash@0.6.0
@emdash-cms/gutenberg-to-portable-text@0.6.0
@emdash-cms/x402@0.6.0
@emdash-cms/fixture-perf-site@0.0.1
Patch Changes
ada4ac7,f279320,7f75193,cfd01f3,38d637b,31d2f4e,445b3bf,943d540,2cb3165,1859347,14c923b,c5ef0f5,f839381,002d0ac,134f776,0a61ef4,6d41fe1,b158e40,f97d6ab,e67b940,0896ec8,629fe1d,f52154d,8221c2a,8fb93eb,6d7f288,4ffa141,04e6cca,9295cc1]:@emdash-cms/perf-demo-site@0.0.1
Patch Changes
ada4ac7,f279320,7f75193,cfd01f3,38d637b,31d2f4e,445b3bf,943d540,2cb3165,1859347,14c923b,c5ef0f5,f839381,002d0ac,134f776,0a61ef4,6d41fe1,b158e40,f97d6ab,e67b940,0896ec8,629fe1d,f52154d,8221c2a,8fb93eb,6d7f288,4ffa141,04e6cca,9295cc1]:@emdash-cms/cache-demo-site@0.0.1
Patch Changes
ada4ac7,f279320,7f75193,cfd01f3,38d637b,31d2f4e,445b3bf,943d540,2cb3165,1859347,14c923b,c5ef0f5,f839381,002d0ac,134f776,0a61ef4,6d41fe1,b158e40,f97d6ab,e67b940,0896ec8,629fe1d,f52154d,8221c2a,8fb93eb,6d7f288,4ffa141,04e6cca,9295cc1]: