From 905bdcd70b9f02841639351f8110b22393164115 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 22:17:54 +0000 Subject: [PATCH] ci: release --- .changeset/block-menu-fix.md | 5 -- .changeset/byline-avatar-storage-key.md | 5 -- .changeset/cool-lines-dress.md | 5 -- .changeset/empty-falcons-read.md | 7 --- .changeset/extensible-bylines.md | 18 ------- .changeset/fix-byline-picker-search.md | 5 -- .changeset/fix-byline-search-debounce.md | 5 -- .changeset/fix-content-list-search.md | 6 --- .changeset/fix-content-update-locale.md | 5 -- .changeset/fix-locale-aware-tags.md | 6 --- .changeset/fix-media-search.md | 6 --- .../fix-registry-client-workerd-semver.md | 8 --- .changeset/fix-seo-loader-hydration.md | 5 -- .changeset/fix-sticky-editor-toolbar.md | 5 -- .changeset/html-block-editor.md | 6 --- .changeset/id-admin-i18n-fixes.md | 5 -- .changeset/menu-add-content-type.md | 5 -- .changeset/seed-byline-avatar.md | 5 -- .changeset/thai-admin-locale-followup.md | 5 -- .changeset/thai-admin-locale.md | 5 -- fixtures/perf-site/CHANGELOG.md | 8 +++ fixtures/perf-site/package.json | 2 +- infra/blog-demo/CHANGELOG.md | 10 ++++ infra/blog-demo/package.json | 2 +- infra/cache-demo/CHANGELOG.md | 10 ++++ infra/cache-demo/package.json | 2 +- packages/admin/CHANGELOG.md | 48 +++++++++++++++++ packages/admin/package.json | 2 +- packages/auth-atproto/CHANGELOG.md | 7 +++ packages/auth-atproto/package.json | 2 +- packages/auth/CHANGELOG.md | 2 + packages/auth/package.json | 2 +- packages/blocks/CHANGELOG.md | 2 + packages/blocks/package.json | 2 +- packages/cloudflare/CHANGELOG.md | 7 +++ packages/cloudflare/package.json | 2 +- packages/core/CHANGELOG.md | 52 +++++++++++++++++++ packages/core/package.json | 2 +- packages/create-emdash/CHANGELOG.md | 2 + packages/create-emdash/package.json | 2 +- .../gutenberg-to-portable-text/CHANGELOG.md | 2 + .../gutenberg-to-portable-text/package.json | 2 +- packages/plugin-cli/CHANGELOG.md | 7 +++ packages/plugin-cli/package.json | 2 +- packages/plugins/embeds/CHANGELOG.md | 7 +++ packages/plugins/embeds/package.json | 2 +- packages/registry-client/CHANGELOG.md | 8 +++ packages/registry-client/package.json | 2 +- packages/workerd/CHANGELOG.md | 7 +++ packages/workerd/package.json | 2 +- packages/x402/CHANGELOG.md | 2 + packages/x402/package.json | 2 +- 52 files changed, 197 insertions(+), 138 deletions(-) delete mode 100644 .changeset/block-menu-fix.md delete mode 100644 .changeset/byline-avatar-storage-key.md delete mode 100644 .changeset/cool-lines-dress.md delete mode 100644 .changeset/empty-falcons-read.md delete mode 100644 .changeset/extensible-bylines.md delete mode 100644 .changeset/fix-byline-picker-search.md delete mode 100644 .changeset/fix-byline-search-debounce.md delete mode 100644 .changeset/fix-content-list-search.md delete mode 100644 .changeset/fix-content-update-locale.md delete mode 100644 .changeset/fix-locale-aware-tags.md delete mode 100644 .changeset/fix-media-search.md delete mode 100644 .changeset/fix-registry-client-workerd-semver.md delete mode 100644 .changeset/fix-seo-loader-hydration.md delete mode 100644 .changeset/fix-sticky-editor-toolbar.md delete mode 100644 .changeset/html-block-editor.md delete mode 100644 .changeset/id-admin-i18n-fixes.md delete mode 100644 .changeset/menu-add-content-type.md delete mode 100644 .changeset/seed-byline-avatar.md delete mode 100644 .changeset/thai-admin-locale-followup.md delete mode 100644 .changeset/thai-admin-locale.md diff --git a/.changeset/block-menu-fix.md b/.changeset/block-menu-fix.md deleted file mode 100644 index 5bf7895aae..0000000000 --- a/.changeset/block-menu-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Fix content entity editor block menu actions (Duplicate / Delete) not working when the drag handle sets a NodeSelection (#1261). diff --git a/.changeset/byline-avatar-storage-key.md b/.changeset/byline-avatar-storage-key.md deleted file mode 100644 index 7b9eec3e40..0000000000 --- a/.changeset/byline-avatar-storage-key.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"emdash": patch ---- - -Byline hydration now resolves the author avatar's storage key in the same query. `getEmDashCollection` / `getEmDashEntry` populate `entry.data.bylines[].byline.avatarStorageKey` (and `avatarAlt`) via a `LEFT JOIN` on the media table, so list pages can build a direct avatar URL without a per-byline `MediaRepository.findById`. Previously the byline summary exposed only `avatarMediaId` (a bare ULID with no file extension), forcing sites that want direct storage URLs into an N+1 media lookup. A page rendering 20 posts by distinct authors paid ~20 extra queries. The new fields are additive and null on the plain byline finders (`findById`, `findBySlug`), which do not join media; rely on the content-credit hydration path for them. diff --git a/.changeset/cool-lines-dress.md b/.changeset/cool-lines-dress.md deleted file mode 100644 index bd52c43010..0000000000 --- a/.changeset/cool-lines-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"emdash": patch ---- - -Persist welcome-dismissed flag in database instead of session. Previously the welcome modal would be shown every time a user logged-in. diff --git a/.changeset/empty-falcons-read.md b/.changeset/empty-falcons-read.md deleted file mode 100644 index 69df261699..0000000000 --- a/.changeset/empty-falcons-read.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"emdash": patch ---- - -fix(core/redirects): match exact redirects regardless of trailing slash (#1271) - -Exact redirect rules now match requests with or without a trailing slash. A redirect stored with source `/old/` will also match a request for `/old`, and a redirect stored with source `/old` will also match `/old/`. The stored source is preserved unchanged; the fallback happens at lookup time. diff --git a/.changeset/extensible-bylines.md b/.changeset/extensible-bylines.md deleted file mode 100644 index 9ee2c87f56..0000000000 --- a/.changeset/extensible-bylines.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"emdash": minor -"@emdash-cms/admin": minor ---- - -Adds custom fields to bylines. Sites can define site-specific byline metadata (Twitter handle, pronouns, company, localised job title, etc.) via the new `/byline-schema` admin screen, accessed from the **Byline schema** link button at the top of the Bylines admin page (admin-only). - -Per-field `translatable` flag picks whether values are stored per-locale (one value per locale row in a `translation_group`) or shared across every locale variant of the same byline identity. Schema management is gated by `schema:manage`; value editing by `bylines:manage`. - -Custom-field values can be set at both create and update time. `POST` and `PUT` on `/_emdash/api/admin/bylines` accept the same `customFields` map; the row write and the custom-field writes share a single transaction on Node/PG so a partial failure rolls both back. On D1 (no transactions), a retry POST is treated as completing an abandoned create iff three checks all pass: (a) every fixed column on the existing row matches the new payload (`displayName`, `bio`, `avatarMediaId`, `websiteUrl`, `userId`, `isGuest`, effective locale — null-vs-undefined normalised); (b) the existing row's `translationGroup` matches what a fresh create with the same input would produce (`sourceGroup` when `translationOf` is present, `existing.id` when it isn't); (c) every custom-field value already stored on the row appears in the input payload with an equal value (subset-match, so partial mid-loop crashes can be completed). The recovery branch is conservative on every axis: any fixed-column mismatch, any translation-group mismatch, any overlapping custom-field value mismatch, an input that omits a key the existing row stores, or an input with no custom fields at all → standard `CONFLICT`. Validation runs before any DB write so a bad value (unknown slug, type mismatch, select-choice miss, non-URL or non-http(s) URL for a `url` field) returns 400 `VALIDATION_ERROR` without leaving partial state behind. In the admin, registered fields render inline with Name, Bio, etc. — no separate section header — and are available in the **New byline** dialog as well as edit. - -`BylineSummary` gains an optional `customFields: Record` property. Existing object-literal consumers stay source-compatible because the property is optional and runtime always returns `{}` when no fields are registered. - -Hydration is symmetric with writes: rows are only applied to a byline when they live in the table matching the field's current `translatable` flag, so stale rows from a `translatable` flip can't leak into hydrated output. Schema mutations on `/byline-schema` invalidate the same `byline-fields` query the byline form reads, so newly-registered fields appear in the editor without a page reload. `url` field values are parsed with `new URL(...)` AND restricted to `http:` / `https:` schemes at write time so they can't ship `javascript:` / `data:` / `mailto:` payloads to link rendering. The `BylineFieldEditor` "Save" button stays disabled until a `select` field has at least one option; and select-option lists are accumulated on a null-prototype object so option values that collide with `Object.prototype` keys render correctly. - -The field-definitions cache uses parity on `options.byline_fields_version` as a dirty bit: schema mutations flip the counter to odd before the write lands and to a **new even** value after, with the cache treating any odd version as "bypass the global holder, read fresh from the DB". `markVersionDirty` is parity-aware (ensures odd, no-op if already odd) so a crashed prior attempt's leftover dirty state can't get inverted. `markVersionClean` is **always-advance** (`+2` when starting even, `+1` when starting odd) so two concurrent mutators can't collapse on the same even key and pin the cache on a partial-set snapshot — every committed mutation produces an observable counter change for cache readers. Idempotent-retry exits (`FIELD_EXISTS` on create, `FIELD_NOT_FOUND` on update/delete, no-op input on update) call `markVersionClean` too, which doubles as both the dirty-crash recovery and the false-clean recovery. All version writes use `INSERT … ON CONFLICT DO UPDATE` so a missing options row can't silently turn invalidation into a no-op. - -Implements [#1174](https://github.com/emdash-cms/emdash/discussions/1174). Builds on the bylines-i18n foundation from [#1146](https://github.com/emdash-cms/emdash/pull/1146). diff --git a/.changeset/fix-byline-picker-search.md b/.changeset/fix-byline-picker-search.md deleted file mode 100644 index 527d1a7f3c..0000000000 --- a/.changeset/fix-byline-picker-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Add search to the byline picker on content entities and remove the effective 100-byline cap. The picker now performs a debounced server-side search via the bylines API instead of rendering a fixed dropdown of the first 100 results, so bylines beyond the first page can be found and credited. Credited bylines from the saved entry are also resolved from the entry itself, so a credit that falls outside the initial list still renders its name instead of disappearing. diff --git a/.changeset/fix-byline-search-debounce.md b/.changeset/fix-byline-search-debounce.md deleted file mode 100644 index f7eacc1c9a..0000000000 --- a/.changeset/fix-byline-search-debounce.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Fixes the byline search box reloading the whole page on every keystroke. The search term is now debounced (300ms) before it feeds the bylines query, and the full-page loader only takes over when there is no data yet (`isLoading && !data`) instead of on every new query key. Typing now stays responsive and keeps the input focused, matching the behaviour of the users page. The load-more snapshot and its filter-match check both use the debounced search value so appended pages are no longer discarded. diff --git a/.changeset/fix-content-list-search.md b/.changeset/fix-content-list-search.md deleted file mode 100644 index e93764d53c..0000000000 --- a/.changeset/fix-content-list-search.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"emdash": patch -"@emdash-cms/admin": patch ---- - -Make content list search work on large collections (#1219). The admin content list previously filtered only the rows already loaded on the current page, so an entry far back in a big collection could not be found until you navigated near it. The list endpoint now accepts a `q` parameter and performs a case-insensitive substring search across the collection's title/name/slug columns server-side (LIKE wildcards in the query are escaped), and the admin search box drives that query (debounced) instead of filtering in memory. Also adds locale-aware composite indexes (`idx_{table}_loc_upd` / `idx_{table}_loc_crt`) so locale-filtered content lists stay index-served on large, i18n-enabled tables. diff --git a/.changeset/fix-content-update-locale.md b/.changeset/fix-content-update-locale.md deleted file mode 100644 index aee2c7e5aa..0000000000 --- a/.changeset/fix-content-update-locale.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"emdash": patch ---- - -Fixes locale-aware content updates so REST, CLI, client, and MCP callers can safely update content by slug when multiple locales share the same slug. diff --git a/.changeset/fix-locale-aware-tags.md b/.changeset/fix-locale-aware-tags.md deleted file mode 100644 index a61e157a83..0000000000 --- a/.changeset/fix-locale-aware-tags.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"emdash": patch -"@emdash-cms/admin": patch ---- - -Fix taxonomy terms not being locale-aware in the content editor (#1218). Term assignments are stored against the per-locale content row while the term's `translation_group` spans every locale, so resolving terms for an entry must scope to the entry's locale. The content terms endpoint (`/content/:collection/:id/terms/:taxonomy`) now derives the entry's locale server-side and passes it to `getTermsForEntry`, and the admin `TaxonomySidebar` threads the entry locale through its fetch/save calls (and into its React Query keys, so switching translations refetches). Previously a localized post showed and applied every locale variant of a tag instead of just the variant for its own locale. diff --git a/.changeset/fix-media-search.md b/.changeset/fix-media-search.md deleted file mode 100644 index b363e7232a..0000000000 --- a/.changeset/fix-media-search.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"emdash": patch -"@emdash-cms/admin": patch ---- - -Add search and filtering to the media library (#1221). The media list endpoint now accepts a `q` parameter for a case-insensitive filename substring search (which also matches extensions, with LIKE wildcards escaped), alongside the existing `mimeType` filter. The Media Library page gains a filename search box and a type filter (images / video / audio / documents), and the media picker in the content editor now searches the local library by filename too. Previously neither surface could search or filter local media, which made large libraries hard to navigate. diff --git a/.changeset/fix-registry-client-workerd-semver.md b/.changeset/fix-registry-client-workerd-semver.md deleted file mode 100644 index b0dc98fdba..0000000000 --- a/.changeset/fix-registry-client-workerd-semver.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@emdash-cms/registry-client": patch -"emdash": patch ---- - -Fix `require is not defined` crash on every EmDash API route under `astro dev` on Cloudflare Workers (#1292). - -`@emdash-cms/registry-client` listed `semver` (CommonJS) in `dependencies`, which the build externalizes -- so consumers loaded a nested CJS copy. Vite's SSR module runner (workerd) evaluates modules with no `require` binding, so semver's internal `require()` threw and took down any route whose import graph reached registry-client (schema, plugins, env compatibility checks). semver is now bundled into the ESM output, so nothing CommonJS reaches the worker. diff --git a/.changeset/fix-seo-loader-hydration.md b/.changeset/fix-seo-loader-hydration.md deleted file mode 100644 index a281538fc1..0000000000 --- a/.changeset/fix-seo-loader-hydration.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"emdash": patch ---- - -Fix SEO fields (noindex toggle, canonical URL) not affecting rendered pages. The content loader now surfaces per-entry SEO metadata on `entry.data.seo`, so `getSeoMeta()` reflects values set in the admin SEO panel. SEO is folded into the existing entry query via a LEFT JOIN, adding no extra database round-trips. diff --git a/.changeset/fix-sticky-editor-toolbar.md b/.changeset/fix-sticky-editor-toolbar.md deleted file mode 100644 index 13688aecd8..0000000000 --- a/.changeset/fix-sticky-editor-toolbar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -The rich-text editor formatting toolbar now stays pinned to the top of the editing area while scrolling through long posts, instead of scrolling out of view. The toolbar uses `position: sticky` and the editor wrapper switched from `overflow-hidden` to `overflow-clip` so corners stay clipped without creating a nested scroll container that would break sticky positioning. Distraction-free / minimal editors (e.g. Widgets) are unaffected since they don't render the toolbar. diff --git a/.changeset/html-block-editor.md b/.changeset/html-block-editor.md deleted file mode 100644 index 0b4b046bd0..0000000000 --- a/.changeset/html-block-editor.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"emdash": minor -"@emdash-cms/admin": minor ---- - -First-class HTML block in the admin editor. The existing `htmlBlock` Portable Text type (produced by the WordPress and Contentful importers) is now a fully editable block in the rich-text editor. Authors can insert an HTML block via the `/html` slash command and edit raw HTML in a textarea. Imported `htmlBlock` content that previously fell through to an opaque `pluginBlock` placeholder is now rendered in the same editable UI. The inline (visual-editing) editor preserves HTML blocks as read-only placeholders to prevent data loss. diff --git a/.changeset/id-admin-i18n-fixes.md b/.changeset/id-admin-i18n-fixes.md deleted file mode 100644 index 5dca6d8ac8..0000000000 --- a/.changeset/id-admin-i18n-fixes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Fix the remaining Indonesian admin translations. diff --git a/.changeset/menu-add-content-type.md b/.changeset/menu-add-content-type.md deleted file mode 100644 index 5add7ab37b..0000000000 --- a/.changeset/menu-add-content-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Fix "Add Content" in the menu editor: the admin was sending the raw collection slug (e.g. `pages`) as the menu item `type`, which the API's `menuItemTypeEnum` rejects with a 400. Map the picker's collection to the correct enum value (`pages` → `page`, `posts` → `post`, everything else → `collection`) so picking a page or post actually adds it to the menu. (#1173) diff --git a/.changeset/seed-byline-avatar.md b/.changeset/seed-byline-avatar.md deleted file mode 100644 index b45f68d88a..0000000000 --- a/.changeset/seed-byline-avatar.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"emdash": patch ---- - -Seed files can now attach an avatar to a byline. `bylines[].avatar` takes a `storageKey` (plus optional `alt`, `filename`, `mimeType`, `width`, `height`) for a file that already exists in the configured storage; applying the seed creates a `media` row and links it to the byline via `avatarMediaId`. Unlike a content `$media` reference, nothing is downloaded or uploaded, which suits seeding bylines alongside a media migration. diff --git a/.changeset/thai-admin-locale-followup.md b/.changeset/thai-admin-locale-followup.md deleted file mode 100644 index e12441769f..0000000000 --- a/.changeset/thai-admin-locale-followup.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -i18n(th): translate remaining untranslated Thai (ไทย) admin UI strings, including the newly-added plugin registry and Portable Text HTML-block strings diff --git a/.changeset/thai-admin-locale.md b/.changeset/thai-admin-locale.md deleted file mode 100644 index 7a56849ed7..0000000000 --- a/.changeset/thai-admin-locale.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@emdash-cms/admin": patch ---- - -Adds Thai (ไทย) locale to the admin UI. diff --git a/fixtures/perf-site/CHANGELOG.md b/fixtures/perf-site/CHANGELOG.md index 2f9b547155..f84f0cb749 100644 --- a/fixtures/perf-site/CHANGELOG.md +++ b/fixtures/perf-site/CHANGELOG.md @@ -1,5 +1,13 @@ # @emdash-cms/fixture-perf-site +## 0.0.14 + +### Patch Changes + +- Updated dependencies [[`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8), [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd), [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8)]: + - emdash@0.17.0 + - @emdash-cms/cloudflare@0.17.0 + ## 0.0.13 ### Patch Changes diff --git a/fixtures/perf-site/package.json b/fixtures/perf-site/package.json index 8aace89753..4b7d40cbd7 100644 --- a/fixtures/perf-site/package.json +++ b/fixtures/perf-site/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/fixture-perf-site", - "version": "0.0.13", + "version": "0.0.14", "private": true, "type": "module", "description": "Fixture site for query-count perf snapshots. Runs under sqlite+node or d1+cloudflare based on EMDASH_FIXTURE_TARGET.", diff --git a/infra/blog-demo/CHANGELOG.md b/infra/blog-demo/CHANGELOG.md index 631c926f67..2482b8b78b 100644 --- a/infra/blog-demo/CHANGELOG.md +++ b/infra/blog-demo/CHANGELOG.md @@ -1,5 +1,15 @@ # @emdash-cms/perf-demo-site +## 0.0.14 + +### Patch Changes + +- Updated dependencies [[`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8), [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd), [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8)]: + - emdash@0.17.0 + - @emdash-cms/cloudflare@0.17.0 + - @emdash-cms/plugin-cli@0.5.1 + - @emdash-cms/plugin-webhook-notifier@0.2.0 + ## 0.0.13 ### Patch Changes diff --git a/infra/blog-demo/package.json b/infra/blog-demo/package.json index 9a71ccd9fc..c5e9f87af9 100644 --- a/infra/blog-demo/package.json +++ b/infra/blog-demo/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/perf-demo-site", - "version": "0.0.13", + "version": "0.0.14", "private": true, "type": "module", "scripts": { diff --git a/infra/cache-demo/CHANGELOG.md b/infra/cache-demo/CHANGELOG.md index 6fc6d84c2d..d9e6cd6164 100644 --- a/infra/cache-demo/CHANGELOG.md +++ b/infra/cache-demo/CHANGELOG.md @@ -1,5 +1,15 @@ # @emdash-cms/cache-demo-site +## 0.0.14 + +### Patch Changes + +- Updated dependencies [[`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8), [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd), [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8)]: + - emdash@0.17.0 + - @emdash-cms/cloudflare@0.17.0 + - @emdash-cms/plugin-cli@0.5.1 + - @emdash-cms/plugin-webhook-notifier@0.2.0 + ## 0.0.13 ### Patch Changes diff --git a/infra/cache-demo/package.json b/infra/cache-demo/package.json index c5435a51da..d909c2920e 100644 --- a/infra/cache-demo/package.json +++ b/infra/cache-demo/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/cache-demo-site", - "version": "0.0.13", + "version": "0.0.14", "private": true, "type": "module", "scripts": { diff --git a/packages/admin/CHANGELOG.md b/packages/admin/CHANGELOG.md index a9e8c047a1..2fcdfb92cc 100644 --- a/packages/admin/CHANGELOG.md +++ b/packages/admin/CHANGELOG.md @@ -1,5 +1,53 @@ # @emdash-cms/admin +## 0.17.0 + +### Minor Changes + +- [#1258](https://github.com/emdash-cms/emdash/pull/1258) [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950) Thanks [@MohamedH1998](https://github.com/MohamedH1998)! - Adds custom fields to bylines. Sites can define site-specific byline metadata (Twitter handle, pronouns, company, localised job title, etc.) via the new `/byline-schema` admin screen, accessed from the **Byline schema** link button at the top of the Bylines admin page (admin-only). + + Per-field `translatable` flag picks whether values are stored per-locale (one value per locale row in a `translation_group`) or shared across every locale variant of the same byline identity. Schema management is gated by `schema:manage`; value editing by `bylines:manage`. + + Custom-field values can be set at both create and update time. `POST` and `PUT` on `/_emdash/api/admin/bylines` accept the same `customFields` map; the row write and the custom-field writes share a single transaction on Node/PG so a partial failure rolls both back. On D1 (no transactions), a retry POST is treated as completing an abandoned create iff three checks all pass: (a) every fixed column on the existing row matches the new payload (`displayName`, `bio`, `avatarMediaId`, `websiteUrl`, `userId`, `isGuest`, effective locale — null-vs-undefined normalised); (b) the existing row's `translationGroup` matches what a fresh create with the same input would produce (`sourceGroup` when `translationOf` is present, `existing.id` when it isn't); (c) every custom-field value already stored on the row appears in the input payload with an equal value (subset-match, so partial mid-loop crashes can be completed). The recovery branch is conservative on every axis: any fixed-column mismatch, any translation-group mismatch, any overlapping custom-field value mismatch, an input that omits a key the existing row stores, or an input with no custom fields at all → standard `CONFLICT`. Validation runs before any DB write so a bad value (unknown slug, type mismatch, select-choice miss, non-URL or non-http(s) URL for a `url` field) returns 400 `VALIDATION_ERROR` without leaving partial state behind. In the admin, registered fields render inline with Name, Bio, etc. — no separate section header — and are available in the **New byline** dialog as well as edit. + + `BylineSummary` gains an optional `customFields: Record` property. Existing object-literal consumers stay source-compatible because the property is optional and runtime always returns `{}` when no fields are registered. + + Hydration is symmetric with writes: rows are only applied to a byline when they live in the table matching the field's current `translatable` flag, so stale rows from a `translatable` flip can't leak into hydrated output. Schema mutations on `/byline-schema` invalidate the same `byline-fields` query the byline form reads, so newly-registered fields appear in the editor without a page reload. `url` field values are parsed with `new URL(...)` AND restricted to `http:` / `https:` schemes at write time so they can't ship `javascript:` / `data:` / `mailto:` payloads to link rendering. The `BylineFieldEditor` "Save" button stays disabled until a `select` field has at least one option; and select-option lists are accumulated on a null-prototype object so option values that collide with `Object.prototype` keys render correctly. + + The field-definitions cache uses parity on `options.byline_fields_version` as a dirty bit: schema mutations flip the counter to odd before the write lands and to a **new even** value after, with the cache treating any odd version as "bypass the global holder, read fresh from the DB". `markVersionDirty` is parity-aware (ensures odd, no-op if already odd) so a crashed prior attempt's leftover dirty state can't get inverted. `markVersionClean` is **always-advance** (`+2` when starting even, `+1` when starting odd) so two concurrent mutators can't collapse on the same even key and pin the cache on a partial-set snapshot — every committed mutation produces an observable counter change for cache readers. Idempotent-retry exits (`FIELD_EXISTS` on create, `FIELD_NOT_FOUND` on update/delete, no-op input on update) call `markVersionClean` too, which doubles as both the dirty-crash recovery and the false-clean recovery. All version writes use `INSERT … ON CONFLICT DO UPDATE` so a missing options row can't silently turn invalidation into a no-op. + + Implements [#1174](https://github.com/emdash-cms/emdash/discussions/1174). Builds on the bylines-i18n foundation from [#1146](https://github.com/emdash-cms/emdash/pull/1146). + +- [#1215](https://github.com/emdash-cms/emdash/pull/1215) [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - First-class HTML block in the admin editor. The existing `htmlBlock` Portable Text type (produced by the WordPress and Contentful importers) is now a fully editable block in the rich-text editor. Authors can insert an HTML block via the `/html` slash command and edit raw HTML in a textarea. Imported `htmlBlock` content that previously fell through to an opaque `pluginBlock` placeholder is now rendered in the same editable UI. The inline (visual-editing) editor preserves HTML blocks as read-only placeholders to prevent data loss. + +### Patch Changes + +- [#1297](https://github.com/emdash-cms/emdash/pull/1297) [`cccf4f2`](https://github.com/emdash-cms/emdash/commit/cccf4f2b40451efa724136e815158ebca189a135) Thanks [@emdashbot](https://github.com/apps/emdashbot)! - Fix content entity editor block menu actions (Duplicate / Delete) not working when the drag handle sets a NodeSelection ([#1261](https://github.com/emdash-cms/emdash/issues/1261)). + +- [#1225](https://github.com/emdash-cms/emdash/pull/1225) [`886f2d1`](https://github.com/emdash-cms/emdash/commit/886f2d1e4969403787cc39dfbda6dcdfe034372c) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Add search to the byline picker on content entities and remove the effective 100-byline cap. The picker now performs a debounced server-side search via the bylines API instead of rendering a fixed dropdown of the first 100 results, so bylines beyond the first page can be found and credited. Credited bylines from the saved entry are also resolved from the entry itself, so a credit that falls outside the initial list still renders its name instead of disappearing. + +- [#1222](https://github.com/emdash-cms/emdash/pull/1222) [`a5dafb3`](https://github.com/emdash-cms/emdash/commit/a5dafb32b75358c96be5f2a2487bf323a0045bb8) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Fixes the byline search box reloading the whole page on every keystroke. The search term is now debounced (300ms) before it feeds the bylines query, and the full-page loader only takes over when there is no data yet (`isLoading && !data`) instead of on every new query key. Typing now stays responsive and keeps the input focused, matching the behaviour of the users page. The load-more snapshot and its filter-match check both use the debounced search value so appended pages are no longer discarded. + +- [#1226](https://github.com/emdash-cms/emdash/pull/1226) [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Make content list search work on large collections ([#1219](https://github.com/emdash-cms/emdash/issues/1219)). The admin content list previously filtered only the rows already loaded on the current page, so an entry far back in a big collection could not be found until you navigated near it. The list endpoint now accepts a `q` parameter and performs a case-insensitive substring search across the collection's title/name/slug columns server-side (LIKE wildcards in the query are escaped), and the admin search box drives that query (debounced) instead of filtering in memory. Also adds locale-aware composite indexes (`idx_{table}_loc_upd` / `idx_{table}_loc_crt`) so locale-filtered content lists stay index-served on large, i18n-enabled tables. + +- [#1224](https://github.com/emdash-cms/emdash/pull/1224) [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Fix taxonomy terms not being locale-aware in the content editor ([#1218](https://github.com/emdash-cms/emdash/issues/1218)). Term assignments are stored against the per-locale content row while the term's `translation_group` spans every locale, so resolving terms for an entry must scope to the entry's locale. The content terms endpoint (`/content/:collection/:id/terms/:taxonomy`) now derives the entry's locale server-side and passes it to `getTermsForEntry`, and the admin `TaxonomySidebar` threads the entry locale through its fetch/save calls (and into its React Query keys, so switching translations refetches). Previously a localized post showed and applied every locale variant of a tag instead of just the variant for its own locale. + +- [#1227](https://github.com/emdash-cms/emdash/pull/1227) [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Add search and filtering to the media library ([#1221](https://github.com/emdash-cms/emdash/issues/1221)). The media list endpoint now accepts a `q` parameter for a case-insensitive filename substring search (which also matches extensions, with LIKE wildcards escaped), alongside the existing `mimeType` filter. The Media Library page gains a filename search box and a type filter (images / video / audio / documents), and the media picker in the content editor now searches the local library by filename too. Previously neither surface could search or filter local media, which made large libraries hard to navigate. + +- [#1223](https://github.com/emdash-cms/emdash/pull/1223) [`34afc14`](https://github.com/emdash-cms/emdash/commit/34afc1448440f8ffab956f096322d67ec42127cb) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - The rich-text editor formatting toolbar now stays pinned to the top of the editing area while scrolling through long posts, instead of scrolling out of view. The toolbar uses `position: sticky` and the editor wrapper switched from `overflow-hidden` to `overflow-clip` so corners stay clipped without creating a nested scroll container that would break sticky positioning. Distraction-free / minimal editors (e.g. Widgets) are unaffected since they don't render the toolbar. + +- [#1309](https://github.com/emdash-cms/emdash/pull/1309) [`019d9e4`](https://github.com/emdash-cms/emdash/commit/019d9e44c5331d92abad78d7f9abfe2aefa4d1fe) Thanks [@ahliweb](https://github.com/ahliweb)! - Fix the remaining Indonesian admin translations. + +- [#1310](https://github.com/emdash-cms/emdash/pull/1310) [`ba0f3d4`](https://github.com/emdash-cms/emdash/commit/ba0f3d4f1d13d30d540895225556560bee176026) Thanks [@emdashbot](https://github.com/apps/emdashbot)! - Fix "Add Content" in the menu editor: the admin was sending the raw collection slug (e.g. `pages`) as the menu item `type`, which the API's `menuItemTypeEnum` rejects with a 400. Map the picker's collection to the correct enum value (`pages` → `page`, `posts` → `post`, everything else → `collection`) so picking a page or post actually adds it to the menu. ([#1173](https://github.com/emdash-cms/emdash/issues/1173)) + +- [#1290](https://github.com/emdash-cms/emdash/pull/1290) [`aacdf20`](https://github.com/emdash-cms/emdash/commit/aacdf207b6e31b98debacf12d52138d74371869f) Thanks [@SL33PiNg](https://github.com/SL33PiNg)! - i18n(th): translate remaining untranslated Thai (ไทย) admin UI strings, including the newly-added plugin registry and Portable Text HTML-block strings + +- [#1245](https://github.com/emdash-cms/emdash/pull/1245) [`7d55db6`](https://github.com/emdash-cms/emdash/commit/7d55db6ca3291eac1c2cfda865e1b0e507fdece5) Thanks [@SL33PiNg](https://github.com/SL33PiNg)! - Adds Thai (ไทย) locale to the admin UI. + +- Updated dependencies [[`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d)]: + - @emdash-cms/registry-client@0.3.1 + - @emdash-cms/blocks@0.17.0 + ## 0.16.1 ### Patch Changes diff --git a/packages/admin/package.json b/packages/admin/package.json index 8df69fc9b4..438454ed54 100644 --- a/packages/admin/package.json +++ b/packages/admin/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/admin", - "version": "0.16.1", + "version": "0.17.0", "description": "Admin UI for EmDash CMS", "type": "module", "main": "dist/index.js", diff --git a/packages/auth-atproto/CHANGELOG.md b/packages/auth-atproto/CHANGELOG.md index 59bffaa5bf..eee4a88866 100644 --- a/packages/auth-atproto/CHANGELOG.md +++ b/packages/auth-atproto/CHANGELOG.md @@ -1,5 +1,12 @@ # @emdash-cms/auth-atproto +## 0.2.11 + +### Patch Changes + +- Updated dependencies []: + - @emdash-cms/auth@0.17.0 + ## 0.2.10 ### Patch Changes diff --git a/packages/auth-atproto/package.json b/packages/auth-atproto/package.json index 2ed5d66da2..390149e864 100644 --- a/packages/auth-atproto/package.json +++ b/packages/auth-atproto/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/auth-atproto", - "version": "0.2.10", + "version": "0.2.11", "description": "AT Protocol / Atmosphere authentication provider for EmDash CMS", "type": "module", "main": "src/auth.ts", diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 60db56005f..07a0ccc98f 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,7 @@ # @emdash-cms/auth +## 0.17.0 + ## 0.16.1 ## 0.16.0 diff --git a/packages/auth/package.json b/packages/auth/package.json index e2e4c2bc9e..3ccce18ff6 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/auth", - "version": "0.16.1", + "version": "0.17.0", "description": "Passkey-first authentication for EmDash", "type": "module", "main": "dist/index.mjs", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 8a000ea8f1..c75833c36d 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -1,5 +1,7 @@ # @emdash-cms/blocks +## 0.17.0 + ## 0.16.1 ## 0.16.0 diff --git a/packages/blocks/package.json b/packages/blocks/package.json index 8c70cdb095..ca876e7942 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/blocks", - "version": "0.16.1", + "version": "0.17.0", "description": "Declarative plugin UI blocks for EmDash CMS", "type": "module", "main": "dist/index.js", diff --git a/packages/cloudflare/CHANGELOG.md b/packages/cloudflare/CHANGELOG.md index 9593046421..a4eb0c8cb0 100644 --- a/packages/cloudflare/CHANGELOG.md +++ b/packages/cloudflare/CHANGELOG.md @@ -1,5 +1,12 @@ # @emdash-cms/cloudflare +## 0.17.0 + +### Patch Changes + +- Updated dependencies [[`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8), [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd), [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8)]: + - emdash@0.17.0 + ## 0.16.1 ### Patch Changes diff --git a/packages/cloudflare/package.json b/packages/cloudflare/package.json index 9a09ec5f4b..bf77f37fe7 100644 --- a/packages/cloudflare/package.json +++ b/packages/cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/cloudflare", - "version": "0.16.1", + "version": "0.17.0", "description": "Cloudflare adapters for EmDash - D1, R2, Access, and Worker Loader sandbox", "type": "module", "main": "dist/index.mjs", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 3ee6d7d563..f05dea0a40 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,57 @@ # emdash +## 0.17.0 + +### Minor Changes + +- [#1258](https://github.com/emdash-cms/emdash/pull/1258) [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950) Thanks [@MohamedH1998](https://github.com/MohamedH1998)! - Adds custom fields to bylines. Sites can define site-specific byline metadata (Twitter handle, pronouns, company, localised job title, etc.) via the new `/byline-schema` admin screen, accessed from the **Byline schema** link button at the top of the Bylines admin page (admin-only). + + Per-field `translatable` flag picks whether values are stored per-locale (one value per locale row in a `translation_group`) or shared across every locale variant of the same byline identity. Schema management is gated by `schema:manage`; value editing by `bylines:manage`. + + Custom-field values can be set at both create and update time. `POST` and `PUT` on `/_emdash/api/admin/bylines` accept the same `customFields` map; the row write and the custom-field writes share a single transaction on Node/PG so a partial failure rolls both back. On D1 (no transactions), a retry POST is treated as completing an abandoned create iff three checks all pass: (a) every fixed column on the existing row matches the new payload (`displayName`, `bio`, `avatarMediaId`, `websiteUrl`, `userId`, `isGuest`, effective locale — null-vs-undefined normalised); (b) the existing row's `translationGroup` matches what a fresh create with the same input would produce (`sourceGroup` when `translationOf` is present, `existing.id` when it isn't); (c) every custom-field value already stored on the row appears in the input payload with an equal value (subset-match, so partial mid-loop crashes can be completed). The recovery branch is conservative on every axis: any fixed-column mismatch, any translation-group mismatch, any overlapping custom-field value mismatch, an input that omits a key the existing row stores, or an input with no custom fields at all → standard `CONFLICT`. Validation runs before any DB write so a bad value (unknown slug, type mismatch, select-choice miss, non-URL or non-http(s) URL for a `url` field) returns 400 `VALIDATION_ERROR` without leaving partial state behind. In the admin, registered fields render inline with Name, Bio, etc. — no separate section header — and are available in the **New byline** dialog as well as edit. + + `BylineSummary` gains an optional `customFields: Record` property. Existing object-literal consumers stay source-compatible because the property is optional and runtime always returns `{}` when no fields are registered. + + Hydration is symmetric with writes: rows are only applied to a byline when they live in the table matching the field's current `translatable` flag, so stale rows from a `translatable` flip can't leak into hydrated output. Schema mutations on `/byline-schema` invalidate the same `byline-fields` query the byline form reads, so newly-registered fields appear in the editor without a page reload. `url` field values are parsed with `new URL(...)` AND restricted to `http:` / `https:` schemes at write time so they can't ship `javascript:` / `data:` / `mailto:` payloads to link rendering. The `BylineFieldEditor` "Save" button stays disabled until a `select` field has at least one option; and select-option lists are accumulated on a null-prototype object so option values that collide with `Object.prototype` keys render correctly. + + The field-definitions cache uses parity on `options.byline_fields_version` as a dirty bit: schema mutations flip the counter to odd before the write lands and to a **new even** value after, with the cache treating any odd version as "bypass the global holder, read fresh from the DB". `markVersionDirty` is parity-aware (ensures odd, no-op if already odd) so a crashed prior attempt's leftover dirty state can't get inverted. `markVersionClean` is **always-advance** (`+2` when starting even, `+1` when starting odd) so two concurrent mutators can't collapse on the same even key and pin the cache on a partial-set snapshot — every committed mutation produces an observable counter change for cache readers. Idempotent-retry exits (`FIELD_EXISTS` on create, `FIELD_NOT_FOUND` on update/delete, no-op input on update) call `markVersionClean` too, which doubles as both the dirty-crash recovery and the false-clean recovery. All version writes use `INSERT … ON CONFLICT DO UPDATE` so a missing options row can't silently turn invalidation into a no-op. + + Implements [#1174](https://github.com/emdash-cms/emdash/discussions/1174). Builds on the bylines-i18n foundation from [#1146](https://github.com/emdash-cms/emdash/pull/1146). + +- [#1215](https://github.com/emdash-cms/emdash/pull/1215) [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - First-class HTML block in the admin editor. The existing `htmlBlock` Portable Text type (produced by the WordPress and Contentful importers) is now a fully editable block in the rich-text editor. Authors can insert an HTML block via the `/html` slash command and edit raw HTML in a textarea. Imported `htmlBlock` content that previously fell through to an opaque `pluginBlock` placeholder is now rendered in the same editable UI. The inline (visual-editing) editor preserves HTML blocks as read-only placeholders to prevent data loss. + +### Patch Changes + +- [#1298](https://github.com/emdash-cms/emdash/pull/1298) [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8) Thanks [@ascorbic](https://github.com/ascorbic)! - Byline hydration now resolves the author avatar's storage key in the same query. `getEmDashCollection` / `getEmDashEntry` populate `entry.data.bylines[].byline.avatarStorageKey` (and `avatarAlt`) via a `LEFT JOIN` on the media table, so list pages can build a direct avatar URL without a per-byline `MediaRepository.findById`. Previously the byline summary exposed only `avatarMediaId` (a bare ULID with no file extension), forcing sites that want direct storage URLs into an N+1 media lookup. A page rendering 20 posts by distinct authors paid ~20 extra queries. The new fields are additive and null on the plain byline finders (`findById`, `findBySlug`), which do not join media; rely on the content-credit hydration path for them. + +- [#1197](https://github.com/emdash-cms/emdash/pull/1197) [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Persist welcome-dismissed flag in database instead of session. Previously the welcome modal would be shown every time a user logged-in. + +- [#1295](https://github.com/emdash-cms/emdash/pull/1295) [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15) Thanks [@emdashbot](https://github.com/apps/emdashbot)! - fix(core/redirects): match exact redirects regardless of trailing slash ([#1271](https://github.com/emdash-cms/emdash/issues/1271)) + + Exact redirect rules now match requests with or without a trailing slash. A redirect stored with source `/old/` will also match a request for `/old`, and a redirect stored with source `/old` will also match `/old/`. The stored source is preserved unchanged; the fallback happens at lookup time. + +- [#1226](https://github.com/emdash-cms/emdash/pull/1226) [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Make content list search work on large collections ([#1219](https://github.com/emdash-cms/emdash/issues/1219)). The admin content list previously filtered only the rows already loaded on the current page, so an entry far back in a big collection could not be found until you navigated near it. The list endpoint now accepts a `q` parameter and performs a case-insensitive substring search across the collection's title/name/slug columns server-side (LIKE wildcards in the query are escaped), and the admin search box drives that query (debounced) instead of filtering in memory. Also adds locale-aware composite indexes (`idx_{table}_loc_upd` / `idx_{table}_loc_crt`) so locale-filtered content lists stay index-served on large, i18n-enabled tables. + +- [#1302](https://github.com/emdash-cms/emdash/pull/1302) [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b) Thanks [@WellDunDun](https://github.com/WellDunDun)! - Fixes locale-aware content updates so REST, CLI, client, and MCP callers can safely update content by slug when multiple locales share the same slug. + +- [#1224](https://github.com/emdash-cms/emdash/pull/1224) [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Fix taxonomy terms not being locale-aware in the content editor ([#1218](https://github.com/emdash-cms/emdash/issues/1218)). Term assignments are stored against the per-locale content row while the term's `translation_group` spans every locale, so resolving terms for an entry must scope to the entry's locale. The content terms endpoint (`/content/:collection/:id/terms/:taxonomy`) now derives the entry's locale server-side and passes it to `getTermsForEntry`, and the admin `TaxonomySidebar` threads the entry locale through its fetch/save calls (and into its React Query keys, so switching translations refetches). Previously a localized post showed and applied every locale variant of a tag instead of just the variant for its own locale. + +- [#1227](https://github.com/emdash-cms/emdash/pull/1227) [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0) Thanks [@scottbuscemi](https://github.com/scottbuscemi)! - Add search and filtering to the media library ([#1221](https://github.com/emdash-cms/emdash/issues/1221)). The media list endpoint now accepts a `q` parameter for a case-insensitive filename substring search (which also matches extensions, with LIKE wildcards escaped), alongside the existing `mimeType` filter. The Media Library page gains a filename search box and a type filter (images / video / audio / documents), and the media picker in the content editor now searches the local library by filename too. Previously neither surface could search or filter local media, which made large libraries hard to navigate. + +- [#1319](https://github.com/emdash-cms/emdash/pull/1319) [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d) Thanks [@ascorbic](https://github.com/ascorbic)! - Fix `require is not defined` crash on every EmDash API route under `astro dev` on Cloudflare Workers ([#1292](https://github.com/emdash-cms/emdash/issues/1292)). + + `@emdash-cms/registry-client` listed `semver` (CommonJS) in `dependencies`, which the build externalizes -- so consumers loaded a nested CJS copy. Vite's SSR module runner (workerd) evaluates modules with no `require` binding, so semver's internal `require()` threw and took down any route whose import graph reached registry-client (schema, plugins, env compatibility checks). semver is now bundled into the ESM output, so nothing CommonJS reaches the worker. + +- [#1285](https://github.com/emdash-cms/emdash/pull/1285) [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482) Thanks [@ascorbic](https://github.com/ascorbic)! - Fix SEO fields (noindex toggle, canonical URL) not affecting rendered pages. The content loader now surfaces per-entry SEO metadata on `entry.data.seo`, so `getSeoMeta()` reflects values set in the admin SEO panel. SEO is folded into the existing entry query via a LEFT JOIN, adding no extra database round-trips. + +- [#1298](https://github.com/emdash-cms/emdash/pull/1298) [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8) Thanks [@ascorbic](https://github.com/ascorbic)! - Seed files can now attach an avatar to a byline. `bylines[].avatar` takes a `storageKey` (plus optional `alt`, `filename`, `mimeType`, `width`, `height`) for a file that already exists in the configured storage; applying the seed creates a `media` row and links it to the byline via `avatarMediaId`. Unlike a content `$media` reference, nothing is downloaded or uploaded, which suits seeding bylines alongside a media migration. + +- Updated dependencies [[`cccf4f2`](https://github.com/emdash-cms/emdash/commit/cccf4f2b40451efa724136e815158ebca189a135), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`886f2d1`](https://github.com/emdash-cms/emdash/commit/886f2d1e4969403787cc39dfbda6dcdfe034372c), [`a5dafb3`](https://github.com/emdash-cms/emdash/commit/a5dafb32b75358c96be5f2a2487bf323a0045bb8), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`34afc14`](https://github.com/emdash-cms/emdash/commit/34afc1448440f8ffab956f096322d67ec42127cb), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`019d9e4`](https://github.com/emdash-cms/emdash/commit/019d9e44c5331d92abad78d7f9abfe2aefa4d1fe), [`ba0f3d4`](https://github.com/emdash-cms/emdash/commit/ba0f3d4f1d13d30d540895225556560bee176026), [`aacdf20`](https://github.com/emdash-cms/emdash/commit/aacdf207b6e31b98debacf12d52138d74371869f), [`7d55db6`](https://github.com/emdash-cms/emdash/commit/7d55db6ca3291eac1c2cfda865e1b0e507fdece5)]: + - @emdash-cms/admin@0.17.0 + - @emdash-cms/registry-client@0.3.1 + - @emdash-cms/auth@0.17.0 + - @emdash-cms/gutenberg-to-portable-text@0.17.0 + ## 0.16.1 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 1806597c66..46215d26a1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "emdash", - "version": "0.16.1", + "version": "0.17.0", "description": "Astro-native CMS with WordPress migration support", "type": "module", "main": "dist/index.mjs", diff --git a/packages/create-emdash/CHANGELOG.md b/packages/create-emdash/CHANGELOG.md index b9d4e774da..b0c5c00cff 100644 --- a/packages/create-emdash/CHANGELOG.md +++ b/packages/create-emdash/CHANGELOG.md @@ -1,5 +1,7 @@ # create-emdash +## 0.17.0 + ## 0.16.1 ## 0.16.0 diff --git a/packages/create-emdash/package.json b/packages/create-emdash/package.json index 5f7fb06346..7383e4f29e 100644 --- a/packages/create-emdash/package.json +++ b/packages/create-emdash/package.json @@ -1,6 +1,6 @@ { "name": "create-emdash", - "version": "0.16.1", + "version": "0.17.0", "description": "Create a new EmDash CMS project", "type": "module", "bin": "./dist/index.mjs", diff --git a/packages/gutenberg-to-portable-text/CHANGELOG.md b/packages/gutenberg-to-portable-text/CHANGELOG.md index c550a290ff..f694bcfb8a 100644 --- a/packages/gutenberg-to-portable-text/CHANGELOG.md +++ b/packages/gutenberg-to-portable-text/CHANGELOG.md @@ -1,5 +1,7 @@ # @emdash-cms/gutenberg-to-portable-text +## 0.17.0 + ## 0.16.1 ## 0.16.0 diff --git a/packages/gutenberg-to-portable-text/package.json b/packages/gutenberg-to-portable-text/package.json index cbf8c4007a..b8d96eb447 100644 --- a/packages/gutenberg-to-portable-text/package.json +++ b/packages/gutenberg-to-portable-text/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/gutenberg-to-portable-text", - "version": "0.16.1", + "version": "0.17.0", "description": "Convert WordPress Gutenberg blocks to Portable Text", "type": "module", "main": "dist/index.mjs", diff --git a/packages/plugin-cli/CHANGELOG.md b/packages/plugin-cli/CHANGELOG.md index 0704afd2d3..69c72b81fc 100644 --- a/packages/plugin-cli/CHANGELOG.md +++ b/packages/plugin-cli/CHANGELOG.md @@ -1,5 +1,12 @@ # @emdash-cms/registry-cli +## 0.5.1 + +### Patch Changes + +- Updated dependencies [[`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d)]: + - @emdash-cms/registry-client@0.3.1 + ## 0.5.0 ### Minor Changes diff --git a/packages/plugin-cli/package.json b/packages/plugin-cli/package.json index 78ca32fb52..7313efb81e 100644 --- a/packages/plugin-cli/package.json +++ b/packages/plugin-cli/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/plugin-cli", - "version": "0.5.0", + "version": "0.5.1", "description": "CLI for authoring, building, and publishing EmDash plugins. Covers init / build / dev / bundle / publish plus registry search and identity. Atproto OAuth, FAIR-shaped records, sandboxed-plugin-only.", "type": "module", "main": "dist/api.mjs", diff --git a/packages/plugins/embeds/CHANGELOG.md b/packages/plugins/embeds/CHANGELOG.md index 7c15192e21..cd7c066fc2 100644 --- a/packages/plugins/embeds/CHANGELOG.md +++ b/packages/plugins/embeds/CHANGELOG.md @@ -1,5 +1,12 @@ # @emdash-cms/plugin-embeds +## 0.1.19 + +### Patch Changes + +- Updated dependencies []: + - @emdash-cms/blocks@0.17.0 + ## 0.1.18 ### Patch Changes diff --git a/packages/plugins/embeds/package.json b/packages/plugins/embeds/package.json index cdc56f8921..644d130402 100644 --- a/packages/plugins/embeds/package.json +++ b/packages/plugins/embeds/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/plugin-embeds", - "version": "0.1.18", + "version": "0.1.19", "description": "Embed blocks for EmDash CMS - YouTube, Vimeo, Twitter, Bluesky, Mastodon, and more", "type": "module", "main": "src/index.ts", diff --git a/packages/registry-client/CHANGELOG.md b/packages/registry-client/CHANGELOG.md index c94d2fdefd..b8ce878194 100644 --- a/packages/registry-client/CHANGELOG.md +++ b/packages/registry-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @emdash-cms/registry-client +## 0.3.1 + +### Patch Changes + +- [#1319](https://github.com/emdash-cms/emdash/pull/1319) [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d) Thanks [@ascorbic](https://github.com/ascorbic)! - Fix `require is not defined` crash on every EmDash API route under `astro dev` on Cloudflare Workers ([#1292](https://github.com/emdash-cms/emdash/issues/1292)). + + `@emdash-cms/registry-client` listed `semver` (CommonJS) in `dependencies`, which the build externalizes -- so consumers loaded a nested CJS copy. Vite's SSR module runner (workerd) evaluates modules with no `require` binding, so semver's internal `require()` threw and took down any route whose import graph reached registry-client (schema, plugins, env compatibility checks). semver is now bundled into the ESM output, so nothing CommonJS reaches the worker. + ## 0.3.0 ### Minor Changes diff --git a/packages/registry-client/package.json b/packages/registry-client/package.json index 48612342fc..265ff8efde 100644 --- a/packages/registry-client/package.json +++ b/packages/registry-client/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/registry-client", - "version": "0.3.0", + "version": "0.3.1", "description": "Atproto-aware client for the EmDash plugin registry: credential storage, publisher repo operations, and discovery against an aggregator.", "type": "module", "main": "dist/index.js", diff --git a/packages/workerd/CHANGELOG.md b/packages/workerd/CHANGELOG.md index e95395d15d..947e838f7b 100644 --- a/packages/workerd/CHANGELOG.md +++ b/packages/workerd/CHANGELOG.md @@ -1,5 +1,12 @@ # @emdash-cms/sandbox-workerd +## 0.1.3 + +### Patch Changes + +- Updated dependencies [[`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8), [`62c170f`](https://github.com/emdash-cms/emdash/commit/62c170f11403d76370d6c89f8fa25b0bbcf003fd), [`ee67273`](https://github.com/emdash-cms/emdash/commit/ee67273df089d7ed858542fb0df16650f80cbb15), [`28432b9`](https://github.com/emdash-cms/emdash/commit/28432b9b5a045c9227d59f7762bf9cb37067a950), [`9422d6a`](https://github.com/emdash-cms/emdash/commit/9422d6a744b17f477a3966c3c7e07a087a3345e6), [`1f8190d`](https://github.com/emdash-cms/emdash/commit/1f8190d2dee2f93a0a64ddfbe4f481cb6892ce2b), [`67f5992`](https://github.com/emdash-cms/emdash/commit/67f5992aec23d02c724505632ce951e5b7af9cdb), [`a40e455`](https://github.com/emdash-cms/emdash/commit/a40e455a8de730a61291798a3fe0ee32dde24ed0), [`69bdc97`](https://github.com/emdash-cms/emdash/commit/69bdc97e3e4b69a111b3e5210900e23f35134f8d), [`5e7f835`](https://github.com/emdash-cms/emdash/commit/5e7f83571dbc4832e91881aafbb470407c19b482), [`590b2f9`](https://github.com/emdash-cms/emdash/commit/590b2f97367d6881d8c59e5f0a88e7ad69138acb), [`cd2dcc6`](https://github.com/emdash-cms/emdash/commit/cd2dcc6a56d19f38d6e13ba55e8563ceaab90ef8)]: + - emdash@0.17.0 + ## 0.1.2 ### Patch Changes diff --git a/packages/workerd/package.json b/packages/workerd/package.json index c1cd88dd30..d0a897f05d 100644 --- a/packages/workerd/package.json +++ b/packages/workerd/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/sandbox-workerd", - "version": "0.1.2", + "version": "0.1.3", "description": "workerd-based plugin sandbox for EmDash on Node.js", "type": "module", "main": "dist/index.mjs", diff --git a/packages/x402/CHANGELOG.md b/packages/x402/CHANGELOG.md index 1a55a28ea5..0a85b305d0 100644 --- a/packages/x402/CHANGELOG.md +++ b/packages/x402/CHANGELOG.md @@ -1,5 +1,7 @@ # @emdash-cms/x402 +## 0.17.0 + ## 0.16.1 ## 0.16.0 diff --git a/packages/x402/package.json b/packages/x402/package.json index 7a4047d1fd..1fdb6cb21f 100644 --- a/packages/x402/package.json +++ b/packages/x402/package.json @@ -1,6 +1,6 @@ { "name": "@emdash-cms/x402", - "version": "0.16.1", + "version": "0.17.0", "description": "x402 payment protocol integration for Astro sites", "license": "MIT", "repository": {