Minor Changes
-
#1052
0d5843fThanks @Rimander! - Fixes menu REST API consistency:POST /menus/:name/itemsno longer accepts unknown keys silently. Sendingcustom_url(snake_case) orurlused to return 201 withcustom_url: nullbecause Zod's default.strip()quietly dropped them. The schemas now use.strict()and return 400VALIDATION_ERRORwithUnrecognized key: "custom_url". The documented camelCase keys (customUrl,sortOrder,referenceCollection, etc.) are unchanged and persist as before. Thetypefield is now validated against the canonical enum ("custom" | "page" | "post" | "taxonomy" | "collection"); previously any string passed.- Moves per-item writes to
PUTandDELETE /menus/:name/items/:id(path-style). Every other EmDash resource (content,taxonomies,redirects,sections,widget-areas) addresses items by URL path; menus were the lone outlier requiring?id=<id>in the query string. The legacy query-string form is removed (it was undocumented and only used by the admin, which is updated in this PR). Callers should usePUT /menus/:name/items/:id/DELETE /menus/:name/items/:id. - Menu and menu-item API responses are now camelCase, aligning with the rest of EmDash's REST surface (
content,taxonomies,redirects, …).created_at→createdAt,updated_at→updatedAt,menu_id→menuId,parent_id→parentId,sort_order→sortOrder,reference_collection→referenceCollection,reference_id→referenceId,custom_url→customUrl,title_attr→titleAttr,css_classes→cssClasses,translation_group→translationGroup. Breaking for direct REST consumers that depend on snake_case keys in the response body. The admin UI is already updated. - Refactors menus to the standard repository pattern. Adds
MenuRepositorynext toContentRepository,TaxonomyRepository,RedirectRepository,MediaRepository,CommentRepository. Handlers become thin orchestrators; the repository is now the single place where snake_case rows become camelCase entities.
These changes do not touch any database schema or migration. Existing data is preserved.
-
#1011
dbaea9cThanks @ascorbic! - Adds experimental support for the decentralized plugin registry (see RFC #694). Configure withexperimental.registry.aggregatorUrlinastro.config.mjs; the admin UI then uses the registry instead of the centralized marketplace for browse and install. Marketplace behavior is unchanged when the option is not set.The experimental config accepts a
policy.minimumReleaseAgeduration (e.g."48h") that holds back releases below that age from install and update prompts, with apolicy.minimumReleaseAgeExcludeallowlist for trusted publishers or specific packages. The minimum-release-age check is enforced both client-side (for UX) and server-side (in the install endpoint), so stale browser tabs and deep links still hit the gate.
Patch Changes
-
#751
05440b1Thanks @edrpls! - Fix the admin collection list pagination denominator so it no longer grows in increments of 5 as the user pages forward.The
GET /_emdash/api/content/{collection}response now includes atotalfield with the full filtered row count (independent oflimit). The admin uses it as the pagination denominator, so a 143-entry collection reads1/8on page 1 instead of1/5 → 5/10 → 10/15 → …as successive API pages load.The
totalfield is optional; pre-upgrade clients that ignore it still work, and the admin falls back to the loaded-item count when an older server doesn't return it.Also handles the edge case where the current page exceeds
totalPagesafter filtering or deletion — the admin clamps the active page so the table doesn't render empty while waiting for a refetch. -
#1050
484e7abThanks @wojtekpiskorz! - Fixes broken image collapsing media picker container — addsonErrorhandler and fallback placeholder so Change/Remove buttons remain accessible when referenced image is missing from storage -
#1013
0cd8c6dThanks @ascorbic! - Fixes the slash command menu's initial selection getting overridden when the menu opens under a stationary pointer. The menu items previously reacted tomouseenterunconditionally, so an item rendered beneath the cursor would steal selection from the keyboard default before any user interaction. Mouse-hover-selects still works, but only after the user actually moves the pointer over the menu. -
#1020
d014b48Thanks @ahliweb! - Adds missing Indonesian (id) translations for SEO settings labels and replaces "Edit" with "Sunting" and "Tagline" with "Slogan" across the admin UI. -
Updated dependencies []:
- @emdash-cms/blocks@0.13.0