emdash@0.19.0
Minor Changes
-
#1442
e96587fThanks @ascorbic! - Add status, author, and date-range filtering to the admin content list (#1288). The content list API gainsauthorId,dateField,dateFrom, anddateToquery params (all additive and optional), and a newGET /_emdash/api/content/{collection}/authorsendpoint lists the distinct authors of a collection's content (gated oncontent:read). Filtering runs server-side, so it works across the whole collection rather than only the loaded page. -
#1439
023893aThanks @ascorbic! - Add content filtering by byline credit.getEmDashCollectionnow accepts a reservedbylinekey inwherethat returns entries credited to a byline in any position, including co-authored entries where the byline is a secondary credit. This makes author archive pages possible without querying the database directly. Pass a single byline translation group or an array to match any of several.const byline = await getBylineBySlug("jane-doe"); const { entries } = await getEmDashCollection("posts", { where: { byline: byline.translationGroup ?? byline.id }, orderBy: { published_at: "desc" }, });
A
getEntriesByByline(collection, byline, options)helper wraps the same filter, mirroringgetEntriesByTerm. -
#1367
f41092bThanks @MA2153! - Add content-reference database schema:_emdash_relations(relationship-type definitions, row-per-locale) and_emdash_content_references(directed, locale-agnostic edges between content entries linked bytranslation_group). Additive, forward-only migration043; no existing tables change. Groundwork for reference fields — no field type, API, or admin UI yet. -
#1438
850c1b7Thanks @ascorbic! - Generate responsivesrcsets for media rendered with theImageand Portable Text image components. EmDash now routes locally/R2-stored media through Astro's configured image service (astro:assets) -- the Cloudflare Images binding on Workers, sharp on Node -- producing width-appropriate candidates and modern formats (e.g. WebP) instead of a single full-size<img>.This works automatically:
- Media served from a configured storage
publicUrl(R2 custom domain, S3/CDN) is authorized and optimized. - Same-origin proxied media (local storage, or R2 without a public URL) is optimized when
siteUrlis set; the matchingimage.remotePatternsentry is registered for you, scoped to the media route. - In
astro devit works out of the box without configuration.
When optimization isn't possible (no image service available, an unauthorized host, or unknown dimensions) the components fall back to a plain
<img>, so existing sites keep rendering exactly as before. No template changes are required. - Media served from a configured storage
-
#1312
c39789cThanks @ascorbic! - Drive scheduled publishing from a real heartbeat instead of request side effects (#1303).Content scheduled via the admin now actually transitions to
publishedwhen its time arrives. Previously nothing promoted the row —statusstayedscheduledandpublished_atstayed null forever.A new sweep (
publishDueContent) promotes due content and runs alongside the existing cron tick and system cleanup:- Node / single-process: the timer-based scheduler already drives it — no action needed.
- Cloudflare Workers: a
scheduled()handler driven by a Cron Trigger now runs the sweep. The request-drivenPiggybackScheduleris gone, so there are no maintenance side effects on visitor requests.
@emdash-cms/cloudflareships a Worker entry that wraps Astro's handler with thescheduled()handler (@emdash-cms/cloudflare/worker, pluscreateScheduledHandler()for hand-assembled Workers). When a cache provider is configured, the handler also purges edge-cache tags for whatever it published, so stale snapshots produced before the scheduled time are evicted.Migration for existing Cloudflare sites. New sites get this from the templates. Existing deployments must update two files:
// src/worker.ts export { default, PluginBridge } from "@emdash-cms/cloudflare/worker";
Without the Cron Trigger, scheduled publishing and plugin cron do not run on Workers.
Scheduled publishing matches manual publishing exactly: it fires
content:afterPublishhooks (search indexing, webhooks, syndication), and records the scheduled time aspublished_aton first publication rather than the (later) sweep time. The sweep claims each row atomically before promoting it, so an entry unscheduled or rescheduled just before its time is never published, and overlapping sweeps can't double-publish. Localastro devkeeps running the timer-driven sweep even under the Cloudflare adapter (where production relies on the Cron Trigger).Each tick promotes at most 100 items per collection (a large backlog drains over successive ticks) so a single Worker invocation can't exhaust its CPU/subrequest budget, and edge-cache tags are purged incrementally after each collection's batch rather than only at the end. On Node, the maintenance interval is capped at 60s so scheduled-publish latency matches the Cloudflare Cron Trigger cadence instead of lagging up to five minutes when no plugin cron is due.
Patch Changes
-
#1307
cedfcc5Thanks @emdashbot! - Read?locale=in content write routes (DELETE, publish, unpublish, discard-draft, schedule, unschedule) and forward it tohandleContentGetfor locale-aware slug resolution (#1242) -
#1420
c63f9caThanks @swissky! -getTaxonomyTerms()now returns the termdescriptionfor flat
(non-hierarchical) taxonomies (#1419)The query already fetched the
datacolumn, but the non-hierarchical branch
dropped it when mapping rows toTaxonomyTerm— only hierarchical taxonomies
(viabuildTree) parsed the description. Descriptions set in the admin UI are
now returned for both kinds of taxonomies. -
#1426
61ea3c9Thanks @MA2153! - Fix seed CLI hardcodingenas the default locale (#1421)emdash export-seednow emits a top-leveldefaultLocalefor single-locale
projects, andemdash seed(applySeed) honors it when backfilling the locale
of menus, taxonomies, and content rows that omit an explicitlocale. Previously
anexport-seed→seedround-trip silently rewrote a non-endefault locale
(e.g.de) toen, since the CLI runs outside the Astro runtime and the
fallback collapsed toen. Projects whose default locale isenare unaffected. -
#1445
a4c2af2Thanks @ascorbic! - FixgetEmDashEntry/getEmDashCollectionhydrating taxonomy terms in the request-context or default locale instead of the entry's resolved locale (#1441). When querying with an explicitlocale(or via a localized route),entry.data.termscould return default-locale term variants even though the content row was correctly localized. Term hydration now uses the same resolved locale as the content query. -
Updated dependencies [
e96587f,cedfcc5,7e70abc,783e663,157237d]:- @emdash-cms/admin@0.19.0
- @emdash-cms/auth@0.19.0
- @emdash-cms/gutenberg-to-portable-text@0.19.0